Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge in latest from trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | pledge-additions
Files: files | file ages | folders
SHA3-256:0d11ea056b0998b5fe9c337b68ec4a62ffa1e5ce03135ce53553564da006dc4c
User & Date: andybradford 2018-03-08 04:03:43
Context
2018-03-08
04:03
Merge in latest from trunk. Leaf check-in: 0d11ea05 user: andybradford tags: pledge-additions
2018-03-07
19:46
Rid the code of the legacy UUID_SIZE macro. Replace it everywhere with either HNAME_MAX or HNAME_LEN_SHA1 or HNAME_LEN_K256, as appropriate. check-in: 323299cb user: drh tags: trunk
2018-01-22
03:01
Merge in recent fixes from trunk. check-in: c0f94f69 user: andybradford tags: pledge-additions
Changes

Changes to src/cgi.c.

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324














325
326
327
328
329
330
331
...
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
...
454
455
456
457
458
459
460























461
462
463
464
465
466
467
....
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962

1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984

1985
1986
1987

1988
1989
1990
1991
1992
1993
1994
1995
1996
1997

1998
1999
2000
2001
2002





2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
    zPath = g.zTop;
    if( zPath[0]==0 ) zPath = "/";
  }
  if( g.zBaseURL!=0 && strncmp(g.zBaseURL, "https:", 6)==0 ){
    zSecure = " secure;";
  }
  if( lifetime>0 ){
    lifetime += (int)time(0);
    blob_appendf(&extraHeader,
       "Set-Cookie: %s=%t; Path=%s; expires=%z; HttpOnly;%s Version=1\r\n",
        zName, zValue, zPath, cgi_rfc822_datestamp(lifetime), zSecure);
  }else{
    blob_appendf(&extraHeader,
       "Set-Cookie: %s=%t; Path=%s; HttpOnly;%s Version=1\r\n",
       zName, zValue, zPath, zSecure);
  }
}

#if 0
/*
** Add an ETag header line
*/
static char *cgi_add_etag(char *zTxt, int nLen){
  MD5Context ctx;
  unsigned char digest[16];
  int i, j;
  char zETag[64];

  MD5Init(&ctx);
  MD5Update(&ctx,zTxt,nLen);
  MD5Final(digest,&ctx);
  for(j=i=0; i<16; i++,j+=2){
    bprintf(&zETag[j],sizeof(zETag)-j,"%02x",(int)digest[i]);
  }
  blob_appendf(&extraHeader, "ETag: %s\r\n", zETag);
  return fossil_strdup(zETag);
}

/*
** Do some cache control stuff. First, we generate an ETag and include it in
** the response headers. Second, we do whatever is necessary to determine if
** the request was asking about caching and whether we need to send back the
** response body. If we shouldn't send a body, return non-zero.
**
** Currently, we just check the ETag against any If-None-Match header.
**
** FIXME: In some cases (attachments, file contents) we could check
** If-Modified-Since headers and always include Last-Modified in responses.
*/
static int check_cache_control(void){
  /* FIXME: there's some gotchas wth cookies and some headers. */
  char *zETag = cgi_add_etag(blob_buffer(&cgiContent),blob_size(&cgiContent));
  char *zMatch = P("HTTP_IF_NONE_MATCH");

  if( zETag!=0 && zMatch!=0 ) {
    char *zBuf = fossil_strdup(zMatch);
    if( zBuf!=0 ){
      char *zTok = 0;
      char *zPos;
      for( zTok = strtok_r(zBuf, ",\"",&zPos);
           zTok && fossil_stricmp(zTok,zETag);
           zTok =  strtok_r(0, ",\"",&zPos)){}
      fossil_free(zBuf);
      if(zTok) return 1;
    }
  }

  return 0;
}
#endif

/*
** Return true if the response should be sent with Content-Encoding: gzip.
*/
static int is_gzippable(void){
  if( strstr(PD("HTTP_ACCEPT_ENCODING", ""), "gzip")==0 ) return 0;
  return strncmp(zContentType, "text/", 5)==0
................................................................................
void cgi_reply(void){
  int total_size;
  if( iReplyStatus<=0 ){
    iReplyStatus = 200;
    zReplyStatus = "OK";
  }

#if 0
  if( iReplyStatus==200 && check_cache_control() ) {
    /* change the status to "unchanged" and we can skip sending the
    ** actual response body. Obviously we only do this when we _have_ a
    ** body (code 200).
    */
    iReplyStatus = 304;
    zReplyStatus = "Not Modified";
  }
#endif

  if( g.fullHttpReply ){
    fprintf(g.httpOut, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
    fprintf(g.httpOut, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));
    fprintf(g.httpOut, "Connection: close\r\n");
    fprintf(g.httpOut, "X-UA-Compatible: IE=edge\r\n");
  }else{
    fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
  }















  if( blob_size(&extraHeader)>0 ){
    fprintf(g.httpOut, "%s", blob_buffer(&extraHeader));
  }

  /* Add headers to turn on useful security options in browsers. */
  fprintf(g.httpOut, "X-Frame-Options: SAMEORIGIN\r\n");
................................................................................
  ** deliberate inclusion of external resources, such as JavaScript syntax
  ** highlighter scripts.
  **
  ** These headers are probably best added by the web server hosting fossil as
  ** a CGI script.
  */

  if( g.isConst ){
    /* constant means that the input URL will _never_ generate anything
    ** else. In the case of attachments, the contents won't change because
    ** an attempt to change them generates a new attachment number. In the
    ** case of most /getfile calls for specific versions, the only way the
    ** content changes is if someone breaks the SCM. And if that happens, a
    ** stale cache is the least of the problem. So we provide an Expires
    ** header set to a reasonable period (default: one week).
    */
    fprintf(g.httpOut, "Cache-control: max-age=28800\r\n");
  }else{
    fprintf(g.httpOut, "Cache-control: no-cache\r\n");
  }

  /* Content intended for logged in users should only be cached in
  ** the browser, not some shared location.
  */
  fprintf(g.httpOut, "Content-Type: %s; charset=utf-8\r\n", zContentType);
  if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
    cgi_combine_header_and_body();
    blob_compress(&cgiContent[0], &cgiContent[0]);
................................................................................
  const char *zRef = P("referer");
  if( zRef==0 ){
    zRef = P("HTTP_REFERER");
    if( zRef==0 ) zRef = zDefault;
  }
  return zRef;
}
























/*
** Information about all query parameters and cookies are stored
** in these variables.
*/
static int nAllocQP = 0; /* Space allocated for aParamQP[] */
static int nUsedQP = 0;  /* Space actually used in aParamQP[] */
................................................................................
** Parse an RFC822-formatted timestamp as we'd expect from HTTP and return
** a Unix epoch time. <= zero is returned on failure.
**
** Note that this won't handle all the _allowed_ HTTP formats, just the
** most popular one (the one generated by cgi_rfc822_datestamp(), actually).
*/
time_t cgi_rfc822_parsedate(const char *zDate){
  struct tm t;
  char zIgnore[16];
  char zMonth[16];


  memset(&t, 0, sizeof(t));
  if( 7==sscanf(zDate, "%12[A-Za-z,] %d %12[A-Za-z] %d %d:%d:%d", zIgnore,
                       &t.tm_mday, zMonth, &t.tm_year, &t.tm_hour, &t.tm_min,
                       &t.tm_sec)){

    if( t.tm_year > 1900 ) t.tm_year -= 1900;
    for(t.tm_mon=0; azMonths[t.tm_mon]; t.tm_mon++){
      if( !fossil_strnicmp( azMonths[t.tm_mon], zMonth, 3 )){
        return mkgmtime(&t);
      }
    }
  }

  return 0;
}

/*
** Convert a struct tm* that represents a moment in UTC into the number
** of seconds in 1970, UTC.
*/
time_t mkgmtime(struct tm *p){
  time_t t;

  int nDay;
  int isLeapYr;
  /* Days in each month:       31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 */

  static int priorDays[]   = {  0, 31, 59, 90,120,151,181,212,243,273,304,334 };
  if( p->tm_mon<0 ){
    int nYear = (11 - p->tm_mon)/12;
    p->tm_year -= nYear;
    p->tm_mon += nYear*12;
  }else if( p->tm_mon>11 ){
    p->tm_year += p->tm_mon/12;
    p->tm_mon %= 12;
  }
  isLeapYr = p->tm_year%4==0 && (p->tm_year%100!=0 || (p->tm_year+300)%400==0);

  p->tm_yday = priorDays[p->tm_mon] + p->tm_mday - 1;
  if( isLeapYr && p->tm_mon>1 ) p->tm_yday++;
  nDay = (p->tm_year-70)*365 + (p->tm_year-69)/4 -p->tm_year/100 +
         (p->tm_year+300)/400 + p->tm_yday;
  t = ((nDay*24 + p->tm_hour)*60 + p->tm_min)*60 + p->tm_sec;





  return t;
}

/*
** Check the objectTime against the If-Modified-Since request header. If the
** object time isn't any newer than the header, we immediately send back
** a 304 reply and exit.
*/
void cgi_modified_since(time_t objectTime){
  const char *zIf = P("HTTP_IF_MODIFIED_SINCE");







<

|
|







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<








>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
|
|
<
>
|
|
|
|
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
|
|
<
>
|
|
|
|
|
|
|
|
|
<
>
|
|
<
<
<
>
>
>
>
>
|









215
216
217
218
219
220
221

222
223
224
225
226
227
228
229
230
231




















































232
233
234
235
236
237
238
...
246
247
248
249
250
251
252











253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
...
291
292
293
294
295
296
297














298
299
300
301
302
303
304
...
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
....
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920

1921
1922
1923
1924
1925

1926
1927















1928
1929
1930

1931
1932
1933
1934
1935
1936
1937
1938
1939
1940

1941
1942
1943



1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
    zPath = g.zTop;
    if( zPath[0]==0 ) zPath = "/";
  }
  if( g.zBaseURL!=0 && strncmp(g.zBaseURL, "https:", 6)==0 ){
    zSecure = " secure;";
  }
  if( lifetime>0 ){

    blob_appendf(&extraHeader,
       "Set-Cookie: %s=%t; Path=%s; max-age=%d; HttpOnly;%s Version=1\r\n",
        zName, zValue, zPath, lifetime, zSecure);
  }else{
    blob_appendf(&extraHeader,
       "Set-Cookie: %s=%t; Path=%s; HttpOnly;%s Version=1\r\n",
       zName, zValue, zPath, zSecure);
  }
}






















































/*
** Return true if the response should be sent with Content-Encoding: gzip.
*/
static int is_gzippable(void){
  if( strstr(PD("HTTP_ACCEPT_ENCODING", ""), "gzip")==0 ) return 0;
  return strncmp(zContentType, "text/", 5)==0
................................................................................
void cgi_reply(void){
  int total_size;
  if( iReplyStatus<=0 ){
    iReplyStatus = 200;
    zReplyStatus = "OK";
  }












  if( g.fullHttpReply ){
    fprintf(g.httpOut, "HTTP/1.0 %d %s\r\n", iReplyStatus, zReplyStatus);
    fprintf(g.httpOut, "Date: %s\r\n", cgi_rfc822_datestamp(time(0)));
    fprintf(g.httpOut, "Connection: close\r\n");
    fprintf(g.httpOut, "X-UA-Compatible: IE=edge\r\n");
  }else{
    fprintf(g.httpOut, "Status: %d %s\r\n", iReplyStatus, zReplyStatus);
  }
  if( g.isConst ){
    /* isConst means that the reply is guaranteed to be invariant, even
    ** after configuration changes and/or Fossil binary recompiles. */
    fprintf(g.httpOut, "Cache-Control: max-age=31536000\r\n");
  }else if( etag_tag()!=0 ){
    fprintf(g.httpOut, "ETag: %s\r\n", etag_tag());
    fprintf(g.httpOut, "Cache-Control: max-age=%d\r\n", etag_maxage());
  }else{
    fprintf(g.httpOut, "Cache-control: no-cache\r\n");
  }
  if( etag_mtime()>0 ){
    fprintf(g.httpOut, "Last-Modified: %s\r\n",
            cgi_rfc822_datestamp(etag_mtime()));
  }

  if( blob_size(&extraHeader)>0 ){
    fprintf(g.httpOut, "%s", blob_buffer(&extraHeader));
  }

  /* Add headers to turn on useful security options in browsers. */
  fprintf(g.httpOut, "X-Frame-Options: SAMEORIGIN\r\n");
................................................................................
  ** deliberate inclusion of external resources, such as JavaScript syntax
  ** highlighter scripts.
  **
  ** These headers are probably best added by the web server hosting fossil as
  ** a CGI script.
  */















  /* Content intended for logged in users should only be cached in
  ** the browser, not some shared location.
  */
  fprintf(g.httpOut, "Content-Type: %s; charset=utf-8\r\n", zContentType);
  if( fossil_strcmp(zContentType,"application/x-fossil")==0 ){
    cgi_combine_header_and_body();
    blob_compress(&cgiContent[0], &cgiContent[0]);
................................................................................
  const char *zRef = P("referer");
  if( zRef==0 ){
    zRef = P("HTTP_REFERER");
    if( zRef==0 ) zRef = zDefault;
  }
  return zRef;
}

/*
** Return true if the current request appears to be safe from a
** Cross-Site Request Forgery (CSRF) attack.  Conditions that must
** be met:
**
**    *   The HTTP_REFERER must have the same origin
**    *   The REQUEST_METHOD must be POST - or requirePost==0
*/
int cgi_csrf_safe(int requirePost){
  const char *zRef = P("HTTP_REFERER");
  int nBase;
  if( zRef==0 ) return 0;
  if( requirePost ){
    const char *zMethod = P("REQUEST_METHOD");
    if( zMethod==0 ) return 0;
    if( strcmp(zMethod,"POST")!=0 ) return 0;
  }
  nBase = (int)strlen(g.zBaseURL);
  if( strncmp(g.zBaseURL,zRef,nBase)!=0 ) return 0;
  if( zRef[nBase]!=0 && zRef[nBase]!='/' ) return 0;
  return 1;
}

/*
** Information about all query parameters and cookies are stored
** in these variables.
*/
static int nAllocQP = 0; /* Space allocated for aParamQP[] */
static int nUsedQP = 0;  /* Space actually used in aParamQP[] */
................................................................................
** Parse an RFC822-formatted timestamp as we'd expect from HTTP and return
** a Unix epoch time. <= zero is returned on failure.
**
** Note that this won't handle all the _allowed_ HTTP formats, just the
** most popular one (the one generated by cgi_rfc822_datestamp(), actually).
*/
time_t cgi_rfc822_parsedate(const char *zDate){
  int mday, mon, year, yday, hour, min, sec;
  char zIgnore[4];
  char zMonth[4];

  static const char *const azMonths[] =
    {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", 0};
  if( 7==sscanf(zDate, "%3[A-Za-z], %d %3[A-Za-z] %d %d:%d:%d", zIgnore,
                       &mday, zMonth, &year, &hour, &min, &sec)){

    if( year > 1900 ) year -= 1900;
    for(mon=0; azMonths[mon]; mon++){















      if( !strncmp( azMonths[mon], zMonth, 3 )){
        int nDay;
        int isLeapYr;

        static int priorDays[] =
         {  0, 31, 59, 90,120,151,181,212,243,273,304,334 };
        if( mon<0 ){
          int nYear = (11 - mon)/12;
          year -= nYear;
          mon += nYear*12;
        }else if( mon>11 ){
          year += mon/12;
          mon %= 12;
        }

        isLeapYr = year%4==0 && (year%100!=0 || (year+300)%400==0);
        yday = priorDays[mon] + mday - 1;
        if( isLeapYr && mon>1 ) yday++;



        nDay = (year-70)*365 + (year-69)/4 - year/100 + (year+300)/400 + yday;
        return ((time_t)(nDay*24 + hour)*60 + min)*60 + sec;
      }
    }
  }
  return 0;
}

/*
** Check the objectTime against the If-Modified-Since request header. If the
** object time isn't any newer than the header, we immediately send back
** a 304 reply and exit.
*/
void cgi_modified_since(time_t objectTime){
  const char *zIf = P("HTTP_IF_MODIFIED_SINCE");

Changes to src/checkin.c.

557
558
559
560
561
562
563

564
565
566
567
568
569
570
571
572
...
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
  fossil_pledge("stdio rpath flock tty");

  /* Find and print all requested changes. */
  blob_zero(&report);
  status_report(&report, flags);
  if( blob_size(&report) ){
    if( showHdr ){

      fossil_print("Changes for %s at %s:\n", db_get("project-name", "???"),
                   g.zLocalRoot);
    }
    blob_write_to_file(&report, "-");
  }else if( verboseFlag ){
    fossil_print("  (none)\n");
  }
  blob_reset(&report);

................................................................................
  locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
  glob_free(pIgnore);

  blob_zero(&report);
  status_report(&report, flags);
  if( blob_size(&report) ){
    if( showHdr ){
      fossil_print("Extras for %s at %s:\n", db_get("project-name","???"),
                   g.zLocalRoot);
    }
    blob_write_to_file(&report, "-");
  }
  blob_reset(&report);
}








>
|
|







 







|







557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
...
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
  fossil_pledge("stdio rpath flock tty");

  /* Find and print all requested changes. */
  blob_zero(&report);
  status_report(&report, flags);
  if( blob_size(&report) ){
    if( showHdr ){
      fossil_print(
        "Changes for %s at %s:\n", db_get("project-name", "<unnamed>"),
        g.zLocalRoot);
    }
    blob_write_to_file(&report, "-");
  }else if( verboseFlag ){
    fossil_print("  (none)\n");
  }
  blob_reset(&report);

................................................................................
  locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
  glob_free(pIgnore);

  blob_zero(&report);
  status_report(&report, flags);
  if( blob_size(&report) ){
    if( showHdr ){
      fossil_print("Extras for %s at %s:\n", db_get("project-name","<unnamed>"),
                   g.zLocalRoot);
    }
    blob_write_to_file(&report, "-");
  }
  blob_reset(&report);
}

Changes to src/dispatch.c.

357
358
359
360
361
362
363

364
365
366
367
368
369
370
371

372
373
374
375
376
377
378
...
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576

    @ <a name='commands'></a>
    @ <h1>Available commands:</h1>
    @ <table border="0"><tr>
    for(i=j=0; i<MX_COMMAND; i++){
      const char *z = aCommand[i].zName;
      if( '/'==*z || strncmp(z,"test",4)==0 ) continue;

      j++;
    }
    n = (j+5)/6;
    for(i=j=0; i<MX_COMMAND; i++){
      const char *z = aCommand[i].zName;
      const char *zBoldOn  = aCommand[i].eCmdFlags&CMDFLAG_1ST_TIER?"<b>" :"";
      const char *zBoldOff = aCommand[i].eCmdFlags&CMDFLAG_1ST_TIER?"</b>":"";
      if( '/'==*z || strncmp(z,"test",4)==0 ) continue;

      if( j==0 ){
        @ <td valign="top"><ul>
      }
      @ <li><a href="%R/help?cmd=%s(z)">%s(zBoldOn)%s(z)%s(zBoldOff)</a></li>
      j++;
      if( j>=n ){
        @ </ul></td>
................................................................................
**
** Display information on how to use TOPIC, which may be a command, webpage, or
** setting.  Webpage names begin with "/".  To display a list of available
** topics, use one of:
**
**    %fossil help                Show common commands
**    %fossil help -a|--all       Show both common and auxiliary commands
**    %fossil help -s|--settings  Show setting names
**    %fossil help -t|--test      Show test commands only
**    %fossil help -x|--aux       Show auxiliary commands only
**    %fossil help -w|--www       Show list of webpages
*/
void help_cmd(void){
  int rc;
  int isPage = 0;







>








>







 







|







357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
...
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578

    @ <a name='commands'></a>
    @ <h1>Available commands:</h1>
    @ <table border="0"><tr>
    for(i=j=0; i<MX_COMMAND; i++){
      const char *z = aCommand[i].zName;
      if( '/'==*z || strncmp(z,"test",4)==0 ) continue;
      if( (aCommand[i].eCmdFlags & CMDFLAG_SETTING)!=0 ) continue;
      j++;
    }
    n = (j+5)/6;
    for(i=j=0; i<MX_COMMAND; i++){
      const char *z = aCommand[i].zName;
      const char *zBoldOn  = aCommand[i].eCmdFlags&CMDFLAG_1ST_TIER?"<b>" :"";
      const char *zBoldOff = aCommand[i].eCmdFlags&CMDFLAG_1ST_TIER?"</b>":"";
      if( '/'==*z || strncmp(z,"test",4)==0 ) continue;
      if( (aCommand[i].eCmdFlags & CMDFLAG_SETTING)!=0 ) continue;
      if( j==0 ){
        @ <td valign="top"><ul>
      }
      @ <li><a href="%R/help?cmd=%s(z)">%s(zBoldOn)%s(z)%s(zBoldOff)</a></li>
      j++;
      if( j>=n ){
        @ </ul></td>
................................................................................
**
** Display information on how to use TOPIC, which may be a command, webpage, or
** setting.  Webpage names begin with "/".  To display a list of available
** topics, use one of:
**
**    %fossil help                Show common commands
**    %fossil help -a|--all       Show both common and auxiliary commands
**    %fossil help -s|--setting   Show setting names
**    %fossil help -t|--test      Show test commands only
**    %fossil help -x|--aux       Show auxiliary commands only
**    %fossil help -w|--www       Show list of webpages
*/
void help_cmd(void){
  int rc;
  int isPage = 0;

Changes to src/doc.c.

637
638
639
640
641
642
643
644








645
646
647
648

649
650
651
652
653
654
655
...
837
838
839
840
841
842
843

844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
...
871
872
873
874
875
876
877

878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
          goto doc_not_found;
        }
      }else{
        goto doc_not_found;
      }
    }
    if( isUV ){
      if( db_table_exists("repository","unversioned")








       && unversioned_content(zName, &filebody)==0
      ){
        rid = 1;
        zDfltTitle = zName;

      }
    }else if( fossil_strcmp(zCheckin,"ckout")==0 ){
      /* Read from the local checkout */
      char *zFullpath;
      db_must_be_within_tree();
      zFullpath = mprintf("%s/%s", g.zLocalRoot, zName);
      if( file_isfile(zFullpath, RepoFILE)
................................................................................
** the login page.  It is designed for use in the upper left-hand corner
** of the header.
*/
void logo_page(void){
  Blob logo;
  char *zMime;


  zMime = db_get("logo-mimetype", "image/gif");
  blob_zero(&logo);
  db_blob(&logo, "SELECT value FROM config WHERE name='logo-image'");
  if( blob_size(&logo)==0 ){
    blob_init(&logo, (char*)aLogo, sizeof(aLogo));
  }
  cgi_set_content_type(zMime);
  cgi_set_content(&logo);
  g.isConst = 1;
}

/*
** The default background image:  a 16x16 white GIF
*/
static const unsigned char aBackground[] = {
    71,  73,  70,  56,  57,  97,  16,   0,  16,   0,
................................................................................
** Return the background image.  If no background image is defined, a
** built-in 16x16 pixel white GIF is returned.
*/
void background_page(void){
  Blob bgimg;
  char *zMime;


  zMime = db_get("background-mimetype", "image/gif");
  blob_zero(&bgimg);
  db_blob(&bgimg, "SELECT value FROM config WHERE name='background-image'");
  if( blob_size(&bgimg)==0 ){
    blob_init(&bgimg, (char*)aBackground, sizeof(aBackground));
  }
  cgi_set_content_type(zMime);
  cgi_set_content(&bgimg);
  g.isConst = 1;
}


/*
** WEBPAGE: docsrch
**
** Search for documents that match a user-supplied full-text search pattern.







|
>
>
>
>
>
>
>
>
|
<
|
|
>







 







>








<







 







>








<







637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
661
662
663
...
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860

861
862
863
864
865
866
867
...
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894

895
896
897
898
899
900
901
          goto doc_not_found;
        }
      }else{
        goto doc_not_found;
      }
    }
    if( isUV ){
      if( db_table_exists("repository","unversioned") ){
        Stmt q;
        db_prepare(&q, "SELECT hash, mtime FROM unversioned"
                       " WHERE name=%Q", zName);
        if( db_step(&q)==SQLITE_ROW ){
          etag_check(ETAG_HASH, db_column_text(&q,0));
          etag_last_modified(db_column_int64(&q,1));
        }
        db_finalize(&q);
        if( unversioned_content(zName, &filebody)==0 ){

          rid = 1;
          zDfltTitle = zName;
        }
      }
    }else if( fossil_strcmp(zCheckin,"ckout")==0 ){
      /* Read from the local checkout */
      char *zFullpath;
      db_must_be_within_tree();
      zFullpath = mprintf("%s/%s", g.zLocalRoot, zName);
      if( file_isfile(zFullpath, RepoFILE)
................................................................................
** the login page.  It is designed for use in the upper left-hand corner
** of the header.
*/
void logo_page(void){
  Blob logo;
  char *zMime;

  etag_check(ETAG_CONFIG, 0);
  zMime = db_get("logo-mimetype", "image/gif");
  blob_zero(&logo);
  db_blob(&logo, "SELECT value FROM config WHERE name='logo-image'");
  if( blob_size(&logo)==0 ){
    blob_init(&logo, (char*)aLogo, sizeof(aLogo));
  }
  cgi_set_content_type(zMime);
  cgi_set_content(&logo);

}

/*
** The default background image:  a 16x16 white GIF
*/
static const unsigned char aBackground[] = {
    71,  73,  70,  56,  57,  97,  16,   0,  16,   0,
................................................................................
** Return the background image.  If no background image is defined, a
** built-in 16x16 pixel white GIF is returned.
*/
void background_page(void){
  Blob bgimg;
  char *zMime;

  etag_check(ETAG_CONFIG, 0);
  zMime = db_get("background-mimetype", "image/gif");
  blob_zero(&bgimg);
  db_blob(&bgimg, "SELECT value FROM config WHERE name='background-image'");
  if( blob_size(&bgimg)==0 ){
    blob_init(&bgimg, (char*)aBackground, sizeof(aBackground));
  }
  cgi_set_content_type(zMime);
  cgi_set_content(&bgimg);

}


/*
** WEBPAGE: docsrch
**
** Search for documents that match a user-supplied full-text search pattern.

Added src/etag.c.



































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/*
** Copyright (c) 2018 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
**
** This program is distributed in the hope that it will be useful,
** but without any warranty; without even the implied warranty of
** merchantability or fitness for a particular purpose.
**
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This file implements ETags: cache control for Fossil
**
** An ETag is a hash that encodes attributes which must be the same for
** the page to continue to be valid.  Attributes that might be contained
** in the ETag include:
**
**   (1)  The mtime on the Fossil executable
**   (2)  The last change to the CONFIG table
**   (3)  The last change to the EVENT table
**   (4)  The value of the display cookie
**   (5)  A hash value supplied by the page generator
**
** Item (1) is always included in the ETag.  The other elements are
** optional.  Because (1) is always included as part of the ETag, all
** outstanding ETags can be invalidated by touching the fossil executable.
**
** A page generator routine invokes etag_check() exactly once, with
** arguments that indicates which of the above elements to include in the
** hash.  If the request contained an If-None-Match header which matches
** the generated ETag, then a 304 Not Modified reply is generated and
** the process exits.  In other words, etag_check() never returns.  But
** if there is no If-None_Match header or if the ETag does not match,
** then etag_check() returns normally.  Later, during reply generation,
** the cgi.c module will invoke etag_tag() to recover the generated tag
** and include it in the reply header.
**
** 2018-02-25:
**
** Also support Last-Modified: and If-Modified-Since:.  The
** etag_last_modified(mtime) API records a timestamp for the page in
** seconds since 1970.  This causes a Last-Modified: header to be
** issued in the reply.  Or, if the request contained If-Modified-Since:
** and the new mtime is not greater than the mtime associated with
** If-Modified-Since, then a 304 Not Modified reply is generated and
** the etag_last_modified() API never returns.
*/
#include "config.h"
#include "etag.h"

#if INTERFACE
/*
** Things to monitor
*/
#define ETAG_CONFIG   0x01 /* Output depends on the CONFIG table */
#define ETAG_DATA     0x02 /* Output depends on the EVENT table */
#define ETAG_COOKIE   0x04 /* Output depends on a display cookie value */
#define ETAG_HASH     0x08 /* Output depends on a hash */
#endif

static char zETag[33];      /* The generated ETag */
static int iMaxAge = 0;     /* The max-age parameter in the reply */
static sqlite3_int64 iEtagMtime = 0;  /* Last-Modified time */

/*
** Generate an ETag
*/
void etag_check(unsigned eFlags, const char *zHash){
  sqlite3_int64 mtime;
  const char *zIfNoneMatch;
  char zBuf[50];
  assert( zETag[0]==0 );  /* Only call this routine once! */

  iMaxAge = 86400;
  md5sum_init();

  /* Always include the mtime of the executable as part of the hash */
  mtime = file_mtime(g.nameOfExe, ExtFILE);
  sqlite3_snprintf(sizeof(zBuf),zBuf,"mtime: %lld\n", mtime);
  md5sum_step_text(zBuf, -1);
  
  if( (eFlags & ETAG_HASH)!=0 && zHash ){
    md5sum_step_text("hash: ", -1);
    md5sum_step_text(zHash, -1);
    md5sum_step_text("\n", 1);
    iMaxAge = 0;
  }else if( eFlags & ETAG_DATA ){
    int iKey = db_int(0, "SELECT max(rcvid) FROM rcvfrom");
    sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",iKey);
    md5sum_step_text("data: ", -1);
    md5sum_step_text(zBuf, -1);
    md5sum_step_text("\n", 1);
    iMaxAge = 60;
  }else if( eFlags & ETAG_CONFIG ){
    int iKey = db_int(0, "SELECT value FROM config WHERE name='cfgcnt'");
    sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",iKey);
    md5sum_step_text("data: ", -1);
    md5sum_step_text(zBuf, -1);
    md5sum_step_text("\n", 1);
    iMaxAge = 3600;
  }

  /* Include the display cookie */
  if( eFlags & ETAG_COOKIE ){
    md5sum_step_text("display-cookie: ", -1);
    md5sum_step_text(PD(DISPLAY_SETTINGS_COOKIE,""), -1);
    md5sum_step_text("\n", 1);
    iMaxAge = 0;
  }

  /* Generate the ETag */
  memcpy(zETag, md5sum_finish(0), 33);

  /* Check to see if the generated ETag matches If-None-Match and
  ** generate a 304 reply if it does. */
  zIfNoneMatch = P("HTTP_IF_NONE_MATCH");
  if( zIfNoneMatch==0 ) return;
  if( strcmp(zIfNoneMatch,zETag)!=0 ) return;

  /* If we get this far, it means that the content has
  ** not changed and we can do a 304 reply */
  cgi_reset_content();
  cgi_set_status(304, "Not Modified");
  cgi_reply();
  fossil_exit(0);
}

/*
** Accept a new Last-Modified time.  This routine should be called by
** page generators that know a valid last-modified time.  This routine
** might generate a 304 Not Modified reply and exit(), never returnning.
** Or, if not, it will cause a Last-Modified: header to be included in the
** reply.
*/
void etag_last_modified(sqlite3_int64 mtime){
  const char *zIfModifiedSince;
  sqlite3_int64 x, exeMtime;
  assert( iEtagMtime==0 );   /* Only call this routine once */
  assert( mtime>0 );         /* Only call with a valid mtime */
  iEtagMtime = mtime;

  /* Check to see the If-Modified-Since constraint is satisfied */
  zIfModifiedSince = P("HTTP_IF_MODIFIED_SINCE");
  if( zIfModifiedSince==0 ) return;
  x = cgi_rfc822_parsedate(zIfModifiedSince);
  if( x<=0 || x>mtime ) return;

  /* If the Fossil executable is more recent than If-Modified-Since,
  ** go ahead and regenerate the resource. */
  exeMtime = file_mtime(g.nameOfExe, ExtFILE);
  if( exeMtime>x ) return;

  /* If we reach this point, it means that the resource has not changed
  ** and that we should generate a 304 Not Modified reply */
  cgi_reset_content();
  cgi_set_status(304, "Not Modified");
  cgi_reply();
  fossil_exit(0);
}

/* Return the ETag, if there is one.
*/
const char *etag_tag(void){
  return zETag;
}

/* Return the recommended max-age
*/
int etag_maxage(void){
  return iMaxAge;
}

/* Return the last-modified time in seconds since 1970.  Or return 0 if
** there is no last-modified time.
*/
sqlite3_int64 etag_mtime(void){
  return iEtagMtime;
}

/* 
** COMMAND: test-etag
**
** Usage:  fossil test-etag -key KEY-NUMBER  -hash HASH
**
** Generate an etag given a KEY-NUMBER and/or a HASH.
**
** KEY-NUMBER is some combination of:
**
**    1   ETAG_CONFIG   The config table version number
**    2   ETAG_DATA     The event table version number
**    4   ETAG_COOKIE   The display cookie
*/
void test_etag_cmd(void){
  const char *zHash = 0;
  const char *zKey;
  int iKey = 0;
  db_find_and_open_repository(0, 0);
  zKey = find_option("key",0,1);
  zHash = find_option("hash",0,1);
  if( zKey ) iKey = atoi(zKey);
  etag_check(iKey, zHash);
  fossil_print("%s\n", etag_tag());
}

Changes to src/graph.c.

25
26
27
28
29
30
31



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
...
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
...
453
454
455
456
457
458
459

460
461
462
463
464
465
466
...
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504

#define GR_MAX_RAIL   40      /* Max number of "rails" to display */

/* The graph appears vertically beside a timeline.  Each row in the
** timeline corresponds to a row in the graph.  GraphRow.idx is 0 for
** the top-most row and increases moving down.  Hence (in the absence of
** time skew) parents have a larger index than their children.



*/
struct GraphRow {
  int rid;                    /* The rid for the check-in */
  i8 nParent;                 /* Number of parents */
  int *aParent;               /* Array of parents.  0 element is primary .*/
  char *zBranch;              /* Branch name */
  char *zBgClr;               /* Background Color */
  char zUuid[41];             /* Check-in for file ID */

  GraphRow *pNext;            /* Next row down in the list of all rows */
  GraphRow *pPrev;            /* Previous row */

  int idx;                    /* Row index.  First is 1.  0 used for "none" */
  int idxTop;                 /* Direct descendent highest up on the graph */
  GraphRow *pChild;           /* Child immediately above this node */
................................................................................
){
  GraphRow *pRow;
  int nByte;
  static int nRow = 0;

  if( p->nErr ) return 0;
  nByte = sizeof(GraphRow);
  nByte += sizeof(pRow->aParent[0])*nParent;
  pRow = (GraphRow*)safeMalloc( nByte );
  pRow->aParent = (int*)&pRow[1];
  pRow->rid = rid;
  pRow->nParent = nParent;
  pRow->zBranch = persistBranchName(p, zBranch);
  if( zUuid==0 ) zUuid = "";
  sqlite3_snprintf(sizeof(pRow->zUuid), pRow->zUuid, "%s", zUuid);
  pRow->isLeaf = isLeaf;
  memset(pRow->aiRiser, -1, sizeof(pRow->aiRiser));
  if( zBgClr==0 ) zBgClr = "";
  pRow->zBgClr = persistBranchName(p, zBgClr);
  memcpy(pRow->aParent, aParent, sizeof(aParent[0])*nParent);
  if( p->pFirst==0 ){
    p->pFirst = pRow;
  }else{
    p->pLast->pNext = pRow;
  }
  p->pLast = pRow;
  p->nRow++;
................................................................................
  ** pChild.
  **
  ** In the case of a fork, choose the pChild that results in the
  ** longest rail.
  */
  for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
    if( pRow->isDup ) continue;
    if( pRow->nParent==0 ) continue;                   /* Root node */
    pParent = hashFind(p, pRow->aParent[0]);
    if( pParent==0 ) continue;                         /* Parent off-screen */
    if( pParent->zBranch!=pRow->zBranch ) continue;    /* Different branch */
    if( pParent->idx <= pRow->idx ){
       pParent->timeWarp = 1;
       continue;                                       /* Time-warp */
    }
................................................................................
  **
  ** Strive to put the "trunk" branch on far left.
  */
  zTrunk = persistBranchName(p, "trunk");
  for(i=0; i<2; i++){
    for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
      if( pRow->isDup ) continue;

      if( i==0 ){
        if( pRow->zBranch!=zTrunk ) continue;
      }else {
        if( pRow->iRail>=0 ) continue;
      }
      if( pRow->nParent==0 || hashFind(p,pRow->aParent[0])==0 ){
        if( omitDescenders ){
................................................................................
      if( pRow->pChild==0 && !pRow->timeWarp ){
        if( !omitDescenders && count_nonbranch_children(pRow->rid)!=0 ){
          riser_to_top(pRow);
        }
      }
      continue;
    }
    if( pRow->isDup ){
      continue;
    }else{
      assert( pRow->nParent>0 );
      parentRid = pRow->aParent[0];
      pParent = hashFind(p, parentRid);
      if( pParent==0 ){
        pRow->iRail = ++p->mxRail;







>
>
>



|



|







 







|

|









|







 







|







 







>







 







|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
...
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
...
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
...
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
...
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508

#define GR_MAX_RAIL   40      /* Max number of "rails" to display */

/* The graph appears vertically beside a timeline.  Each row in the
** timeline corresponds to a row in the graph.  GraphRow.idx is 0 for
** the top-most row and increases moving down.  Hence (in the absence of
** time skew) parents have a larger index than their children.
**
** The nParent field is -1 for entires that do not participate in the graph
** but which are included just so that we can capture their background color.
*/
struct GraphRow {
  int rid;                    /* The rid for the check-in */
  i8 nParent;                 /* Number of parents.  -1 for technote lines */
  int *aParent;               /* Array of parents.  0 element is primary .*/
  char *zBranch;              /* Branch name */
  char *zBgClr;               /* Background Color */
  char zUuid[HNAME_MAX+1];    /* Check-in for file ID */

  GraphRow *pNext;            /* Next row down in the list of all rows */
  GraphRow *pPrev;            /* Previous row */

  int idx;                    /* Row index.  First is 1.  0 used for "none" */
  int idxTop;                 /* Direct descendent highest up on the graph */
  GraphRow *pChild;           /* Child immediately above this node */
................................................................................
){
  GraphRow *pRow;
  int nByte;
  static int nRow = 0;

  if( p->nErr ) return 0;
  nByte = sizeof(GraphRow);
  if( nParent>0 ) nByte += sizeof(pRow->aParent[0])*nParent;
  pRow = (GraphRow*)safeMalloc( nByte );
  pRow->aParent = nParent>0 ? (int*)&pRow[1] : 0;
  pRow->rid = rid;
  pRow->nParent = nParent;
  pRow->zBranch = persistBranchName(p, zBranch);
  if( zUuid==0 ) zUuid = "";
  sqlite3_snprintf(sizeof(pRow->zUuid), pRow->zUuid, "%s", zUuid);
  pRow->isLeaf = isLeaf;
  memset(pRow->aiRiser, -1, sizeof(pRow->aiRiser));
  if( zBgClr==0 ) zBgClr = "";
  pRow->zBgClr = persistBranchName(p, zBgClr);
  if( nParent>0 ) memcpy(pRow->aParent, aParent, sizeof(aParent[0])*nParent);
  if( p->pFirst==0 ){
    p->pFirst = pRow;
  }else{
    p->pLast->pNext = pRow;
  }
  p->pLast = pRow;
  p->nRow++;
................................................................................
  ** pChild.
  **
  ** In the case of a fork, choose the pChild that results in the
  ** longest rail.
  */
  for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
    if( pRow->isDup ) continue;
    if( pRow->nParent<=0 ) continue;                   /* Root node */
    pParent = hashFind(p, pRow->aParent[0]);
    if( pParent==0 ) continue;                         /* Parent off-screen */
    if( pParent->zBranch!=pRow->zBranch ) continue;    /* Different branch */
    if( pParent->idx <= pRow->idx ){
       pParent->timeWarp = 1;
       continue;                                       /* Time-warp */
    }
................................................................................
  **
  ** Strive to put the "trunk" branch on far left.
  */
  zTrunk = persistBranchName(p, "trunk");
  for(i=0; i<2; i++){
    for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
      if( pRow->isDup ) continue;
      if( pRow->nParent<0 ) continue;
      if( i==0 ){
        if( pRow->zBranch!=zTrunk ) continue;
      }else {
        if( pRow->iRail>=0 ) continue;
      }
      if( pRow->nParent==0 || hashFind(p,pRow->aParent[0])==0 ){
        if( omitDescenders ){
................................................................................
      if( pRow->pChild==0 && !pRow->timeWarp ){
        if( !omitDescenders && count_nonbranch_children(pRow->rid)!=0 ){
          riser_to_top(pRow);
        }
      }
      continue;
    }
    if( pRow->isDup || pRow->nParent<0 ){
      continue;
    }else{
      assert( pRow->nParent>0 );
      parentRid = pRow->aParent[0];
      pParent = hashFind(p, parentRid);
      if( pParent==0 ){
        pRow->iRail = ++p->mxRail;

Changes to src/graph.js.

206
207
208
209
210
211
212

213
214
215
216
217
218
219
...
340
341
342
343
344
345
346


347
348
349
350
351
352
353
354
355
356
357
358



359
360
361
362
363
364
365
...
380
381
382
383
384
385
386
387
388
389
  function drawNode(p, btm){
    if( p.bg ){
      var e = document.getElementById("mc"+p.id);
      if(e) e.style.backgroundColor = p.bg;
      e = document.getElementById("md"+p.id);
      if(e) e.style.backgroundColor = p.bg;
    }

    if( p.u>0 ) drawUpArrow(p,tx.rowinfo[p.u-tx.iTopRow],p.fg);
    var cls = node.cls;
    if( p.mi.length ) cls += " merge";
    if( p.f&1 ) cls += " leaf";
    var n = drawBox(cls,p.bg,p.x,p.y);
    n.id = "tln"+p.id;
    n.onclick = clickOnNode;
................................................................................
    var x = document.getElementsByClassName('timelineSelected');
    if(x[0]){
      var h = window.innerHeight;
      var y = absoluteY(x[0]) - h/2;
      if( y>0 ) window.scrollTo(0, y);
    }
  }


  var lastRow = document.getElementById("m"+tx.rowinfo[tx.rowinfo.length-1].id);
  var lastY = 0;
  function checkHeight(){
    var h = absoluteY(lastRow);
    if( h!=lastY ){
      renderGraph();
      lastY = h;
    }
    setTimeout(checkHeight, 1000);
  }
  initGraph();
  checkHeight();



  if( tx.scrollToSelect ){
    scrollToSelected();
  }

  /* Set the onclick= attributes for elements of the "Compact" display
  ** mode so that clicking turns the details on and off.
  */
................................................................................
(function(){
  var i;
  for(i=0; 1; i++){
    var dataObj = document.getElementById("timeline-data-"+i);
    if(!dataObj) break;
    var txJson = dataObj.textContent || dataObj.innerText;
    var tx = JSON.parse(txJson);
    if(tx.rowinfo) TimelineGraph(tx);
  }
}())







>







 







>
>
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>







 







|


206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
...
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
...
386
387
388
389
390
391
392
393
394
395
  function drawNode(p, btm){
    if( p.bg ){
      var e = document.getElementById("mc"+p.id);
      if(e) e.style.backgroundColor = p.bg;
      e = document.getElementById("md"+p.id);
      if(e) e.style.backgroundColor = p.bg;
    }
    if( p.r<0 ) return;
    if( p.u>0 ) drawUpArrow(p,tx.rowinfo[p.u-tx.iTopRow],p.fg);
    var cls = node.cls;
    if( p.mi.length ) cls += " merge";
    if( p.f&1 ) cls += " leaf";
    var n = drawBox(cls,p.bg,p.x,p.y);
    n.id = "tln"+p.id;
    n.onclick = clickOnNode;
................................................................................
    var x = document.getElementsByClassName('timelineSelected');
    if(x[0]){
      var h = window.innerHeight;
      var y = absoluteY(x[0]) - h/2;
      if( y>0 ) window.scrollTo(0, y);
    }
  }
  if( tx.rowinfo ){
    var lastRow = 
       document.getElementById("m"+tx.rowinfo[tx.rowinfo.length-1].id);
    var lastY = 0;
    function checkHeight(){
      var h = absoluteY(lastRow);
      if( h!=lastY ){
        renderGraph();
        lastY = h;
      }
      setTimeout(checkHeight, 1000);
    }
    initGraph();
    checkHeight();
  }else{
    function checkHeight(){}
  }
  if( tx.scrollToSelect ){
    scrollToSelected();
  }

  /* Set the onclick= attributes for elements of the "Compact" display
  ** mode so that clicking turns the details on and off.
  */
................................................................................
(function(){
  var i;
  for(i=0; 1; i++){
    var dataObj = document.getElementById("timeline-data-"+i);
    if(!dataObj) break;
    var txJson = dataObj.textContent || dataObj.innerText;
    var tx = JSON.parse(txJson);
    TimelineGraph(tx);
  }
}())

Changes to src/import.c.

515
516
517
518
519
520
521

522
523
524
525
526
527
528
...
617
618
619
620
621
622
623
624


625
626
627
628
629
630
631


632
633
634
635
636
637
638
639
....
1601
1602
1603
1604
1605
1606
1607

1608
1609
1610
1611
1612
1613
1614
....
1725
1726
1727
1728
1729
1730
1731

1732
1733
1734
1735
1736
1737
1738
  }
  zName[i] = 0;
}


static struct{
  const char *zMasterName;    /* Name of master branch */

} ggit;

/*
** Read the git-fast-import format from pIn and insert the corresponding
** content into the database.
*/
static void git_fast_import(FILE *pIn){
................................................................................
	    gg.aData[got-1] = '\0';
          gg.zComment = gg.aData;
          gg.aData = 0;
          gg.nData = 0;
        }
      }
    }else
    if( strncmp(zLine, "author ", 7)==0 ){


      /* No-op */
    }else
    if( strncmp(zLine, "mark ", 5)==0 ){
      trim_newline(&zLine[5]);
      fossil_free(gg.zMark);
      gg.zMark = fossil_strdup(&zLine[5]);
    }else


    if( strncmp(zLine, "tagger ", 7)==0 || strncmp(zLine, "committer ",10)==0 ){
      sqlite3_int64 secSince1970;
      z = strchr(zLine, ' ');
      while( fossil_isspace(*z) ) z++;
      if( (zTo=strchr(z, '>'))==NULL ) goto malformed_line;
      *(++zTo) = '\0';
      /* Lookup user by contact info. */
      fossil_free(gg.zUser);
................................................................................
** The following formats are currently understood by this command
**
**   --git        Import from the git-fast-export file format (default)
**                Options:
**                  --import-marks  FILE Restore marks table from FILE
**                  --export-marks  FILE Save marks table to FILE
**                  --rename-master NAME Renames the master branch to NAME

**
**   --svn        Import from the svnadmin-dump file format.  The default
**                behaviour (unless overridden by --flat) is to treat 3
**                folders in the SVN root as special, following the
**                common layout of SVN repositories.  These are (by
**                default) trunk/, branches/ and tags/.  The SVN --deltas
**                format is supported but not required.
................................................................................
                || (incrFlag && !find_option("no-rev-tags", 0, 0));
  }else if( gitFlag ){
    markfile_in = find_option("import-marks", 0, 1);
    markfile_out = find_option("export-marks", 0, 1);
    if( !(ggit.zMasterName = find_option("rename-master", 0, 1)) ){
      ggit.zMasterName = "master";
    }

  }
  verify_all_options();

  if( g.argc!=3 && g.argc!=4 ){
    usage("--git|--svn ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?");
  }
  if( g.argc==4 ){







>







 







|
>
>







>
>
|







 







>







 







>







515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
...
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
....
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
....
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
  }
  zName[i] = 0;
}


static struct{
  const char *zMasterName;    /* Name of master branch */
  int authorFlag;             /* Use author as checkin committer */
} ggit;

/*
** Read the git-fast-import format from pIn and insert the corresponding
** content into the database.
*/
static void git_fast_import(FILE *pIn){
................................................................................
	    gg.aData[got-1] = '\0';
          gg.zComment = gg.aData;
          gg.aData = 0;
          gg.nData = 0;
        }
      }
    }else
    if( (!ggit.authorFlag && strncmp(zLine, "author ", 7)==0)
        || (ggit.authorFlag && strncmp(zLine, "committer ",10)==0
            && gg.zUser!=NULL) ){
      /* No-op */
    }else
    if( strncmp(zLine, "mark ", 5)==0 ){
      trim_newline(&zLine[5]);
      fossil_free(gg.zMark);
      gg.zMark = fossil_strdup(&zLine[5]);
    }else
    if( strncmp(zLine, "tagger ", 7)==0
        || (ggit.authorFlag && strncmp(zLine, "author ", 7)==0)
        || strncmp(zLine, "committer ",10)==0 ){
      sqlite3_int64 secSince1970;
      z = strchr(zLine, ' ');
      while( fossil_isspace(*z) ) z++;
      if( (zTo=strchr(z, '>'))==NULL ) goto malformed_line;
      *(++zTo) = '\0';
      /* Lookup user by contact info. */
      fossil_free(gg.zUser);
................................................................................
** The following formats are currently understood by this command
**
**   --git        Import from the git-fast-export file format (default)
**                Options:
**                  --import-marks  FILE Restore marks table from FILE
**                  --export-marks  FILE Save marks table to FILE
**                  --rename-master NAME Renames the master branch to NAME
**                  --use-author    Uses author as the committer
**
**   --svn        Import from the svnadmin-dump file format.  The default
**                behaviour (unless overridden by --flat) is to treat 3
**                folders in the SVN root as special, following the
**                common layout of SVN repositories.  These are (by
**                default) trunk/, branches/ and tags/.  The SVN --deltas
**                format is supported but not required.
................................................................................
                || (incrFlag && !find_option("no-rev-tags", 0, 0));
  }else if( gitFlag ){
    markfile_in = find_option("import-marks", 0, 1);
    markfile_out = find_option("export-marks", 0, 1);
    if( !(ggit.zMasterName = find_option("rename-master", 0, 1)) ){
      ggit.zMasterName = "master";
    }
    ggit.authorFlag = find_option("use-author", 0, 0)!=0;
  }
  verify_all_options();

  if( g.argc!=3 && g.argc!=4 ){
    usage("--git|--svn ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?");
  }
  if( g.argc==4 ){

Changes to src/info.c.

1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
....
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
....
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
....
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
    "  FROM attachment"
    " WHERE src=(SELECT uuid FROM blob WHERE rid=%d)"
    " ORDER BY mtime DESC /*sort*/",
    rid
  );
  while( db_step(&q)==SQLITE_ROW ){
    const char *zTarget = db_column_text(&q, 0);
    int nTarget = db_column_bytes(&q, 0);
    const char *zFilename = db_column_text(&q, 1);
    const char *zDate = db_column_text(&q, 2);
    const char *zUser = db_column_text(&q, 3);
    /* const char *zSrc = db_column_text(&q, 4); */
    if( cnt>0 ){
      @ Also attachment "%h(zFilename)" to
    }else{
      @ Attachment "%h(zFilename)" to
    }
    objType |= OBJTYPE_ATTACHMENT;
    if( nTarget==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
      if ( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
            zTarget)
      ){
        if( g.perm.Hyperlink && g.anon.RdTkt ){
          @ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>]
        }else{
          @ ticket [%S(zTarget)]
................................................................................
**
** Show the details of a ticket change control artifact.
*/
void tinfo_page(void){
  int rid;
  char *zDate;
  const char *zUuid;
  char zTktName[UUID_SIZE+1];
  Manifest *pTktChng;
  int modPending;
  const char *zModAction;
  char *zTktTitle;
  login_check_credentials();
  if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
  rid = name_to_rid_www("name");
................................................................................
    }else{
      style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid);
    }
  }
  pTktChng = manifest_get(rid, CFTYPE_TICKET, 0);
  if( pTktChng==0 ) fossil_redirect_home();
  zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
  memcpy(zTktName, pTktChng->zTicketUuid, UUID_SIZE+1);
  if( g.perm.ModTkt && (zModAction = P("modaction"))!=0 ){
    if( strcmp(zModAction,"delete")==0 ){
      moderation_disapprove(rid);
      /*
      ** Next, check if the ticket still exists; if not, we cannot
      ** redirect to it.
      */
................................................................................
  zNewColorFlag = P("newclr") ? " checked" : "";
  zNewTagFlag = P("newtag") ? " checked" : "";
  zNewTag = PDT("tagname","");
  zNewBrFlag = P("newbr") ? " checked" : "";
  zNewBranch = PDT("brname","");
  zCloseFlag = P("close") ? " checked" : "";
  zHideFlag = P("hide") ? " checked" : "";
  if( P("apply") ){
    Blob ctrl;
    char *zNow;

    login_verify_csrf_secret();
    blob_zero(&ctrl);
    zNow = date_in_standard_format(zChngTime ? zChngTime : "now");
    blob_appendf(&ctrl, "D %s\n", zNow);







<










|







 







|







 







|







 







|







1462
1463
1464
1465
1466
1467
1468

1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
....
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
....
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
....
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
    "  FROM attachment"
    " WHERE src=(SELECT uuid FROM blob WHERE rid=%d)"
    " ORDER BY mtime DESC /*sort*/",
    rid
  );
  while( db_step(&q)==SQLITE_ROW ){
    const char *zTarget = db_column_text(&q, 0);

    const char *zFilename = db_column_text(&q, 1);
    const char *zDate = db_column_text(&q, 2);
    const char *zUser = db_column_text(&q, 3);
    /* const char *zSrc = db_column_text(&q, 4); */
    if( cnt>0 ){
      @ Also attachment "%h(zFilename)" to
    }else{
      @ Attachment "%h(zFilename)" to
    }
    objType |= OBJTYPE_ATTACHMENT;
    if( fossil_is_uuid(zTarget) ){
      if ( db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
            zTarget)
      ){
        if( g.perm.Hyperlink && g.anon.RdTkt ){
          @ ticket [%z(href("%R/tktview?name=%!S",zTarget))%S(zTarget)</a>]
        }else{
          @ ticket [%S(zTarget)]
................................................................................
**
** Show the details of a ticket change control artifact.
*/
void tinfo_page(void){
  int rid;
  char *zDate;
  const char *zUuid;
  char zTktName[HNAME_MAX+1];
  Manifest *pTktChng;
  int modPending;
  const char *zModAction;
  char *zTktTitle;
  login_check_credentials();
  if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
  rid = name_to_rid_www("name");
................................................................................
    }else{
      style_submenu_element("Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid);
    }
  }
  pTktChng = manifest_get(rid, CFTYPE_TICKET, 0);
  if( pTktChng==0 ) fossil_redirect_home();
  zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
  sqlite3_snprintf(sizeof(zTktName), zTktName, "%s", pTktChng->zTicketUuid);
  if( g.perm.ModTkt && (zModAction = P("modaction"))!=0 ){
    if( strcmp(zModAction,"delete")==0 ){
      moderation_disapprove(rid);
      /*
      ** Next, check if the ticket still exists; if not, we cannot
      ** redirect to it.
      */
................................................................................
  zNewColorFlag = P("newclr") ? " checked" : "";
  zNewTagFlag = P("newtag") ? " checked" : "";
  zNewTag = PDT("tagname","");
  zNewBrFlag = P("newbr") ? " checked" : "";
  zNewBranch = PDT("brname","");
  zCloseFlag = P("close") ? " checked" : "";
  zHideFlag = P("hide") ? " checked" : "";
  if( P("apply") && cgi_csrf_safe(1) ){
    Blob ctrl;
    char *zNow;

    login_verify_csrf_secret();
    blob_zero(&ctrl);
    zNow = date_in_standard_format(zChngTime ? zChngTime : "now");
    blob_appendf(&ctrl, "D %s\n", zNow);

Changes to src/login.c.

500
501
502
503
504
505
506














507
508
509
510
511
512
513
514
515
516
517
...
659
660
661
662
663
664
665













666
667
668
669
670
671
672
....
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
  char *zSha1Pw;
  const char *zIpAddr;         /* IP address of requestor */
  const char *zReferer;

  login_check_credentials();
  if( login_wants_https_redirect() ){
    const char *zQS = P("QUERY_STRING");














    if( zQS==0 ){
      zQS = "";
    }else if( zQS[0]!=0 ){
      zQS = mprintf("?%s", zQS);
    }
    cgi_redirectf("%s%s%s", g.zHttpsURL, P("PATH_INFO"), zQS);
    return;
  }
  sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
                  constant_time_cmp_function, 0, 0);
  zUsername = P("u");
................................................................................
  @ <table class="login_out">
  @ <tr>
  @   <td class="login_out_label">User ID:</td>
  if( anonFlag ){
    @ <td><input type="text" id="u" name="u" value="anonymous" size="30" /></td>
  }else{
    @ <td><input type="text" id="u" name="u" value="" size="30" /></td>













  }
  @ </tr>
  @ <tr>
  @  <td class="login_out_label">Password:</td>
  @   <td><input type="password" id="p" name="p" value="" size="30" /></td>
  @ </tr>
  if( g.zLogin==0 && (anonFlag || zGoto==0) ){
................................................................................
  }else
#endif /* FOSSIL_ENABLE_JSON */
  {
    const char *zUrl = PD("REQUEST_URI", "index");
    const char *zQS = P("QUERY_STRING");
    Blob redir;
    blob_init(&redir, 0, 0);
    if( login_wants_https_redirect() ){
      blob_appendf(&redir, "%s/login?g=%T", g.zHttpsURL, zUrl);
    }else{
      blob_appendf(&redir, "%R/login?g=%T", zUrl);
    }
    if( anonOk ) blob_append(&redir, "&anon", 5);
    if( zQS && zQS[0] ){
      blob_appendf(&redir, "&%s", zQS);







>
>
>
>
>
>
>
>
>
>
>
>
>
>

|

|







 







>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
...
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
....
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
  char *zSha1Pw;
  const char *zIpAddr;         /* IP address of requestor */
  const char *zReferer;

  login_check_credentials();
  if( login_wants_https_redirect() ){
    const char *zQS = P("QUERY_STRING");
    if( P("redir")!=0 ){
      style_header("Insecure Connection");
      @ <h1>Unable To Establish An Encrypted Connection</h1>
      @ <p>This website requires that login credentials be sent over
      @ an encrypted connection.  The current connection is not encrypted
      @ across the entire route between your browser and the server.
      @ An attempt was made to redirect to %h(g.zHttpsURL) but
      @ the connection is still insecure even after the redirect.</p>
      @ <p>This is probably some kind of configuration problem.  Please
      @ contact your sysadmin.</p>
      @ <p>Sorry it did not work out.</p>
      style_footer();
      return;
    }
    if( zQS==0 ){
      zQS = "?redir=1";
    }else if( zQS[0]!=0 ){
      zQS = mprintf("?%s&redir=1", zQS);
    }
    cgi_redirectf("%s%s%s", g.zHttpsURL, P("PATH_INFO"), zQS);
    return;
  }
  sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
                  constant_time_cmp_function, 0, 0);
  zUsername = P("u");
................................................................................
  @ <table class="login_out">
  @ <tr>
  @   <td class="login_out_label">User ID:</td>
  if( anonFlag ){
    @ <td><input type="text" id="u" name="u" value="anonymous" size="30" /></td>
  }else{
    @ <td><input type="text" id="u" name="u" value="" size="30" /></td>
  }
  if( P("HTTPS")==0 ){
    @ <td width="15"><td rowspan="3">
    @ <p class='securityWarning'>
    @ Warning: Your password will be sent in the clear over an
    @ unencrypted connection.
    if( g.sslNotAvailable ){
      @ No encrypted connection is available on this server.
    }else{
      @ Consider logging in at
      @ <a href='%s(g.zHttpsURL)'>%h(g.zHttpsURL)</a> instead.
    }
    @ </p>
  }
  @ </tr>
  @ <tr>
  @  <td class="login_out_label">Password:</td>
  @   <td><input type="password" id="p" name="p" value="" size="30" /></td>
  @ </tr>
  if( g.zLogin==0 && (anonFlag || zGoto==0) ){
................................................................................
  }else
#endif /* FOSSIL_ENABLE_JSON */
  {
    const char *zUrl = PD("REQUEST_URI", "index");
    const char *zQS = P("QUERY_STRING");
    Blob redir;
    blob_init(&redir, 0, 0);
    if( login_wants_https_redirect() && !g.sslNotAvailable ){
      blob_appendf(&redir, "%s/login?g=%T", g.zHttpsURL, zUrl);
    }else{
      blob_appendf(&redir, "%R/login?g=%T", zUrl);
    }
    if( anonOk ) blob_append(&redir, "&anon", 5);
    if( zQS && zQS[0] ){
      blob_appendf(&redir, "&%s", zQS);

Changes to src/main.c.

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
....
1282
1283
1284
1285
1286
1287
1288
1289
1290




1291
1292

1293
1294
1295
1296


1297
1298


















1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311


1312
1313
1314

1315
1316
1317

1318
1319
1320
1321
1322
1323
1324


















1325
1326
1327
1328
1329
1330
1331
....
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
#  include "tcl.h"
#endif
#ifdef FOSSIL_ENABLE_JSON
#  include "cson_amalgamation.h" /* JSON API. */
#  include "json_detail.h"
#endif

/*
** Size of a UUID in characters.   A UUID is a randomly generated
** lower-case hexadecimal number used to identify tickets.
**
** In Fossil 1.x, UUID also referred to a SHA1 artifact hash.  But that
** usage is now obsolete.  The term UUID should now mean only a very large
** random number used as a unique identifier for tickets or other objects.
*/
#define UUID_SIZE 40

/*
** Maximum number of auxiliary parameters on reports
*/
#define MX_AUX  5

/*
** Holds flags for fossil user permissions.
................................................................................
  @ <base href="%s(g.zBaseURL)/" />
  @ <title>Repository List</title>
  @ </head>
  @ <body>
  n = db_int(0, "SELECT count(*) FROM sfile");
  if( n>0 ){
    Stmt q;
    @ <h1>Available Repositories:</h1>
    @ <ol>




    db_prepare(&q, "SELECT pathname"
                   " FROM sfile ORDER BY pathname COLLATE nocase;");

    while( db_step(&q)==SQLITE_ROW ){
      const char *zName = db_column_text(&q, 0);
      int nName = (int)strlen(zName);
      char *zUrl;


      if( nName<7 ) continue;
      zUrl = sqlite3_mprintf("%.*s", nName-7, zName);


















      if( sqlite3_strglob("*.fossil", zName)!=0 ){
        /* The "fossil server DIRECTORY" and "fossil ui DIRECTORY" commands
        ** do not work for repositories whose names do not end in ".fossil".
        ** So do not hyperlink those cases. */
        @ <li>%h(zName)</li>
      } else if( sqlite3_strglob("*/.*", zName)==0 ){
        /* Do not show hidden repos */
        @ <li>%h(zName) (hidden)</li>
      } else if( allRepo && sqlite3_strglob("[a-zA-Z]:/?*", zName)!=0 ){
        @ <li><a href="%R/%T(zUrl)/home" target="_blank">/%h(zName)</a></li>
      }else{
        @ <li><a href="%R/%T(zUrl)/home" target="_blank">%h(zName)</a></li>
      }


      sqlite3_free(zUrl);
    }
    @ </ol>

  }else{
    @ <h1>No Repositories Found</h1>
  }

  @ </body>
  @ </html>
  cgi_reply();
  sqlite3_close(g.db);
  g.db = 0;
  return n;
}



















/*
** Preconditions:
**
**  * Environment variables are set up according to the CGI standard.
**
** If the repository is known, it has already been opened.  If unknown,
................................................................................
  if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
  if( zAltBase ){
    set_base_url(zAltBase);
  }
  g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
  if( find_option("https",0,0)!=0 ){
    cgi_replace_parameter("HTTPS","on");
  }else{
    /* without --https, defaults to not available. */
    g.sslNotAvailable = 1;
  }
  if( find_option("localhost", 0, 0)!=0 ){
    flags |= HTTP_SERVER_LOCALHOST;
  }

#if defined(_WIN32) && USE_SEE
  zPidKey = find_option("usepidkey", 0, 1);







<
<
<
<
<
<
<
<
<
<







 







|
|
>
>
>
>


>




>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|


|

|

|

>
>


<
>



>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<







47
48
49
50
51
52
53










54
55
56
57
58
59
60
....
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330

1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
....
2494
2495
2496
2497
2498
2499
2500



2501
2502
2503
2504
2505
2506
2507
#  include "tcl.h"
#endif
#ifdef FOSSIL_ENABLE_JSON
#  include "cson_amalgamation.h" /* JSON API. */
#  include "json_detail.h"
#endif











/*
** Maximum number of auxiliary parameters on reports
*/
#define MX_AUX  5

/*
** Holds flags for fossil user permissions.
................................................................................
  @ <base href="%s(g.zBaseURL)/" />
  @ <title>Repository List</title>
  @ </head>
  @ <body>
  n = db_int(0, "SELECT count(*) FROM sfile");
  if( n>0 ){
    Stmt q;
    sqlite3_int64 iNow, iMTime;
    @ <h1 align="center">Fossil Repositories</h1>
    @ <table border="0" class="sortable" data-init-sort="1" \
    @ data-column-types="tnk"><thead>
    @ <tr><th>Filename<th width="20"><th>Last Modified</tr>
    @ </thead><tbody>
    db_prepare(&q, "SELECT pathname"
                   " FROM sfile ORDER BY pathname COLLATE nocase;");
    iNow = db_int64(0, "SELECT strftime('%%s','now')");
    while( db_step(&q)==SQLITE_ROW ){
      const char *zName = db_column_text(&q, 0);
      int nName = (int)strlen(zName);
      char *zUrl;
      char *zAge;
      char *zFull;
      if( nName<7 ) continue;
      zUrl = sqlite3_mprintf("%.*s", nName-7, zName);
      if( zName[0]=='/'
#ifdef _WIN32
          || sqlite3_strglob("[a-zA-Z]:/*", zName)==0
#endif
      ){
        zFull = mprintf("%s", zName);
      }else if ( allRepo ){
        zFull = mprintf("/%s", zName);
      }else{
        zFull = mprintf("%s/%s", g.zRepositoryName, zName);
      }
      iMTime = file_mtime(zFull, ExtFILE);
      fossil_free(zFull);
      if( iMTime<=0 ){
        zAge = mprintf("...");
      }else{
        zAge = human_readable_age((iNow - iMTime)/86400.0);
      }
      if( sqlite3_strglob("*.fossil", zName)!=0 ){
        /* The "fossil server DIRECTORY" and "fossil ui DIRECTORY" commands
        ** do not work for repositories whose names do not end in ".fossil".
        ** So do not hyperlink those cases. */
        @ <tr><td>%h(zName)
      } else if( sqlite3_strglob("*/.*", zName)==0 ){
        /* Do not show hidden repos */
        @ <tr><td>%h(zName) (hidden)
      } else if( allRepo && sqlite3_strglob("[a-zA-Z]:/?*", zName)!=0 ){
        @ <tr><td><a href="%R/%T(zUrl)/home" target="_blank">/%h(zName)</a>
      }else{
        @ <tr><td><a href="%R/%T(zUrl)/home" target="_blank">%h(zName)</a>
      }
      @ <td></td><td data-sortkey='%010llx(iNow - iMTime)'>%h(zAge)</tr>
      fossil_free(zAge);
      sqlite3_free(zUrl);
    }

    @ </tbody></table>
  }else{
    @ <h1>No Repositories Found</h1>
  }
  @ <script>%s(builtin_text("sorttable.js"))</script>
  @ </body>
  @ </html>
  cgi_reply();
  sqlite3_close(g.db);
  g.db = 0;
  return n;
}

/*
** COMMAND: test-list-page
**
** Usage: %fossil test-list-page DIRECTORY
**
** Show all repositories underneath DIRECTORY.  Or if DIRECTORY is "/"
** show all repositories in the ~/.fossil file.
*/
void test_list_page(void){
  if( g.argc<3 ){
    g.zRepositoryName = "/";
  }else{
    g.zRepositoryName = g.argv[2];
  }
  g.httpOut = stdout;
  repo_list_page();
}

/*
** Preconditions:
**
**  * Environment variables are set up according to the CGI standard.
**
** If the repository is known, it has already been opened.  If unknown,
................................................................................
  if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
  if( zAltBase ){
    set_base_url(zAltBase);
  }
  g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
  if( find_option("https",0,0)!=0 ){
    cgi_replace_parameter("HTTPS","on");



  }
  if( find_option("localhost", 0, 0)!=0 ){
    flags |= HTTP_SERVER_LOCALHOST;
  }

#if defined(_WIN32) && USE_SEE
  zPidKey = find_option("usepidkey", 0, 1);

Changes to src/main.mk.

41
42
43
44
45
46
47

48
49
50
51
52
53
54
...
241
242
243
244
245
246
247

248
249
250
251
252
253
254
...
370
371
372
373
374
375
376

377
378
379
380
381
382
383
...
671
672
673
674
675
676
677

678
679
680
681
682
683
684
....
1014
1015
1016
1017
1018
1019
1020








1021
1022
1023
1024
1025
1026
1027
  $(SRCDIR)/deltacmd.c \
  $(SRCDIR)/descendants.c \
  $(SRCDIR)/diff.c \
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/dispatch.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \

  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/file.c \
  $(SRCDIR)/finfo.c \
  $(SRCDIR)/foci.c \
  $(SRCDIR)/fshell.c \
  $(SRCDIR)/fusefs.c \
................................................................................
  $(OBJDIR)/deltacmd_.c \
  $(OBJDIR)/descendants_.c \
  $(OBJDIR)/diff_.c \
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/dispatch_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \

  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/file_.c \
  $(OBJDIR)/finfo_.c \
  $(OBJDIR)/foci_.c \
  $(OBJDIR)/fshell_.c \
  $(OBJDIR)/fusefs_.c \
................................................................................
 $(OBJDIR)/deltacmd.o \
 $(OBJDIR)/descendants.o \
 $(OBJDIR)/diff.o \
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/dispatch.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \

 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/file.o \
 $(OBJDIR)/finfo.o \
 $(OBJDIR)/foci.o \
 $(OBJDIR)/fshell.o \
 $(OBJDIR)/fusefs.o \
................................................................................
	$(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h \
	$(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h \
	$(OBJDIR)/diff_.c:$(OBJDIR)/diff.h \
	$(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h \
	$(OBJDIR)/dispatch_.c:$(OBJDIR)/dispatch.h \
	$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
	$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \

	$(OBJDIR)/event_.c:$(OBJDIR)/event.h \
	$(OBJDIR)/export_.c:$(OBJDIR)/export.h \
	$(OBJDIR)/file_.c:$(OBJDIR)/file.h \
	$(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
	$(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
	$(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
	$(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
................................................................................
$(OBJDIR)/encode_.c:	$(SRCDIR)/encode.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/encode.c >$@

$(OBJDIR)/encode.o:	$(OBJDIR)/encode_.c $(OBJDIR)/encode.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/encode.o -c $(OBJDIR)/encode_.c

$(OBJDIR)/encode.h:	$(OBJDIR)/headers









$(OBJDIR)/event_.c:	$(SRCDIR)/event.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/event.c >$@

$(OBJDIR)/event.o:	$(OBJDIR)/event_.c $(OBJDIR)/event.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/event.o -c $(OBJDIR)/event_.c








>







 







>







 







>







 







>







 







>
>
>
>
>
>
>
>







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
...
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
...
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
....
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
  $(SRCDIR)/deltacmd.c \
  $(SRCDIR)/descendants.c \
  $(SRCDIR)/diff.c \
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/dispatch.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/etag.c \
  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/file.c \
  $(SRCDIR)/finfo.c \
  $(SRCDIR)/foci.c \
  $(SRCDIR)/fshell.c \
  $(SRCDIR)/fusefs.c \
................................................................................
  $(OBJDIR)/deltacmd_.c \
  $(OBJDIR)/descendants_.c \
  $(OBJDIR)/diff_.c \
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/dispatch_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/etag_.c \
  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/file_.c \
  $(OBJDIR)/finfo_.c \
  $(OBJDIR)/foci_.c \
  $(OBJDIR)/fshell_.c \
  $(OBJDIR)/fusefs_.c \
................................................................................
 $(OBJDIR)/deltacmd.o \
 $(OBJDIR)/descendants.o \
 $(OBJDIR)/diff.o \
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/dispatch.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/etag.o \
 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/file.o \
 $(OBJDIR)/finfo.o \
 $(OBJDIR)/foci.o \
 $(OBJDIR)/fshell.o \
 $(OBJDIR)/fusefs.o \
................................................................................
	$(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h \
	$(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h \
	$(OBJDIR)/diff_.c:$(OBJDIR)/diff.h \
	$(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h \
	$(OBJDIR)/dispatch_.c:$(OBJDIR)/dispatch.h \
	$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
	$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
	$(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
	$(OBJDIR)/event_.c:$(OBJDIR)/event.h \
	$(OBJDIR)/export_.c:$(OBJDIR)/export.h \
	$(OBJDIR)/file_.c:$(OBJDIR)/file.h \
	$(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
	$(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
	$(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
	$(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
................................................................................
$(OBJDIR)/encode_.c:	$(SRCDIR)/encode.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/encode.c >$@

$(OBJDIR)/encode.o:	$(OBJDIR)/encode_.c $(OBJDIR)/encode.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/encode.o -c $(OBJDIR)/encode_.c

$(OBJDIR)/encode.h:	$(OBJDIR)/headers

$(OBJDIR)/etag_.c:	$(SRCDIR)/etag.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/etag.c >$@

$(OBJDIR)/etag.o:	$(OBJDIR)/etag_.c $(OBJDIR)/etag.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/etag.o -c $(OBJDIR)/etag_.c

$(OBJDIR)/etag.h:	$(OBJDIR)/headers

$(OBJDIR)/event_.c:	$(SRCDIR)/event.c $(OBJDIR)/translate
	$(OBJDIR)/translate $(SRCDIR)/event.c >$@

$(OBJDIR)/event.o:	$(OBJDIR)/event_.c $(OBJDIR)/event.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/event.o -c $(OBJDIR)/event_.c

Changes to src/makemake.tcl.

53
54
55
56
57
58
59

60
61
62
63
64
65
66
  deltacmd
  descendants
  diff
  diffcmd
  dispatch
  doc
  encode

  event
  export
  file
  finfo
  foci
  fshell
  fusefs







>







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  deltacmd
  descendants
  diff
  diffcmd
  dispatch
  doc
  encode
  etag
  event
  export
  file
  finfo
  foci
  fshell
  fusefs

Changes to src/manifest.c.

605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
....
1265
1266
1267
1268
1269
1270
1271



1272
1273
1274
1275
1276
1277
1278
      **
      ** A K-line gives the UUID for the ticket which this control file
      ** is amending.
      */
      case 'K': {
        if( p->zTicketUuid!=0 ) SYNTAX("more than one K-card");
        p->zTicketUuid = next_token(&x, &sz);
        if( sz!=UUID_SIZE ) SYNTAX("K-card UUID is the wrong size");
        if( !validate16(p->zTicketUuid, UUID_SIZE) ){
          SYNTAX("invalid K-card UUID");
        }
        break;
      }

      /*
      **     L <wikititle>
................................................................................
  Manifest *p,             /* Manifest to search */
  const char *zName,       /* Name of the file we are looking for */
  int bBest                /* 0: exact match only.  1: closest match */
){
  int lwr, upr;
  int c;
  int i;



  lwr = 0;
  upr = p->nFile - 1;
  if( p->iFile>=lwr && p->iFile<upr ){
    c = fossil_strcmp(p->aFile[p->iFile+1].zName, zName);
    if( c==0 ){
      return &p->aFile[++p->iFile];
    }else if( c>0 ){







|
|







 







>
>
>







605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
....
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
      **
      ** A K-line gives the UUID for the ticket which this control file
      ** is amending.
      */
      case 'K': {
        if( p->zTicketUuid!=0 ) SYNTAX("more than one K-card");
        p->zTicketUuid = next_token(&x, &sz);
        if( sz!=HNAME_LEN_SHA1 ) SYNTAX("K-card UUID is the wrong size");
        if( !validate16(p->zTicketUuid, sz) ){
          SYNTAX("invalid K-card UUID");
        }
        break;
      }

      /*
      **     L <wikititle>
................................................................................
  Manifest *p,             /* Manifest to search */
  const char *zName,       /* Name of the file we are looking for */
  int bBest                /* 0: exact match only.  1: closest match */
){
  int lwr, upr;
  int c;
  int i;
  if( p->aFile==0 ){
    return 0;
  }
  lwr = 0;
  upr = p->nFile - 1;
  if( p->iFile>=lwr && p->iFile<upr ){
    c = fossil_strcmp(p->aFile[p->iFile+1].zName, zName);
    if( c==0 ){
      return &p->aFile[++p->iFile];
    }else if( c>0 ){

Changes to src/search.c.

1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
     { 1,  "reindex"  },
     { 2,  "index"    },
     { 3,  "disable"  },
     { 4,  "enable"   },
     { 5,  "stemmer"  },
  };
  static const struct { char *zSetting; char *zName; char *zSw; } aSetng[] = {
     { "search-ckin",     "check-in search:",  "c" },
     { "search-doc",      "document search:",  "d" },
     { "search-tkt",      "ticket search:",    "t" },
     { "search-wiki",     "wiki search:",      "w" },
     { "search-technote", "tech note search:", "e" },
  };
  char *zSubCmd = 0;
  int i, j, n;







|







1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
     { 1,  "reindex"  },
     { 2,  "index"    },
     { 3,  "disable"  },
     { 4,  "enable"   },
     { 5,  "stemmer"  },
  };
  static const struct { char *zSetting; char *zName; char *zSw; } aSetng[] = {
     { "search-ci",       "check-in search:",  "c" },
     { "search-doc",      "document search:",  "d" },
     { "search-tkt",      "ticket search:",    "t" },
     { "search-wiki",     "wiki search:",      "w" },
     { "search-technote", "tech note search:", "e" },
  };
  char *zSubCmd = 0;
  int i, j, n;

Changes to src/setup.c.

16
17
18
19
20
21
22















23
24
25
26
27
28
29
...
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
...
494
495
496
497
498
499
500

501
502
503
504
505
506
507
....
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
....
1803
1804
1805
1806
1807
1808
1809


1810
1811
1812
1813
1814
1815
1816
1817
....
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953

1954
1955
1956
1957
1958
1959
1960
....
2268
2269
2270
2271
2272
2273
2274

2275
2276
2277
2278
2279
2280
2281
*******************************************************************************
**
** Implementation of the Setup page
*/
#include "config.h"
#include <assert.h>
#include "setup.h"
















/*
** Output a single entry for a menu generated using an HTML table.
** If zLink is not NULL or an empty string, then it is the page that
** the menu entry will hyperlink to.  If zLink is NULL or "", then
** the menu entry has no hyperlink - it is disabled.
*/
................................................................................
    return;
  }

  /* If we have all the necessary information, write the new or
  ** modified user record.  After writing the user record, redirect
  ** to the page that displays a list of users.
  */
  doWrite = cgi_all("login","info","pw") && !higherUser;
  if( doWrite ){
    char c;
    char zCap[50], zNm[4];
    zNm[0] = 'a';
    zNm[2] = 0;
    for(i=0, c='a'; c<='z'; c++){
      zNm[1] = c;
................................................................................
    }
    login_verify_csrf_secret();
    db_multi_exec(
       "REPLACE INTO user(uid,login,info,pw,cap,mtime) "
       "VALUES(nullif(%d,0),%Q,%Q,%Q,%Q,now())",
      uid, zLogin, P("info"), zPw, zCap
    );

    admin_log( "Updated user [%q] with capabilities [%q].",
               zLogin, zCap );
    if( atoi(PD("all","0"))>0 ){
      Blob sql;
      char *zErr = 0;
      blob_zero(&sql);
      if( zOldLogin==0 ){
................................................................................
void setup_adunit(void){
  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed(0);
    return;
  }
  db_begin_transaction();
  if( P("clear")!=0 ){
    db_multi_exec("DELETE FROM config WHERE name GLOB 'adunit*'");
    cgi_replace_parameter("adunit","");
  }

  style_header("Edit Ad Unit");
  @ <form action="%s(g.zTop)/setup_adunit" method="post"><div>
  login_insert_csrf_secret();
................................................................................
  }
  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed(0);
    return;
  }
  db_begin_transaction();


  if( P("setlogo")!=0 && zLogoMime && zLogoMime[0] && szLogoImg>0 ){
    Blob img;
    Stmt ins;
    blob_init(&img, aLogoImg, szLogoImg);
    db_prepare(&ins,
        "REPLACE INTO config(name,value,mtime)"
        " VALUES('logo-image',:bytes,now())"
    );
................................................................................
/*
** WEBPAGE: admin_sql
**
** Run raw SQL commands against the database file using the web interface.
** Requires Admin privileges.
*/
void sql_page(void){
  const char *zQ = P("q");
  int go = P("go")!=0;
  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed(0);
    return;
  }
  add_content_sql_commands(g.db);
  db_begin_transaction();

  style_header("Raw SQL Commands");
  @ <p><b>Caution:</b> There are no restrictions on the SQL that can be
  @ run by this page.  You can do serious and irrepairable damage to the
  @ repository.  Proceed with extreme caution.</p>
  @
#if 0
  @ <p>Only the first statement in the entry box will be run.
................................................................................
*/
static void setup_update_url_alias(
  Blob *pSql,
  const char *zOldName,
  const char *zNewName,
  const char *zValue
){

  if( zNewName[0]==0 || zValue[0]==0 ){
    if( zOldName[0] ){
      blob_append_sql(pSql,
        "DELETE FROM config WHERE name='walias:%q';\n",
        zOldName);
    }
    return;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







>







 







|







 







>
>
|







 







|








>







 







>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
...
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
...
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
....
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
....
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
....
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
....
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
*******************************************************************************
**
** Implementation of the Setup page
*/
#include "config.h"
#include <assert.h>
#include "setup.h"

/*
** Increment the "cfgcnt" variable, so that ETags will know that
** the configuration has changed.
*/
void setup_incr_cfgcnt(void){
  static int once = 1;
  if( once ){
    once = 0;
    db_multi_exec("UPDATE config SET value=value+1 WHERE name='cfgcnt'");
    if( db_changes()==0 ){
      db_multi_exec("INSERT INTO config(name,value) VALUES('cfgcnt',1)");
    }
  }
}

/*
** Output a single entry for a menu generated using an HTML table.
** If zLink is not NULL or an empty string, then it is the page that
** the menu entry will hyperlink to.  If zLink is NULL or "", then
** the menu entry has no hyperlink - it is disabled.
*/
................................................................................
    return;
  }

  /* If we have all the necessary information, write the new or
  ** modified user record.  After writing the user record, redirect
  ** to the page that displays a list of users.
  */
  doWrite = cgi_all("login","info","pw") && !higherUser && cgi_csrf_safe(1);
  if( doWrite ){
    char c;
    char zCap[50], zNm[4];
    zNm[0] = 'a';
    zNm[2] = 0;
    for(i=0, c='a'; c<='z'; c++){
      zNm[1] = c;
................................................................................
    }
    login_verify_csrf_secret();
    db_multi_exec(
       "REPLACE INTO user(uid,login,info,pw,cap,mtime) "
       "VALUES(nullif(%d,0),%Q,%Q,%Q,%Q,now())",
      uid, zLogin, P("info"), zPw, zCap
    );
    setup_incr_cfgcnt();
    admin_log( "Updated user [%q] with capabilities [%q].",
               zLogin, zCap );
    if( atoi(PD("all","0"))>0 ){
      Blob sql;
      char *zErr = 0;
      blob_zero(&sql);
      if( zOldLogin==0 ){
................................................................................
void setup_adunit(void){
  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed(0);
    return;
  }
  db_begin_transaction();
  if( P("clear")!=0 && cgi_csrf_safe(1) ){
    db_multi_exec("DELETE FROM config WHERE name GLOB 'adunit*'");
    cgi_replace_parameter("adunit","");
  }

  style_header("Edit Ad Unit");
  @ <form action="%s(g.zTop)/setup_adunit" method="post"><div>
  login_insert_csrf_secret();
................................................................................
  }
  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed(0);
    return;
  }
  db_begin_transaction();
  if( !cgi_csrf_safe(1) ){
    /* Allow no state changes if not safe from CSRF */
  }else if( P("setlogo")!=0 && zLogoMime && zLogoMime[0] && szLogoImg>0 ){
    Blob img;
    Stmt ins;
    blob_init(&img, aLogoImg, szLogoImg);
    db_prepare(&ins,
        "REPLACE INTO config(name,value,mtime)"
        " VALUES('logo-image',:bytes,now())"
    );
................................................................................
/*
** WEBPAGE: admin_sql
**
** Run raw SQL commands against the database file using the web interface.
** Requires Admin privileges.
*/
void sql_page(void){
  const char *zQ;
  int go = P("go")!=0;
  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed(0);
    return;
  }
  add_content_sql_commands(g.db);
  db_begin_transaction();
  zQ = cgi_csrf_safe(1) ? P("q") : 0;
  style_header("Raw SQL Commands");
  @ <p><b>Caution:</b> There are no restrictions on the SQL that can be
  @ run by this page.  You can do serious and irrepairable damage to the
  @ repository.  Proceed with extreme caution.</p>
  @
#if 0
  @ <p>Only the first statement in the entry box will be run.
................................................................................
*/
static void setup_update_url_alias(
  Blob *pSql,
  const char *zOldName,
  const char *zNewName,
  const char *zValue
){
  if( !cgi_csrf_safe(1) ) return;
  if( zNewName[0]==0 || zValue[0]==0 ){
    if( zOldName[0] ){
      blob_append_sql(pSql,
        "DELETE FROM config WHERE name='walias:%q';\n",
        zOldName);
    }
    return;

Changes to src/skins.c.

465
466
467
468
469
470
471

472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537

538
539
540
541
542
543
544
  }
  db_begin_transaction();
  zCurrent = getSkin(0);
  for(i=0; i<count(aBuiltinSkin); i++){
    aBuiltinSkin[i].zSQL = getSkin(aBuiltinSkin[i].zLabel);
  }


  /* Process requests to delete a user-defined skin */
  if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){
    style_header("Confirm Custom Skin Delete");
    @ <form action="%s(g.zTop)/setup_skin_admin" method="post"><div>
    @ <p>Deletion of a custom skin is a permanent action that cannot
    @ be undone.  Please confirm that this is what you want to do:</p>
    @ <input type="hidden" name="sn" value="%h(P("sn"))" />
    @ <input type="submit" name="del2" value="Confirm - Delete The Skin" />
    @ <input type="submit" name="cancel" value="Cancel - Do Not Delete" />
    login_insert_csrf_secret();
    @ </div></form>
    style_footer();
    return;
  }
  if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){
    db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
  }
  if( P("draftdel")!=0 ){
    const char *zDraft = P("name");
    if( sqlite3_strglob("draft[1-9]",zDraft)==0 ){
      db_multi_exec("DELETE FROM config WHERE name GLOB '%q-*'", zDraft);
    }
  }
  if( skinRename() ) return;
  if( skinSave(zCurrent) ) return;

  /* The user pressed one of the "Install" buttons. */
  if( P("load") && (z = P("sn"))!=0 && z[0] ){
    int seen = 0;

    /* Check to see if the current skin is already saved.  If it is, there
    ** is no need to create a backup */
    zCurrent = getSkin(0);
    for(i=0; i<count(aBuiltinSkin); i++){
      if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){
        seen = 1;
        break;
      }
    }
    if( !seen ){
      seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'"
                       " AND value=%Q", zCurrent);
      if( !seen ){
        db_multi_exec(
          "INSERT INTO config(name,value,mtime) VALUES("
          "  strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S'),"
          "  %Q,now())", zCurrent
        );
      }
    }
    seen = 0;
    for(i=0; i<count(aBuiltinSkin); i++){
      if( fossil_strcmp(aBuiltinSkin[i].zDesc, z)==0 ){
        seen = 1;
        zCurrent = aBuiltinSkin[i].zSQL;
        db_multi_exec("%s", zCurrent/*safe-for-%s*/);
        break;
      }
    }
    if( !seen ){
      zName = skinVarName(z,0);
      zCurrent = db_get(zName, 0);
      db_multi_exec("%s", zCurrent/*safe-for-%s*/);
    }
  }


  style_header("Skins");
  if( zErr ){
    @ <p style="color:red">%h(zErr)</p>
  }
  @ <table border="0">
  @ <tr><td colspan=4><h2>Built-in Skins:</h2></td></th>
  for(i=0; i<count(aBuiltinSkin); i++){







>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>







465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
  }
  db_begin_transaction();
  zCurrent = getSkin(0);
  for(i=0; i<count(aBuiltinSkin); i++){
    aBuiltinSkin[i].zSQL = getSkin(aBuiltinSkin[i].zLabel);
  }

  if( cgi_csrf_safe(1) ){
    /* Process requests to delete a user-defined skin */
    if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){
      style_header("Confirm Custom Skin Delete");
      @ <form action="%s(g.zTop)/setup_skin_admin" method="post"><div>
      @ <p>Deletion of a custom skin is a permanent action that cannot
      @ be undone.  Please confirm that this is what you want to do:</p>
      @ <input type="hidden" name="sn" value="%h(P("sn"))" />
      @ <input type="submit" name="del2" value="Confirm - Delete The Skin" />
      @ <input type="submit" name="cancel" value="Cancel - Do Not Delete" />
      login_insert_csrf_secret();
      @ </div></form>
      style_footer();
      return;
    }
    if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){
      db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
    }
    if( P("draftdel")!=0 ){
      const char *zDraft = P("name");
      if( sqlite3_strglob("draft[1-9]",zDraft)==0 ){
        db_multi_exec("DELETE FROM config WHERE name GLOB '%q-*'", zDraft);
      }
    }
    if( skinRename() ) return;
    if( skinSave(zCurrent) ) return;
  
    /* The user pressed one of the "Install" buttons. */
    if( P("load") && (z = P("sn"))!=0 && z[0] ){
      int seen = 0;
  
      /* Check to see if the current skin is already saved.  If it is, there
      ** is no need to create a backup */
      zCurrent = getSkin(0);
      for(i=0; i<count(aBuiltinSkin); i++){
        if( fossil_strcmp(aBuiltinSkin[i].zSQL, zCurrent)==0 ){
          seen = 1;
          break;
        }
      }
      if( !seen ){
        seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'"
                         " AND value=%Q", zCurrent);
        if( !seen ){
          db_multi_exec(
            "INSERT INTO config(name,value,mtime) VALUES("
            "  strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S'),"
            "  %Q,now())", zCurrent
          );
        }
      }
      seen = 0;
      for(i=0; i<count(aBuiltinSkin); i++){
        if( fossil_strcmp(aBuiltinSkin[i].zDesc, z)==0 ){
          seen = 1;
          zCurrent = aBuiltinSkin[i].zSQL;
          db_multi_exec("%s", zCurrent/*safe-for-%s*/);
          break;
        }
      }
      if( !seen ){
        zName = skinVarName(z,0);
        zCurrent = db_get(zName, 0);
        db_multi_exec("%s", zCurrent/*safe-for-%s*/);
      }
    }
  }
  
  style_header("Skins");
  if( zErr ){
    @ <p style="color:red">%h(zErr)</p>
  }
  @ <table border="0">
  @ <tr><td colspan=4><h2>Built-in Skins:</h2></td></th>
  for(i=0; i<count(aBuiltinSkin); i++){

Changes to src/sqlite3.c.

1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
.....
60522
60523
60524
60525
60526
60527
60528


60529
60530
60531

60532
60533
60534
60535
60536
60537
60538
......
203326
203327
203328
203329
203330
203331
203332
203333
203334
203335
203336
203337
203338
203339
203340
......
207594
207595
207596
207597
207598
207599
207600
207601
207602
207603
207604
207605
207606
207607
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.22.0"
#define SQLITE_VERSION_NUMBER 3022000
#define SQLITE_SOURCE_ID      "2018-01-20 15:48:45 136bf323e42dc90e1780199a381bcbb084b069eca5c7343ee6fc6e2550831536"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
................................................................................
** If SQLITE_DEBUG is not defined, then this macro is equivalent to
** SQLITE_CORRUPT_BKPT. Or, if SQLITE_DEBUG is set, then the log message
** normally produced as a side-effect of SQLITE_CORRUPT_BKPT is augmented
** with the page number and filename associated with the (MemPage*).
*/
#ifdef SQLITE_DEBUG
int corruptPageError(int lineno, MemPage *p){


  char *zMsg = sqlite3_mprintf("database corruption page %d of %s",
      (int)p->pgno, sqlite3PagerFilename(p->pBt->pPager, 0)
  );

  if( zMsg ){
    sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg);
  }
  sqlite3_free(zMsg);
  return SQLITE_CORRUPT_BKPT;
}
# define SQLITE_CORRUPT_PAGE(pMemPage) corruptPageError(__LINE__, pMemPage)
................................................................................
static void fts5SourceIdFunc(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args */
  sqlite3_value **apUnused        /* Function arguments */
){
  assert( nArg==0 );
  UNUSED_PARAM2(nArg, apUnused);
  sqlite3_result_text(pCtx, "fts5: 2018-01-20 15:48:45 136bf323e42dc90e1780199a381bcbb084b069eca5c7343ee6fc6e2550831536", -1, SQLITE_TRANSIENT);
}

static int fts5Init(sqlite3 *db){
  static const sqlite3_module fts5Mod = {
    /* iVersion      */ 2,
    /* xCreate       */ fts5CreateMethod,
    /* xConnect      */ fts5ConnectMethod,
................................................................................
#endif
  return rc;
}
#endif /* SQLITE_CORE */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */

/************** End of stmt.c ************************************************/
#if __LINE__!=207601
#undef SQLITE_SOURCE_ID
#define SQLITE_SOURCE_ID      "2018-01-20 15:48:45 136bf323e42dc90e1780199a381bcbb084b069eca5c7343ee6fc6e255083alt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
/************************** End of sqlite3.c ******************************/







|







 







>
>
|


>







 







|







 







|

|




1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
.....
60522
60523
60524
60525
60526
60527
60528
60529
60530
60531
60532
60533
60534
60535
60536
60537
60538
60539
60540
60541
......
203329
203330
203331
203332
203333
203334
203335
203336
203337
203338
203339
203340
203341
203342
203343
......
207597
207598
207599
207600
207601
207602
207603
207604
207605
207606
207607
207608
207609
207610
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.22.0"
#define SQLITE_VERSION_NUMBER 3022000
#define SQLITE_SOURCE_ID      "2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2171d"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
................................................................................
** If SQLITE_DEBUG is not defined, then this macro is equivalent to
** SQLITE_CORRUPT_BKPT. Or, if SQLITE_DEBUG is set, then the log message
** normally produced as a side-effect of SQLITE_CORRUPT_BKPT is augmented
** with the page number and filename associated with the (MemPage*).
*/
#ifdef SQLITE_DEBUG
int corruptPageError(int lineno, MemPage *p){
  char *zMsg;
  sqlite3BeginBenignMalloc();
  zMsg = sqlite3_mprintf("database corruption page %d of %s",
      (int)p->pgno, sqlite3PagerFilename(p->pBt->pPager, 0)
  );
  sqlite3EndBenignMalloc();
  if( zMsg ){
    sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg);
  }
  sqlite3_free(zMsg);
  return SQLITE_CORRUPT_BKPT;
}
# define SQLITE_CORRUPT_PAGE(pMemPage) corruptPageError(__LINE__, pMemPage)
................................................................................
static void fts5SourceIdFunc(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args */
  sqlite3_value **apUnused        /* Function arguments */
){
  assert( nArg==0 );
  UNUSED_PARAM2(nArg, apUnused);
  sqlite3_result_text(pCtx, "fts5: 2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2171d", -1, SQLITE_TRANSIENT);
}

static int fts5Init(sqlite3 *db){
  static const sqlite3_module fts5Mod = {
    /* iVersion      */ 2,
    /* xCreate       */ fts5CreateMethod,
    /* xConnect      */ fts5ConnectMethod,
................................................................................
#endif
  return rc;
}
#endif /* SQLITE_CORE */
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */

/************** End of stmt.c ************************************************/
#if __LINE__!=207604
#undef SQLITE_SOURCE_ID
#define SQLITE_SOURCE_ID      "2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2alt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
/************************** End of sqlite3.c ******************************/

Changes to src/sqlite3.h.

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.22.0"
#define SQLITE_VERSION_NUMBER 3022000
#define SQLITE_SOURCE_ID      "2018-01-20 15:48:45 136bf323e42dc90e1780199a381bcbb084b069eca5c7343ee6fc6e2550831536"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros







|







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.22.0"
#define SQLITE_VERSION_NUMBER 3022000
#define SQLITE_SOURCE_ID      "2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2171d"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros

Changes to src/statrep.c.

56
57
58
59
60
61
62

63
64
65
66
67
68
69
..
88
89
90
91
92
93
94







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
** filter it applies, or '*' if no filter is applied (i.e. if "all" is
** used).
*/
static int stats_report_init_view(){
  const char *zType = PD("type","*");  /* analog to /timeline?y=... */
  const char *zRealType = NULL;        /* normalized form of zType */
  int rc = 0;                          /* result code */

  assert( !statsReportType && "Must not be called more than once." );
  switch( (zType && *zType) ? *zType : 0 ){
    case 'c':
    case 'C':
      zRealType = "ci";
      rc = *zRealType;
      break;
................................................................................
      rc = *zRealType;
      break;
    default:
      rc = '*';
      break;
  }
  assert(0 != rc);







  if(zRealType){
    statsReportTimelineYFlag = zRealType;
    db_multi_exec("CREATE TEMP VIEW v_reports AS "
                  "SELECT * FROM event WHERE type GLOB %Q",
                  zRealType);
  }else{
    statsReportTimelineYFlag = "a";
    db_multi_exec("CREATE TEMP VIEW v_reports AS "
                  "SELECT * FROM event");
  }
  return statsReportType = rc;
}

/*
** Returns a string suitable (for a given value of suitable) for
** use in a label with the header of the /reports pages, dependent







>







 







>
>
>
>
>
>
>



|
|



|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
..
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
** filter it applies, or '*' if no filter is applied (i.e. if "all" is
** used).
*/
static int stats_report_init_view(){
  const char *zType = PD("type","*");  /* analog to /timeline?y=... */
  const char *zRealType = NULL;        /* normalized form of zType */
  int rc = 0;                          /* result code */
  char *zTimeSpan;                     /* Time span */
  assert( !statsReportType && "Must not be called more than once." );
  switch( (zType && *zType) ? *zType : 0 ){
    case 'c':
    case 'C':
      zRealType = "ci";
      rc = *zRealType;
      break;
................................................................................
      rc = *zRealType;
      break;
    default:
      rc = '*';
      break;
  }
  assert(0 != rc);
  if( P("from")!=0 && P("to")!=0 ){
    zTimeSpan = mprintf(
          " (event.mtime BETWEEN julianday(%Q) AND julianday(%Q))",
          P("from"), P("to"));
  }else{
    zTimeSpan = " 1";
  }
  if(zRealType){
    statsReportTimelineYFlag = zRealType;
    db_multi_exec("CREATE TEMP VIEW v_reports AS "
                  "SELECT * FROM event WHERE (type GLOB %Q) AND %s",
                  zRealType, zTimeSpan/*safe-for-%s*/);
  }else{
    statsReportTimelineYFlag = "a";
    db_multi_exec("CREATE TEMP VIEW v_reports AS "
                  "SELECT * FROM event WHERE %s", zTimeSpan/*safe-for-%s*/);
  }
  return statsReportType = rc;
}

/*
** Returns a string suitable (for a given value of suitable) for
** use in a label with the header of the /reports pages, dependent

Changes to src/style.c.

831
832
833
834
835
836
837



838
839
840
841
842


843
844
845
846
847
848
849
850
851
852





853
854
855
856
857
858
859
860
861
862
863
...
868
869
870
871
872
873
874
875

876
877
878
879
880
881
882
...
923
924
925
926
927
928
929

930
931
932
933
934
935
936

/*
** WEBPAGE: builtin
** URL:  builtin/FILENAME
**
** Return the built-in text given by FILENAME.  This is used internally 
** by many Fossil web pages to load built-in javascript files.



*/
void page_builtin_text(void){
  Blob out;
  const char *zName = P("name");
  const char *zTxt = 0;


  if( zName ) zTxt = builtin_text(zName);
  if( zTxt==0 ){
    cgi_set_status(404, "Not Found");
    @ File "%h(zName)" not found
    return;
  }
  if( sqlite3_strglob("*.js", zName)==0 ){
    cgi_set_content_type("application/javascript");
  }else{
    cgi_set_content_type("text/plain");





  }
  blob_init(&out, zTxt, -1);
  cgi_set_content(&out);
  g.isConst = 1;
}


/*
** WEBPAGE: test_env
**
** Display CGI-variables and other aspects of the run-time
................................................................................
  int i;
  int showAll;
  char zCap[30];
  static const char *const azCgiVars[] = {
    "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",
    "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING",
    "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHENICATION",
    "HTTP_CONNECTION", "HTTP_HOST", "HTTP_IF_NONE_MATCH",

    "HTTP_USER_AGENT", "HTTP_REFERER", "PATH_INFO", "PATH_TRANSLATED",
    "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT",
    "REMOTE_USER", "REQUEST_METHOD",
    "REQUEST_URI", "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_PROTOCOL",
    "HOME", "FOSSIL_HOME", "USERNAME", "USER", "FOSSIL_USER",
    "SQLITE_TMPDIR", "TMPDIR",
    "TEMP", "TMP", "FOSSIL_VFS",
................................................................................
  }
  zCap[i] = 0;
  if( i>0 ){
    @ anonymous-adds = %s(zCap)<br />
  }
  @ g.zRepositoryName = %h(g.zRepositoryName)<br />
  @ load_average() = %f(load_average())<br />

  @ <hr />
  P("HTTP_USER_AGENT");
  cgi_print_all(showAll);
  if( showAll && blob_size(&g.httpHeader)>0 ){
    @ <hr />
    @ <pre>
    @ %h(blob_str(&g.httpHeader))







>
>
>





>
>










>
>
>
>
>



<







 







|
>







 







>







831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865

866
867
868
869
870
871
872
...
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
...
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947

/*
** WEBPAGE: builtin
** URL:  builtin/FILENAME
**
** Return the built-in text given by FILENAME.  This is used internally 
** by many Fossil web pages to load built-in javascript files.
**
** If the id= query parameter is present, then Fossil assumes that the
** result is immutable and sets a very large cache retention time (1 year).
*/
void page_builtin_text(void){
  Blob out;
  const char *zName = P("name");
  const char *zTxt = 0;
  const char *zId = P("id");
  int nId;
  if( zName ) zTxt = builtin_text(zName);
  if( zTxt==0 ){
    cgi_set_status(404, "Not Found");
    @ File "%h(zName)" not found
    return;
  }
  if( sqlite3_strglob("*.js", zName)==0 ){
    cgi_set_content_type("application/javascript");
  }else{
    cgi_set_content_type("text/plain");
  }
  if( zId && (nId = (int)strlen(zId))>=8 && strncmp(zId,MANIFEST_UUID,nId)==0 ){
    g.isConst = 1;
  }else{
    etag_check(0,0);
  }
  blob_init(&out, zTxt, -1);
  cgi_set_content(&out);

}


/*
** WEBPAGE: test_env
**
** Display CGI-variables and other aspects of the run-time
................................................................................
  int i;
  int showAll;
  char zCap[30];
  static const char *const azCgiVars[] = {
    "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",
    "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING",
    "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHENICATION",
    "HTTP_CONNECTION", "HTTP_HOST",
    "HTTP_IF_NONE_MATCH", "HTTP_IF_MODIFIED_SINCE",
    "HTTP_USER_AGENT", "HTTP_REFERER", "PATH_INFO", "PATH_TRANSLATED",
    "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT",
    "REMOTE_USER", "REQUEST_METHOD",
    "REQUEST_URI", "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_PROTOCOL",
    "HOME", "FOSSIL_HOME", "USERNAME", "USER", "FOSSIL_USER",
    "SQLITE_TMPDIR", "TMPDIR",
    "TEMP", "TMP", "FOSSIL_VFS",
................................................................................
  }
  zCap[i] = 0;
  if( i>0 ){
    @ anonymous-adds = %s(zCap)<br />
  }
  @ g.zRepositoryName = %h(g.zRepositoryName)<br />
  @ load_average() = %f(load_average())<br />
  @ cgi_csrf_safe(0) = %d(cgi_csrf_safe(0))<br />
  @ <hr />
  P("HTTP_USER_AGENT");
  cgi_print_all(showAll);
  if( showAll && blob_size(&g.httpHeader)>0 ){
    @ <hr />
    @ <pre>
    @ %h(blob_str(&g.httpHeader))

Changes to src/tar.c.

729
730
731
732
733
734
735

736
737
738
739
740
741
742
  /* Compute a unique key for the cache entry based on query parameters */
  blob_init(&cacheKey, 0, 0);
  blob_appendf(&cacheKey, "/tarball/%z", rid_to_uuid(rid));
  blob_appendf(&cacheKey, "/%q", zName);
  if( zInclude ) blob_appendf(&cacheKey, ",in=%Q", zInclude);
  if( zExclude ) blob_appendf(&cacheKey, ",ex=%Q", zExclude);
  zKey = blob_str(&cacheKey);


  if( P("debug")!=0 ){
    style_header("Tarball Generator Debug Screen");
    @ zName = "%h(zName)"<br />
    @ rid = %d(rid)<br />
    if( zInclude ){
      @ zInclude = "%h(zInclude)"<br />







>







729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
  /* Compute a unique key for the cache entry based on query parameters */
  blob_init(&cacheKey, 0, 0);
  blob_appendf(&cacheKey, "/tarball/%z", rid_to_uuid(rid));
  blob_appendf(&cacheKey, "/%q", zName);
  if( zInclude ) blob_appendf(&cacheKey, ",in=%Q", zInclude);
  if( zExclude ) blob_appendf(&cacheKey, ",ex=%Q", zExclude);
  zKey = blob_str(&cacheKey);
  etag_check(ETAG_HASH, zKey);

  if( P("debug")!=0 ){
    style_header("Tarball Generator Debug Screen");
    @ zName = "%h(zName)"<br />
    @ rid = %d(rid)<br />
    if( zInclude ){
      @ zInclude = "%h(zInclude)"<br />

Changes to src/th_tcl.c.

129
130
131
132
133
134
135







136
137
138
139
140
141
142
#    elif defined(__APPLE__)
#      ifndef TCL_LIBRARY_NAME
#        define TCL_LIBRARY_NAME "libtcl8.6.dylib\0"
#      endif
#      ifndef TCL_MINOR_OFFSET
#        define TCL_MINOR_OFFSET (8)
#      endif







#    else
#      ifndef TCL_LIBRARY_NAME
#        define TCL_LIBRARY_NAME "libtcl8.6.so\0"
#      endif
#      ifndef TCL_MINOR_OFFSET
#        define TCL_MINOR_OFFSET (8)
#      endif







>
>
>
>
>
>
>







129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#    elif defined(__APPLE__)
#      ifndef TCL_LIBRARY_NAME
#        define TCL_LIBRARY_NAME "libtcl8.6.dylib\0"
#      endif
#      ifndef TCL_MINOR_OFFSET
#        define TCL_MINOR_OFFSET (8)
#      endif
#    elif defined(__FreeBSD__)
#      ifndef TCL_LIBRARY_NAME
#        define TCL_LIBRARY_NAME "libtcl86.so\0"
#      endif
#      ifndef TCL_MINOR_OFFSET
#        define TCL_MINOR_OFFSET (7)
#      endif
#    else
#      ifndef TCL_LIBRARY_NAME
#        define TCL_LIBRARY_NAME "libtcl8.6.so\0"
#      endif
#      ifndef TCL_MINOR_OFFSET
#        define TCL_MINOR_OFFSET (8)
#      endif

Changes to src/timeline.c.

416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
...
434
435
436
437
438
439
440






441
442
443
444
445
446
447
...
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
...
563
564
565
566
567
568
569


570
571
572
573
574
575
576
        if( zBr==0 || strcmp(zBr,"trunk")==0 ){
          zBgClr = 0;
        }else{
          zBgClr = hash_color(zBr);
        }
      }
    }
    if( zType[0]=='c' && (pGraph || (tmFlags & TIMELINE_BRCOLOR)!=0) ){
      int nParent = 0;
      int aParent[GR_MAX_RAIL];
      static Stmt qparent;
      db_static_prepare(&qparent,
        "SELECT pid FROM plink"
        " WHERE cid=:rid AND pid NOT IN phantom"
        " ORDER BY isprim DESC /*sort*/"
................................................................................
        aParent[nParent++] = db_column_int(&qparent, 0);
      }
      db_reset(&qparent);
      gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr,
                           zUuid, isLeaf);
      db_reset(&qbranch);
      @ <div id="m%d(gidx)" class="tl-nodemark"></div>






    }
    @</td>
    if( !isSelectedOrCurrent ){
      @ <td class="timeline%s(zStyle)Cell" id='mc%d(gidx)'>
    }else{
      @ <td class="timeline%s(zStyle)Cell">
    }
................................................................................
    @ </span>
    blob_reset(&comment);

    /* Generate extra information and hyperlinks to follow the comment.
    ** Example:  "(check-in: [abcdefg], user: drh, tags: trunk)"
    */
    if( drawDetailEllipsis ){
      @ <span class='timelineEllipsis' id='ellipsis-%d(rid)'\
      @ data-id='%d(rid)'>...</span>
    }
    if( tmFlags & TIMELINE_COLUMNAR ){
      if( !isSelectedOrCurrent ){
        @ <td class="timelineDetailCell" id='md%d(gidx)'>
      }else{
        @ <td class="timelineDetailCell">
................................................................................
        cgi_printf("check-in:&nbsp;%z%S</a> ",href("%R/info/%!S",zUuid),zUuid);
      }else if( zType[0]=='e' && tagid ){
        cgi_printf("technote:&nbsp;");
        hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
      }else{
        cgi_printf("artifact:&nbsp;%z%S</a> ",href("%R/info/%!S",zUuid),zUuid);
      }


    }

    if( g.perm.Hyperlink && fossil_strcmp(zDispUser, zThisUser)!=0 ){
      char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd&n=200", zDispUser, zDate);
      cgi_printf("user:&nbsp;%z%h</a>", href("%z",zLink), zDispUser);
    }else{
      cgi_printf("user:&nbsp;%h", zDispUser);







|







 







>
>
>
>
>
>







 







|







 







>
>







416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
...
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
...
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
...
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
        if( zBr==0 || strcmp(zBr,"trunk")==0 ){
          zBgClr = 0;
        }else{
          zBgClr = hash_color(zBr);
        }
      }
    }
    if( zType[0]=='c' && pGraph ){
      int nParent = 0;
      int aParent[GR_MAX_RAIL];
      static Stmt qparent;
      db_static_prepare(&qparent,
        "SELECT pid FROM plink"
        " WHERE cid=:rid AND pid NOT IN phantom"
        " ORDER BY isprim DESC /*sort*/"
................................................................................
        aParent[nParent++] = db_column_int(&qparent, 0);
      }
      db_reset(&qparent);
      gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr,
                           zUuid, isLeaf);
      db_reset(&qbranch);
      @ <div id="m%d(gidx)" class="tl-nodemark"></div>
    }else if( zType[0]=='e' && pGraph && zBgClr && zBgClr[0] ){
      /* For technotes, make a graph node with nParent==(-1).  This will
      ** not actually draw anything on the graph, but it will set the
      ** background color of the timeline entry */
      gidx = graph_add_row(pGraph, rid, -1, 0, zBr, zBgClr, zUuid, 0);
      @ <div id="m%d(gidx)" class="tl-nodemark"></div>
    }
    @</td>
    if( !isSelectedOrCurrent ){
      @ <td class="timeline%s(zStyle)Cell" id='mc%d(gidx)'>
    }else{
      @ <td class="timeline%s(zStyle)Cell">
    }
................................................................................
    @ </span>
    blob_reset(&comment);

    /* Generate extra information and hyperlinks to follow the comment.
    ** Example:  "(check-in: [abcdefg], user: drh, tags: trunk)"
    */
    if( drawDetailEllipsis ){
      @ <span class='timelineEllipsis' id='ellipsis-%d(rid)' \
      @ data-id='%d(rid)'>...</span>
    }
    if( tmFlags & TIMELINE_COLUMNAR ){
      if( !isSelectedOrCurrent ){
        @ <td class="timelineDetailCell" id='md%d(gidx)'>
      }else{
        @ <td class="timelineDetailCell">
................................................................................
        cgi_printf("check-in:&nbsp;%z%S</a> ",href("%R/info/%!S",zUuid),zUuid);
      }else if( zType[0]=='e' && tagid ){
        cgi_printf("technote:&nbsp;");
        hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
      }else{
        cgi_printf("artifact:&nbsp;%z%S</a> ",href("%R/info/%!S",zUuid),zUuid);
      }
    }else if( zType[0]=='g' || zType[0]=='w' || zType[0]=='t' ){
      cgi_printf("artifact:&nbsp;%z%S</a> ",href("%R/info/%!S",zUuid),zUuid);
    }

    if( g.perm.Hyperlink && fossil_strcmp(zDispUser, zThisUser)!=0 ){
      char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd&n=200", zDispUser, zDate);
      cgi_printf("user:&nbsp;%z%h</a>", href("%z",zLink), zDispUser);
    }else{
      cgi_printf("user:&nbsp;%h", zDispUser);

Changes to src/tkt.c.

745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
    return;
  }
  zName = P("name");
  if( P("cancel") ){
    cgi_redirectf("tktview?name=%T", zName);
  }
  style_header("Edit Ticket");
  if( zName==0 || (nName = strlen(zName))<4 || nName>UUID_SIZE
          || !validate16(zName,nName) ){
    @ <span class="tktError">Not a valid ticket id: "%h(zName)"</span>
    style_footer();
    return;
  }
  nRec = db_int(0, "SELECT count(*) FROM ticket WHERE tkt_uuid GLOB '%q*'",
                zName);







|







745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
    return;
  }
  zName = P("name");
  if( P("cancel") ){
    cgi_redirectf("tktview?name=%T", zName);
  }
  style_header("Edit Ticket");
  if( zName==0 || (nName = strlen(zName))<4 || nName>HNAME_LEN_SHA1
          || !validate16(zName,nName) ){
    @ <span class="tktError">Not a valid ticket id: "%h(zName)"</span>
    style_footer();
    return;
  }
  nRec = db_int(0, "SELECT count(*) FROM ticket WHERE tkt_uuid GLOB '%q*'",
                zName);

Changes to src/unversioned.c.

151
152
153
154
155
156
157
158




159
160
161
162
163
164
165
**    0:     zName does not exist in the unversioned table.
**    1:     zName exists and should be replaced by the mtime/zHash remote.
**    2:     zName exists and is the same as zHash but has a older mtime
**    3:     zName exists and is identical to mtime/zHash in all respects.
**    4:     zName exists and is the same as zHash but has a newer mtime.
**    5:     zName exists and should override the mtime/zHash remote.
*/
int unversioned_status(const char *zName, sqlite3_int64 mtime, const char *zHash){




  int iStatus = 0;
  Stmt q;
  db_prepare(&q, "SELECT mtime, hash FROM unversioned WHERE name=%Q", zName);
  if( db_step(&q)==SQLITE_ROW ){
    const char *zLocalHash = db_column_text(&q, 1);
    int hashCmp;
    sqlite3_int64 iLocalMtime = db_column_int64(&q, 0);







|
>
>
>
>







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
**    0:     zName does not exist in the unversioned table.
**    1:     zName exists and should be replaced by the mtime/zHash remote.
**    2:     zName exists and is the same as zHash but has a older mtime
**    3:     zName exists and is identical to mtime/zHash in all respects.
**    4:     zName exists and is the same as zHash but has a newer mtime.
**    5:     zName exists and should override the mtime/zHash remote.
*/
int unversioned_status(
  const char *zName,
  sqlite3_int64 mtime,
  const char *zHash
){
  int iStatus = 0;
  Stmt q;
  db_prepare(&q, "SELECT mtime, hash FROM unversioned WHERE name=%Q", zName);
  if( db_step(&q)==SQLITE_ROW ){
    const char *zLocalHash = db_column_text(&q, 1);
    int hashCmp;
    sqlite3_int64 iLocalMtime = db_column_int64(&q, 0);

Changes to src/util.c.

374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
  return 1;
#else
  return fcntl(fd, F_GETFL)!=(-1) || errno!=EBADF;
#endif
}

/*
** Returns TRUE if zSym is exactly UUID_SIZE bytes long and contains
** only lower-case ASCII hexadecimal values.
*/
int fossil_is_uuid(const char *zSym){
  return zSym
    && (UUID_SIZE==strlen(zSym))
    && validate16(zSym, UUID_SIZE);
}

/*
** Return true if the input string is NULL or all whitespace.
** Return false if the input string contains text.
*/
int fossil_all_whitespace(const char *z){







|
|


|
<
|







374
375
376
377
378
379
380
381
382
383
384
385

386
387
388
389
390
391
392
393
  return 1;
#else
  return fcntl(fd, F_GETFL)!=(-1) || errno!=EBADF;
#endif
}

/*
** Returns TRUE if zSym is exactly HNAME_LEN_SHA1 or HNAME_LEN_K256
** bytes long and contains only lower-case ASCII hexadecimal values.
*/
int fossil_is_uuid(const char *zSym){
  int sz = zSym ? (int)strlen(zSym) : 0;

  return (HNAME_LEN_SHA1==sz || HNAME_LEN_K256==sz) && validate16(zSym, sz);
}

/*
** Return true if the input string is NULL or all whitespace.
** Return false if the input string contains text.
*/
int fossil_all_whitespace(const char *z){

Changes to src/wikiformat.c.

1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
....
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
....
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
  const char *zTarget,    /* Ticket UUID */
  int *pClosed            /* True if the ticket is closed */
){
  static Stmt q;
  static int once = 1;
  int n;
  int rc;
  char zLower[UUID_SIZE+1];
  char zUpper[UUID_SIZE+1];
  n = strlen(zTarget);
  memcpy(zLower, zTarget, n+1);
  canonical16(zLower, n+1);
  memcpy(zUpper, zLower, n+1);
  zUpper[n-1]++;
  if( once ){
    const char *zClosedExpr = db_get("ticket-closed-expr", "status='Closed'");
................................................................................
         && (zTarget[1]=='/' || (zTarget[1]=='.' && zTarget[2]=='/'))
         && (p->state & WIKI_LINKSONLY)==0 ){
    blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
  }else if( zTarget[0]=='#' ){
    blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
  }else if( is_valid_hname(zTarget) ){
    int isClosed = 0;
    if( strlen(zTarget)<=UUID_SIZE && is_ticket(zTarget, &isClosed) ){
      /* Special display processing for tickets.  Display the hyperlink
      ** as crossed out if the ticket is closed.
      */
      if( isClosed ){
        if( g.perm.Hyperlink ){
          blob_appendf(p->pOut,
             "%z<span class=\"wikiTagCancelled\">[",
................................................................................
    }else{
      n = nextWikiToken(z, &renderer, &tokenType);
    }
    switch( tokenType ){
      case TOKEN_LINK: {
        char *zTarget;
        int i, c;
        char zLink[42];

        zTarget = &z[1];
        for(i=0; zTarget[i] && zTarget[i]!='|' && zTarget[i]!=']'; i++){}
        while(i>1 && zTarget[i-1]==' '){ i--; }
        c = zTarget[i];
        zTarget[i] = 0;
        if( is_valid_hname(zTarget) ){







|
|







 







|







 







|







1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
....
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
....
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
  const char *zTarget,    /* Ticket UUID */
  int *pClosed            /* True if the ticket is closed */
){
  static Stmt q;
  static int once = 1;
  int n;
  int rc;
  char zLower[HNAME_MAX+1];
  char zUpper[HNAME_MAX+1];
  n = strlen(zTarget);
  memcpy(zLower, zTarget, n+1);
  canonical16(zLower, n+1);
  memcpy(zUpper, zLower, n+1);
  zUpper[n-1]++;
  if( once ){
    const char *zClosedExpr = db_get("ticket-closed-expr", "status='Closed'");
................................................................................
         && (zTarget[1]=='/' || (zTarget[1]=='.' && zTarget[2]=='/'))
         && (p->state & WIKI_LINKSONLY)==0 ){
    blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
  }else if( zTarget[0]=='#' ){
    blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
  }else if( is_valid_hname(zTarget) ){
    int isClosed = 0;
    if( strlen(zTarget)<=HNAME_MAX && is_ticket(zTarget, &isClosed) ){
      /* Special display processing for tickets.  Display the hyperlink
      ** as crossed out if the ticket is closed.
      */
      if( isClosed ){
        if( g.perm.Hyperlink ){
          blob_appendf(p->pOut,
             "%z<span class=\"wikiTagCancelled\">[",
................................................................................
    }else{
      n = nextWikiToken(z, &renderer, &tokenType);
    }
    switch( tokenType ){
      case TOKEN_LINK: {
        char *zTarget;
        int i, c;
        char zLink[HNAME_MAX+4];

        zTarget = &z[1];
        for(i=0; zTarget[i] && zTarget[i]!='|' && zTarget[i]!=']'; i++){}
        while(i>1 && zTarget[i-1]==' '){ i--; }
        c = zTarget[i];
        zTarget[i] = 0;
        if( is_valid_hname(zTarget) ){

Changes to src/zip.c.

930
931
932
933
934
935
936

937
938
939
940
941
942
943
  /* Compute a unique key for the cache entry based on query parameters */
  blob_init(&cacheKey, 0, 0);
  blob_appendf(&cacheKey, "/%s/%z", g.zPath, rid_to_uuid(rid));
  blob_appendf(&cacheKey, "/%q", zName);
  if( zInclude ) blob_appendf(&cacheKey, ",in=%Q", zInclude);
  if( zExclude ) blob_appendf(&cacheKey, ",ex=%Q", zExclude);
  zKey = blob_str(&cacheKey);


  if( P("debug")!=0 ){
    style_header("%s Archive Generator Debug Screen", zType);
    @ zName = "%h(zName)"<br />
    @ rid = %d(rid)<br />
    if( zInclude ){
      @ zInclude = "%h(zInclude)"<br />







>







930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
  /* Compute a unique key for the cache entry based on query parameters */
  blob_init(&cacheKey, 0, 0);
  blob_appendf(&cacheKey, "/%s/%z", g.zPath, rid_to_uuid(rid));
  blob_appendf(&cacheKey, "/%q", zName);
  if( zInclude ) blob_appendf(&cacheKey, ",in=%Q", zInclude);
  if( zExclude ) blob_appendf(&cacheKey, ",ex=%Q", zExclude);
  zKey = blob_str(&cacheKey);
  etag_check(ETAG_HASH, zKey);

  if( P("debug")!=0 ){
    style_header("%s Archive Generator Debug Screen", zType);
    @ zName = "%h(zName)"<br />
    @ rid = %d(rid)<br />
    if( zInclude ){
      @ zInclude = "%h(zInclude)"<br />

Changes to win/Makefile.dmc.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
..
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
306
307
308
309
310
311
312






313
314
315
316
317
318
319
...
890
891
892
893
894
895
896
897
898
TCC    = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
LIBS   = $(DMDIR)\extra\lib\ zlib wsock32 advapi32

SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_USE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB

SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen

SRC   = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c hname_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c

OBJ   = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O


RC=$(DMDIR)\bin\rcc
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__

APPNAME = $(OBJDIR)\fossil$(E)

................................................................................
	codecheck1$E $(SRC)
	$(DMDIR)\bin\link @link

$(OBJDIR)\fossil.res:	$B\win\fossil.rc
	$(RC) $(RCFLAGS) -o$@ $**

$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
	+echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content cookies db delta deltacmd descendants diff diffcmd dispatch doc encode event export file finfo foci fshell fusefs glob graph gzip hname http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path piechart pivot popen pqueue printf publish purge rebuild regexp report rss schema search security_audit setup sha1 sha1hard sha3 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
	+echo fossil >> $@
	+echo fossil >> $@
	+echo $(LIBS) >> $@
	+echo. >> $@
	+echo fossil >> $@

translate$E: $(SRCDIR)\translate.c
................................................................................
	+translate$E $** > $@

$(OBJDIR)\encode$O : encode_.c encode.h
	$(TCC) -o$@ -c encode_.c

encode_.c : $(SRCDIR)\encode.c
	+translate$E $** > $@







$(OBJDIR)\event$O : event_.c event.h
	$(TCC) -o$@ -c event_.c

event_.c : $(SRCDIR)\event.c
	+translate$E $** > $@

................................................................................
$(OBJDIR)\zip$O : zip_.c zip.h
	$(TCC) -o$@ -c zip_.c

zip_.c : $(SRCDIR)\zip.c
	+translate$E $** > $@

headers: makeheaders$E page_index.h builtin_data.h default_css.h VERSION.h
	 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fshell_.c:fshell.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h piechart_.c:piechart.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
	@copy /Y nul: headers







|

|







 







|







 







>
>
>
>
>
>







 







|

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
..
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
...
896
897
898
899
900
901
902
903
904
TCC    = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
LIBS   = $(DMDIR)\extra\lib\ zlib wsock32 advapi32

SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_OMIT_DECLTYPE -DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_GET_TABLE -DSQLITE_OMIT_PROGRESS_CALLBACK -DSQLITE_OMIT_SHARED_CACHE -DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_USE_ALLOCA -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_USE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB

SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen

SRC   = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c cookies_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c file_.c finfo_.c foci_.c fshell_.c fusefs_.c glob_.c graph_.c gzip_.c hname_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c piechart_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c unversioned_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c

OBJ   = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\cookies$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\dispatch$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\etag$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fshell$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\hname$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\piechart$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\unversioned$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O


RC=$(DMDIR)\bin\rcc
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__

APPNAME = $(OBJDIR)\fossil$(E)

................................................................................
	codecheck1$E $(SRC)
	$(DMDIR)\bin\link @link

$(OBJDIR)\fossil.res:	$B\win\fossil.rc
	$(RC) $(RCFLAGS) -o$@ $**

$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
	+echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content cookies db delta deltacmd descendants diff diffcmd dispatch doc encode etag event export file finfo foci fshell fusefs glob graph gzip hname http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path piechart pivot popen pqueue printf publish purge rebuild regexp report rss schema search security_audit setup sha1 sha1hard sha3 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
	+echo fossil >> $@
	+echo fossil >> $@
	+echo $(LIBS) >> $@
	+echo. >> $@
	+echo fossil >> $@

translate$E: $(SRCDIR)\translate.c
................................................................................
	+translate$E $** > $@

$(OBJDIR)\encode$O : encode_.c encode.h
	$(TCC) -o$@ -c encode_.c

encode_.c : $(SRCDIR)\encode.c
	+translate$E $** > $@

$(OBJDIR)\etag$O : etag_.c etag.h
	$(TCC) -o$@ -c etag_.c

etag_.c : $(SRCDIR)\etag.c
	+translate$E $** > $@

$(OBJDIR)\event$O : event_.c event.h
	$(TCC) -o$@ -c event_.c

event_.c : $(SRCDIR)\event.c
	+translate$E $** > $@

................................................................................
$(OBJDIR)\zip$O : zip_.c zip.h
	$(TCC) -o$@ -c zip_.c

zip_.c : $(SRCDIR)\zip.c
	+translate$E $** > $@

headers: makeheaders$E page_index.h builtin_data.h default_css.h VERSION.h
	 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h cookies_.c:cookies.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h dispatch_.c:dispatch.h doc_.c:doc.h encode_.c:encode.h etag_.c:etag.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fshell_.c:fshell.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h hname_.c:hname.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h piechart_.c:piechart.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h security_audit_.c:security_audit.h setup_.c:setup.h sha1_.c:sha1.h sha1hard_.c:sha1hard.h sha3_.c:sha3.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h unversioned_.c:unversioned.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
	@copy /Y nul: headers

Changes to win/Makefile.mingw.

450
451
452
453
454
455
456

457
458
459
460
461
462
463
...
650
651
652
653
654
655
656

657
658
659
660
661
662
663
...
779
780
781
782
783
784
785

786
787
788
789
790
791
792
....
1127
1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139
1140
....
1472
1473
1474
1475
1476
1477
1478








1479
1480
1481
1482
1483
1484
1485
  $(SRCDIR)/deltacmd.c \
  $(SRCDIR)/descendants.c \
  $(SRCDIR)/diff.c \
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/dispatch.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \

  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/file.c \
  $(SRCDIR)/finfo.c \
  $(SRCDIR)/foci.c \
  $(SRCDIR)/fshell.c \
  $(SRCDIR)/fusefs.c \
................................................................................
  $(OBJDIR)/deltacmd_.c \
  $(OBJDIR)/descendants_.c \
  $(OBJDIR)/diff_.c \
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/dispatch_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \

  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/file_.c \
  $(OBJDIR)/finfo_.c \
  $(OBJDIR)/foci_.c \
  $(OBJDIR)/fshell_.c \
  $(OBJDIR)/fusefs_.c \
................................................................................
 $(OBJDIR)/deltacmd.o \
 $(OBJDIR)/descendants.o \
 $(OBJDIR)/diff.o \
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/dispatch.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \

 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/file.o \
 $(OBJDIR)/finfo.o \
 $(OBJDIR)/foci.o \
 $(OBJDIR)/fshell.o \
 $(OBJDIR)/fusefs.o \
................................................................................
		$(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h \
		$(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h \
		$(OBJDIR)/diff_.c:$(OBJDIR)/diff.h \
		$(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h \
		$(OBJDIR)/dispatch_.c:$(OBJDIR)/dispatch.h \
		$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
		$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \

		$(OBJDIR)/event_.c:$(OBJDIR)/event.h \
		$(OBJDIR)/export_.c:$(OBJDIR)/export.h \
		$(OBJDIR)/file_.c:$(OBJDIR)/file.h \
		$(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
		$(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
		$(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
		$(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
................................................................................
$(OBJDIR)/encode_.c:	$(SRCDIR)/encode.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/encode.c >$@

$(OBJDIR)/encode.o:	$(OBJDIR)/encode_.c $(OBJDIR)/encode.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/encode.o -c $(OBJDIR)/encode_.c

$(OBJDIR)/encode.h:	$(OBJDIR)/headers









$(OBJDIR)/event_.c:	$(SRCDIR)/event.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/event.c >$@

$(OBJDIR)/event.o:	$(OBJDIR)/event_.c $(OBJDIR)/event.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/event.o -c $(OBJDIR)/event_.c








>







 







>







 







>







 







>







 







>
>
>
>
>
>
>
>







450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
...
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
...
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
....
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
....
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
  $(SRCDIR)/deltacmd.c \
  $(SRCDIR)/descendants.c \
  $(SRCDIR)/diff.c \
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/dispatch.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/etag.c \
  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/file.c \
  $(SRCDIR)/finfo.c \
  $(SRCDIR)/foci.c \
  $(SRCDIR)/fshell.c \
  $(SRCDIR)/fusefs.c \
................................................................................
  $(OBJDIR)/deltacmd_.c \
  $(OBJDIR)/descendants_.c \
  $(OBJDIR)/diff_.c \
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/dispatch_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/etag_.c \
  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/file_.c \
  $(OBJDIR)/finfo_.c \
  $(OBJDIR)/foci_.c \
  $(OBJDIR)/fshell_.c \
  $(OBJDIR)/fusefs_.c \
................................................................................
 $(OBJDIR)/deltacmd.o \
 $(OBJDIR)/descendants.o \
 $(OBJDIR)/diff.o \
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/dispatch.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/etag.o \
 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/file.o \
 $(OBJDIR)/finfo.o \
 $(OBJDIR)/foci.o \
 $(OBJDIR)/fshell.o \
 $(OBJDIR)/fusefs.o \
................................................................................
		$(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h \
		$(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h \
		$(OBJDIR)/diff_.c:$(OBJDIR)/diff.h \
		$(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h \
		$(OBJDIR)/dispatch_.c:$(OBJDIR)/dispatch.h \
		$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
		$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
		$(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
		$(OBJDIR)/event_.c:$(OBJDIR)/event.h \
		$(OBJDIR)/export_.c:$(OBJDIR)/export.h \
		$(OBJDIR)/file_.c:$(OBJDIR)/file.h \
		$(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
		$(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
		$(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
		$(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
................................................................................
$(OBJDIR)/encode_.c:	$(SRCDIR)/encode.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/encode.c >$@

$(OBJDIR)/encode.o:	$(OBJDIR)/encode_.c $(OBJDIR)/encode.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/encode.o -c $(OBJDIR)/encode_.c

$(OBJDIR)/encode.h:	$(OBJDIR)/headers

$(OBJDIR)/etag_.c:	$(SRCDIR)/etag.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/etag.c >$@

$(OBJDIR)/etag.o:	$(OBJDIR)/etag_.c $(OBJDIR)/etag.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/etag.o -c $(OBJDIR)/etag_.c

$(OBJDIR)/etag.h:	$(OBJDIR)/headers

$(OBJDIR)/event_.c:	$(SRCDIR)/event.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/event.c >$@

$(OBJDIR)/event.o:	$(OBJDIR)/event_.c $(OBJDIR)/event.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/event.o -c $(OBJDIR)/event_.c

Changes to win/Makefile.mingw.mistachkin.

450
451
452
453
454
455
456

457
458
459
460
461
462
463
...
550
551
552
553
554
555
556




557
558
559
560
561
562
563
...
646
647
648
649
650
651
652

653
654
655
656
657
658
659
...
775
776
777
778
779
780
781

782
783
784
785
786
787
788
....
1123
1124
1125
1126
1127
1128
1129

1130
1131
1132
1133
1134
1135
1136
....
1468
1469
1470
1471
1472
1473
1474








1475
1476
1477
1478
1479
1480
1481
....
2269
2270
2271
2272
2273
2274
2275



2276
2277
2278
2279
2280
2281
2282
  $(SRCDIR)/deltacmd.c \
  $(SRCDIR)/descendants.c \
  $(SRCDIR)/diff.c \
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/dispatch.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \

  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/file.c \
  $(SRCDIR)/finfo.c \
  $(SRCDIR)/foci.c \
  $(SRCDIR)/fshell.c \
  $(SRCDIR)/fusefs.c \
................................................................................
  $(SRCDIR)/wysiwyg.c \
  $(SRCDIR)/xfer.c \
  $(SRCDIR)/xfersetup.c \
  $(SRCDIR)/zip.c

EXTRA_FILES = \
  $(SRCDIR)/../skins/aht/details.txt \




  $(SRCDIR)/../skins/black_and_white/css.txt \
  $(SRCDIR)/../skins/black_and_white/details.txt \
  $(SRCDIR)/../skins/black_and_white/footer.txt \
  $(SRCDIR)/../skins/black_and_white/header.txt \
  $(SRCDIR)/../skins/blitz/css.txt \
  $(SRCDIR)/../skins/blitz/details.txt \
  $(SRCDIR)/../skins/blitz/footer.txt \
................................................................................
  $(OBJDIR)/deltacmd_.c \
  $(OBJDIR)/descendants_.c \
  $(OBJDIR)/diff_.c \
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/dispatch_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \

  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/file_.c \
  $(OBJDIR)/finfo_.c \
  $(OBJDIR)/foci_.c \
  $(OBJDIR)/fshell_.c \
  $(OBJDIR)/fusefs_.c \
................................................................................
 $(OBJDIR)/deltacmd.o \
 $(OBJDIR)/descendants.o \
 $(OBJDIR)/diff.o \
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/dispatch.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \

 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/file.o \
 $(OBJDIR)/finfo.o \
 $(OBJDIR)/foci.o \
 $(OBJDIR)/fshell.o \
 $(OBJDIR)/fusefs.o \
................................................................................
		$(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h \
		$(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h \
		$(OBJDIR)/diff_.c:$(OBJDIR)/diff.h \
		$(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h \
		$(OBJDIR)/dispatch_.c:$(OBJDIR)/dispatch.h \
		$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
		$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \

		$(OBJDIR)/event_.c:$(OBJDIR)/event.h \
		$(OBJDIR)/export_.c:$(OBJDIR)/export.h \
		$(OBJDIR)/file_.c:$(OBJDIR)/file.h \
		$(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
		$(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
		$(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
		$(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
................................................................................
$(OBJDIR)/encode_.c:	$(SRCDIR)/encode.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/encode.c >$@

$(OBJDIR)/encode.o:	$(OBJDIR)/encode_.c $(OBJDIR)/encode.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/encode.o -c $(OBJDIR)/encode_.c

$(OBJDIR)/encode.h:	$(OBJDIR)/headers









$(OBJDIR)/event_.c:	$(SRCDIR)/event.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/event.c >$@

$(OBJDIR)/event.o:	$(OBJDIR)/event_.c $(OBJDIR)/event.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/event.o -c $(OBJDIR)/event_.c

................................................................................
                 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
                 -DSQLITE_ENABLE_FTS4 \
                 -DSQLITE_ENABLE_FTS3_PARENTHESIS \
                 -DSQLITE_ENABLE_DBSTAT_VTAB \
                 -DSQLITE_ENABLE_JSON1 \
                 -DSQLITE_ENABLE_FTS5 \
                 -DSQLITE_ENABLE_STMTVTAB \



                 -DSQLITE_WIN32_NO_ANSI \
                 $(MINGW_OPTIONS) \
                 -DSQLITE_USE_MALLOC_H \
                 -DSQLITE_USE_MSIZE

SHELL_OPTIONS = -Dmain=sqlite3_shell \
                -DSQLITE_SHELL_IS_UTF8=1 \







>







 







>
>
>
>







 







>







 







>







 







>







 







>
>
>
>
>
>
>
>







 







>
>
>







450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
...
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
...
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
...
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
....
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
....
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
....
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
  $(SRCDIR)/deltacmd.c \
  $(SRCDIR)/descendants.c \
  $(SRCDIR)/diff.c \
  $(SRCDIR)/diffcmd.c \
  $(SRCDIR)/dispatch.c \
  $(SRCDIR)/doc.c \
  $(SRCDIR)/encode.c \
  $(SRCDIR)/etag.c \
  $(SRCDIR)/event.c \
  $(SRCDIR)/export.c \
  $(SRCDIR)/file.c \
  $(SRCDIR)/finfo.c \
  $(SRCDIR)/foci.c \
  $(SRCDIR)/fshell.c \
  $(SRCDIR)/fusefs.c \
................................................................................
  $(SRCDIR)/wysiwyg.c \
  $(SRCDIR)/xfer.c \
  $(SRCDIR)/xfersetup.c \
  $(SRCDIR)/zip.c

EXTRA_FILES = \
  $(SRCDIR)/../skins/aht/details.txt \
  $(SRCDIR)/../skins/ardoise/css.txt \
  $(SRCDIR)/../skins/ardoise/details.txt \
  $(SRCDIR)/../skins/ardoise/footer.txt \
  $(SRCDIR)/../skins/ardoise/header.txt \
  $(SRCDIR)/../skins/black_and_white/css.txt \
  $(SRCDIR)/../skins/black_and_white/details.txt \
  $(SRCDIR)/../skins/black_and_white/footer.txt \
  $(SRCDIR)/../skins/black_and_white/header.txt \
  $(SRCDIR)/../skins/blitz/css.txt \
  $(SRCDIR)/../skins/blitz/details.txt \
  $(SRCDIR)/../skins/blitz/footer.txt \
................................................................................
  $(OBJDIR)/deltacmd_.c \
  $(OBJDIR)/descendants_.c \
  $(OBJDIR)/diff_.c \
  $(OBJDIR)/diffcmd_.c \
  $(OBJDIR)/dispatch_.c \
  $(OBJDIR)/doc_.c \
  $(OBJDIR)/encode_.c \
  $(OBJDIR)/etag_.c \
  $(OBJDIR)/event_.c \
  $(OBJDIR)/export_.c \
  $(OBJDIR)/file_.c \
  $(OBJDIR)/finfo_.c \
  $(OBJDIR)/foci_.c \
  $(OBJDIR)/fshell_.c \
  $(OBJDIR)/fusefs_.c \
................................................................................
 $(OBJDIR)/deltacmd.o \
 $(OBJDIR)/descendants.o \
 $(OBJDIR)/diff.o \
 $(OBJDIR)/diffcmd.o \
 $(OBJDIR)/dispatch.o \
 $(OBJDIR)/doc.o \
 $(OBJDIR)/encode.o \
 $(OBJDIR)/etag.o \
 $(OBJDIR)/event.o \
 $(OBJDIR)/export.o \
 $(OBJDIR)/file.o \
 $(OBJDIR)/finfo.o \
 $(OBJDIR)/foci.o \
 $(OBJDIR)/fshell.o \
 $(OBJDIR)/fusefs.o \
................................................................................
		$(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h \
		$(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h \
		$(OBJDIR)/diff_.c:$(OBJDIR)/diff.h \
		$(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h \
		$(OBJDIR)/dispatch_.c:$(OBJDIR)/dispatch.h \
		$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
		$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
		$(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
		$(OBJDIR)/event_.c:$(OBJDIR)/event.h \
		$(OBJDIR)/export_.c:$(OBJDIR)/export.h \
		$(OBJDIR)/file_.c:$(OBJDIR)/file.h \
		$(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
		$(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
		$(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
		$(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \
................................................................................
$(OBJDIR)/encode_.c:	$(SRCDIR)/encode.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/encode.c >$@

$(OBJDIR)/encode.o:	$(OBJDIR)/encode_.c $(OBJDIR)/encode.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/encode.o -c $(OBJDIR)/encode_.c

$(OBJDIR)/encode.h:	$(OBJDIR)/headers

$(OBJDIR)/etag_.c:	$(SRCDIR)/etag.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/etag.c >$@

$(OBJDIR)/etag.o:	$(OBJDIR)/etag_.c $(OBJDIR)/etag.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/etag.o -c $(OBJDIR)/etag_.c

$(OBJDIR)/etag.h:	$(OBJDIR)/headers

$(OBJDIR)/event_.c:	$(SRCDIR)/event.c $(TRANSLATE)
	$(TRANSLATE) $(SRCDIR)/event.c >$@

$(OBJDIR)/event.o:	$(OBJDIR)/event_.c $(OBJDIR)/event.h $(SRCDIR)/config.h
	$(XTCC) -o $(OBJDIR)/event.o -c $(OBJDIR)/event_.c

................................................................................
                 -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
                 -DSQLITE_ENABLE_FTS4 \
                 -DSQLITE_ENABLE_FTS3_PARENTHESIS \
                 -DSQLITE_ENABLE_DBSTAT_VTAB \
                 -DSQLITE_ENABLE_JSON1 \
                 -DSQLITE_ENABLE_FTS5 \
                 -DSQLITE_ENABLE_STMTVTAB \
                 -DSQLITE_USE_ZLIB \
                 -DSQLITE_INTROSPECTION_PRAGMAS \
                 -DSQLITE_ENABLE_DBPAGE_VTAB \
                 -DSQLITE_WIN32_NO_ANSI \
                 $(MINGW_OPTIONS) \
                 -DSQLITE_USE_MALLOC_H \
                 -DSQLITE_USE_MSIZE

SHELL_OPTIONS = -Dmain=sqlite3_shell \
                -DSQLITE_SHELL_IS_UTF8=1 \

Changes to win/Makefile.msc.

380
381
382
383
384
385
386

387
388
389
390
391
392
393
...
579
580
581
582
583
584
585

586
587
588
589
590
591
592
...
767
768
769
770
771
772
773

774
775
776
777
778
779
780
....
1166
1167
1168
1169
1170
1171
1172






1173
1174
1175
1176
1177
1178
1179
....
1783
1784
1785
1786
1787
1788
1789

1790
1791
1792
1793
1794
1795
1796
        deltacmd_.c \
        descendants_.c \
        diff_.c \
        diffcmd_.c \
        dispatch_.c \
        doc_.c \
        encode_.c \

        event_.c \
        export_.c \
        file_.c \
        finfo_.c \
        foci_.c \
        fshell_.c \
        fusefs_.c \
................................................................................
        $(OX)\deltacmd$O \
        $(OX)\descendants$O \
        $(OX)\diff$O \
        $(OX)\diffcmd$O \
        $(OX)\dispatch$O \
        $(OX)\doc$O \
        $(OX)\encode$O \

        $(OX)\event$O \
        $(OX)\export$O \
        $(OX)\file$O \
        $(OX)\finfo$O \
        $(OX)\foci$O \
        $(OX)\fshell$O \
        $(OX)\fusefs$O \
................................................................................
	echo $(OX)\deltacmd.obj >> $@
	echo $(OX)\descendants.obj >> $@
	echo $(OX)\diff.obj >> $@
	echo $(OX)\diffcmd.obj >> $@
	echo $(OX)\dispatch.obj >> $@
	echo $(OX)\doc.obj >> $@
	echo $(OX)\encode.obj >> $@

	echo $(OX)\event.obj >> $@
	echo $(OX)\export.obj >> $@
	echo $(OX)\file.obj >> $@
	echo $(OX)\finfo.obj >> $@
	echo $(OX)\foci.obj >> $@
	echo $(OX)\fshell.obj >> $@
	echo $(OX)\fusefs.obj >> $@
................................................................................
	translate$E $** > $@

$(OX)\encode$O : encode_.c encode.h
	$(TCC) /Fo$@ -c encode_.c

encode_.c : $(SRCDIR)\encode.c
	translate$E $** > $@







$(OX)\event$O : event_.c event.h
	$(TCC) /Fo$@ -c event_.c

event_.c : $(SRCDIR)\event.c
	translate$E $** > $@

................................................................................
			deltacmd_.c:deltacmd.h \
			descendants_.c:descendants.h \
			diff_.c:diff.h \
			diffcmd_.c:diffcmd.h \
			dispatch_.c:dispatch.h \
			doc_.c:doc.h \
			encode_.c:encode.h \

			event_.c:event.h \
			export_.c:export.h \
			file_.c:file.h \
			finfo_.c:finfo.h \
			foci_.c:foci.h \
			fshell_.c:fshell.h \
			fusefs_.c:fusefs.h \







>







 







>







 







>







 







>
>
>
>
>
>







 







>







380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
...
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
...
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
....
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
....
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
        deltacmd_.c \
        descendants_.c \
        diff_.c \
        diffcmd_.c \
        dispatch_.c \
        doc_.c \
        encode_.c \
        etag_.c \
        event_.c \
        export_.c \
        file_.c \
        finfo_.c \
        foci_.c \
        fshell_.c \
        fusefs_.c \
................................................................................
        $(OX)\deltacmd$O \
        $(OX)\descendants$O \
        $(OX)\diff$O \
        $(OX)\diffcmd$O \
        $(OX)\dispatch$O \
        $(OX)\doc$O \
        $(OX)\encode$O \
        $(OX)\etag$O \
        $(OX)\event$O \
        $(OX)\export$O \
        $(OX)\file$O \
        $(OX)\finfo$O \
        $(OX)\foci$O \
        $(OX)\fshell$O \
        $(OX)\fusefs$O \
................................................................................
	echo $(OX)\deltacmd.obj >> $@
	echo $(OX)\descendants.obj >> $@
	echo $(OX)\diff.obj >> $@
	echo $(OX)\diffcmd.obj >> $@
	echo $(OX)\dispatch.obj >> $@
	echo $(OX)\doc.obj >> $@
	echo $(OX)\encode.obj >> $@
	echo $(OX)\etag.obj >> $@
	echo $(OX)\event.obj >> $@
	echo $(OX)\export.obj >> $@
	echo $(OX)\file.obj >> $@
	echo $(OX)\finfo.obj >> $@
	echo $(OX)\foci.obj >> $@
	echo $(OX)\fshell.obj >> $@
	echo $(OX)\fusefs.obj >> $@
................................................................................
	translate$E $** > $@

$(OX)\encode$O : encode_.c encode.h
	$(TCC) /Fo$@ -c encode_.c

encode_.c : $(SRCDIR)\encode.c
	translate$E $** > $@

$(OX)\etag$O : etag_.c etag.h
	$(TCC) /Fo$@ -c etag_.c

etag_.c : $(SRCDIR)\etag.c
	translate$E $** > $@

$(OX)\event$O : event_.c event.h
	$(TCC) /Fo$@ -c event_.c

event_.c : $(SRCDIR)\event.c
	translate$E $** > $@

................................................................................
			deltacmd_.c:deltacmd.h \
			descendants_.c:descendants.h \
			diff_.c:diff.h \
			diffcmd_.c:diffcmd.h \
			dispatch_.c:dispatch.h \
			doc_.c:doc.h \
			encode_.c:encode.h \
			etag_.c:etag.h \
			event_.c:event.h \
			export_.c:export.h \
			file_.c:file.h \
			finfo_.c:finfo.h \
			foci_.c:foci.h \
			fshell_.c:fshell.h \
			fusefs_.c:fusefs.h \

Changes to www/changes.wiki.

1
2
3
4
5
6
















7
8
9
10


11
12







13
14
15
16
17
18
19
<title>Change Log</title>

<a name='v2_5'></a>
<h2>Changes for Version 2.5 (pending)</h2>

  *  Numerous enhancements to the look and feel of the web interface
















  *  Fossil now automatically generates the
     &lt;html&gt;&lt;head&gt;...&lt;/head&gt;&lt;body&gt;
     at the beginning of each web page if the configurable header
     lacks a &lt;body&gt; tag.


  *  Upgrade to the latest versions of SQLite and OpenSSL.
  *  Improved key bindings on the Tk diff screen generated by "fossil diff --tk".








<a name='v2_4'></a>
<h2>Changes for Version 2.4 (2017-11-03)</h2>

  *  New feature: URL Aliases.  URL Aliases allow an administrator
     to define their own URLs on the web interface that are rewritten to
     built-in URLs with specific parameters.  Create and configure URL Aliases



|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>
>

|
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<title>Change Log</title>

<a name='v2_5'></a>
<h2>Changes for Version 2.5 (2018-02-07)</h2>

  *  Numerous enhancements to the look and feel of the web interface.
     Especially:  Added separate "Modern", "Compact", "Verbose", and 
     "Columnar" view options on timelines.
  *  Common display settings (such as the "view" option and the number
     of rows in a timeline) are held in a cookie and thus persist
     across multiple pages.
  *  Rework the skin editing process so that changes are implemented
     on one of nine /draft pages, evaluated, then merged back to the
     default.
  *  Added the [https://fossil-scm.org/skins/ardoise/timeline|Ardoise]
     skin.
  *  Fix the "fossil server" command on Unix to be much more responsive
     to multiple simultaneous web requests.
  *  Use the IPv6 stack for the "fossil ui" and "fossil server"
     commands on Windows.
  *  Support for [https://sqlite.org/sqlar|SQL Archives] as a download
     option.
  *  Fossil now automatically generates the
     &lt;html&gt;&lt;head&gt;...&lt;/head&gt;&lt;body&gt;
     at the beginning of each web page if the configurable header
     lacks a &lt;body&gt; tag.
  *  Added the /artifact_stats page, currently accessible only by
     the administrator.
  *  Upgrade to the latest versions of SQLite and OpenSSL.
  *  Improved key bindings on the Tk diff screen generated by
     "fossil diff --tk".
  *  Begin factoring out in-line javascript into separately loaded
     script files.  This is a step along the
     road toward supporting a strict Content Security Policy.  More work
     is to be done.
  *  Initial infrastructure is in place to make use of the pledge()
     system call in OpenBSD.  More work is to be done.

<a name='v2_4'></a>
<h2>Changes for Version 2.4 (2017-11-03)</h2>

  *  New feature: URL Aliases.  URL Aliases allow an administrator
     to define their own URLs on the web interface that are rewritten to
     built-in URLs with specific parameters.  Create and configure URL Aliases

Changes to www/env-opts.md.

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

`--localtime`: Override the `timeline-utc` option to explicitly use
local time.

`--nocgi`: Prevent fossil from acting as a CGI by default even if the
`GATEWAY_INTERFACE` environment variable is set.

`--no-dir-symlinks`: Disables support for directory symlinks, thus
preventing them from being traversed into.

`--no-th-hook`: (Sets `g.fNoThHook`.) Override the `th1-hooks` setting
and prevent any TH1 hooks from being executed.

`--quiet`: (Sets `g.fQuiet`.) Cause fossil to suppress various messages and progress
indicators that would otherwise be printed.

`--sqltrace`: (Sets `g.SqlTrace`.) Implies `--sqlstats`. Trace certain







<
<
<







71
72
73
74
75
76
77



78
79
80
81
82
83
84

`--localtime`: Override the `timeline-utc` option to explicitly use
local time.

`--nocgi`: Prevent fossil from acting as a CGI by default even if the
`GATEWAY_INTERFACE` environment variable is set.




`--no-th-hook`: (Sets `g.fNoThHook`.) Override the `th1-hooks` setting
and prevent any TH1 hooks from being executed.

`--quiet`: (Sets `g.fQuiet`.) Cause fossil to suppress various messages and progress
indicators that would otherwise be printed.

`--sqltrace`: (Sets `g.SqlTrace`.) Implies `--sqlstats`. Trace certain

Changes to www/index.wiki.

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
      [./selfhost.wiki | self-hosting repositories],
      you get more than just source code - you get this entire website.

  3.  <b>Self-Contained</b> -
      Fossil is a single self-contained stand-alone executable.
      To install, simply download a
      [/uv/download.html | precompiled binary]
      for Linux, Mac, OpenBSD, or Windows and put it on your $PATH.
      [./build.wiki | Easy-to-compile source code] is also available.

  4.  <b>Simple Networking</b> -
      No custom protocols or TCP ports.
      Fossil uses ordinary HTTP (or HTTPS or SSH)
      for network communications, so it works fine from behind
      restrictive firewalls, including [./quickstart.wiki#proxy|proxies].







|







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
      [./selfhost.wiki | self-hosting repositories],
      you get more than just source code - you get this entire website.

  3.  <b>Self-Contained</b> -
      Fossil is a single self-contained stand-alone executable.
      To install, simply download a
      [/uv/download.html | precompiled binary]
      for Linux, Mac, or Windows and put it on your $PATH.
      [./build.wiki | Easy-to-compile source code] is also available.

  4.  <b>Simple Networking</b> -
      No custom protocols or TCP ports.
      Fossil uses ordinary HTTP (or HTTPS or SSH)
      for network communications, so it works fine from behind
      restrictive firewalls, including [./quickstart.wiki#proxy|proxies].

Deleted www/mkdownload.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/tclsh
#
# Run this script to build and install the "download.html" page of
# unversioned comment.
#
# Also generate the fossil_download_checksums.html page.
#
#
set out [open download.html w]
fconfigure $out -encoding utf-8 -translation lf
puts $out \
{<div class='fossil-doc' data-title='Download Page'>

<center><font size=4>}
puts $out \
"<b>To install Fossil &rarr;</b> download the stand-alone executable"
puts $out \
{and put it on your $PATH.
</font><p><small>
RPMs available
<a href="http://download.opensuse.org/repositories/home:/rmax:/fossil/">
here.</a>
Cryptographic checksums for download files are
<a href="http://www.hwaci.com/fossil_download_checksums.html">here</a>.
</small></p>
<table cellpadding="10">
}

# Find all unique timestamps.
#
set in [open {|fossil uv list} rb]
while {[gets $in line]>0} {
  set fn [lindex $line 5]
  set filesize($fn) [lindex $line 3]
  if {[regexp -- {-(\d\.\d+)\.(tar\.gz|zip)$} $fn all version]} {
    set filehash($fn) [lindex $line 1]
    set avers($version) 1
  }
}
close $in

set vdate(2.0) 2017-03-03
set vdate(1.37) 2017-01-15

# Do all versions from newest to oldest
#
foreach vers [lsort -decr -real [array names avers]] {
  #  set hr "../timeline?c=version-$vers;y=ci"
  set v2 v[string map {. _} $vers]
  set hr "../doc/trunk/www/changes.wiki#$v2"
  puts $out "<tr><td colspan=6 align=left><hr>"
  puts $out "<center><b><a href=\"$hr\">Version $vers</a>"
  if {[info exists vdate($vers)]} {
    set hr2 "../timeline?c=version-$vers&amp;y=ci"
    puts $out " (<a href='$hr2'>$vdate($vers)</a>)"
  }
  puts $out "</b></center>"
  puts $out "</td></tr>"
  puts $out "<tr>"

  foreach {prefix img desc} {
    fossil-linux linux.gif {Linux 3.x x64}
    fossil-macosx mac.gif {Mac 10.x x86}
    fossil-openbsd-x86 openbsd.gif {OpenBSD 5.x x86}
    fossil-w32 win32.gif {Windows}
    fossil-src src.gif {Source Tarball}
  } {
    set glob download/$prefix*-$vers*
    set filename [array names filesize $glob]
    if {[info exists filesize($filename)]} {
      set size [set filesize($filename)]
      set units bytes
      if {$size>1024*1024} {
        set size [format %.2f [expr {$size/(1024.0*1024.0)}]]
        set units MiB
      } elseif {$size>1024} {
        set size [format %.2f [expr {$size/(1024.0)}]]
        set units KiB
      }
      puts $out "<td align=center valign=bottom><a href=\"$filename\">"
      puts $out "<img src=\"build-icons/$img\" border=0><br>$desc</a><br>"
      puts $out "$size $units</td>"
    } else {
      puts $out "<td>&nbsp;</td>"
    }
  }
  puts $out "</tr>"
#
#  if {[info exists filesize(download/releasenotes-$vers.html)]} {
#    puts $out "<tr><td colspan=6 align=left>"
#    set rn [|open uv cat download/releasenotes-$vers.html]
#    fconfigure $rn -encoding utf-8
#    puts $out "[read $rn]"
#    close $rn
#    puts $out "</td></tr>"
#  }
}
puts $out "<tr><td colspan=5><hr></td></tr>"

puts $out {</table></center></div>}
close $out

# Generate the checksum page
#
set out [open fossil_download_checksums.html w]
fconfigure $out -encoding utf-8 -translation lf
puts $out {<html>
<title>Fossil Download Checksums</title>
<body>
<h1 align="center">Checksums For Fossil Downloads</h1>
<p>The following table shows the SHA1 checksums for the precompiled
binaries available on the
<a href="/uv/download.html">Fossil website</a>.</p>
<pre>}

foreach {line} [split [exec fossil sql "SELECT hash, name FROM unversioned\
                                     WHERE name GLOB '*.tar.gz' OR\
                                           name GLOB '*.zip'"] \n] {
  set x [split $line |]
  set hash [lindex $x 0]
  set nm [file tail [lindex $x 1]]
  puts $out "$hash   $nm"
}
puts $out {</pre></body></html>}
close $out
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


























































































































































































































































Changes to www/server.wiki.

315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
Fossil provides two capabilities to help avoid server overload problems
due to excessive requests to expensive pages:
<ol>
<li><p>An optional cache is available that remembers the 10 most recently
    requested /zip or /tarball pages and returns the precomputed answer
    if the same page is requested again.
<li><p>Page requests can be configured to fail with a
    [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.3 | "503 Server Overload"]
    HTTP error if an expensive request is received while the host load
    average is too high.
</ol>
Both of these load-control mechanisms are turned off by default, but they
are recommended for high-traffic sites.
<p>
The webpage cache is activated using the [/help?cmd=cache|fossil cache init]







|







315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
Fossil provides two capabilities to help avoid server overload problems
due to excessive requests to expensive pages:
<ol>
<li><p>An optional cache is available that remembers the 10 most recently
    requested /zip or /tarball pages and returns the precomputed answer
    if the same page is requested again.
<li><p>Page requests can be configured to fail with a
    [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4 | "503 Server Overload"]
    HTTP error if an expensive request is received while the host load
    average is too high.
</ol>
Both of these load-control mechanisms are turned off by default, but they
are recommended for high-traffic sites.
<p>
The webpage cache is activated using the [/help?cmd=cache|fossil cache init]