Fossil SCM

Merge in updates from trunk.

andybradford 2019-07-30 01:17 test-updates merge
Commit 7e7258b3ed91ea05aabcbe9abfb0c2f542c81175a29a91f1d53e14f29b55cfd0
+3 -1
--- src/alerts.c
+++ src/alerts.c
@@ -804,11 +804,13 @@
804804
}else{
805805
blob_init(&all, 0, 0);
806806
pOut = &all;
807807
}
808808
blob_append(pOut, blob_buffer(pHdr), blob_size(pHdr));
809
- if( zFromName ){
809
+ if( p->zFrom==0 || p->zFrom[0]==0 ){
810
+ return; /* email-self is not set. Error will be reported separately */
811
+ }else if( zFromName ){
810812
blob_appendf(pOut, "From: %s <%s@%s>\r\n",
811813
zFromName, alert_mailbox_name(zFromName), alert_hostname(p->zFrom));
812814
blob_appendf(pOut, "X-Fossil-From: <%s>\r\n", p->zFrom);
813815
}else{
814816
blob_appendf(pOut, "From: <%s>\r\n", p->zFrom);
815817
--- src/alerts.c
+++ src/alerts.c
@@ -804,11 +804,13 @@
804 }else{
805 blob_init(&all, 0, 0);
806 pOut = &all;
807 }
808 blob_append(pOut, blob_buffer(pHdr), blob_size(pHdr));
809 if( zFromName ){
 
 
810 blob_appendf(pOut, "From: %s <%s@%s>\r\n",
811 zFromName, alert_mailbox_name(zFromName), alert_hostname(p->zFrom));
812 blob_appendf(pOut, "X-Fossil-From: <%s>\r\n", p->zFrom);
813 }else{
814 blob_appendf(pOut, "From: <%s>\r\n", p->zFrom);
815
--- src/alerts.c
+++ src/alerts.c
@@ -804,11 +804,13 @@
804 }else{
805 blob_init(&all, 0, 0);
806 pOut = &all;
807 }
808 blob_append(pOut, blob_buffer(pHdr), blob_size(pHdr));
809 if( p->zFrom==0 || p->zFrom[0]==0 ){
810 return; /* email-self is not set. Error will be reported separately */
811 }else if( zFromName ){
812 blob_appendf(pOut, "From: %s <%s@%s>\r\n",
813 zFromName, alert_mailbox_name(zFromName), alert_hostname(p->zFrom));
814 blob_appendf(pOut, "X-Fossil-From: <%s>\r\n", p->zFrom);
815 }else{
816 blob_appendf(pOut, "From: <%s>\r\n", p->zFrom);
817
--- src/capabilities.c
+++ src/capabilities.c
@@ -100,10 +100,11 @@
100100
void capability_expand(CapabilityString *pIn){
101101
static char *zNobody = 0;
102102
static char *zAnon = 0;
103103
static char *zReader = 0;
104104
static char *zDev = 0;
105
+ static char *zAdmin = "bcdefghijklmnopqrtwxz234567AD";
105106
int doneV = 0;
106107
107108
if( pIn==0 ){
108109
fossil_free(zNobody); zNobody = 0;
109110
fossil_free(zAnon); zAnon = 0;
@@ -117,10 +118,13 @@
117118
zReader = db_text(0, "SELECT cap FROM user WHERE login='reader'");
118119
zDev = db_text(0, "SELECT cap FROM user WHERE login='developer'");
119120
}
120121
pIn = capability_add(pIn, zAnon);
121122
pIn = capability_add(pIn, zNobody);
123
+ if( pIn->x['a'] || pIn->x['s'] ){
124
+ pIn = capability_add(pIn, zAdmin);
125
+ }
122126
if( pIn->x['v'] ){
123127
pIn = capability_add(pIn, zDev);
124128
doneV = 1;
125129
}
126130
if( pIn->x['u'] ){
127131
--- src/capabilities.c
+++ src/capabilities.c
@@ -100,10 +100,11 @@
100 void capability_expand(CapabilityString *pIn){
101 static char *zNobody = 0;
102 static char *zAnon = 0;
103 static char *zReader = 0;
104 static char *zDev = 0;
 
105 int doneV = 0;
106
107 if( pIn==0 ){
108 fossil_free(zNobody); zNobody = 0;
109 fossil_free(zAnon); zAnon = 0;
@@ -117,10 +118,13 @@
117 zReader = db_text(0, "SELECT cap FROM user WHERE login='reader'");
118 zDev = db_text(0, "SELECT cap FROM user WHERE login='developer'");
119 }
120 pIn = capability_add(pIn, zAnon);
121 pIn = capability_add(pIn, zNobody);
 
 
 
122 if( pIn->x['v'] ){
123 pIn = capability_add(pIn, zDev);
124 doneV = 1;
125 }
126 if( pIn->x['u'] ){
127
--- src/capabilities.c
+++ src/capabilities.c
@@ -100,10 +100,11 @@
100 void capability_expand(CapabilityString *pIn){
101 static char *zNobody = 0;
102 static char *zAnon = 0;
103 static char *zReader = 0;
104 static char *zDev = 0;
105 static char *zAdmin = "bcdefghijklmnopqrtwxz234567AD";
106 int doneV = 0;
107
108 if( pIn==0 ){
109 fossil_free(zNobody); zNobody = 0;
110 fossil_free(zAnon); zAnon = 0;
@@ -117,10 +118,13 @@
118 zReader = db_text(0, "SELECT cap FROM user WHERE login='reader'");
119 zDev = db_text(0, "SELECT cap FROM user WHERE login='developer'");
120 }
121 pIn = capability_add(pIn, zAnon);
122 pIn = capability_add(pIn, zNobody);
123 if( pIn->x['a'] || pIn->x['s'] ){
124 pIn = capability_add(pIn, zAdmin);
125 }
126 if( pIn->x['v'] ){
127 pIn = capability_add(pIn, zDev);
128 doneV = 1;
129 }
130 if( pIn->x['u'] ){
131
+33 -21
--- src/cgi.c
+++ src/cgi.c
@@ -13,15 +13,20 @@
1313
** [email protected]
1414
** http://www.hwaci.com/drh/
1515
**
1616
*******************************************************************************
1717
**
18
-** This file contains C functions and procedures that provide useful
19
-** services to CGI programs. There are procedures for parsing and
20
-** dispensing QUERY_STRING parameters and cookies, the "mprintf()"
21
-** formatting function and its cousins, and routines to encode and
22
-** decode strings in HTML or HTTP.
18
+** This file contains C functions and procedures used by CGI programs
19
+** (Fossil launched as CGI) to interpret CGI environment variables,
20
+** gather the results, and send they reply back to the CGI server.
21
+** This file also contains routines for running a simple web-server
22
+** (the "fossil ui" or "fossil server" command) and launching subprocesses
23
+** to handle each inbound HTTP request using CGI.
24
+**
25
+** This file contains routines used by Fossil when it is acting as a
26
+** CGI client. For the code used by Fossil when it is acting as a
27
+** CGI server (for the /ext webpage) see the "extcgi.c" source file.
2328
*/
2429
#include "config.h"
2530
#ifdef _WIN32
2631
# if !defined(_WIN32_WINNT)
2732
# define _WIN32_WINNT 0x0501
@@ -981,28 +986,13 @@
981986
982987
len = atoi(PD("CONTENT_LENGTH", "0"));
983988
g.zContentType = zType = P("CONTENT_TYPE");
984989
blob_zero(&g.cgiIn);
985990
if( len>0 && zType ){
986
- if( fossil_strcmp(zType,"application/x-www-form-urlencoded")==0
987
- || strncmp(zType,"multipart/form-data",19)==0 ){
988
- z = fossil_malloc( len+1 );
989
- len = fread(z, 1, len, g.httpIn);
990
- z[len] = 0;
991
- cgi_trace(z);
992
- if( zType[0]=='a' ){
993
- add_param_list(z, '&');
994
- }else{
995
- process_multipart_form_data(z, len);
996
- }
997
- }else if( fossil_strcmp(zType, "application/x-fossil")==0 ){
991
+ if( fossil_strcmp(zType, "application/x-fossil")==0 ){
998992
blob_read_from_channel(&g.cgiIn, g.httpIn, len);
999993
blob_uncompress(&g.cgiIn, &g.cgiIn);
1000
- }else if( fossil_strcmp(zType, "application/x-fossil-debug")==0 ){
1001
- blob_read_from_channel(&g.cgiIn, g.httpIn, len);
1002
- }else if( fossil_strcmp(zType, "application/x-fossil-uncompressed")==0 ){
1003
- blob_read_from_channel(&g.cgiIn, g.httpIn, len);
1004994
}
1005995
#ifdef FOSSIL_ENABLE_JSON
1006996
else if( fossil_strcmp(zType, "application/json")
1007997
|| fossil_strcmp(zType,"text/plain")/*assume this MIGHT be JSON*/
1008998
|| fossil_strcmp(zType,"application/javascript")){
@@ -1024,12 +1014,34 @@
10241014
need to process QUERY_STRING _after_ reading the POST data.
10251015
*/
10261016
cgi_set_content_type(json_guess_content_type());
10271017
}
10281018
#endif /* FOSSIL_ENABLE_JSON */
1019
+ else{
1020
+ blob_read_from_channel(&g.cgiIn, g.httpIn, len);
1021
+ }
10291022
}
1023
+}
10301024
1025
+/*
1026
+** Decode POST parameter information in the cgiIn content, if any.
1027
+*/
1028
+void cgi_decode_post_parameters(void){
1029
+ int len = blob_size(&g.cgiIn);
1030
+ if( len==0 ) return;
1031
+ if( fossil_strcmp(g.zContentType,"application/x-www-form-urlencoded")==0
1032
+ || strncmp(g.zContentType,"multipart/form-data",19)==0
1033
+ ){
1034
+ char *z = blob_str(&g.cgiIn);
1035
+ cgi_trace(z);
1036
+ if( g.zContentType[0]=='a' ){
1037
+ add_param_list(z, '&');
1038
+ }else{
1039
+ process_multipart_form_data(z, len);
1040
+ }
1041
+ blob_init(&g.cgiIn, 0, 0);
1042
+ }
10311043
}
10321044
10331045
/*
10341046
** This is the comparison function used to sort the aParamQP[] array of
10351047
** query parameters and cookies.
10361048
--- src/cgi.c
+++ src/cgi.c
@@ -13,15 +13,20 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains C functions and procedures that provide useful
19 ** services to CGI programs. There are procedures for parsing and
20 ** dispensing QUERY_STRING parameters and cookies, the "mprintf()"
21 ** formatting function and its cousins, and routines to encode and
22 ** decode strings in HTML or HTTP.
 
 
 
 
 
23 */
24 #include "config.h"
25 #ifdef _WIN32
26 # if !defined(_WIN32_WINNT)
27 # define _WIN32_WINNT 0x0501
@@ -981,28 +986,13 @@
981
982 len = atoi(PD("CONTENT_LENGTH", "0"));
983 g.zContentType = zType = P("CONTENT_TYPE");
984 blob_zero(&g.cgiIn);
985 if( len>0 && zType ){
986 if( fossil_strcmp(zType,"application/x-www-form-urlencoded")==0
987 || strncmp(zType,"multipart/form-data",19)==0 ){
988 z = fossil_malloc( len+1 );
989 len = fread(z, 1, len, g.httpIn);
990 z[len] = 0;
991 cgi_trace(z);
992 if( zType[0]=='a' ){
993 add_param_list(z, '&');
994 }else{
995 process_multipart_form_data(z, len);
996 }
997 }else if( fossil_strcmp(zType, "application/x-fossil")==0 ){
998 blob_read_from_channel(&g.cgiIn, g.httpIn, len);
999 blob_uncompress(&g.cgiIn, &g.cgiIn);
1000 }else if( fossil_strcmp(zType, "application/x-fossil-debug")==0 ){
1001 blob_read_from_channel(&g.cgiIn, g.httpIn, len);
1002 }else if( fossil_strcmp(zType, "application/x-fossil-uncompressed")==0 ){
1003 blob_read_from_channel(&g.cgiIn, g.httpIn, len);
1004 }
1005 #ifdef FOSSIL_ENABLE_JSON
1006 else if( fossil_strcmp(zType, "application/json")
1007 || fossil_strcmp(zType,"text/plain")/*assume this MIGHT be JSON*/
1008 || fossil_strcmp(zType,"application/javascript")){
@@ -1024,12 +1014,34 @@
1024 need to process QUERY_STRING _after_ reading the POST data.
1025 */
1026 cgi_set_content_type(json_guess_content_type());
1027 }
1028 #endif /* FOSSIL_ENABLE_JSON */
 
 
 
1029 }
 
1030
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1031 }
1032
1033 /*
1034 ** This is the comparison function used to sort the aParamQP[] array of
1035 ** query parameters and cookies.
1036
--- src/cgi.c
+++ src/cgi.c
@@ -13,15 +13,20 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains C functions and procedures used by CGI programs
19 ** (Fossil launched as CGI) to interpret CGI environment variables,
20 ** gather the results, and send they reply back to the CGI server.
21 ** This file also contains routines for running a simple web-server
22 ** (the "fossil ui" or "fossil server" command) and launching subprocesses
23 ** to handle each inbound HTTP request using CGI.
24 **
25 ** This file contains routines used by Fossil when it is acting as a
26 ** CGI client. For the code used by Fossil when it is acting as a
27 ** CGI server (for the /ext webpage) see the "extcgi.c" source file.
28 */
29 #include "config.h"
30 #ifdef _WIN32
31 # if !defined(_WIN32_WINNT)
32 # define _WIN32_WINNT 0x0501
@@ -981,28 +986,13 @@
986
987 len = atoi(PD("CONTENT_LENGTH", "0"));
988 g.zContentType = zType = P("CONTENT_TYPE");
989 blob_zero(&g.cgiIn);
990 if( len>0 && zType ){
991 if( fossil_strcmp(zType, "application/x-fossil")==0 ){
 
 
 
 
 
 
 
 
 
 
 
992 blob_read_from_channel(&g.cgiIn, g.httpIn, len);
993 blob_uncompress(&g.cgiIn, &g.cgiIn);
 
 
 
 
994 }
995 #ifdef FOSSIL_ENABLE_JSON
996 else if( fossil_strcmp(zType, "application/json")
997 || fossil_strcmp(zType,"text/plain")/*assume this MIGHT be JSON*/
998 || fossil_strcmp(zType,"application/javascript")){
@@ -1024,12 +1014,34 @@
1014 need to process QUERY_STRING _after_ reading the POST data.
1015 */
1016 cgi_set_content_type(json_guess_content_type());
1017 }
1018 #endif /* FOSSIL_ENABLE_JSON */
1019 else{
1020 blob_read_from_channel(&g.cgiIn, g.httpIn, len);
1021 }
1022 }
1023 }
1024
1025 /*
1026 ** Decode POST parameter information in the cgiIn content, if any.
1027 */
1028 void cgi_decode_post_parameters(void){
1029 int len = blob_size(&g.cgiIn);
1030 if( len==0 ) return;
1031 if( fossil_strcmp(g.zContentType,"application/x-www-form-urlencoded")==0
1032 || strncmp(g.zContentType,"multipart/form-data",19)==0
1033 ){
1034 char *z = blob_str(&g.cgiIn);
1035 cgi_trace(z);
1036 if( g.zContentType[0]=='a' ){
1037 add_param_list(z, '&');
1038 }else{
1039 process_multipart_form_data(z, len);
1040 }
1041 blob_init(&g.cgiIn, 0, 0);
1042 }
1043 }
1044
1045 /*
1046 ** This is the comparison function used to sort the aParamQP[] array of
1047 ** query parameters and cookies.
1048
+21
--- src/db.c
+++ src/db.c
@@ -3422,10 +3422,31 @@
34223422
** SETTING: repo-cksum boolean default=on
34233423
** Compute checksums over all files in each checkout as a double-check
34243424
** of correctness. Disable this on large repositories for a performance
34253425
** improvement.
34263426
*/
3427
+/*
3428
+** SETTING: repolist-skin width=2 default=0
3429
+** If non-zero then use this repository as the skin for a repository list
3430
+** such as created by the one of:
3431
+**
3432
+** 1) fossil server DIRECTORY --repolist
3433
+** 2) fossil ui DIRECTORY --repolist
3434
+** 3) fossil http DIRECTORY --repolist
3435
+** 4) (The "repolist" option in a CGI script)
3436
+** 5) fossil all ui
3437
+** 6) fossil all server
3438
+**
3439
+** All repositories are searched (in lexicographical order) and the first
3440
+** repository with a non-zero "repolist-skin" value is used as the skin
3441
+** for the repository list page. If none of the repositories on the list
3442
+** have a non-zero "repolist-skin" setting then the repository list is
3443
+** displayed using unadorned HTML ("skinless").
3444
+**
3445
+** If repolist-skin has a value of 2, then the repository is omitted from
3446
+** the list in use cases 1 through 4, but not for 5 and 6.
3447
+*/
34273448
/*
34283449
** SETTING: self-register boolean default=off
34293450
** Allow users to register themselves through the HTTP UI.
34303451
** This is useful if you want to see other names than
34313452
** "Anonymous" in e.g. ticketing system. On the other hand
34323453
--- src/db.c
+++ src/db.c
@@ -3422,10 +3422,31 @@
3422 ** SETTING: repo-cksum boolean default=on
3423 ** Compute checksums over all files in each checkout as a double-check
3424 ** of correctness. Disable this on large repositories for a performance
3425 ** improvement.
3426 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3427 /*
3428 ** SETTING: self-register boolean default=off
3429 ** Allow users to register themselves through the HTTP UI.
3430 ** This is useful if you want to see other names than
3431 ** "Anonymous" in e.g. ticketing system. On the other hand
3432
--- src/db.c
+++ src/db.c
@@ -3422,10 +3422,31 @@
3422 ** SETTING: repo-cksum boolean default=on
3423 ** Compute checksums over all files in each checkout as a double-check
3424 ** of correctness. Disable this on large repositories for a performance
3425 ** improvement.
3426 */
3427 /*
3428 ** SETTING: repolist-skin width=2 default=0
3429 ** If non-zero then use this repository as the skin for a repository list
3430 ** such as created by the one of:
3431 **
3432 ** 1) fossil server DIRECTORY --repolist
3433 ** 2) fossil ui DIRECTORY --repolist
3434 ** 3) fossil http DIRECTORY --repolist
3435 ** 4) (The "repolist" option in a CGI script)
3436 ** 5) fossil all ui
3437 ** 6) fossil all server
3438 **
3439 ** All repositories are searched (in lexicographical order) and the first
3440 ** repository with a non-zero "repolist-skin" value is used as the skin
3441 ** for the repository list page. If none of the repositories on the list
3442 ** have a non-zero "repolist-skin" setting then the repository list is
3443 ** displayed using unadorned HTML ("skinless").
3444 **
3445 ** If repolist-skin has a value of 2, then the repository is omitted from
3446 ** the list in use cases 1 through 4, but not for 5 and 6.
3447 */
3448 /*
3449 ** SETTING: self-register boolean default=off
3450 ** Allow users to register themselves through the HTTP UI.
3451 ** This is useful if you want to see other names than
3452 ** "Anonymous" in e.g. ticketing system. On the other hand
3453
--- src/default_css.txt
+++ src/default_css.txt
@@ -777,11 +777,11 @@
777777
margin: -2px .24em 0 0;
778778
padding: 0;
779779
border: 0;
780780
vertical-align: middle;
781781
//Note: the mkcss utility does not support line breaks in data URIs.
782
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath style='fill: black; opacity:0' d='M 14 14 H 0 V 0 h 14 v 14 z'/%3E%3Cpath style='fill:rgb(240,240,240)' d='M 1 0 h 6.6 l 2 2 h 1 l 3.4 3.4 v 8.6 h -10 v -2 h -3 z'/%3E%3Cpath style='fill:rgb(64,64,64)' d='M 2 1 h 5 l 3 3 v 7 h -8 z'/%3E%3Cpath style='fill:rgb(248,248,248)' d='M 3 2 h 3.6 l 2.4 2.4 v 5.6 h -6 z'/%3E%3Cpath style='fill:rgb(80,128,208)' d='M 4 5 h 4 v 1 h -4 z m 0 2 h 4 v 1 h -4 z'/%3E%3Cpath style='fill:rgb(64,64,64)' d='M 5 3 h 5 l 3 3 v 7 h -8 z'/%3E%3Cpath style='fill:rgb(248,248,248)' d='M 10 4.4 v 1.6 h 1.6 z m -4 -0.6 h 3 v 3 h -3 z m 0 3 h 6 v 5.4 h -6 z'/%3E%3Cpath style='fill:rgb(80,128,208)' d='M 7 8 h 4 v 1 h -4 z m 0 2 h 4 v 1 h -4 z'/%3E%3C/svg%3E");
782
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0,0,14,14'%3E%3Cpath style='fill:black;opacity:0' d='M14,14H0V0h14v14z'/%3E%3Cpath style='fill:rgb(240,240,240)' d='M1,0h6.6l2,2h1l3.4,3.4v8.6h-10v-2h-3z'/%3E%3Cpath style='fill:rgb(64,64,64)' d='M2,1h5l3,3v7h-8z'/%3E%3Cpath style='fill:rgb(248,248,248)' d='M3,2h3.6l2.4,2.4v5.6h-6z'/%3E%3Cpath style='fill:rgb(80,128,208)' d='M4,5h4v1h-4zm0,2h4v1h-4z'/%3E%3Cpath style='fill:rgb(64,64,64)' d='M5,3h5l3,3v7h-8z'/%3E%3Cpath style='fill:rgb(248,248,248)' d='M10,4.4v1.6h1.6zm-4,-0.6h3v3h-3zm0,3h6v5.4h-6z'/%3E%3Cpath style='fill:rgb(80,128,208)' d='M7,8h4v1h-4zm0,2h4v1h-4z'/%3E%3C/svg%3E");
783783
background-repeat: no-repeat;
784784
background-position: center;
785785
cursor: pointer;
786786
}
787787
.copy-button-flipped {
788788
--- src/default_css.txt
+++ src/default_css.txt
@@ -777,11 +777,11 @@
777 margin: -2px .24em 0 0;
778 padding: 0;
779 border: 0;
780 vertical-align: middle;
781 //Note: the mkcss utility does not support line breaks in data URIs.
782 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath style='fill: black; opacity:0' d='M 14 14 H 0 V 0 h 14 v 14 z'/%3E%3Cpath style='fill:rgb(240,240,240)' d='M 1 0 h 6.6 l 2 2 h 1 l 3.4 3.4 v 8.6 h -10 v -2 h -3 z'/%3E%3Cpath style='fill:rgb(64,64,64)' d='M 2 1 h 5 l 3 3 v 7 h -8 z'/%3E%3Cpath style='fill:rgb(248,248,248)' d='M 3 2 h 3.6 l 2.4 2.4 v 5.6 h -6 z'/%3E%3Cpath style='fill:rgb(80,128,208)' d='M 4 5 h 4 v 1 h -4 z m 0 2 h 4 v 1 h -4 z'/%3E%3Cpath style='fill:rgb(64,64,64)' d='M 5 3 h 5 l 3 3 v 7 h -8 z'/%3E%3Cpath style='fill:rgb(248,248,248)' d='M 10 4.4 v 1.6 h 1.6 z m -4 -0.6 h 3 v 3 h -3 z m 0 3 h 6 v 5.4 h -6 z'/%3E%3Cpath style='fill:rgb(80,128,208)' d='M 7 8 h 4 v 1 h -4 z m 0 2 h 4 v 1 h -4 z'/%3E%3C/svg%3E");
783 background-repeat: no-repeat;
784 background-position: center;
785 cursor: pointer;
786 }
787 .copy-button-flipped {
788
--- src/default_css.txt
+++ src/default_css.txt
@@ -777,11 +777,11 @@
777 margin: -2px .24em 0 0;
778 padding: 0;
779 border: 0;
780 vertical-align: middle;
781 //Note: the mkcss utility does not support line breaks in data URIs.
782 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0,0,14,14'%3E%3Cpath style='fill:black;opacity:0' d='M14,14H0V0h14v14z'/%3E%3Cpath style='fill:rgb(240,240,240)' d='M1,0h6.6l2,2h1l3.4,3.4v8.6h-10v-2h-3z'/%3E%3Cpath style='fill:rgb(64,64,64)' d='M2,1h5l3,3v7h-8z'/%3E%3Cpath style='fill:rgb(248,248,248)' d='M3,2h3.6l2.4,2.4v5.6h-6z'/%3E%3Cpath style='fill:rgb(80,128,208)' d='M4,5h4v1h-4zm0,2h4v1h-4z'/%3E%3Cpath style='fill:rgb(64,64,64)' d='M5,3h5l3,3v7h-8z'/%3E%3Cpath style='fill:rgb(248,248,248)' d='M10,4.4v1.6h1.6zm-4,-0.6h3v3h-3zm0,3h6v5.4h-6z'/%3E%3Cpath style='fill:rgb(80,128,208)' d='M7,8h4v1h-4zm0,2h4v1h-4z'/%3E%3C/svg%3E");
783 background-repeat: no-repeat;
784 background-position: center;
785 cursor: pointer;
786 }
787 .copy-button-flipped {
788
--- src/dispatch.c
+++ src/dispatch.c
@@ -47,10 +47,11 @@
4747
#define CMDFLAG_COMMAND 0x0010 /* A command */
4848
#define CMDFLAG_SETTING 0x0020 /* A setting */
4949
#define CMDFLAG_VERSIONABLE 0x0040 /* A versionable setting */
5050
#define CMDFLAG_BLOCKTEXT 0x0080 /* Multi-line text setting */
5151
#define CMDFLAG_BOOLEAN 0x0100 /* A boolean setting */
52
+#define CMDFLAG_RAWCONTENT 0x0200 /* Do not interpret POST content */
5253
/**************************************************************************/
5354
5455
/* Values for the 2nd parameter to dispatch_name_search() */
5556
#define CMDFLAG_ANY 0x0038 /* Match anything */
5657
#define CMDFLAG_PREFIX 0x0200 /* Prefix match is ok */
5758
--- src/dispatch.c
+++ src/dispatch.c
@@ -47,10 +47,11 @@
47 #define CMDFLAG_COMMAND 0x0010 /* A command */
48 #define CMDFLAG_SETTING 0x0020 /* A setting */
49 #define CMDFLAG_VERSIONABLE 0x0040 /* A versionable setting */
50 #define CMDFLAG_BLOCKTEXT 0x0080 /* Multi-line text setting */
51 #define CMDFLAG_BOOLEAN 0x0100 /* A boolean setting */
 
52 /**************************************************************************/
53
54 /* Values for the 2nd parameter to dispatch_name_search() */
55 #define CMDFLAG_ANY 0x0038 /* Match anything */
56 #define CMDFLAG_PREFIX 0x0200 /* Prefix match is ok */
57
--- src/dispatch.c
+++ src/dispatch.c
@@ -47,10 +47,11 @@
47 #define CMDFLAG_COMMAND 0x0010 /* A command */
48 #define CMDFLAG_SETTING 0x0020 /* A setting */
49 #define CMDFLAG_VERSIONABLE 0x0040 /* A versionable setting */
50 #define CMDFLAG_BLOCKTEXT 0x0080 /* Multi-line text setting */
51 #define CMDFLAG_BOOLEAN 0x0100 /* A boolean setting */
52 #define CMDFLAG_RAWCONTENT 0x0200 /* Do not interpret POST content */
53 /**************************************************************************/
54
55 /* Values for the 2nd parameter to dispatch_name_search() */
56 #define CMDFLAG_ANY 0x0038 /* Match anything */
57 #define CMDFLAG_PREFIX 0x0200 /* Prefix match is ok */
58
+77 -60
--- src/doc.c
+++ src/doc.c
@@ -529,10 +529,85 @@
529529
base = i+5;
530530
}
531531
}
532532
blob_append(cgi_output_blob(), &z[base], i-base);
533533
}
534
+
535
+/*
536
+** Render a document as the reply to the HTTP request. The body
537
+** of the document is contained in pBody. The body might be binary.
538
+** The mimetype is in zMimetype.
539
+*/
540
+void document_render(
541
+ Blob *pBody, /* Document content */
542
+ const char *zMime, /* MIME-type */
543
+ const char *zDefaultTitle, /* Default title */
544
+ const char *zFilename /* Name of the file being rendered */
545
+){
546
+ Blob title;
547
+ blob_init(&title,0,0);
548
+ if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 ){
549
+ Blob tail;
550
+ style_adunit_config(ADUNIT_RIGHT_OK);
551
+ if( wiki_find_title(pBody, &title, &tail) ){
552
+ style_header("%s", blob_str(&title));
553
+ wiki_convert(&tail, 0, WIKI_BUTTONS);
554
+ }else{
555
+ style_header("%s", zDefaultTitle);
556
+ wiki_convert(pBody, 0, WIKI_BUTTONS);
557
+ }
558
+ style_footer();
559
+ }else if( fossil_strcmp(zMime, "text/x-markdown")==0 ){
560
+ Blob tail = BLOB_INITIALIZER;
561
+ markdown_to_html(pBody, &title, &tail);
562
+ if( blob_size(&title)>0 ){
563
+ style_header("%s", blob_str(&title));
564
+ }else{
565
+ style_header("%s", zDefaultTitle);
566
+ }
567
+ convert_href_and_output(&tail);
568
+ style_footer();
569
+ }else if( fossil_strcmp(zMime, "text/plain")==0 ){
570
+ style_header("%s", zDefaultTitle);
571
+ @ <blockquote><pre>
572
+ @ %h(blob_str(pBody))
573
+ @ </pre></blockquote>
574
+ style_footer();
575
+ }else if( fossil_strcmp(zMime, "text/html")==0
576
+ && doc_is_embedded_html(pBody, &title) ){
577
+ if( blob_size(&title)==0 ) blob_append(&title,zFilename,-1);
578
+ style_header("%s", blob_str(&title));
579
+ convert_href_and_output(pBody);
580
+ style_footer();
581
+#ifdef FOSSIL_ENABLE_TH1_DOCS
582
+ }else if( Th_AreDocsEnabled() &&
583
+ fossil_strcmp(zMime, "application/x-th1")==0 ){
584
+ int raw = P("raw")!=0;
585
+ if( !raw ){
586
+ Blob tail;
587
+ blob_zero(&tail);
588
+ if( wiki_find_title(pBody, &title, &tail) ){
589
+ style_header("%s", blob_str(&title));
590
+ Th_Render(blob_str(&tail));
591
+ blob_reset(&tail);
592
+ }else{
593
+ style_header("%h", zDefaultTitle);
594
+ Th_Render(blob_str(pBody));
595
+ }
596
+ }else{
597
+ Th_Render(blob_str(pBody));
598
+ }
599
+ if( !raw ){
600
+ style_footer();
601
+ }
602
+#endif
603
+ }else{
604
+ cgi_set_content_type(zMime);
605
+ cgi_set_content(pBody);
606
+ }
607
+}
608
+
534609
535610
/*
536611
** WEBPAGE: uv
537612
** WEBPAGE: doc
538613
** URL: /uv/FILE
@@ -618,10 +693,11 @@
618693
zCheckin = "tip";
619694
}
620695
}
621696
if( nMiss==count(azSuffix) ){
622697
zName = "404.md";
698
+ zDfltTitle = "Not Found";
623699
}else if( zName[i]==0 ){
624700
assert( nMiss>=0 && nMiss<count(azSuffix) );
625701
zName = azSuffix[nMiss];
626702
}else if( !isUV ){
627703
zName += i;
@@ -690,70 +766,11 @@
690766
Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'"
691767
" FROM blob WHERE rid=%d", vid));
692768
Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event"
693769
" WHERE objid=%d AND type='ci'", vid));
694770
}
695
- if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 ){
696
- Blob tail;
697
- style_adunit_config(ADUNIT_RIGHT_OK);
698
- if( wiki_find_title(&filebody, &title, &tail) ){
699
- style_header("%s", blob_str(&title));
700
- wiki_convert(&tail, 0, WIKI_BUTTONS);
701
- }else{
702
- style_header("%s", zDfltTitle);
703
- wiki_convert(&filebody, 0, WIKI_BUTTONS);
704
- }
705
- style_footer();
706
- }else if( fossil_strcmp(zMime, "text/x-markdown")==0 ){
707
- Blob tail = BLOB_INITIALIZER;
708
- markdown_to_html(&filebody, &title, &tail);
709
- if( blob_size(&title)>0 ){
710
- style_header("%s", blob_str(&title));
711
- }else{
712
- style_header("%s", nMiss>=count(azSuffix)?
713
- "Not Found" : zDfltTitle);
714
- }
715
- convert_href_and_output(&tail);
716
- style_footer();
717
- }else if( fossil_strcmp(zMime, "text/plain")==0 ){
718
- style_header("%s", zDfltTitle);
719
- @ <blockquote><pre>
720
- @ %h(blob_str(&filebody))
721
- @ </pre></blockquote>
722
- style_footer();
723
- }else if( fossil_strcmp(zMime, "text/html")==0
724
- && doc_is_embedded_html(&filebody, &title) ){
725
- if( blob_size(&title)==0 ) blob_append(&title,zName,-1);
726
- style_header("%s", blob_str(&title));
727
- convert_href_and_output(&filebody);
728
- style_footer();
729
-#ifdef FOSSIL_ENABLE_TH1_DOCS
730
- }else if( Th_AreDocsEnabled() &&
731
- fossil_strcmp(zMime, "application/x-th1")==0 ){
732
- int raw = P("raw")!=0;
733
- if( !raw ){
734
- Blob tail;
735
- blob_zero(&tail);
736
- if( wiki_find_title(&filebody, &title, &tail) ){
737
- style_header("%s", blob_str(&title));
738
- Th_Render(blob_str(&tail));
739
- blob_reset(&tail);
740
- }else{
741
- style_header("%h", zName);
742
- Th_Render(blob_str(&filebody));
743
- }
744
- }else{
745
- Th_Render(blob_str(&filebody));
746
- }
747
- if( !raw ){
748
- style_footer();
749
- }
750
-#endif
751
- }else{
752
- cgi_set_content_type(zMime);
753
- cgi_set_content(&filebody);
754
- }
771
+ document_render(&filebody, zMime, zDfltTitle, zName);
755772
if( nMiss>=count(azSuffix) ) cgi_set_status(404, "Not Found");
756773
db_end_transaction(0);
757774
return;
758775
759776
/* Jump here when unable to locate the document */
760777
761778
ADDED src/extcgi.c
--- src/doc.c
+++ src/doc.c
@@ -529,10 +529,85 @@
529 base = i+5;
530 }
531 }
532 blob_append(cgi_output_blob(), &z[base], i-base);
533 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
534
535 /*
536 ** WEBPAGE: uv
537 ** WEBPAGE: doc
538 ** URL: /uv/FILE
@@ -618,10 +693,11 @@
618 zCheckin = "tip";
619 }
620 }
621 if( nMiss==count(azSuffix) ){
622 zName = "404.md";
 
623 }else if( zName[i]==0 ){
624 assert( nMiss>=0 && nMiss<count(azSuffix) );
625 zName = azSuffix[nMiss];
626 }else if( !isUV ){
627 zName += i;
@@ -690,70 +766,11 @@
690 Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'"
691 " FROM blob WHERE rid=%d", vid));
692 Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event"
693 " WHERE objid=%d AND type='ci'", vid));
694 }
695 if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 ){
696 Blob tail;
697 style_adunit_config(ADUNIT_RIGHT_OK);
698 if( wiki_find_title(&filebody, &title, &tail) ){
699 style_header("%s", blob_str(&title));
700 wiki_convert(&tail, 0, WIKI_BUTTONS);
701 }else{
702 style_header("%s", zDfltTitle);
703 wiki_convert(&filebody, 0, WIKI_BUTTONS);
704 }
705 style_footer();
706 }else if( fossil_strcmp(zMime, "text/x-markdown")==0 ){
707 Blob tail = BLOB_INITIALIZER;
708 markdown_to_html(&filebody, &title, &tail);
709 if( blob_size(&title)>0 ){
710 style_header("%s", blob_str(&title));
711 }else{
712 style_header("%s", nMiss>=count(azSuffix)?
713 "Not Found" : zDfltTitle);
714 }
715 convert_href_and_output(&tail);
716 style_footer();
717 }else if( fossil_strcmp(zMime, "text/plain")==0 ){
718 style_header("%s", zDfltTitle);
719 @ <blockquote><pre>
720 @ %h(blob_str(&filebody))
721 @ </pre></blockquote>
722 style_footer();
723 }else if( fossil_strcmp(zMime, "text/html")==0
724 && doc_is_embedded_html(&filebody, &title) ){
725 if( blob_size(&title)==0 ) blob_append(&title,zName,-1);
726 style_header("%s", blob_str(&title));
727 convert_href_and_output(&filebody);
728 style_footer();
729 #ifdef FOSSIL_ENABLE_TH1_DOCS
730 }else if( Th_AreDocsEnabled() &&
731 fossil_strcmp(zMime, "application/x-th1")==0 ){
732 int raw = P("raw")!=0;
733 if( !raw ){
734 Blob tail;
735 blob_zero(&tail);
736 if( wiki_find_title(&filebody, &title, &tail) ){
737 style_header("%s", blob_str(&title));
738 Th_Render(blob_str(&tail));
739 blob_reset(&tail);
740 }else{
741 style_header("%h", zName);
742 Th_Render(blob_str(&filebody));
743 }
744 }else{
745 Th_Render(blob_str(&filebody));
746 }
747 if( !raw ){
748 style_footer();
749 }
750 #endif
751 }else{
752 cgi_set_content_type(zMime);
753 cgi_set_content(&filebody);
754 }
755 if( nMiss>=count(azSuffix) ) cgi_set_status(404, "Not Found");
756 db_end_transaction(0);
757 return;
758
759 /* Jump here when unable to locate the document */
760
761 DDED src/extcgi.c
--- src/doc.c
+++ src/doc.c
@@ -529,10 +529,85 @@
529 base = i+5;
530 }
531 }
532 blob_append(cgi_output_blob(), &z[base], i-base);
533 }
534
535 /*
536 ** Render a document as the reply to the HTTP request. The body
537 ** of the document is contained in pBody. The body might be binary.
538 ** The mimetype is in zMimetype.
539 */
540 void document_render(
541 Blob *pBody, /* Document content */
542 const char *zMime, /* MIME-type */
543 const char *zDefaultTitle, /* Default title */
544 const char *zFilename /* Name of the file being rendered */
545 ){
546 Blob title;
547 blob_init(&title,0,0);
548 if( fossil_strcmp(zMime, "text/x-fossil-wiki")==0 ){
549 Blob tail;
550 style_adunit_config(ADUNIT_RIGHT_OK);
551 if( wiki_find_title(pBody, &title, &tail) ){
552 style_header("%s", blob_str(&title));
553 wiki_convert(&tail, 0, WIKI_BUTTONS);
554 }else{
555 style_header("%s", zDefaultTitle);
556 wiki_convert(pBody, 0, WIKI_BUTTONS);
557 }
558 style_footer();
559 }else if( fossil_strcmp(zMime, "text/x-markdown")==0 ){
560 Blob tail = BLOB_INITIALIZER;
561 markdown_to_html(pBody, &title, &tail);
562 if( blob_size(&title)>0 ){
563 style_header("%s", blob_str(&title));
564 }else{
565 style_header("%s", zDefaultTitle);
566 }
567 convert_href_and_output(&tail);
568 style_footer();
569 }else if( fossil_strcmp(zMime, "text/plain")==0 ){
570 style_header("%s", zDefaultTitle);
571 @ <blockquote><pre>
572 @ %h(blob_str(pBody))
573 @ </pre></blockquote>
574 style_footer();
575 }else if( fossil_strcmp(zMime, "text/html")==0
576 && doc_is_embedded_html(pBody, &title) ){
577 if( blob_size(&title)==0 ) blob_append(&title,zFilename,-1);
578 style_header("%s", blob_str(&title));
579 convert_href_and_output(pBody);
580 style_footer();
581 #ifdef FOSSIL_ENABLE_TH1_DOCS
582 }else if( Th_AreDocsEnabled() &&
583 fossil_strcmp(zMime, "application/x-th1")==0 ){
584 int raw = P("raw")!=0;
585 if( !raw ){
586 Blob tail;
587 blob_zero(&tail);
588 if( wiki_find_title(pBody, &title, &tail) ){
589 style_header("%s", blob_str(&title));
590 Th_Render(blob_str(&tail));
591 blob_reset(&tail);
592 }else{
593 style_header("%h", zDefaultTitle);
594 Th_Render(blob_str(pBody));
595 }
596 }else{
597 Th_Render(blob_str(pBody));
598 }
599 if( !raw ){
600 style_footer();
601 }
602 #endif
603 }else{
604 cgi_set_content_type(zMime);
605 cgi_set_content(pBody);
606 }
607 }
608
609
610 /*
611 ** WEBPAGE: uv
612 ** WEBPAGE: doc
613 ** URL: /uv/FILE
@@ -618,10 +693,11 @@
693 zCheckin = "tip";
694 }
695 }
696 if( nMiss==count(azSuffix) ){
697 zName = "404.md";
698 zDfltTitle = "Not Found";
699 }else if( zName[i]==0 ){
700 assert( nMiss>=0 && nMiss<count(azSuffix) );
701 zName = azSuffix[nMiss];
702 }else if( !isUV ){
703 zName += i;
@@ -690,70 +766,11 @@
766 Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'"
767 " FROM blob WHERE rid=%d", vid));
768 Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event"
769 " WHERE objid=%d AND type='ci'", vid));
770 }
771 document_render(&filebody, zMime, zDfltTitle, zName);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
772 if( nMiss>=count(azSuffix) ) cgi_set_status(404, "Not Found");
773 db_end_transaction(0);
774 return;
775
776 /* Jump here when unable to locate the document */
777
778 DDED src/extcgi.c
--- a/src/extcgi.c
+++ b/src/extcgi.c
@@ -0,0 +1,3 @@
1
+/* }
2
+ }SER",
3
+
--- a/src/extcgi.c
+++ b/src/extcgi.c
@@ -0,0 +1,3 @@
 
 
 
--- a/src/extcgi.c
+++ b/src/extcgi.c
@@ -0,0 +1,3 @@
1 /* }
2 }SER",
3
+133 -30
--- src/http.c
+++ src/http.c
@@ -29,10 +29,21 @@
2929
#ifndef fileno
3030
#define fileno(s) _fileno(s)
3131
#endif
3232
#endif
3333
34
+
35
+#if INTERFACE
36
+/*
37
+** Bits of the mHttpFlags parameter to http_exchange()
38
+*/
39
+#define HTTP_USE_LOGIN 0x00001 /* Add a login card to the sync message */
40
+#define HTTP_GENERIC 0x00002 /* Generic HTTP request */
41
+#define HTTP_VERBOSE 0x00004 /* HTTP status messages */
42
+#define HTTP_QUIET 0x00008 /* No surplus output */
43
+#endif
44
+
3445
/* Maximum number of HTTP Authorization attempts */
3546
#define MAX_HTTP_AUTH 2
3647
3748
/* Keep track of HTTP Basic Authorization failures */
3849
static int fSeenHttpAuth = 0;
@@ -97,22 +108,21 @@
97108
/*
98109
** Construct an appropriate HTTP request header. Write the header
99110
** into pHdr. This routine initializes the pHdr blob. pPayload is
100111
** the complete payload (including the login card) already compressed.
101112
*/
102
-static void http_build_header(Blob *pPayload, Blob *pHdr){
103
- int i;
104
- const char *zSep;
113
+static void http_build_header(
114
+ Blob *pPayload, /* the payload that will be sent */
115
+ Blob *pHdr, /* construct the header here */
116
+ const char *zAltMimetype /* Alternative mimetype */
117
+){
118
+ int nPayload = pPayload ? blob_size(pPayload) : 0;
105119
106120
blob_zero(pHdr);
107
- i = strlen(g.url.path);
108
- if( i>0 && g.url.path[i-1]=='/' ){
109
- zSep = "";
110
- }else{
111
- zSep = "/";
112
- }
113
- blob_appendf(pHdr, "POST %s%s HTTP/1.0\r\n", g.url.path, zSep);
121
+ blob_appendf(pHdr, "%s %s%s HTTP/1.0\r\n",
122
+ nPayload>0 ? "POST" : "GET", g.url.path,
123
+ g.url.path[0]==0 ? "/" : "");
114124
if( g.url.proxyAuth ){
115125
blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.url.proxyAuth);
116126
}
117127
if( g.zHttpAuth && g.zHttpAuth[0] ){
118128
const char *zCredentials = g.zHttpAuth;
@@ -121,16 +131,21 @@
121131
fossil_free(zEncoded);
122132
}
123133
blob_appendf(pHdr, "Host: %s\r\n", g.url.hostname);
124134
blob_appendf(pHdr, "User-Agent: %s\r\n", get_user_agent());
125135
if( g.url.isSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
126
- if( g.fHttpTrace ){
127
- blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
128
- }else{
129
- blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
136
+ if( nPayload ){
137
+ if( zAltMimetype ){
138
+ blob_appendf(pHdr, "Content-Type: %s\r\n", zAltMimetype);
139
+ }else if( g.fHttpTrace ){
140
+ blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
141
+ }else{
142
+ blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
143
+ }
144
+ blob_appendf(pHdr, "Content-Length: %d\r\n", blob_size(pPayload));
130145
}
131
- blob_appendf(pHdr, "Content-Length: %d\r\n\r\n", blob_size(pPayload));
146
+ blob_append(pHdr, "\r\n", 2);
132147
}
133148
134149
/*
135150
** Use Fossil credentials for HTTP Basic Authorization prompt
136151
*/
@@ -200,11 +215,17 @@
200215
**
201216
** The server address is contain in the "g" global structure. The
202217
** url_parse() routine should have been called prior to this routine
203218
** in order to fill this structure appropriately.
204219
*/
205
-int http_exchange(Blob *pSend, Blob *pReply, int useLogin, int maxRedirect){
220
+int http_exchange(
221
+ Blob *pSend, /* Message to be sent */
222
+ Blob *pReply, /* Write the reply here */
223
+ int mHttpFlags, /* Flags. See above */
224
+ int maxRedirect, /* Max number of redirects */
225
+ const char *zAltMimetype /* Alternative mimetype if not NULL */
226
+){
206227
Blob login; /* The login card */
207228
Blob payload; /* The complete payload including login card */
208229
Blob hdr; /* The HTTP request header */
209230
int closeConnection; /* True to close the connection when done */
210231
int iLength; /* Expected length of the reply payload */
@@ -220,22 +241,26 @@
220241
fossil_warning("%s", transport_errmsg(&g.url));
221242
return 1;
222243
}
223244
224245
/* Construct the login card and prepare the complete payload */
225
- blob_zero(&login);
226
- if( useLogin ) http_build_login_card(pSend, &login);
227
- if( g.fHttpTrace ){
228
- payload = login;
229
- blob_append(&payload, blob_buffer(pSend), blob_size(pSend));
246
+ if( blob_size(pSend)==0 ){
247
+ blob_zero(&payload);
230248
}else{
231
- blob_compress2(&login, pSend, &payload);
232
- blob_reset(&login);
249
+ blob_zero(&login);
250
+ if( mHttpFlags & HTTP_USE_LOGIN ) http_build_login_card(pSend, &login);
251
+ if( g.fHttpTrace ){
252
+ payload = login;
253
+ blob_append(&payload, blob_buffer(pSend), blob_size(pSend));
254
+ }else{
255
+ blob_compress2(&login, pSend, &payload);
256
+ blob_reset(&login);
257
+ }
233258
}
234259
235260
/* Construct the HTTP request header */
236
- http_build_header(&payload, &hdr);
261
+ http_build_header(&payload, &hdr, zAltMimetype);
237262
238263
/* When tracing, write the transmitted HTTP message both to standard
239264
** output and into a file. The file can then be used to drive the
240265
** server-side like this:
241266
**
@@ -261,10 +286,15 @@
261286
}
262287
263288
/*
264289
** Send the request to the server.
265290
*/
291
+ if( mHttpFlags & HTTP_VERBOSE ){
292
+ fossil_print("URL: %s\n", g.url.canonical);
293
+ fossil_print("Sending %d byte header and %d byte payload\n",
294
+ blob_size(&hdr), blob_size(&payload));
295
+ }
266296
transport_send(&g.url, &hdr);
267297
transport_send(&g.url, &payload);
268298
blob_reset(&hdr);
269299
blob_reset(&payload);
270300
transport_flip(&g.url);
@@ -273,21 +303,24 @@
273303
** Read and interpret the server reply
274304
*/
275305
closeConnection = 1;
276306
iLength = -1;
277307
while( (zLine = transport_receive_line(&g.url))!=0 && zLine[0]!=0 ){
278
- /* printf("[%s]\n", zLine); fflush(stdout); */
308
+ if( mHttpFlags & HTTP_VERBOSE ){
309
+ fossil_print("Read: [%s]\n", zLine);
310
+ }
279311
if( fossil_strnicmp(zLine, "http/1.", 7)==0 ){
280312
if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
281313
if( rc==401 ){
282314
if( fSeenHttpAuth++ < MAX_HTTP_AUTH ){
283315
if( g.zHttpAuth ){
284316
if( g.zHttpAuth ) free(g.zHttpAuth);
285317
}
286318
g.zHttpAuth = prompt_for_httpauth_creds();
287319
transport_close(&g.url);
288
- return http_exchange(pSend, pReply, useLogin, maxRedirect);
320
+ return http_exchange(pSend, pReply, mHttpFlags,
321
+ maxRedirect, zAltMimetype);
289322
}
290323
}
291324
if( rc!=200 && rc!=301 && rc!=302 && rc!=307 && rc!=308 ){
292325
int ii;
293326
for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
@@ -323,10 +356,11 @@
323356
closeConnection = 0;
324357
}
325358
}else if( ( rc==301 || rc==302 || rc==307 || rc==308 ) &&
326359
fossil_strnicmp(zLine, "location:", 9)==0 ){
327360
int i, j;
361
+ int wasHttps;
328362
329363
if ( --maxRedirect == 0){
330364
fossil_warning("redirect limit exceeded");
331365
goto write_err;
332366
}
@@ -338,27 +372,39 @@
338372
j = strlen(zLine) - 1;
339373
while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){
340374
j -= 4;
341375
zLine[j] = 0;
342376
}
343
- fossil_print("redirect with status %d to %s\n", rc, &zLine[i]);
377
+ if( (mHttpFlags & HTTP_QUIET)==0 ){
378
+ fossil_print("redirect with status %d to %s\n", rc, &zLine[i]);
379
+ }
380
+ wasHttps = g.url.isHttps;
344381
url_parse(&zLine[i], 0);
382
+ if( wasHttps && !g.url.isHttps ){
383
+ fossil_warning("cannot redirect from HTTPS to HTTP");
384
+ goto write_err;
385
+ }
345386
transport_close(&g.url);
346387
transport_global_shutdown(&g.url);
347388
fSeenHttpAuth = 0;
348389
if( g.zHttpAuth ) free(g.zHttpAuth);
349390
g.zHttpAuth = get_httpauth();
350391
if( rc==301 || rc==308 ) url_remember();
351
- return http_exchange(pSend, pReply, useLogin, maxRedirect);
392
+ return http_exchange(pSend, pReply, mHttpFlags,
393
+ maxRedirect, zAltMimetype);
352394
}else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
353395
if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
354396
isCompressed = 0;
355397
}else if( fossil_strnicmp(&zLine[14],
356398
"application/x-fossil-uncompressed", -1)==0 ){
357399
isCompressed = 0;
358
- }else if( fossil_strnicmp(&zLine[14], "application/x-fossil", -1)!=0 ){
359
- isError = 1;
400
+ }else{
401
+ if( (mHttpFlags & HTTP_GENERIC)==0
402
+ && fossil_strnicmp(&zLine[14], "application/x-fossil", -1)!=0
403
+ ){
404
+ isError = 1;
405
+ }
360406
}
361407
}
362408
}
363409
if( iLength<0 ){
364410
fossil_warning("server did not reply");
@@ -419,5 +465,62 @@
419465
*/
420466
write_err:
421467
transport_close(&g.url);
422468
return 1;
423469
}
470
+
471
+/*
472
+** COMMAND: test-httpmsg
473
+**
474
+** Usage: %fossil test-httpmsg URL ?PAYLOAD? ?OPTIONS?
475
+**
476
+** Send an HTTP message to URL and get the reply. PAYLOAD is a file containing
477
+** the payload, or "-" to read payload from standard input. a POST message
478
+** is sent if PAYLOAD is specified and is non-empty. If PAYLOAD is omitted
479
+** or is an empty file, then a GET message is sent.
480
+**
481
+** Options:
482
+**
483
+** --mimetype TYPE Mimetype of the payload
484
+** --out FILE Store the reply in FILE
485
+** -v Verbose output
486
+*/
487
+void test_wget_command(void){
488
+ const char *zMimetype;
489
+ const char *zInFile;
490
+ const char *zOutFile;
491
+ Blob in, out;
492
+ unsigned int mHttpFlags = HTTP_GENERIC;
493
+
494
+ zMimetype = find_option("mimetype",0,1);
495
+ zOutFile = find_option("out","o",1);
496
+ if( find_option("verbose","v",0)!=0 ) mHttpFlags |= HTTP_VERBOSE;
497
+ if( g.argc!=3 && g.argc!=4 ){
498
+ usage("URL ?PAYLOAD?");
499
+ }
500
+ zInFile = g.argc==4 ? g.argv[3] : 0;
501
+ url_parse(g.argv[2], 0);
502
+ if( g.url.protocol[0]!='h' ){
503
+ fossil_fatal("the %s command supports only http: and https:", g.argv[1]);
504
+ }
505
+ if( zInFile ){
506
+ blob_read_from_file(&in, zInFile, ExtFILE);
507
+ if( zMimetype==0 ){
508
+ if( fossil_strcmp(zInFile,"-")==0 ){
509
+ zMimetype = "application/x-unknown";
510
+ }else{
511
+ zMimetype = mimetype_from_name(zInFile);
512
+ }
513
+ }
514
+ }else{
515
+ blob_init(&in, 0, 0);
516
+ }
517
+ blob_init(&out, 0, 0);
518
+ if( (mHttpFlags & HTTP_VERBOSE)==0 && zOutFile==0 ){
519
+ zOutFile = "-";
520
+ mHttpFlags |= HTTP_QUIET;
521
+ }
522
+ http_exchange(&in, &out, mHttpFlags, 4, zMimetype);
523
+ if( zOutFile ) blob_write_to_file(&out, zOutFile);
524
+ blob_zero(&in);
525
+ blob_zero(&out);
526
+}
424527
--- src/http.c
+++ src/http.c
@@ -29,10 +29,21 @@
29 #ifndef fileno
30 #define fileno(s) _fileno(s)
31 #endif
32 #endif
33
 
 
 
 
 
 
 
 
 
 
 
34 /* Maximum number of HTTP Authorization attempts */
35 #define MAX_HTTP_AUTH 2
36
37 /* Keep track of HTTP Basic Authorization failures */
38 static int fSeenHttpAuth = 0;
@@ -97,22 +108,21 @@
97 /*
98 ** Construct an appropriate HTTP request header. Write the header
99 ** into pHdr. This routine initializes the pHdr blob. pPayload is
100 ** the complete payload (including the login card) already compressed.
101 */
102 static void http_build_header(Blob *pPayload, Blob *pHdr){
103 int i;
104 const char *zSep;
 
 
 
105
106 blob_zero(pHdr);
107 i = strlen(g.url.path);
108 if( i>0 && g.url.path[i-1]=='/' ){
109 zSep = "";
110 }else{
111 zSep = "/";
112 }
113 blob_appendf(pHdr, "POST %s%s HTTP/1.0\r\n", g.url.path, zSep);
114 if( g.url.proxyAuth ){
115 blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.url.proxyAuth);
116 }
117 if( g.zHttpAuth && g.zHttpAuth[0] ){
118 const char *zCredentials = g.zHttpAuth;
@@ -121,16 +131,21 @@
121 fossil_free(zEncoded);
122 }
123 blob_appendf(pHdr, "Host: %s\r\n", g.url.hostname);
124 blob_appendf(pHdr, "User-Agent: %s\r\n", get_user_agent());
125 if( g.url.isSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
126 if( g.fHttpTrace ){
127 blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
128 }else{
129 blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
 
 
 
 
 
130 }
131 blob_appendf(pHdr, "Content-Length: %d\r\n\r\n", blob_size(pPayload));
132 }
133
134 /*
135 ** Use Fossil credentials for HTTP Basic Authorization prompt
136 */
@@ -200,11 +215,17 @@
200 **
201 ** The server address is contain in the "g" global structure. The
202 ** url_parse() routine should have been called prior to this routine
203 ** in order to fill this structure appropriately.
204 */
205 int http_exchange(Blob *pSend, Blob *pReply, int useLogin, int maxRedirect){
 
 
 
 
 
 
206 Blob login; /* The login card */
207 Blob payload; /* The complete payload including login card */
208 Blob hdr; /* The HTTP request header */
209 int closeConnection; /* True to close the connection when done */
210 int iLength; /* Expected length of the reply payload */
@@ -220,22 +241,26 @@
220 fossil_warning("%s", transport_errmsg(&g.url));
221 return 1;
222 }
223
224 /* Construct the login card and prepare the complete payload */
225 blob_zero(&login);
226 if( useLogin ) http_build_login_card(pSend, &login);
227 if( g.fHttpTrace ){
228 payload = login;
229 blob_append(&payload, blob_buffer(pSend), blob_size(pSend));
230 }else{
231 blob_compress2(&login, pSend, &payload);
232 blob_reset(&login);
 
 
 
 
 
 
 
233 }
234
235 /* Construct the HTTP request header */
236 http_build_header(&payload, &hdr);
237
238 /* When tracing, write the transmitted HTTP message both to standard
239 ** output and into a file. The file can then be used to drive the
240 ** server-side like this:
241 **
@@ -261,10 +286,15 @@
261 }
262
263 /*
264 ** Send the request to the server.
265 */
 
 
 
 
 
266 transport_send(&g.url, &hdr);
267 transport_send(&g.url, &payload);
268 blob_reset(&hdr);
269 blob_reset(&payload);
270 transport_flip(&g.url);
@@ -273,21 +303,24 @@
273 ** Read and interpret the server reply
274 */
275 closeConnection = 1;
276 iLength = -1;
277 while( (zLine = transport_receive_line(&g.url))!=0 && zLine[0]!=0 ){
278 /* printf("[%s]\n", zLine); fflush(stdout); */
 
 
279 if( fossil_strnicmp(zLine, "http/1.", 7)==0 ){
280 if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
281 if( rc==401 ){
282 if( fSeenHttpAuth++ < MAX_HTTP_AUTH ){
283 if( g.zHttpAuth ){
284 if( g.zHttpAuth ) free(g.zHttpAuth);
285 }
286 g.zHttpAuth = prompt_for_httpauth_creds();
287 transport_close(&g.url);
288 return http_exchange(pSend, pReply, useLogin, maxRedirect);
 
289 }
290 }
291 if( rc!=200 && rc!=301 && rc!=302 && rc!=307 && rc!=308 ){
292 int ii;
293 for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
@@ -323,10 +356,11 @@
323 closeConnection = 0;
324 }
325 }else if( ( rc==301 || rc==302 || rc==307 || rc==308 ) &&
326 fossil_strnicmp(zLine, "location:", 9)==0 ){
327 int i, j;
 
328
329 if ( --maxRedirect == 0){
330 fossil_warning("redirect limit exceeded");
331 goto write_err;
332 }
@@ -338,27 +372,39 @@
338 j = strlen(zLine) - 1;
339 while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){
340 j -= 4;
341 zLine[j] = 0;
342 }
343 fossil_print("redirect with status %d to %s\n", rc, &zLine[i]);
 
 
 
344 url_parse(&zLine[i], 0);
 
 
 
 
345 transport_close(&g.url);
346 transport_global_shutdown(&g.url);
347 fSeenHttpAuth = 0;
348 if( g.zHttpAuth ) free(g.zHttpAuth);
349 g.zHttpAuth = get_httpauth();
350 if( rc==301 || rc==308 ) url_remember();
351 return http_exchange(pSend, pReply, useLogin, maxRedirect);
 
352 }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
353 if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
354 isCompressed = 0;
355 }else if( fossil_strnicmp(&zLine[14],
356 "application/x-fossil-uncompressed", -1)==0 ){
357 isCompressed = 0;
358 }else if( fossil_strnicmp(&zLine[14], "application/x-fossil", -1)!=0 ){
359 isError = 1;
 
 
 
 
360 }
361 }
362 }
363 if( iLength<0 ){
364 fossil_warning("server did not reply");
@@ -419,5 +465,62 @@
419 */
420 write_err:
421 transport_close(&g.url);
422 return 1;
423 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
424
--- src/http.c
+++ src/http.c
@@ -29,10 +29,21 @@
29 #ifndef fileno
30 #define fileno(s) _fileno(s)
31 #endif
32 #endif
33
34
35 #if INTERFACE
36 /*
37 ** Bits of the mHttpFlags parameter to http_exchange()
38 */
39 #define HTTP_USE_LOGIN 0x00001 /* Add a login card to the sync message */
40 #define HTTP_GENERIC 0x00002 /* Generic HTTP request */
41 #define HTTP_VERBOSE 0x00004 /* HTTP status messages */
42 #define HTTP_QUIET 0x00008 /* No surplus output */
43 #endif
44
45 /* Maximum number of HTTP Authorization attempts */
46 #define MAX_HTTP_AUTH 2
47
48 /* Keep track of HTTP Basic Authorization failures */
49 static int fSeenHttpAuth = 0;
@@ -97,22 +108,21 @@
108 /*
109 ** Construct an appropriate HTTP request header. Write the header
110 ** into pHdr. This routine initializes the pHdr blob. pPayload is
111 ** the complete payload (including the login card) already compressed.
112 */
113 static void http_build_header(
114 Blob *pPayload, /* the payload that will be sent */
115 Blob *pHdr, /* construct the header here */
116 const char *zAltMimetype /* Alternative mimetype */
117 ){
118 int nPayload = pPayload ? blob_size(pPayload) : 0;
119
120 blob_zero(pHdr);
121 blob_appendf(pHdr, "%s %s%s HTTP/1.0\r\n",
122 nPayload>0 ? "POST" : "GET", g.url.path,
123 g.url.path[0]==0 ? "/" : "");
 
 
 
 
124 if( g.url.proxyAuth ){
125 blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.url.proxyAuth);
126 }
127 if( g.zHttpAuth && g.zHttpAuth[0] ){
128 const char *zCredentials = g.zHttpAuth;
@@ -121,16 +131,21 @@
131 fossil_free(zEncoded);
132 }
133 blob_appendf(pHdr, "Host: %s\r\n", g.url.hostname);
134 blob_appendf(pHdr, "User-Agent: %s\r\n", get_user_agent());
135 if( g.url.isSsh ) blob_appendf(pHdr, "X-Fossil-Transport: SSH\r\n");
136 if( nPayload ){
137 if( zAltMimetype ){
138 blob_appendf(pHdr, "Content-Type: %s\r\n", zAltMimetype);
139 }else if( g.fHttpTrace ){
140 blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
141 }else{
142 blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
143 }
144 blob_appendf(pHdr, "Content-Length: %d\r\n", blob_size(pPayload));
145 }
146 blob_append(pHdr, "\r\n", 2);
147 }
148
149 /*
150 ** Use Fossil credentials for HTTP Basic Authorization prompt
151 */
@@ -200,11 +215,17 @@
215 **
216 ** The server address is contain in the "g" global structure. The
217 ** url_parse() routine should have been called prior to this routine
218 ** in order to fill this structure appropriately.
219 */
220 int http_exchange(
221 Blob *pSend, /* Message to be sent */
222 Blob *pReply, /* Write the reply here */
223 int mHttpFlags, /* Flags. See above */
224 int maxRedirect, /* Max number of redirects */
225 const char *zAltMimetype /* Alternative mimetype if not NULL */
226 ){
227 Blob login; /* The login card */
228 Blob payload; /* The complete payload including login card */
229 Blob hdr; /* The HTTP request header */
230 int closeConnection; /* True to close the connection when done */
231 int iLength; /* Expected length of the reply payload */
@@ -220,22 +241,26 @@
241 fossil_warning("%s", transport_errmsg(&g.url));
242 return 1;
243 }
244
245 /* Construct the login card and prepare the complete payload */
246 if( blob_size(pSend)==0 ){
247 blob_zero(&payload);
 
 
 
248 }else{
249 blob_zero(&login);
250 if( mHttpFlags & HTTP_USE_LOGIN ) http_build_login_card(pSend, &login);
251 if( g.fHttpTrace ){
252 payload = login;
253 blob_append(&payload, blob_buffer(pSend), blob_size(pSend));
254 }else{
255 blob_compress2(&login, pSend, &payload);
256 blob_reset(&login);
257 }
258 }
259
260 /* Construct the HTTP request header */
261 http_build_header(&payload, &hdr, zAltMimetype);
262
263 /* When tracing, write the transmitted HTTP message both to standard
264 ** output and into a file. The file can then be used to drive the
265 ** server-side like this:
266 **
@@ -261,10 +286,15 @@
286 }
287
288 /*
289 ** Send the request to the server.
290 */
291 if( mHttpFlags & HTTP_VERBOSE ){
292 fossil_print("URL: %s\n", g.url.canonical);
293 fossil_print("Sending %d byte header and %d byte payload\n",
294 blob_size(&hdr), blob_size(&payload));
295 }
296 transport_send(&g.url, &hdr);
297 transport_send(&g.url, &payload);
298 blob_reset(&hdr);
299 blob_reset(&payload);
300 transport_flip(&g.url);
@@ -273,21 +303,24 @@
303 ** Read and interpret the server reply
304 */
305 closeConnection = 1;
306 iLength = -1;
307 while( (zLine = transport_receive_line(&g.url))!=0 && zLine[0]!=0 ){
308 if( mHttpFlags & HTTP_VERBOSE ){
309 fossil_print("Read: [%s]\n", zLine);
310 }
311 if( fossil_strnicmp(zLine, "http/1.", 7)==0 ){
312 if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
313 if( rc==401 ){
314 if( fSeenHttpAuth++ < MAX_HTTP_AUTH ){
315 if( g.zHttpAuth ){
316 if( g.zHttpAuth ) free(g.zHttpAuth);
317 }
318 g.zHttpAuth = prompt_for_httpauth_creds();
319 transport_close(&g.url);
320 return http_exchange(pSend, pReply, mHttpFlags,
321 maxRedirect, zAltMimetype);
322 }
323 }
324 if( rc!=200 && rc!=301 && rc!=302 && rc!=307 && rc!=308 ){
325 int ii;
326 for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){}
@@ -323,10 +356,11 @@
356 closeConnection = 0;
357 }
358 }else if( ( rc==301 || rc==302 || rc==307 || rc==308 ) &&
359 fossil_strnicmp(zLine, "location:", 9)==0 ){
360 int i, j;
361 int wasHttps;
362
363 if ( --maxRedirect == 0){
364 fossil_warning("redirect limit exceeded");
365 goto write_err;
366 }
@@ -338,27 +372,39 @@
372 j = strlen(zLine) - 1;
373 while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){
374 j -= 4;
375 zLine[j] = 0;
376 }
377 if( (mHttpFlags & HTTP_QUIET)==0 ){
378 fossil_print("redirect with status %d to %s\n", rc, &zLine[i]);
379 }
380 wasHttps = g.url.isHttps;
381 url_parse(&zLine[i], 0);
382 if( wasHttps && !g.url.isHttps ){
383 fossil_warning("cannot redirect from HTTPS to HTTP");
384 goto write_err;
385 }
386 transport_close(&g.url);
387 transport_global_shutdown(&g.url);
388 fSeenHttpAuth = 0;
389 if( g.zHttpAuth ) free(g.zHttpAuth);
390 g.zHttpAuth = get_httpauth();
391 if( rc==301 || rc==308 ) url_remember();
392 return http_exchange(pSend, pReply, mHttpFlags,
393 maxRedirect, zAltMimetype);
394 }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
395 if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
396 isCompressed = 0;
397 }else if( fossil_strnicmp(&zLine[14],
398 "application/x-fossil-uncompressed", -1)==0 ){
399 isCompressed = 0;
400 }else{
401 if( (mHttpFlags & HTTP_GENERIC)==0
402 && fossil_strnicmp(&zLine[14], "application/x-fossil", -1)!=0
403 ){
404 isError = 1;
405 }
406 }
407 }
408 }
409 if( iLength<0 ){
410 fossil_warning("server did not reply");
@@ -419,5 +465,62 @@
465 */
466 write_err:
467 transport_close(&g.url);
468 return 1;
469 }
470
471 /*
472 ** COMMAND: test-httpmsg
473 **
474 ** Usage: %fossil test-httpmsg URL ?PAYLOAD? ?OPTIONS?
475 **
476 ** Send an HTTP message to URL and get the reply. PAYLOAD is a file containing
477 ** the payload, or "-" to read payload from standard input. a POST message
478 ** is sent if PAYLOAD is specified and is non-empty. If PAYLOAD is omitted
479 ** or is an empty file, then a GET message is sent.
480 **
481 ** Options:
482 **
483 ** --mimetype TYPE Mimetype of the payload
484 ** --out FILE Store the reply in FILE
485 ** -v Verbose output
486 */
487 void test_wget_command(void){
488 const char *zMimetype;
489 const char *zInFile;
490 const char *zOutFile;
491 Blob in, out;
492 unsigned int mHttpFlags = HTTP_GENERIC;
493
494 zMimetype = find_option("mimetype",0,1);
495 zOutFile = find_option("out","o",1);
496 if( find_option("verbose","v",0)!=0 ) mHttpFlags |= HTTP_VERBOSE;
497 if( g.argc!=3 && g.argc!=4 ){
498 usage("URL ?PAYLOAD?");
499 }
500 zInFile = g.argc==4 ? g.argv[3] : 0;
501 url_parse(g.argv[2], 0);
502 if( g.url.protocol[0]!='h' ){
503 fossil_fatal("the %s command supports only http: and https:", g.argv[1]);
504 }
505 if( zInFile ){
506 blob_read_from_file(&in, zInFile, ExtFILE);
507 if( zMimetype==0 ){
508 if( fossil_strcmp(zInFile,"-")==0 ){
509 zMimetype = "application/x-unknown";
510 }else{
511 zMimetype = mimetype_from_name(zInFile);
512 }
513 }
514 }else{
515 blob_init(&in, 0, 0);
516 }
517 blob_init(&out, 0, 0);
518 if( (mHttpFlags & HTTP_VERBOSE)==0 && zOutFile==0 ){
519 zOutFile = "-";
520 mHttpFlags |= HTTP_QUIET;
521 }
522 http_exchange(&in, &out, mHttpFlags, 4, zMimetype);
523 if( zOutFile ) blob_write_to_file(&out, zOutFile);
524 blob_zero(&in);
525 blob_zero(&out);
526 }
527
--- src/http_transport.c
+++ src/http_transport.c
@@ -140,11 +140,11 @@
140140
fossil_panic("ssh:// URI does not specify a path to the repository");
141141
}
142142
if( g.fSshTrace ){
143143
fossil_print("%s\n", blob_str(&zCmd)); /* Show the whole SSH command */
144144
}
145
- popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
145
+ popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid, 0);
146146
if( sshPid==0 ){
147147
socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);
148148
}
149149
blob_reset(&zCmd);
150150
return sshPid==0;
@@ -165,17 +165,17 @@
165165
if( transport.isOpen==0 ){
166166
if( pUrlData->isSsh ){
167167
rc = transport_ssh_open(pUrlData);
168168
if( rc==0 ) transport.isOpen = 1;
169169
}else if( pUrlData->isHttps ){
170
- #ifdef FOSSIL_ENABLE_SSL
170
+#ifdef FOSSIL_ENABLE_SSL
171171
rc = ssl_open(pUrlData);
172172
if( rc==0 ) transport.isOpen = 1;
173
- #else
173
+#else
174174
socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support");
175175
rc = 1;
176
- #endif
176
+#endif
177177
}else if( pUrlData->isFile ){
178178
sqlite3_uint64 iRandId;
179179
sqlite3_randomness(sizeof(iRandId), &iRandId);
180180
transport.zOutFile = mprintf("%s-%llu-out.http",
181181
g.zRepositoryName, iRandId);
@@ -239,19 +239,19 @@
239239
transport.nSent += n;
240240
if( pUrlData->isSsh ){
241241
fwrite(z, 1, n, sshOut);
242242
fflush(sshOut);
243243
}else if( pUrlData->isHttps ){
244
- #ifdef FOSSIL_ENABLE_SSL
244
+#ifdef FOSSIL_ENABLE_SSL
245245
int sent;
246246
while( n>0 ){
247247
sent = ssl_send(0, z, n);
248248
/* printf("Sent %d of %d bytes\n", sent, n); fflush(stdout); */
249249
if( sent<=0 ) break;
250250
n -= sent;
251251
}
252
- #endif
252
+#endif
253253
}else if( pUrlData->isFile ){
254254
fwrite(z, 1, n, transport.pFile);
255255
}else{
256256
int sent;
257257
while( n>0 ){
258258
--- src/http_transport.c
+++ src/http_transport.c
@@ -140,11 +140,11 @@
140 fossil_panic("ssh:// URI does not specify a path to the repository");
141 }
142 if( g.fSshTrace ){
143 fossil_print("%s\n", blob_str(&zCmd)); /* Show the whole SSH command */
144 }
145 popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid);
146 if( sshPid==0 ){
147 socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);
148 }
149 blob_reset(&zCmd);
150 return sshPid==0;
@@ -165,17 +165,17 @@
165 if( transport.isOpen==0 ){
166 if( pUrlData->isSsh ){
167 rc = transport_ssh_open(pUrlData);
168 if( rc==0 ) transport.isOpen = 1;
169 }else if( pUrlData->isHttps ){
170 #ifdef FOSSIL_ENABLE_SSL
171 rc = ssl_open(pUrlData);
172 if( rc==0 ) transport.isOpen = 1;
173 #else
174 socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support");
175 rc = 1;
176 #endif
177 }else if( pUrlData->isFile ){
178 sqlite3_uint64 iRandId;
179 sqlite3_randomness(sizeof(iRandId), &iRandId);
180 transport.zOutFile = mprintf("%s-%llu-out.http",
181 g.zRepositoryName, iRandId);
@@ -239,19 +239,19 @@
239 transport.nSent += n;
240 if( pUrlData->isSsh ){
241 fwrite(z, 1, n, sshOut);
242 fflush(sshOut);
243 }else if( pUrlData->isHttps ){
244 #ifdef FOSSIL_ENABLE_SSL
245 int sent;
246 while( n>0 ){
247 sent = ssl_send(0, z, n);
248 /* printf("Sent %d of %d bytes\n", sent, n); fflush(stdout); */
249 if( sent<=0 ) break;
250 n -= sent;
251 }
252 #endif
253 }else if( pUrlData->isFile ){
254 fwrite(z, 1, n, transport.pFile);
255 }else{
256 int sent;
257 while( n>0 ){
258
--- src/http_transport.c
+++ src/http_transport.c
@@ -140,11 +140,11 @@
140 fossil_panic("ssh:// URI does not specify a path to the repository");
141 }
142 if( g.fSshTrace ){
143 fossil_print("%s\n", blob_str(&zCmd)); /* Show the whole SSH command */
144 }
145 popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid, 0);
146 if( sshPid==0 ){
147 socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd);
148 }
149 blob_reset(&zCmd);
150 return sshPid==0;
@@ -165,17 +165,17 @@
165 if( transport.isOpen==0 ){
166 if( pUrlData->isSsh ){
167 rc = transport_ssh_open(pUrlData);
168 if( rc==0 ) transport.isOpen = 1;
169 }else if( pUrlData->isHttps ){
170 #ifdef FOSSIL_ENABLE_SSL
171 rc = ssl_open(pUrlData);
172 if( rc==0 ) transport.isOpen = 1;
173 #else
174 socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support");
175 rc = 1;
176 #endif
177 }else if( pUrlData->isFile ){
178 sqlite3_uint64 iRandId;
179 sqlite3_randomness(sizeof(iRandId), &iRandId);
180 transport.zOutFile = mprintf("%s-%llu-out.http",
181 g.zRepositoryName, iRandId);
@@ -239,19 +239,19 @@
239 transport.nSent += n;
240 if( pUrlData->isSsh ){
241 fwrite(z, 1, n, sshOut);
242 fflush(sshOut);
243 }else if( pUrlData->isHttps ){
244 #ifdef FOSSIL_ENABLE_SSL
245 int sent;
246 while( n>0 ){
247 sent = ssl_send(0, z, n);
248 /* printf("Sent %d of %d bytes\n", sent, n); fflush(stdout); */
249 if( sent<=0 ) break;
250 n -= sent;
251 }
252 #endif
253 }else if( pUrlData->isFile ){
254 fwrite(z, 1, n, transport.pFile);
255 }else{
256 int sent;
257 while( n>0 ){
258
--- src/json_user.c
+++ src/json_user.c
@@ -186,17 +186,10 @@
186186
char const tgtHasSetup = zCap && (NULL!=strchr(zCap, 's'));
187187
char tgtHadSetup = 0;
188188
Blob sql = empty_blob;
189189
Stmt q = empty_Stmt;
190190
191
-#if 0
192
- if(!g.perm.Admin && !g.perm.Setup && !g.perm.Password){
193
- return json_set_err( FSL_JSON_E_DENIED,
194
- "Password change requires 'a', 's', "
195
- "or 'p' permissions.");
196
- }
197
-#endif
198191
if(uid<=0 && (!zName||!*zName)){
199192
return json_set_err(FSL_JSON_E_MISSING_ARGS,
200193
"One of 'uid' or 'name' is required.");
201194
}else if(uid>0){
202195
zNameFree = db_text(NULL, "SELECT login FROM user WHERE uid=%d",uid);
203196
--- src/json_user.c
+++ src/json_user.c
@@ -186,17 +186,10 @@
186 char const tgtHasSetup = zCap && (NULL!=strchr(zCap, 's'));
187 char tgtHadSetup = 0;
188 Blob sql = empty_blob;
189 Stmt q = empty_Stmt;
190
191 #if 0
192 if(!g.perm.Admin && !g.perm.Setup && !g.perm.Password){
193 return json_set_err( FSL_JSON_E_DENIED,
194 "Password change requires 'a', 's', "
195 "or 'p' permissions.");
196 }
197 #endif
198 if(uid<=0 && (!zName||!*zName)){
199 return json_set_err(FSL_JSON_E_MISSING_ARGS,
200 "One of 'uid' or 'name' is required.");
201 }else if(uid>0){
202 zNameFree = db_text(NULL, "SELECT login FROM user WHERE uid=%d",uid);
203
--- src/json_user.c
+++ src/json_user.c
@@ -186,17 +186,10 @@
186 char const tgtHasSetup = zCap && (NULL!=strchr(zCap, 's'));
187 char tgtHadSetup = 0;
188 Blob sql = empty_blob;
189 Stmt q = empty_Stmt;
190
 
 
 
 
 
 
 
191 if(uid<=0 && (!zName||!*zName)){
192 return json_set_err(FSL_JSON_E_MISSING_ARGS,
193 "One of 'uid' or 'name' is required.");
194 }else if(uid>0){
195 zNameFree = db_text(NULL, "SELECT login FROM user WHERE uid=%d",uid);
196
+10 -6
--- src/login.c
+++ src/login.c
@@ -434,11 +434,13 @@
434434
if( sqlite3_strglob("*Safari/537.36Mozilla/5.0*", zAgent)==0 ) return 0;
435435
436436
if( sqlite3_strglob("*Firefox/[1-9]*", zAgent)==0 ) return 1;
437437
if( sqlite3_strglob("*Chrome/[1-9]*", zAgent)==0 ) return 1;
438438
if( sqlite3_strglob("*(compatible;?MSIE?[1789]*", zAgent)==0 ) return 1;
439
- if( sqlite3_strglob("*Trident/[1-9]*;?rv:[1-9]*", zAgent)==0 ) return 1; /* IE11+ */
439
+ if( sqlite3_strglob("*Trident/[1-9]*;?rv:[1-9]*", zAgent)==0 ){
440
+ return 1; /* IE11+ */
441
+ }
440442
if( sqlite3_strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent)==0 ) return 1;
441443
return 0;
442444
}
443445
if( strncmp(zAgent, "Opera/", 6)==0 ) return 1;
444446
if( strncmp(zAgent, "Safari/", 7)==0 ) return 1;
@@ -897,22 +899,24 @@
897899
898900
/*
899901
** Attempt to use Basic Authentication to establish the user. Return the
900902
** (non-zero) uid if successful. Return 0 if it does not work.
901903
*/
902
-static int logic_basic_authentication(const char *zIpAddr){
904
+static int login_basic_authentication(const char *zIpAddr){
903905
const char *zAuth = PD("HTTP_AUTHORIZATION", 0);
904906
int i;
905907
int uid = 0;
906908
int nDecode = 0;
907909
char *zDecode = 0;
908910
const char *zUsername = 0;
909911
const char *zPasswd = 0;
910912
911
- if( zAuth==0 ) return 0; /* Fail: No Authentication: header */
913
+ if( zAuth==0 ) return 0; /* Fail: No Authentication: header */
912914
while( fossil_isspace(zAuth[0]) ) zAuth++; /* Skip leading whitespace */
913
- if( strncmp(zAuth, "Basic ", 6)!=0 ) return 0; /* Fail: Not Basic Authentication */
915
+ if( strncmp(zAuth, "Basic ", 6)!=0 ){
916
+ return 0; /* Fail: Not Basic Authentication */
917
+ }
914918
915919
/* Parse out the username and password, separated by a ":" */
916920
zAuth += 6;
917921
while( fossil_isspace(zAuth[0]) ) zAuth++;
918922
zDecode = decode64(zAuth, &nDecode);
@@ -1069,11 +1073,11 @@
10691073
/* If the request didn't provide a login cookie or the login cookie didn't
10701074
** match a known valid user, check the HTTP "Authorization" header and
10711075
** see if those credentials are valid for a known user.
10721076
*/
10731077
if( uid==0 && db_get_boolean("http_authentication_ok",0) ){
1074
- uid = logic_basic_authentication(zIpAddr);
1078
+ uid = login_basic_authentication(zIpAddr);
10751079
}
10761080
10771081
/* If no user found yet, try to log in as "nobody" */
10781082
if( uid==0 ){
10791083
uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'");
@@ -1226,11 +1230,11 @@
12261230
p->TktFmt = p->Attach = p->ApndTkt =
12271231
p->ModWiki = p->ModTkt = p->Delete =
12281232
p->RdForum = p->WrForum = p->ModForum =
12291233
p->WrTForum = p->AdminForum =
12301234
p->EmailAlert = p->Announce = p->Debug =
1231
- p->WrUnver = p->Private = 1;
1235
+ p->Private = 1;
12321236
/* Fall thru into Read/Write */
12331237
case 'i': p->Read = p->Write = 1; break;
12341238
case 'o': p->Read = 1; break;
12351239
case 'z': p->Zip = 1; break;
12361240
12371241
--- src/login.c
+++ src/login.c
@@ -434,11 +434,13 @@
434 if( sqlite3_strglob("*Safari/537.36Mozilla/5.0*", zAgent)==0 ) return 0;
435
436 if( sqlite3_strglob("*Firefox/[1-9]*", zAgent)==0 ) return 1;
437 if( sqlite3_strglob("*Chrome/[1-9]*", zAgent)==0 ) return 1;
438 if( sqlite3_strglob("*(compatible;?MSIE?[1789]*", zAgent)==0 ) return 1;
439 if( sqlite3_strglob("*Trident/[1-9]*;?rv:[1-9]*", zAgent)==0 ) return 1; /* IE11+ */
 
 
440 if( sqlite3_strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent)==0 ) return 1;
441 return 0;
442 }
443 if( strncmp(zAgent, "Opera/", 6)==0 ) return 1;
444 if( strncmp(zAgent, "Safari/", 7)==0 ) return 1;
@@ -897,22 +899,24 @@
897
898 /*
899 ** Attempt to use Basic Authentication to establish the user. Return the
900 ** (non-zero) uid if successful. Return 0 if it does not work.
901 */
902 static int logic_basic_authentication(const char *zIpAddr){
903 const char *zAuth = PD("HTTP_AUTHORIZATION", 0);
904 int i;
905 int uid = 0;
906 int nDecode = 0;
907 char *zDecode = 0;
908 const char *zUsername = 0;
909 const char *zPasswd = 0;
910
911 if( zAuth==0 ) return 0; /* Fail: No Authentication: header */
912 while( fossil_isspace(zAuth[0]) ) zAuth++; /* Skip leading whitespace */
913 if( strncmp(zAuth, "Basic ", 6)!=0 ) return 0; /* Fail: Not Basic Authentication */
 
 
914
915 /* Parse out the username and password, separated by a ":" */
916 zAuth += 6;
917 while( fossil_isspace(zAuth[0]) ) zAuth++;
918 zDecode = decode64(zAuth, &nDecode);
@@ -1069,11 +1073,11 @@
1069 /* If the request didn't provide a login cookie or the login cookie didn't
1070 ** match a known valid user, check the HTTP "Authorization" header and
1071 ** see if those credentials are valid for a known user.
1072 */
1073 if( uid==0 && db_get_boolean("http_authentication_ok",0) ){
1074 uid = logic_basic_authentication(zIpAddr);
1075 }
1076
1077 /* If no user found yet, try to log in as "nobody" */
1078 if( uid==0 ){
1079 uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'");
@@ -1226,11 +1230,11 @@
1226 p->TktFmt = p->Attach = p->ApndTkt =
1227 p->ModWiki = p->ModTkt = p->Delete =
1228 p->RdForum = p->WrForum = p->ModForum =
1229 p->WrTForum = p->AdminForum =
1230 p->EmailAlert = p->Announce = p->Debug =
1231 p->WrUnver = p->Private = 1;
1232 /* Fall thru into Read/Write */
1233 case 'i': p->Read = p->Write = 1; break;
1234 case 'o': p->Read = 1; break;
1235 case 'z': p->Zip = 1; break;
1236
1237
--- src/login.c
+++ src/login.c
@@ -434,11 +434,13 @@
434 if( sqlite3_strglob("*Safari/537.36Mozilla/5.0*", zAgent)==0 ) return 0;
435
436 if( sqlite3_strglob("*Firefox/[1-9]*", zAgent)==0 ) return 1;
437 if( sqlite3_strglob("*Chrome/[1-9]*", zAgent)==0 ) return 1;
438 if( sqlite3_strglob("*(compatible;?MSIE?[1789]*", zAgent)==0 ) return 1;
439 if( sqlite3_strglob("*Trident/[1-9]*;?rv:[1-9]*", zAgent)==0 ){
440 return 1; /* IE11+ */
441 }
442 if( sqlite3_strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent)==0 ) return 1;
443 return 0;
444 }
445 if( strncmp(zAgent, "Opera/", 6)==0 ) return 1;
446 if( strncmp(zAgent, "Safari/", 7)==0 ) return 1;
@@ -897,22 +899,24 @@
899
900 /*
901 ** Attempt to use Basic Authentication to establish the user. Return the
902 ** (non-zero) uid if successful. Return 0 if it does not work.
903 */
904 static int login_basic_authentication(const char *zIpAddr){
905 const char *zAuth = PD("HTTP_AUTHORIZATION", 0);
906 int i;
907 int uid = 0;
908 int nDecode = 0;
909 char *zDecode = 0;
910 const char *zUsername = 0;
911 const char *zPasswd = 0;
912
913 if( zAuth==0 ) return 0; /* Fail: No Authentication: header */
914 while( fossil_isspace(zAuth[0]) ) zAuth++; /* Skip leading whitespace */
915 if( strncmp(zAuth, "Basic ", 6)!=0 ){
916 return 0; /* Fail: Not Basic Authentication */
917 }
918
919 /* Parse out the username and password, separated by a ":" */
920 zAuth += 6;
921 while( fossil_isspace(zAuth[0]) ) zAuth++;
922 zDecode = decode64(zAuth, &nDecode);
@@ -1069,11 +1073,11 @@
1073 /* If the request didn't provide a login cookie or the login cookie didn't
1074 ** match a known valid user, check the HTTP "Authorization" header and
1075 ** see if those credentials are valid for a known user.
1076 */
1077 if( uid==0 && db_get_boolean("http_authentication_ok",0) ){
1078 uid = login_basic_authentication(zIpAddr);
1079 }
1080
1081 /* If no user found yet, try to log in as "nobody" */
1082 if( uid==0 ){
1083 uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'");
@@ -1226,11 +1230,11 @@
1230 p->TktFmt = p->Attach = p->ApndTkt =
1231 p->ModWiki = p->ModTkt = p->Delete =
1232 p->RdForum = p->WrForum = p->ModForum =
1233 p->WrTForum = p->AdminForum =
1234 p->EmailAlert = p->Announce = p->Debug =
1235 p->Private = 1;
1236 /* Fall thru into Read/Write */
1237 case 'i': p->Read = p->Write = 1; break;
1238 case 'o': p->Read = 1; break;
1239 case 'z': p->Zip = 1; break;
1240
1241
+25 -4
--- src/main.c
+++ src/main.c
@@ -173,10 +173,11 @@
173173
char *zPath; /* Name of webpage being served */
174174
char *zExtra; /* Extra path information past the webpage name */
175175
char *zBaseURL; /* Full text of the URL being served */
176176
char *zHttpsURL; /* zBaseURL translated to https: */
177177
char *zTop; /* Parent directory of zPath */
178
+ const char *zExtRoot; /* Document root for the /ext sub-website */
178179
const char *zContentType; /* The content type of the input HTTP request */
179180
int iErrPriority; /* Priority of current error message */
180181
char *zErrMsg; /* Text of an error message */
181182
int sslNotAvailable; /* SSL is not available. Do not redirect to https: */
182183
Blob cgiIn; /* Input to an xfer www method */
@@ -1193,11 +1194,11 @@
11931194
** The g.zBaseURL is normally set based on HTTP_HOST and SCRIPT_NAME
11941195
** environment variables. However, if zAltBase is not NULL then it
11951196
** is the argument to the --baseurl option command-line option and
11961197
** g.zBaseURL and g.zTop is set from that instead.
11971198
*/
1198
-static void set_base_url(const char *zAltBase){
1199
+void set_base_url(const char *zAltBase){
11991200
int i;
12001201
const char *zHost;
12011202
const char *zMode;
12021203
const char *zCur;
12031204
@@ -1783,10 +1784,13 @@
17831784
@ <h1>Server Configuration Error</h1>
17841785
@ <p>The database schema on the server is out-of-date. Please ask
17851786
@ the administrator to run <b>fossil rebuild</b>.</p>
17861787
}
17871788
}else{
1789
+ if( (pCmd->eCmdFlags & CMDFLAG_RAWCONTENT)==0 ){
1790
+ cgi_decode_post_parameters();
1791
+ }
17881792
if( g.fCgiTrace ){
17891793
fossil_trace("######## Calling %s #########\n", pCmd->zName);
17901794
cgi_print_all(1, 1);
17911795
}
17921796
#ifdef FOSSIL_ENABLE_TH1_HOOKS
@@ -1941,10 +1945,13 @@
19411945
**
19421946
** debug: FILE Causing debugging information to be written
19431947
** into FILE.
19441948
**
19451949
** errorlog: FILE Warnings, errors, and panics written to FILE.
1950
+**
1951
+** extroot: DIR Directory that is the root of the sub-CGI tree
1952
+** on the /ext page.
19461953
**
19471954
** redirect: REPO URL Extract the "name" query parameter and search
19481955
** REPO for a check-in or ticket that matches the
19491956
** value of "name", then redirect to URL. There
19501957
** can be multiple "redirect:" lines that are
@@ -2087,10 +2094,19 @@
20872094
** to FILENAME.
20882095
*/
20892096
g.zErrlog = mprintf("%s", blob_str(&value));
20902097
blob_reset(&value);
20912098
continue;
2099
+ }
2100
+ if( blob_eq(&key, "extroot:") && blob_token(&line, &value) ){
2101
+ /* extroot: DIRECTORY
2102
+ **
2103
+ ** Enables the /ext webpage to use sub-cgi rooted at DIRECTORY
2104
+ */
2105
+ g.zExtRoot = mprintf("%s", blob_str(&value));
2106
+ blob_reset(&value);
2107
+ continue;
20922108
}
20932109
if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
20942110
/* HOME: VALUE
20952111
**
20962112
** Set CGI parameter "HOME" to VALUE. This is legacy. Use
@@ -2240,16 +2256,17 @@
22402256
** for requests coming from localhost, if the "localauth" setting is not
22412257
** enabled.
22422258
**
22432259
** Options:
22442260
** --baseurl URL base URL (useful with reverse proxies)
2261
+** --extroot DIR document root for the /ext extension mechanism
22452262
** --files GLOB comma-separate glob patterns for static file to serve
2246
-** --localauth enable automatic login for local connections
22472263
** --host NAME specify hostname of the server
22482264
** --https signal a request coming in via https
22492265
** --in FILE Take input from FILE instead of standard input
22502266
** --ipaddr ADDR Assume the request comes from the given IP address
2267
+** --localauth enable automatic login for local connections
22512268
** --nocompress do not compress HTTP replies
22522269
** --nodelay omit backoffice processing if it would delay process exit
22532270
** --nojail drop root privilege but do not enter the chroot jail
22542271
** --nossl signal that no SSL connections are available
22552272
** --notfound URL use URL as "HTTP 404, object not found" page.
@@ -2297,10 +2314,11 @@
22972314
noJail = find_option("nojail",0,0)!=0;
22982315
allowRepoList = find_option("repolist",0,0)!=0;
22992316
g.useLocalauth = find_option("localauth", 0, 0)!=0;
23002317
g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
23012318
g.fNoHttpCompress = find_option("nocompress",0,0)!=0;
2319
+ g.zExtRoot = find_option("extroot",0,1);
23022320
zInFile = find_option("in",0,1);
23032321
if( zInFile ){
23042322
backoffice_disable();
23052323
g.httpIn = fossil_fopen(zInFile, "rb");
23062324
if( g.httpIn==0 ) fossil_fatal("cannot open \"%s\" for reading", zInFile);
@@ -2391,10 +2409,11 @@
23912409
Th_InitTraceLog();
23922410
login_set_capabilities("sx", 0);
23932411
g.useLocalauth = 1;
23942412
g.httpIn = stdin;
23952413
g.httpOut = stdout;
2414
+ g.zExtRoot = find_option("extroot",0,1);
23962415
find_server_repository(2, 0);
23972416
g.cgiOutput = 1;
23982417
g.fNoHttpCompress = 1;
23992418
g.fullHttpReply = 1;
24002419
zIpAddr = cgi_ssh_remote_addr(0);
@@ -2402,11 +2421,11 @@
24022421
g.fSshClient |= CGI_SSH_CLIENT;
24032422
ssh_request_loop(zIpAddr, 0);
24042423
}else{
24052424
cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
24062425
cgi_handle_http_request(0);
2407
- process_one_web_page(0, 0, 0);
2426
+ process_one_web_page(0, 0, 1);
24082427
}
24092428
}
24102429
24112430
#if !defined(_WIN32)
24122431
#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
@@ -2484,11 +2503,11 @@
24842503
** by default.
24852504
**
24862505
** Options:
24872506
** --baseurl URL Use URL as the base (useful for reverse proxies)
24882507
** --create Create a new REPOSITORY if it does not already exist
2489
-** --page PAGE Start "ui" on PAGE. ex: --page "timeline?y=ci"
2508
+** --extroot DIR Document root for the /ext extension mechanism
24902509
** --files GLOBLIST Comma-separated list of glob patterns for static files
24912510
** --localauth enable automatic login for requests from localhost
24922511
** --localhost listen on 127.0.0.1 only (always true for "ui")
24932512
** --https Indicates that the input is coming through a reverse
24942513
** proxy that has already translated HTTPS into HTTP.
@@ -2497,10 +2516,11 @@
24972516
** --nocompress Do not compress HTTP replies
24982517
** --nojail Drop root privileges but do not enter the chroot jail
24992518
** --nossl signal that no SSL connections are available (Always
25002519
** set by default for the "ui" command)
25012520
** --notfound URL Redirect
2521
+** --page PAGE Start "ui" on PAGE. ex: --page "timeline?y=ci"
25022522
** -P|--port TCPPORT listen to request on port TCPPORT
25032523
** --th-trace trace TH1 execution (for debugging purposes)
25042524
** --repolist If REPOSITORY is dir, URL "/" lists repos.
25052525
** --scgi Accept SCGI rather than HTTP
25062526
** --skin LABEL Use override skin LABEL
@@ -2537,10 +2557,11 @@
25372557
#endif
25382558
25392559
if( g.zErrlog==0 ){
25402560
g.zErrlog = "-";
25412561
}
2562
+ g.zExtRoot = find_option("extroot",0,1);
25422563
zFileGlob = find_option("files-urlenc",0,1);
25432564
if( zFileGlob ){
25442565
char *z = mprintf("%s", zFileGlob);
25452566
dehttpize(z);
25462567
zFileGlob = z;
25472568
--- src/main.c
+++ src/main.c
@@ -173,10 +173,11 @@
173 char *zPath; /* Name of webpage being served */
174 char *zExtra; /* Extra path information past the webpage name */
175 char *zBaseURL; /* Full text of the URL being served */
176 char *zHttpsURL; /* zBaseURL translated to https: */
177 char *zTop; /* Parent directory of zPath */
 
178 const char *zContentType; /* The content type of the input HTTP request */
179 int iErrPriority; /* Priority of current error message */
180 char *zErrMsg; /* Text of an error message */
181 int sslNotAvailable; /* SSL is not available. Do not redirect to https: */
182 Blob cgiIn; /* Input to an xfer www method */
@@ -1193,11 +1194,11 @@
1193 ** The g.zBaseURL is normally set based on HTTP_HOST and SCRIPT_NAME
1194 ** environment variables. However, if zAltBase is not NULL then it
1195 ** is the argument to the --baseurl option command-line option and
1196 ** g.zBaseURL and g.zTop is set from that instead.
1197 */
1198 static void set_base_url(const char *zAltBase){
1199 int i;
1200 const char *zHost;
1201 const char *zMode;
1202 const char *zCur;
1203
@@ -1783,10 +1784,13 @@
1783 @ <h1>Server Configuration Error</h1>
1784 @ <p>The database schema on the server is out-of-date. Please ask
1785 @ the administrator to run <b>fossil rebuild</b>.</p>
1786 }
1787 }else{
 
 
 
1788 if( g.fCgiTrace ){
1789 fossil_trace("######## Calling %s #########\n", pCmd->zName);
1790 cgi_print_all(1, 1);
1791 }
1792 #ifdef FOSSIL_ENABLE_TH1_HOOKS
@@ -1941,10 +1945,13 @@
1941 **
1942 ** debug: FILE Causing debugging information to be written
1943 ** into FILE.
1944 **
1945 ** errorlog: FILE Warnings, errors, and panics written to FILE.
 
 
 
1946 **
1947 ** redirect: REPO URL Extract the "name" query parameter and search
1948 ** REPO for a check-in or ticket that matches the
1949 ** value of "name", then redirect to URL. There
1950 ** can be multiple "redirect:" lines that are
@@ -2087,10 +2094,19 @@
2087 ** to FILENAME.
2088 */
2089 g.zErrlog = mprintf("%s", blob_str(&value));
2090 blob_reset(&value);
2091 continue;
 
 
 
 
 
 
 
 
 
2092 }
2093 if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
2094 /* HOME: VALUE
2095 **
2096 ** Set CGI parameter "HOME" to VALUE. This is legacy. Use
@@ -2240,16 +2256,17 @@
2240 ** for requests coming from localhost, if the "localauth" setting is not
2241 ** enabled.
2242 **
2243 ** Options:
2244 ** --baseurl URL base URL (useful with reverse proxies)
 
2245 ** --files GLOB comma-separate glob patterns for static file to serve
2246 ** --localauth enable automatic login for local connections
2247 ** --host NAME specify hostname of the server
2248 ** --https signal a request coming in via https
2249 ** --in FILE Take input from FILE instead of standard input
2250 ** --ipaddr ADDR Assume the request comes from the given IP address
 
2251 ** --nocompress do not compress HTTP replies
2252 ** --nodelay omit backoffice processing if it would delay process exit
2253 ** --nojail drop root privilege but do not enter the chroot jail
2254 ** --nossl signal that no SSL connections are available
2255 ** --notfound URL use URL as "HTTP 404, object not found" page.
@@ -2297,10 +2314,11 @@
2297 noJail = find_option("nojail",0,0)!=0;
2298 allowRepoList = find_option("repolist",0,0)!=0;
2299 g.useLocalauth = find_option("localauth", 0, 0)!=0;
2300 g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
2301 g.fNoHttpCompress = find_option("nocompress",0,0)!=0;
 
2302 zInFile = find_option("in",0,1);
2303 if( zInFile ){
2304 backoffice_disable();
2305 g.httpIn = fossil_fopen(zInFile, "rb");
2306 if( g.httpIn==0 ) fossil_fatal("cannot open \"%s\" for reading", zInFile);
@@ -2391,10 +2409,11 @@
2391 Th_InitTraceLog();
2392 login_set_capabilities("sx", 0);
2393 g.useLocalauth = 1;
2394 g.httpIn = stdin;
2395 g.httpOut = stdout;
 
2396 find_server_repository(2, 0);
2397 g.cgiOutput = 1;
2398 g.fNoHttpCompress = 1;
2399 g.fullHttpReply = 1;
2400 zIpAddr = cgi_ssh_remote_addr(0);
@@ -2402,11 +2421,11 @@
2402 g.fSshClient |= CGI_SSH_CLIENT;
2403 ssh_request_loop(zIpAddr, 0);
2404 }else{
2405 cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
2406 cgi_handle_http_request(0);
2407 process_one_web_page(0, 0, 0);
2408 }
2409 }
2410
2411 #if !defined(_WIN32)
2412 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
@@ -2484,11 +2503,11 @@
2484 ** by default.
2485 **
2486 ** Options:
2487 ** --baseurl URL Use URL as the base (useful for reverse proxies)
2488 ** --create Create a new REPOSITORY if it does not already exist
2489 ** --page PAGE Start "ui" on PAGE. ex: --page "timeline?y=ci"
2490 ** --files GLOBLIST Comma-separated list of glob patterns for static files
2491 ** --localauth enable automatic login for requests from localhost
2492 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2493 ** --https Indicates that the input is coming through a reverse
2494 ** proxy that has already translated HTTPS into HTTP.
@@ -2497,10 +2516,11 @@
2497 ** --nocompress Do not compress HTTP replies
2498 ** --nojail Drop root privileges but do not enter the chroot jail
2499 ** --nossl signal that no SSL connections are available (Always
2500 ** set by default for the "ui" command)
2501 ** --notfound URL Redirect
 
2502 ** -P|--port TCPPORT listen to request on port TCPPORT
2503 ** --th-trace trace TH1 execution (for debugging purposes)
2504 ** --repolist If REPOSITORY is dir, URL "/" lists repos.
2505 ** --scgi Accept SCGI rather than HTTP
2506 ** --skin LABEL Use override skin LABEL
@@ -2537,10 +2557,11 @@
2537 #endif
2538
2539 if( g.zErrlog==0 ){
2540 g.zErrlog = "-";
2541 }
 
2542 zFileGlob = find_option("files-urlenc",0,1);
2543 if( zFileGlob ){
2544 char *z = mprintf("%s", zFileGlob);
2545 dehttpize(z);
2546 zFileGlob = z;
2547
--- src/main.c
+++ src/main.c
@@ -173,10 +173,11 @@
173 char *zPath; /* Name of webpage being served */
174 char *zExtra; /* Extra path information past the webpage name */
175 char *zBaseURL; /* Full text of the URL being served */
176 char *zHttpsURL; /* zBaseURL translated to https: */
177 char *zTop; /* Parent directory of zPath */
178 const char *zExtRoot; /* Document root for the /ext sub-website */
179 const char *zContentType; /* The content type of the input HTTP request */
180 int iErrPriority; /* Priority of current error message */
181 char *zErrMsg; /* Text of an error message */
182 int sslNotAvailable; /* SSL is not available. Do not redirect to https: */
183 Blob cgiIn; /* Input to an xfer www method */
@@ -1193,11 +1194,11 @@
1194 ** The g.zBaseURL is normally set based on HTTP_HOST and SCRIPT_NAME
1195 ** environment variables. However, if zAltBase is not NULL then it
1196 ** is the argument to the --baseurl option command-line option and
1197 ** g.zBaseURL and g.zTop is set from that instead.
1198 */
1199 void set_base_url(const char *zAltBase){
1200 int i;
1201 const char *zHost;
1202 const char *zMode;
1203 const char *zCur;
1204
@@ -1783,10 +1784,13 @@
1784 @ <h1>Server Configuration Error</h1>
1785 @ <p>The database schema on the server is out-of-date. Please ask
1786 @ the administrator to run <b>fossil rebuild</b>.</p>
1787 }
1788 }else{
1789 if( (pCmd->eCmdFlags & CMDFLAG_RAWCONTENT)==0 ){
1790 cgi_decode_post_parameters();
1791 }
1792 if( g.fCgiTrace ){
1793 fossil_trace("######## Calling %s #########\n", pCmd->zName);
1794 cgi_print_all(1, 1);
1795 }
1796 #ifdef FOSSIL_ENABLE_TH1_HOOKS
@@ -1941,10 +1945,13 @@
1945 **
1946 ** debug: FILE Causing debugging information to be written
1947 ** into FILE.
1948 **
1949 ** errorlog: FILE Warnings, errors, and panics written to FILE.
1950 **
1951 ** extroot: DIR Directory that is the root of the sub-CGI tree
1952 ** on the /ext page.
1953 **
1954 ** redirect: REPO URL Extract the "name" query parameter and search
1955 ** REPO for a check-in or ticket that matches the
1956 ** value of "name", then redirect to URL. There
1957 ** can be multiple "redirect:" lines that are
@@ -2087,10 +2094,19 @@
2094 ** to FILENAME.
2095 */
2096 g.zErrlog = mprintf("%s", blob_str(&value));
2097 blob_reset(&value);
2098 continue;
2099 }
2100 if( blob_eq(&key, "extroot:") && blob_token(&line, &value) ){
2101 /* extroot: DIRECTORY
2102 **
2103 ** Enables the /ext webpage to use sub-cgi rooted at DIRECTORY
2104 */
2105 g.zExtRoot = mprintf("%s", blob_str(&value));
2106 blob_reset(&value);
2107 continue;
2108 }
2109 if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){
2110 /* HOME: VALUE
2111 **
2112 ** Set CGI parameter "HOME" to VALUE. This is legacy. Use
@@ -2240,16 +2256,17 @@
2256 ** for requests coming from localhost, if the "localauth" setting is not
2257 ** enabled.
2258 **
2259 ** Options:
2260 ** --baseurl URL base URL (useful with reverse proxies)
2261 ** --extroot DIR document root for the /ext extension mechanism
2262 ** --files GLOB comma-separate glob patterns for static file to serve
 
2263 ** --host NAME specify hostname of the server
2264 ** --https signal a request coming in via https
2265 ** --in FILE Take input from FILE instead of standard input
2266 ** --ipaddr ADDR Assume the request comes from the given IP address
2267 ** --localauth enable automatic login for local connections
2268 ** --nocompress do not compress HTTP replies
2269 ** --nodelay omit backoffice processing if it would delay process exit
2270 ** --nojail drop root privilege but do not enter the chroot jail
2271 ** --nossl signal that no SSL connections are available
2272 ** --notfound URL use URL as "HTTP 404, object not found" page.
@@ -2297,10 +2314,11 @@
2314 noJail = find_option("nojail",0,0)!=0;
2315 allowRepoList = find_option("repolist",0,0)!=0;
2316 g.useLocalauth = find_option("localauth", 0, 0)!=0;
2317 g.sslNotAvailable = find_option("nossl", 0, 0)!=0;
2318 g.fNoHttpCompress = find_option("nocompress",0,0)!=0;
2319 g.zExtRoot = find_option("extroot",0,1);
2320 zInFile = find_option("in",0,1);
2321 if( zInFile ){
2322 backoffice_disable();
2323 g.httpIn = fossil_fopen(zInFile, "rb");
2324 if( g.httpIn==0 ) fossil_fatal("cannot open \"%s\" for reading", zInFile);
@@ -2391,10 +2409,11 @@
2409 Th_InitTraceLog();
2410 login_set_capabilities("sx", 0);
2411 g.useLocalauth = 1;
2412 g.httpIn = stdin;
2413 g.httpOut = stdout;
2414 g.zExtRoot = find_option("extroot",0,1);
2415 find_server_repository(2, 0);
2416 g.cgiOutput = 1;
2417 g.fNoHttpCompress = 1;
2418 g.fullHttpReply = 1;
2419 zIpAddr = cgi_ssh_remote_addr(0);
@@ -2402,11 +2421,11 @@
2421 g.fSshClient |= CGI_SSH_CLIENT;
2422 ssh_request_loop(zIpAddr, 0);
2423 }else{
2424 cgi_set_parameter("REMOTE_ADDR", "127.0.0.1");
2425 cgi_handle_http_request(0);
2426 process_one_web_page(0, 0, 1);
2427 }
2428 }
2429
2430 #if !defined(_WIN32)
2431 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
@@ -2484,11 +2503,11 @@
2503 ** by default.
2504 **
2505 ** Options:
2506 ** --baseurl URL Use URL as the base (useful for reverse proxies)
2507 ** --create Create a new REPOSITORY if it does not already exist
2508 ** --extroot DIR Document root for the /ext extension mechanism
2509 ** --files GLOBLIST Comma-separated list of glob patterns for static files
2510 ** --localauth enable automatic login for requests from localhost
2511 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2512 ** --https Indicates that the input is coming through a reverse
2513 ** proxy that has already translated HTTPS into HTTP.
@@ -2497,10 +2516,11 @@
2516 ** --nocompress Do not compress HTTP replies
2517 ** --nojail Drop root privileges but do not enter the chroot jail
2518 ** --nossl signal that no SSL connections are available (Always
2519 ** set by default for the "ui" command)
2520 ** --notfound URL Redirect
2521 ** --page PAGE Start "ui" on PAGE. ex: --page "timeline?y=ci"
2522 ** -P|--port TCPPORT listen to request on port TCPPORT
2523 ** --th-trace trace TH1 execution (for debugging purposes)
2524 ** --repolist If REPOSITORY is dir, URL "/" lists repos.
2525 ** --scgi Accept SCGI rather than HTTP
2526 ** --skin LABEL Use override skin LABEL
@@ -2537,10 +2557,11 @@
2557 #endif
2558
2559 if( g.zErrlog==0 ){
2560 g.zErrlog = "-";
2561 }
2562 g.zExtRoot = find_option("extroot",0,1);
2563 zFileGlob = find_option("files-urlenc",0,1);
2564 if( zFileGlob ){
2565 char *z = mprintf("%s", zFileGlob);
2566 dehttpize(z);
2567 zFileGlob = z;
2568
+12
--- src/main.mk
+++ src/main.mk
@@ -51,10 +51,11 @@
5151
$(SRCDIR)/doc.c \
5252
$(SRCDIR)/encode.c \
5353
$(SRCDIR)/etag.c \
5454
$(SRCDIR)/event.c \
5555
$(SRCDIR)/export.c \
56
+ $(SRCDIR)/extcgi.c \
5657
$(SRCDIR)/file.c \
5758
$(SRCDIR)/finfo.c \
5859
$(SRCDIR)/foci.c \
5960
$(SRCDIR)/forum.c \
6061
$(SRCDIR)/fshell.c \
@@ -264,10 +265,11 @@
264265
$(OBJDIR)/doc_.c \
265266
$(OBJDIR)/encode_.c \
266267
$(OBJDIR)/etag_.c \
267268
$(OBJDIR)/event_.c \
268269
$(OBJDIR)/export_.c \
270
+ $(OBJDIR)/extcgi_.c \
269271
$(OBJDIR)/file_.c \
270272
$(OBJDIR)/finfo_.c \
271273
$(OBJDIR)/foci_.c \
272274
$(OBJDIR)/forum_.c \
273275
$(OBJDIR)/fshell_.c \
@@ -403,10 +405,11 @@
403405
$(OBJDIR)/doc.o \
404406
$(OBJDIR)/encode.o \
405407
$(OBJDIR)/etag.o \
406408
$(OBJDIR)/event.o \
407409
$(OBJDIR)/export.o \
410
+ $(OBJDIR)/extcgi.o \
408411
$(OBJDIR)/file.o \
409412
$(OBJDIR)/finfo.o \
410413
$(OBJDIR)/foci.o \
411414
$(OBJDIR)/forum.o \
412415
$(OBJDIR)/fshell.o \
@@ -740,10 +743,11 @@
740743
$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
741744
$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
742745
$(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
743746
$(OBJDIR)/event_.c:$(OBJDIR)/event.h \
744747
$(OBJDIR)/export_.c:$(OBJDIR)/export.h \
748
+ $(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \
745749
$(OBJDIR)/file_.c:$(OBJDIR)/file.h \
746750
$(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
747751
$(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
748752
$(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \
749753
$(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
@@ -1142,10 +1146,18 @@
11421146
11431147
$(OBJDIR)/export.o: $(OBJDIR)/export_.c $(OBJDIR)/export.h $(SRCDIR)/config.h
11441148
$(XTCC) -o $(OBJDIR)/export.o -c $(OBJDIR)/export_.c
11451149
11461150
$(OBJDIR)/export.h: $(OBJDIR)/headers
1151
+
1152
+$(OBJDIR)/extcgi_.c: $(SRCDIR)/extcgi.c $(OBJDIR)/translate
1153
+ $(OBJDIR)/translate $(SRCDIR)/extcgi.c >$@
1154
+
1155
+$(OBJDIR)/extcgi.o: $(OBJDIR)/extcgi_.c $(OBJDIR)/extcgi.h $(SRCDIR)/config.h
1156
+ $(XTCC) -o $(OBJDIR)/extcgi.o -c $(OBJDIR)/extcgi_.c
1157
+
1158
+$(OBJDIR)/extcgi.h: $(OBJDIR)/headers
11471159
11481160
$(OBJDIR)/file_.c: $(SRCDIR)/file.c $(OBJDIR)/translate
11491161
$(OBJDIR)/translate $(SRCDIR)/file.c >$@
11501162
11511163
$(OBJDIR)/file.o: $(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h
11521164
--- src/main.mk
+++ src/main.mk
@@ -51,10 +51,11 @@
51 $(SRCDIR)/doc.c \
52 $(SRCDIR)/encode.c \
53 $(SRCDIR)/etag.c \
54 $(SRCDIR)/event.c \
55 $(SRCDIR)/export.c \
 
56 $(SRCDIR)/file.c \
57 $(SRCDIR)/finfo.c \
58 $(SRCDIR)/foci.c \
59 $(SRCDIR)/forum.c \
60 $(SRCDIR)/fshell.c \
@@ -264,10 +265,11 @@
264 $(OBJDIR)/doc_.c \
265 $(OBJDIR)/encode_.c \
266 $(OBJDIR)/etag_.c \
267 $(OBJDIR)/event_.c \
268 $(OBJDIR)/export_.c \
 
269 $(OBJDIR)/file_.c \
270 $(OBJDIR)/finfo_.c \
271 $(OBJDIR)/foci_.c \
272 $(OBJDIR)/forum_.c \
273 $(OBJDIR)/fshell_.c \
@@ -403,10 +405,11 @@
403 $(OBJDIR)/doc.o \
404 $(OBJDIR)/encode.o \
405 $(OBJDIR)/etag.o \
406 $(OBJDIR)/event.o \
407 $(OBJDIR)/export.o \
 
408 $(OBJDIR)/file.o \
409 $(OBJDIR)/finfo.o \
410 $(OBJDIR)/foci.o \
411 $(OBJDIR)/forum.o \
412 $(OBJDIR)/fshell.o \
@@ -740,10 +743,11 @@
740 $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
741 $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
742 $(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
743 $(OBJDIR)/event_.c:$(OBJDIR)/event.h \
744 $(OBJDIR)/export_.c:$(OBJDIR)/export.h \
 
745 $(OBJDIR)/file_.c:$(OBJDIR)/file.h \
746 $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
747 $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
748 $(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \
749 $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
@@ -1142,10 +1146,18 @@
1142
1143 $(OBJDIR)/export.o: $(OBJDIR)/export_.c $(OBJDIR)/export.h $(SRCDIR)/config.h
1144 $(XTCC) -o $(OBJDIR)/export.o -c $(OBJDIR)/export_.c
1145
1146 $(OBJDIR)/export.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1147
1148 $(OBJDIR)/file_.c: $(SRCDIR)/file.c $(OBJDIR)/translate
1149 $(OBJDIR)/translate $(SRCDIR)/file.c >$@
1150
1151 $(OBJDIR)/file.o: $(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h
1152
--- src/main.mk
+++ src/main.mk
@@ -51,10 +51,11 @@
51 $(SRCDIR)/doc.c \
52 $(SRCDIR)/encode.c \
53 $(SRCDIR)/etag.c \
54 $(SRCDIR)/event.c \
55 $(SRCDIR)/export.c \
56 $(SRCDIR)/extcgi.c \
57 $(SRCDIR)/file.c \
58 $(SRCDIR)/finfo.c \
59 $(SRCDIR)/foci.c \
60 $(SRCDIR)/forum.c \
61 $(SRCDIR)/fshell.c \
@@ -264,10 +265,11 @@
265 $(OBJDIR)/doc_.c \
266 $(OBJDIR)/encode_.c \
267 $(OBJDIR)/etag_.c \
268 $(OBJDIR)/event_.c \
269 $(OBJDIR)/export_.c \
270 $(OBJDIR)/extcgi_.c \
271 $(OBJDIR)/file_.c \
272 $(OBJDIR)/finfo_.c \
273 $(OBJDIR)/foci_.c \
274 $(OBJDIR)/forum_.c \
275 $(OBJDIR)/fshell_.c \
@@ -403,10 +405,11 @@
405 $(OBJDIR)/doc.o \
406 $(OBJDIR)/encode.o \
407 $(OBJDIR)/etag.o \
408 $(OBJDIR)/event.o \
409 $(OBJDIR)/export.o \
410 $(OBJDIR)/extcgi.o \
411 $(OBJDIR)/file.o \
412 $(OBJDIR)/finfo.o \
413 $(OBJDIR)/foci.o \
414 $(OBJDIR)/forum.o \
415 $(OBJDIR)/fshell.o \
@@ -740,10 +743,11 @@
743 $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
744 $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
745 $(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
746 $(OBJDIR)/event_.c:$(OBJDIR)/event.h \
747 $(OBJDIR)/export_.c:$(OBJDIR)/export.h \
748 $(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \
749 $(OBJDIR)/file_.c:$(OBJDIR)/file.h \
750 $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
751 $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
752 $(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \
753 $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
@@ -1142,10 +1146,18 @@
1146
1147 $(OBJDIR)/export.o: $(OBJDIR)/export_.c $(OBJDIR)/export.h $(SRCDIR)/config.h
1148 $(XTCC) -o $(OBJDIR)/export.o -c $(OBJDIR)/export_.c
1149
1150 $(OBJDIR)/export.h: $(OBJDIR)/headers
1151
1152 $(OBJDIR)/extcgi_.c: $(SRCDIR)/extcgi.c $(OBJDIR)/translate
1153 $(OBJDIR)/translate $(SRCDIR)/extcgi.c >$@
1154
1155 $(OBJDIR)/extcgi.o: $(OBJDIR)/extcgi_.c $(OBJDIR)/extcgi.h $(SRCDIR)/config.h
1156 $(XTCC) -o $(OBJDIR)/extcgi.o -c $(OBJDIR)/extcgi_.c
1157
1158 $(OBJDIR)/extcgi.h: $(OBJDIR)/headers
1159
1160 $(OBJDIR)/file_.c: $(SRCDIR)/file.c $(OBJDIR)/translate
1161 $(OBJDIR)/translate $(SRCDIR)/file.c >$@
1162
1163 $(OBJDIR)/file.o: $(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h
1164
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -61,10 +61,11 @@
6161
dispatch
6262
doc
6363
encode
6464
etag
6565
event
66
+ extcgi
6667
export
6768
file
6869
finfo
6970
foci
7071
forum
7172
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -61,10 +61,11 @@
61 dispatch
62 doc
63 encode
64 etag
65 event
 
66 export
67 file
68 finfo
69 foci
70 forum
71
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -61,10 +61,11 @@
61 dispatch
62 doc
63 encode
64 etag
65 event
66 extcgi
67 export
68 file
69 finfo
70 foci
71 forum
72
--- src/mkindex.c
+++ src/mkindex.c
@@ -89,10 +89,11 @@
8989
#define CMDFLAG_COMMAND 0x0010 /* A command */
9090
#define CMDFLAG_SETTING 0x0020 /* A setting */
9191
#define CMDFLAG_VERSIONABLE 0x0040 /* A versionable setting */
9292
#define CMDFLAG_BLOCKTEXT 0x0080 /* Multi-line text setting */
9393
#define CMDFLAG_BOOLEAN 0x0100 /* A boolean setting */
94
+#define CMDFLAG_RAWCONTENT 0x0200 /* Do not interpret webpage content */
9495
/**************************************************************************/
9596
9697
/*
9798
** Each entry looks like this:
9899
*/
@@ -236,10 +237,12 @@
236237
aEntry[nUsed].eType &= ~(CMDFLAG_1ST_TIER|CMDFLAG_TEST);
237238
aEntry[nUsed].eType |= CMDFLAG_2ND_TIER;
238239
}else if( j==4 && strncmp(&zLine[i], "test", j)==0 ){
239240
aEntry[nUsed].eType &= ~(CMDFLAG_1ST_TIER|CMDFLAG_2ND_TIER);
240241
aEntry[nUsed].eType |= CMDFLAG_TEST;
242
+ }else if( j==11 && strncmp(&zLine[i], "raw-content", j)==0 ){
243
+ aEntry[nUsed].eType |= CMDFLAG_RAWCONTENT;
241244
}else if( j==7 && strncmp(&zLine[i], "boolean", j)==0 ){
242245
aEntry[nUsed].eType &= ~(CMDFLAG_BLOCKTEXT);
243246
aEntry[nUsed].iWidth = 0;
244247
aEntry[nUsed].eType |= CMDFLAG_BOOLEAN;
245248
}else if( j==10 && strncmp(&zLine[i], "block-text", j)==0 ){
246249
--- src/mkindex.c
+++ src/mkindex.c
@@ -89,10 +89,11 @@
89 #define CMDFLAG_COMMAND 0x0010 /* A command */
90 #define CMDFLAG_SETTING 0x0020 /* A setting */
91 #define CMDFLAG_VERSIONABLE 0x0040 /* A versionable setting */
92 #define CMDFLAG_BLOCKTEXT 0x0080 /* Multi-line text setting */
93 #define CMDFLAG_BOOLEAN 0x0100 /* A boolean setting */
 
94 /**************************************************************************/
95
96 /*
97 ** Each entry looks like this:
98 */
@@ -236,10 +237,12 @@
236 aEntry[nUsed].eType &= ~(CMDFLAG_1ST_TIER|CMDFLAG_TEST);
237 aEntry[nUsed].eType |= CMDFLAG_2ND_TIER;
238 }else if( j==4 && strncmp(&zLine[i], "test", j)==0 ){
239 aEntry[nUsed].eType &= ~(CMDFLAG_1ST_TIER|CMDFLAG_2ND_TIER);
240 aEntry[nUsed].eType |= CMDFLAG_TEST;
 
 
241 }else if( j==7 && strncmp(&zLine[i], "boolean", j)==0 ){
242 aEntry[nUsed].eType &= ~(CMDFLAG_BLOCKTEXT);
243 aEntry[nUsed].iWidth = 0;
244 aEntry[nUsed].eType |= CMDFLAG_BOOLEAN;
245 }else if( j==10 && strncmp(&zLine[i], "block-text", j)==0 ){
246
--- src/mkindex.c
+++ src/mkindex.c
@@ -89,10 +89,11 @@
89 #define CMDFLAG_COMMAND 0x0010 /* A command */
90 #define CMDFLAG_SETTING 0x0020 /* A setting */
91 #define CMDFLAG_VERSIONABLE 0x0040 /* A versionable setting */
92 #define CMDFLAG_BLOCKTEXT 0x0080 /* Multi-line text setting */
93 #define CMDFLAG_BOOLEAN 0x0100 /* A boolean setting */
94 #define CMDFLAG_RAWCONTENT 0x0200 /* Do not interpret webpage content */
95 /**************************************************************************/
96
97 /*
98 ** Each entry looks like this:
99 */
@@ -236,10 +237,12 @@
237 aEntry[nUsed].eType &= ~(CMDFLAG_1ST_TIER|CMDFLAG_TEST);
238 aEntry[nUsed].eType |= CMDFLAG_2ND_TIER;
239 }else if( j==4 && strncmp(&zLine[i], "test", j)==0 ){
240 aEntry[nUsed].eType &= ~(CMDFLAG_1ST_TIER|CMDFLAG_2ND_TIER);
241 aEntry[nUsed].eType |= CMDFLAG_TEST;
242 }else if( j==11 && strncmp(&zLine[i], "raw-content", j)==0 ){
243 aEntry[nUsed].eType |= CMDFLAG_RAWCONTENT;
244 }else if( j==7 && strncmp(&zLine[i], "boolean", j)==0 ){
245 aEntry[nUsed].eType &= ~(CMDFLAG_BLOCKTEXT);
246 aEntry[nUsed].iWidth = 0;
247 aEntry[nUsed].eType |= CMDFLAG_BOOLEAN;
248 }else if( j==10 && strncmp(&zLine[i], "block-text", j)==0 ){
249
+12 -2
--- src/popen.c
+++ src/popen.c
@@ -121,11 +121,17 @@
121121
** Note that *ppIn is an unbuffered file descriptor, not a FILE.
122122
** The process ID of the child is written into *pChildPid.
123123
**
124124
** Return the number of errors.
125125
*/
126
-int popen2(const char *zCmd, int *pfdIn, FILE **ppOut, int *pChildPid){
126
+int popen2(
127
+ const char *zCmd, /* Command to run in the child process */
128
+ int *pfdIn, /* Read from child using this file descriptor */
129
+ FILE **ppOut, /* Write to child using this file descriptor */
130
+ int *pChildPid, /* PID of the child process */
131
+ int bDirect /* 0: run zCmd as a shell cmd. 1: run directly */
132
+){
127133
#ifdef _WIN32
128134
HANDLE hStdinRd, hStdinWr, hStdoutRd, hStdoutWr, hStderr;
129135
SECURITY_ATTRIBUTES saAttr;
130136
DWORD childPid = 0;
131137
int fd;
@@ -189,11 +195,15 @@
189195
close(1);
190196
fd = dup(pin[1]);
191197
if( fd!=1 ) nErr++;
192198
close(pin[0]);
193199
close(pin[1]);
194
- execl("/bin/sh", "/bin/sh", "-c", zCmd, (char*)0);
200
+ if( bDirect ){
201
+ execl(zCmd, zCmd, (char*)0);
202
+ }else{
203
+ execl("/bin/sh", "/bin/sh", "-c", zCmd, (char*)0);
204
+ }
195205
return 1;
196206
}else{
197207
/* This is the parent process */
198208
close(pin[1]);
199209
*pfdIn = pin[0];
200210
--- src/popen.c
+++ src/popen.c
@@ -121,11 +121,17 @@
121 ** Note that *ppIn is an unbuffered file descriptor, not a FILE.
122 ** The process ID of the child is written into *pChildPid.
123 **
124 ** Return the number of errors.
125 */
126 int popen2(const char *zCmd, int *pfdIn, FILE **ppOut, int *pChildPid){
 
 
 
 
 
 
127 #ifdef _WIN32
128 HANDLE hStdinRd, hStdinWr, hStdoutRd, hStdoutWr, hStderr;
129 SECURITY_ATTRIBUTES saAttr;
130 DWORD childPid = 0;
131 int fd;
@@ -189,11 +195,15 @@
189 close(1);
190 fd = dup(pin[1]);
191 if( fd!=1 ) nErr++;
192 close(pin[0]);
193 close(pin[1]);
194 execl("/bin/sh", "/bin/sh", "-c", zCmd, (char*)0);
 
 
 
 
195 return 1;
196 }else{
197 /* This is the parent process */
198 close(pin[1]);
199 *pfdIn = pin[0];
200
--- src/popen.c
+++ src/popen.c
@@ -121,11 +121,17 @@
121 ** Note that *ppIn is an unbuffered file descriptor, not a FILE.
122 ** The process ID of the child is written into *pChildPid.
123 **
124 ** Return the number of errors.
125 */
126 int popen2(
127 const char *zCmd, /* Command to run in the child process */
128 int *pfdIn, /* Read from child using this file descriptor */
129 FILE **ppOut, /* Write to child using this file descriptor */
130 int *pChildPid, /* PID of the child process */
131 int bDirect /* 0: run zCmd as a shell cmd. 1: run directly */
132 ){
133 #ifdef _WIN32
134 HANDLE hStdinRd, hStdinWr, hStdoutRd, hStdoutWr, hStderr;
135 SECURITY_ATTRIBUTES saAttr;
136 DWORD childPid = 0;
137 int fd;
@@ -189,11 +195,15 @@
195 close(1);
196 fd = dup(pin[1]);
197 if( fd!=1 ) nErr++;
198 close(pin[0]);
199 close(pin[1]);
200 if( bDirect ){
201 execl(zCmd, zCmd, (char*)0);
202 }else{
203 execl("/bin/sh", "/bin/sh", "-c", zCmd, (char*)0);
204 }
205 return 1;
206 }else{
207 /* This is the parent process */
208 close(pin[1]);
209 *pfdIn = pin[0];
210
+99 -38
--- src/repolist.c
+++ src/repolist.c
@@ -27,30 +27,44 @@
2727
** input. All other fields are outputs.
2828
*/
2929
struct RepoInfo {
3030
char *zRepoName; /* Name of the repository file */
3131
int isValid; /* True if zRepoName is a valid Fossil repository */
32
+ int isRepolistSkin; /* 1 or 2 if this repository wants to be the skin
33
+ ** for the repository list. 2 means do use this
34
+ ** repository but do not display it in the list. */
3235
char *zProjName; /* Project Name. Memory from fossil_malloc() */
3336
double rMTime; /* Last update. Julian day number */
3437
};
3538
#endif
3639
3740
/*
3841
** Discover information about the repository given by
39
-** pRepo->zRepoName.
42
+** pRepo->zRepoName. The discovered information is stored in other
43
+** fields of the RepoInfo object.
4044
*/
41
-void remote_repo_info(RepoInfo *pRepo){
45
+static void remote_repo_info(RepoInfo *pRepo){
4246
sqlite3 *db;
4347
sqlite3_stmt *pStmt;
4448
int rc;
4549
50
+ pRepo->isRepolistSkin = 0;
4651
pRepo->isValid = 0;
4752
pRepo->zProjName = 0;
4853
pRepo->rMTime = 0.0;
4954
5055
g.dbIgnoreErrors++;
5156
rc = sqlite3_open_v2(pRepo->zRepoName, &db, SQLITE_OPEN_READWRITE, 0);
57
+ if( rc ) goto finish_repo_list;
58
+ rc = sqlite3_prepare_v2(db, "SELECT value FROM config"
59
+ " WHERE name='repolist-skin'",
60
+ -1, &pStmt, 0);
61
+ if( rc ) goto finish_repo_list;
62
+ if( sqlite3_step(pStmt)==SQLITE_ROW ){
63
+ pRepo->isRepolistSkin = sqlite3_column_int(pStmt,0);
64
+ }
65
+ sqlite3_finalize(pStmt);
5266
if( rc ) goto finish_repo_list;
5367
rc = sqlite3_prepare_v2(db, "SELECT value FROM config"
5468
" WHERE name='project-name'",
5569
-1, &pStmt, 0);
5670
if( rc ) goto finish_repo_list;
@@ -85,15 +99,20 @@
8599
**
86100
** Or, if no repositories can be located beneath g.zRepositoryName,
87101
** return 0.
88102
*/
89103
int repo_list_page(void){
90
- Blob base;
91
- int n = 0;
92
- int allRepo;
104
+ Blob base; /* document root for all repositories */
105
+ int n = 0; /* Number of repositories found */
106
+ int allRepo; /* True if running "fossil ui all".
107
+ ** False if a directory scan of base for repos */
108
+ Blob html; /* Html for the body of the repository list */
109
+ char *zSkinRepo = 0; /* Name of the repository database used for skins */
110
+ char *zSkinUrl = 0; /* URL for the skin database */
93111
94112
assert( g.db==0 );
113
+ blob_init(&html, 0, 0);
95114
if( fossil_strcmp(g.zRepositoryName,"/")==0 && !g.fJail ){
96115
/* For the special case of the "repository directory" being "/",
97116
** show all of the repositories named in the ~/.fossil database.
98117
**
99118
** On unix systems, then entries are of the form "repo:/home/..."
@@ -118,28 +137,24 @@
118137
db_multi_exec("CREATE TABLE vfile(pathname);");
119138
vfile_scan(&base, blob_size(&base), 0, 0, 0);
120139
db_multi_exec("DELETE FROM sfile WHERE pathname NOT GLOB '*[^/].fossil'");
121140
allRepo = 0;
122141
}
123
- @ <html>
124
- @ <head>
125
- @ <base href="%s(g.zBaseURL)/" />
126
- @ <meta name="viewport" content="width=device-width, initial-scale=1.0">
127
- @ <title>Repository List</title>
128
- @ </head>
129
- @ <body>
130142
n = db_int(0, "SELECT count(*) FROM sfile");
131
- if( n>0 ){
143
+ if( n==0 ){
144
+ sqlite3_close(g.db);
145
+ return 0;
146
+ }else{
132147
Stmt q;
133148
double rNow;
134
- @ <h1 align="center">Fossil Repositories</h1>
135
- @ <table border="0" class="sortable" data-init-sort="1" \
136
- @ data-column-types="tntnk"><thead>
137
- @ <tr><th>Filename<th width="20">\
138
- @ <th>Project Name<th width="20">\
139
- @ <th>Last Modified</tr>
140
- @ </thead><tbody>
149
+ blob_append_sql(&html,
150
+ "<table border='0' class='sortable' data-init-sort='1'"
151
+ " data-column-types='txtxk'><thead>\n"
152
+ "<tr><th>Filename<th width='20'>"
153
+ "<th>Project Name<th width='20'>"
154
+ "<th>Last Modified</tr>\n"
155
+ "</thead><tbody>\n");
141156
db_prepare(&q, "SELECT pathname"
142157
" FROM sfile ORDER BY pathname COLLATE nocase;");
143158
rNow = db_double(0, "SELECT julianday('now')");
144159
while( db_step(&q)==SQLITE_ROW ){
145160
const char *zName = db_column_text(&q, 0);
@@ -162,51 +177,97 @@
162177
}else{
163178
zFull = mprintf("%s/%s", g.zRepositoryName, zName);
164179
}
165180
x.zRepoName = zFull;
166181
remote_repo_info(&x);
182
+ if( x.isRepolistSkin ){
183
+ if( zSkinRepo==0 ){
184
+ zSkinRepo = mprintf("%s", x.zRepoName);
185
+ zSkinUrl = mprintf("%s", zUrl);
186
+ }
187
+ }
167188
fossil_free(zFull);
168189
if( !x.isValid ){
169190
continue;
191
+ }
192
+ if( x.isRepolistSkin==2 && !allRepo ){
193
+ /* Repositories with repolist-skin==2 are omitted from directory
194
+ ** scan lists, but included in "fossil all ui" lists */
195
+ continue;
170196
}
171197
iAge = (rNow - x.rMTime)*86400;
172198
if( iAge<0 ) x.rMTime = rNow;
173199
zAge = human_readable_age(rNow - x.rMTime);
174
- @ <tr><td valign="top">\
200
+ blob_append_sql(&html, "<tr><td valign='top'>");
175201
if( sqlite3_strglob("*.fossil", zName)!=0 ){
176202
/* The "fossil server DIRECTORY" and "fossil ui DIRECTORY" commands
177203
** do not work for repositories whose names do not end in ".fossil".
178204
** So do not hyperlink those cases. */
179
- @ %h(zName)
205
+ blob_append_sql(&html,"%h",zName);
180206
} else if( sqlite3_strglob("*/.*", zName)==0 ){
181
- /* Do not show hidden repos */
182
- @ %h(zName) (hidden)
207
+ /* Do not show hyperlinks for hidden repos */
208
+ blob_append_sql(&html, "%h (hidden)", zName);
183209
} else if( allRepo && sqlite3_strglob("[a-zA-Z]:/?*", zName)!=0 ){
184
- @ <a href="%R/%T(zUrl)/home" target="_blank">/%h(zName)</a>
210
+ blob_append_sql(&html,
211
+ "<a href='/%T/home' target='_blank'>/%h</a>\n",
212
+ zUrl, zName);
185213
}else{
186
- @ <a href="%R/%T(zUrl)/home" target="_blank">%h(zName)</a>
214
+ blob_append_sql(&html,
215
+ "<a href='/%T/home' target='_blank'>%h</a>\n",
216
+ zUrl, zName);
187217
}
188218
if( x.zProjName ){
189
- @ <td></td><td>%h(x.zProjName)</td>
219
+ blob_append_sql(&html, "<td></td><td>%h</td>\n", x.zProjName);
190220
fossil_free(x.zProjName);
191221
}else{
192
- @ <td></td><td></td>
222
+ blob_append_sql(&html, "<td></td><td></td>\n");
193223
}
194
- @ <td></td><td data-sortkey='%08x(iAge)'>%h(zAge)</tr>
224
+ blob_append_sql(&html,
225
+ "<td></td><td data-sortkey='%08x'>%h</tr>\n",
226
+ iAge, zAge);
195227
fossil_free(zAge);
196228
sqlite3_free(zUrl);
197229
}
198
- @ </tbody></table>
230
+ db_finalize(&q);
231
+ blob_append_sql(&html,"</tbody></table>\n");
232
+ }
233
+ if( zSkinRepo ){
234
+ char *zNewBase = mprintf("%s/%s", g.zBaseURL, zSkinUrl);
235
+ g.zBaseURL = 0;
236
+ set_base_url(zNewBase);
237
+ db_open_repository(zSkinRepo);
238
+ fossil_free(zSkinRepo);
239
+ fossil_free(zSkinUrl);
240
+ }
241
+ if( g.repositoryOpen ){
242
+ /* This case runs if remote_repository_info() found a repository
243
+ ** that has the "repolist_skin" property set to non-zero and left
244
+ ** that repository open in g.db. Use the skin of that repository
245
+ ** for display. */
246
+ login_check_credentials();
247
+ style_header("Repository List");
248
+ @ %s(blob_str(&html))
249
+ style_table_sorter();
250
+ style_footer();
199251
}else{
200
- @ <h1>No Repositories Found</h1>
201
- }
202
- @ <script>%s(builtin_text("sorttable.js"))</script>
203
- @ </body>
204
- @ </html>
205
- cgi_reply();
206
- sqlite3_close(g.db);
207
- g.db = 0;
252
+ /* If no repositories were found that had the "repolist_skin"
253
+ ** property set, then use a default skin */
254
+ @ <html>
255
+ @ <head>
256
+ @ <base href="%s(g.zBaseURL)/" />
257
+ @ <meta name="viewport" content="width=device-width, initial-scale=1.0">
258
+ @ <title>Repository List</title>
259
+ @ </head>
260
+ @ <body>
261
+ @ <h1 align="center">Fossil Repositories</h1>
262
+ @ %s(blob_str(&html))
263
+ @ <script>%s(builtin_text("sorttable.js"))</script>
264
+ @ </body>
265
+ @ </html>
266
+ }
267
+ blob_reset(&html);
268
+ cgi_reply();
208269
return n;
209270
}
210271
211272
/*
212273
** COMMAND: test-list-page
213274
--- src/repolist.c
+++ src/repolist.c
@@ -27,30 +27,44 @@
27 ** input. All other fields are outputs.
28 */
29 struct RepoInfo {
30 char *zRepoName; /* Name of the repository file */
31 int isValid; /* True if zRepoName is a valid Fossil repository */
 
 
 
32 char *zProjName; /* Project Name. Memory from fossil_malloc() */
33 double rMTime; /* Last update. Julian day number */
34 };
35 #endif
36
37 /*
38 ** Discover information about the repository given by
39 ** pRepo->zRepoName.
 
40 */
41 void remote_repo_info(RepoInfo *pRepo){
42 sqlite3 *db;
43 sqlite3_stmt *pStmt;
44 int rc;
45
 
46 pRepo->isValid = 0;
47 pRepo->zProjName = 0;
48 pRepo->rMTime = 0.0;
49
50 g.dbIgnoreErrors++;
51 rc = sqlite3_open_v2(pRepo->zRepoName, &db, SQLITE_OPEN_READWRITE, 0);
 
 
 
 
 
 
 
 
 
52 if( rc ) goto finish_repo_list;
53 rc = sqlite3_prepare_v2(db, "SELECT value FROM config"
54 " WHERE name='project-name'",
55 -1, &pStmt, 0);
56 if( rc ) goto finish_repo_list;
@@ -85,15 +99,20 @@
85 **
86 ** Or, if no repositories can be located beneath g.zRepositoryName,
87 ** return 0.
88 */
89 int repo_list_page(void){
90 Blob base;
91 int n = 0;
92 int allRepo;
 
 
 
 
93
94 assert( g.db==0 );
 
95 if( fossil_strcmp(g.zRepositoryName,"/")==0 && !g.fJail ){
96 /* For the special case of the "repository directory" being "/",
97 ** show all of the repositories named in the ~/.fossil database.
98 **
99 ** On unix systems, then entries are of the form "repo:/home/..."
@@ -118,28 +137,24 @@
118 db_multi_exec("CREATE TABLE vfile(pathname);");
119 vfile_scan(&base, blob_size(&base), 0, 0, 0);
120 db_multi_exec("DELETE FROM sfile WHERE pathname NOT GLOB '*[^/].fossil'");
121 allRepo = 0;
122 }
123 @ <html>
124 @ <head>
125 @ <base href="%s(g.zBaseURL)/" />
126 @ <meta name="viewport" content="width=device-width, initial-scale=1.0">
127 @ <title>Repository List</title>
128 @ </head>
129 @ <body>
130 n = db_int(0, "SELECT count(*) FROM sfile");
131 if( n>0 ){
 
 
 
132 Stmt q;
133 double rNow;
134 @ <h1 align="center">Fossil Repositories</h1>
135 @ <table border="0" class="sortable" data-init-sort="1" \
136 @ data-column-types="tntnk"><thead>
137 @ <tr><th>Filename<th width="20">\
138 @ <th>Project Name<th width="20">\
139 @ <th>Last Modified</tr>
140 @ </thead><tbody>
141 db_prepare(&q, "SELECT pathname"
142 " FROM sfile ORDER BY pathname COLLATE nocase;");
143 rNow = db_double(0, "SELECT julianday('now')");
144 while( db_step(&q)==SQLITE_ROW ){
145 const char *zName = db_column_text(&q, 0);
@@ -162,51 +177,97 @@
162 }else{
163 zFull = mprintf("%s/%s", g.zRepositoryName, zName);
164 }
165 x.zRepoName = zFull;
166 remote_repo_info(&x);
 
 
 
 
 
 
167 fossil_free(zFull);
168 if( !x.isValid ){
169 continue;
 
 
 
 
 
170 }
171 iAge = (rNow - x.rMTime)*86400;
172 if( iAge<0 ) x.rMTime = rNow;
173 zAge = human_readable_age(rNow - x.rMTime);
174 @ <tr><td valign="top">\
175 if( sqlite3_strglob("*.fossil", zName)!=0 ){
176 /* The "fossil server DIRECTORY" and "fossil ui DIRECTORY" commands
177 ** do not work for repositories whose names do not end in ".fossil".
178 ** So do not hyperlink those cases. */
179 @ %h(zName)
180 } else if( sqlite3_strglob("*/.*", zName)==0 ){
181 /* Do not show hidden repos */
182 @ %h(zName) (hidden)
183 } else if( allRepo && sqlite3_strglob("[a-zA-Z]:/?*", zName)!=0 ){
184 @ <a href="%R/%T(zUrl)/home" target="_blank">/%h(zName)</a>
 
 
185 }else{
186 @ <a href="%R/%T(zUrl)/home" target="_blank">%h(zName)</a>
 
 
187 }
188 if( x.zProjName ){
189 @ <td></td><td>%h(x.zProjName)</td>
190 fossil_free(x.zProjName);
191 }else{
192 @ <td></td><td></td>
193 }
194 @ <td></td><td data-sortkey='%08x(iAge)'>%h(zAge)</tr>
 
 
195 fossil_free(zAge);
196 sqlite3_free(zUrl);
197 }
198 @ </tbody></table>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199 }else{
200 @ <h1>No Repositories Found</h1>
201 }
202 @ <script>%s(builtin_text("sorttable.js"))</script>
203 @ </body>
204 @ </html>
205 cgi_reply();
206 sqlite3_close(g.db);
207 g.db = 0;
 
 
 
 
 
 
 
 
 
208 return n;
209 }
210
211 /*
212 ** COMMAND: test-list-page
213
--- src/repolist.c
+++ src/repolist.c
@@ -27,30 +27,44 @@
27 ** input. All other fields are outputs.
28 */
29 struct RepoInfo {
30 char *zRepoName; /* Name of the repository file */
31 int isValid; /* True if zRepoName is a valid Fossil repository */
32 int isRepolistSkin; /* 1 or 2 if this repository wants to be the skin
33 ** for the repository list. 2 means do use this
34 ** repository but do not display it in the list. */
35 char *zProjName; /* Project Name. Memory from fossil_malloc() */
36 double rMTime; /* Last update. Julian day number */
37 };
38 #endif
39
40 /*
41 ** Discover information about the repository given by
42 ** pRepo->zRepoName. The discovered information is stored in other
43 ** fields of the RepoInfo object.
44 */
45 static void remote_repo_info(RepoInfo *pRepo){
46 sqlite3 *db;
47 sqlite3_stmt *pStmt;
48 int rc;
49
50 pRepo->isRepolistSkin = 0;
51 pRepo->isValid = 0;
52 pRepo->zProjName = 0;
53 pRepo->rMTime = 0.0;
54
55 g.dbIgnoreErrors++;
56 rc = sqlite3_open_v2(pRepo->zRepoName, &db, SQLITE_OPEN_READWRITE, 0);
57 if( rc ) goto finish_repo_list;
58 rc = sqlite3_prepare_v2(db, "SELECT value FROM config"
59 " WHERE name='repolist-skin'",
60 -1, &pStmt, 0);
61 if( rc ) goto finish_repo_list;
62 if( sqlite3_step(pStmt)==SQLITE_ROW ){
63 pRepo->isRepolistSkin = sqlite3_column_int(pStmt,0);
64 }
65 sqlite3_finalize(pStmt);
66 if( rc ) goto finish_repo_list;
67 rc = sqlite3_prepare_v2(db, "SELECT value FROM config"
68 " WHERE name='project-name'",
69 -1, &pStmt, 0);
70 if( rc ) goto finish_repo_list;
@@ -85,15 +99,20 @@
99 **
100 ** Or, if no repositories can be located beneath g.zRepositoryName,
101 ** return 0.
102 */
103 int repo_list_page(void){
104 Blob base; /* document root for all repositories */
105 int n = 0; /* Number of repositories found */
106 int allRepo; /* True if running "fossil ui all".
107 ** False if a directory scan of base for repos */
108 Blob html; /* Html for the body of the repository list */
109 char *zSkinRepo = 0; /* Name of the repository database used for skins */
110 char *zSkinUrl = 0; /* URL for the skin database */
111
112 assert( g.db==0 );
113 blob_init(&html, 0, 0);
114 if( fossil_strcmp(g.zRepositoryName,"/")==0 && !g.fJail ){
115 /* For the special case of the "repository directory" being "/",
116 ** show all of the repositories named in the ~/.fossil database.
117 **
118 ** On unix systems, then entries are of the form "repo:/home/..."
@@ -118,28 +137,24 @@
137 db_multi_exec("CREATE TABLE vfile(pathname);");
138 vfile_scan(&base, blob_size(&base), 0, 0, 0);
139 db_multi_exec("DELETE FROM sfile WHERE pathname NOT GLOB '*[^/].fossil'");
140 allRepo = 0;
141 }
 
 
 
 
 
 
 
142 n = db_int(0, "SELECT count(*) FROM sfile");
143 if( n==0 ){
144 sqlite3_close(g.db);
145 return 0;
146 }else{
147 Stmt q;
148 double rNow;
149 blob_append_sql(&html,
150 "<table border='0' class='sortable' data-init-sort='1'"
151 " data-column-types='txtxk'><thead>\n"
152 "<tr><th>Filename<th width='20'>"
153 "<th>Project Name<th width='20'>"
154 "<th>Last Modified</tr>\n"
155 "</thead><tbody>\n");
156 db_prepare(&q, "SELECT pathname"
157 " FROM sfile ORDER BY pathname COLLATE nocase;");
158 rNow = db_double(0, "SELECT julianday('now')");
159 while( db_step(&q)==SQLITE_ROW ){
160 const char *zName = db_column_text(&q, 0);
@@ -162,51 +177,97 @@
177 }else{
178 zFull = mprintf("%s/%s", g.zRepositoryName, zName);
179 }
180 x.zRepoName = zFull;
181 remote_repo_info(&x);
182 if( x.isRepolistSkin ){
183 if( zSkinRepo==0 ){
184 zSkinRepo = mprintf("%s", x.zRepoName);
185 zSkinUrl = mprintf("%s", zUrl);
186 }
187 }
188 fossil_free(zFull);
189 if( !x.isValid ){
190 continue;
191 }
192 if( x.isRepolistSkin==2 && !allRepo ){
193 /* Repositories with repolist-skin==2 are omitted from directory
194 ** scan lists, but included in "fossil all ui" lists */
195 continue;
196 }
197 iAge = (rNow - x.rMTime)*86400;
198 if( iAge<0 ) x.rMTime = rNow;
199 zAge = human_readable_age(rNow - x.rMTime);
200 blob_append_sql(&html, "<tr><td valign='top'>");
201 if( sqlite3_strglob("*.fossil", zName)!=0 ){
202 /* The "fossil server DIRECTORY" and "fossil ui DIRECTORY" commands
203 ** do not work for repositories whose names do not end in ".fossil".
204 ** So do not hyperlink those cases. */
205 blob_append_sql(&html,"%h",zName);
206 } else if( sqlite3_strglob("*/.*", zName)==0 ){
207 /* Do not show hyperlinks for hidden repos */
208 blob_append_sql(&html, "%h (hidden)", zName);
209 } else if( allRepo && sqlite3_strglob("[a-zA-Z]:/?*", zName)!=0 ){
210 blob_append_sql(&html,
211 "<a href='/%T/home' target='_blank'>/%h</a>\n",
212 zUrl, zName);
213 }else{
214 blob_append_sql(&html,
215 "<a href='/%T/home' target='_blank'>%h</a>\n",
216 zUrl, zName);
217 }
218 if( x.zProjName ){
219 blob_append_sql(&html, "<td></td><td>%h</td>\n", x.zProjName);
220 fossil_free(x.zProjName);
221 }else{
222 blob_append_sql(&html, "<td></td><td></td>\n");
223 }
224 blob_append_sql(&html,
225 "<td></td><td data-sortkey='%08x'>%h</tr>\n",
226 iAge, zAge);
227 fossil_free(zAge);
228 sqlite3_free(zUrl);
229 }
230 db_finalize(&q);
231 blob_append_sql(&html,"</tbody></table>\n");
232 }
233 if( zSkinRepo ){
234 char *zNewBase = mprintf("%s/%s", g.zBaseURL, zSkinUrl);
235 g.zBaseURL = 0;
236 set_base_url(zNewBase);
237 db_open_repository(zSkinRepo);
238 fossil_free(zSkinRepo);
239 fossil_free(zSkinUrl);
240 }
241 if( g.repositoryOpen ){
242 /* This case runs if remote_repository_info() found a repository
243 ** that has the "repolist_skin" property set to non-zero and left
244 ** that repository open in g.db. Use the skin of that repository
245 ** for display. */
246 login_check_credentials();
247 style_header("Repository List");
248 @ %s(blob_str(&html))
249 style_table_sorter();
250 style_footer();
251 }else{
252 /* If no repositories were found that had the "repolist_skin"
253 ** property set, then use a default skin */
254 @ <html>
255 @ <head>
256 @ <base href="%s(g.zBaseURL)/" />
257 @ <meta name="viewport" content="width=device-width, initial-scale=1.0">
258 @ <title>Repository List</title>
259 @ </head>
260 @ <body>
261 @ <h1 align="center">Fossil Repositories</h1>
262 @ %s(blob_str(&html))
263 @ <script>%s(builtin_text("sorttable.js"))</script>
264 @ </body>
265 @ </html>
266 }
267 blob_reset(&html);
268 cgi_reply();
269 return n;
270 }
271
272 /*
273 ** COMMAND: test-list-page
274
+1 -1
--- src/setupuser.c
+++ src/setupuser.c
@@ -337,11 +337,11 @@
337337
char zCap[70], zNm[4];
338338
zNm[0] = 'a';
339339
zNm[2] = 0;
340340
for(i=0, c='a'; c<='z'; c++){
341341
zNm[1] = c;
342
- a[c&0x7f] = (c!='s' || g.perm.Setup) && P(zNm)!=0;
342
+ a[c&0x7f] = ((c!='s' && c!='y') || g.perm.Setup) && P(zNm)!=0;
343343
if( a[c&0x7f] ) zCap[i++] = c;
344344
}
345345
for(c='0'; c<='9'; c++){
346346
zNm[1] = c;
347347
a[c&0x7f] = P(zNm)!=0;
348348
--- src/setupuser.c
+++ src/setupuser.c
@@ -337,11 +337,11 @@
337 char zCap[70], zNm[4];
338 zNm[0] = 'a';
339 zNm[2] = 0;
340 for(i=0, c='a'; c<='z'; c++){
341 zNm[1] = c;
342 a[c&0x7f] = (c!='s' || g.perm.Setup) && P(zNm)!=0;
343 if( a[c&0x7f] ) zCap[i++] = c;
344 }
345 for(c='0'; c<='9'; c++){
346 zNm[1] = c;
347 a[c&0x7f] = P(zNm)!=0;
348
--- src/setupuser.c
+++ src/setupuser.c
@@ -337,11 +337,11 @@
337 char zCap[70], zNm[4];
338 zNm[0] = 'a';
339 zNm[2] = 0;
340 for(i=0, c='a'; c<='z'; c++){
341 zNm[1] = c;
342 a[c&0x7f] = ((c!='s' && c!='y') || g.perm.Setup) && P(zNm)!=0;
343 if( a[c&0x7f] ) zCap[i++] = c;
344 }
345 for(c='0'; c<='9'; c++){
346 zNm[1] = c;
347 a[c&0x7f] = P(zNm)!=0;
348
+9 -3
--- src/xfer.c
+++ src/xfer.c
@@ -1120,11 +1120,11 @@
11201120
** of application/x-fossil or application/x-fossil-debug to this page,
11211121
** regardless of what path was specified in the HTTP header. This allows
11221122
** clone clients to specify a URL that omits default pathnames, such
11231123
** as "http://fossil-scm.org/" instead of "http://fossil-scm.org/index.cgi".
11241124
**
1125
-** WEBPAGE: xfer
1125
+** WEBPAGE: xfer raw-content
11261126
**
11271127
** This is the transfer handler on the server side. The transfer
11281128
** message has been uncompressed and placed in the g.cgiIn blob.
11291129
** Process this message and form an appropriate reply.
11301130
*/
@@ -1783,10 +1783,11 @@
17831783
int nUvFileRcvd = 0; /* Number of uvfile cards received on this cycle */
17841784
sqlite3_int64 mtime; /* Modification time on a UV file */
17851785
int autopushFailed = 0; /* Autopush following commit failed if true */
17861786
const char *zCkinLock; /* Name of check-in to lock. NULL for none */
17871787
const char *zClientId; /* A unique identifier for this check-out */
1788
+ unsigned int mHttpFlags;/* Flags for the http_exchange() subsystem */
17881789
17891790
if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
17901791
if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED))==0
17911792
&& configRcvMask==0 && configSendMask==0 ) return 0;
17921793
if( syncFlags & SYNC_FROMPARENT ){
@@ -2020,12 +2021,17 @@
20202021
if( syncFlags & SYNC_VERBOSE ){
20212022
fossil_print("waiting for server...");
20222023
}
20232024
fflush(stdout);
20242025
/* Exchange messages with the server */
2025
- if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0,
2026
- MAX_REDIRECTS) ){
2026
+ if( (syncFlags & SYNC_CLONE)!=0 && nCycle==0 ){
2027
+ /* Do not send a login card on the first round-trip of a clone */
2028
+ mHttpFlags = 0;
2029
+ }else{
2030
+ mHttpFlags = HTTP_USE_LOGIN;
2031
+ }
2032
+ if( http_exchange(&send, &recv, mHttpFlags, MAX_REDIRECTS, 0) ){
20272033
nErr++;
20282034
go = 2;
20292035
break;
20302036
}
20312037
20322038
--- src/xfer.c
+++ src/xfer.c
@@ -1120,11 +1120,11 @@
1120 ** of application/x-fossil or application/x-fossil-debug to this page,
1121 ** regardless of what path was specified in the HTTP header. This allows
1122 ** clone clients to specify a URL that omits default pathnames, such
1123 ** as "http://fossil-scm.org/" instead of "http://fossil-scm.org/index.cgi".
1124 **
1125 ** WEBPAGE: xfer
1126 **
1127 ** This is the transfer handler on the server side. The transfer
1128 ** message has been uncompressed and placed in the g.cgiIn blob.
1129 ** Process this message and form an appropriate reply.
1130 */
@@ -1783,10 +1783,11 @@
1783 int nUvFileRcvd = 0; /* Number of uvfile cards received on this cycle */
1784 sqlite3_int64 mtime; /* Modification time on a UV file */
1785 int autopushFailed = 0; /* Autopush following commit failed if true */
1786 const char *zCkinLock; /* Name of check-in to lock. NULL for none */
1787 const char *zClientId; /* A unique identifier for this check-out */
 
1788
1789 if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
1790 if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED))==0
1791 && configRcvMask==0 && configSendMask==0 ) return 0;
1792 if( syncFlags & SYNC_FROMPARENT ){
@@ -2020,12 +2021,17 @@
2020 if( syncFlags & SYNC_VERBOSE ){
2021 fossil_print("waiting for server...");
2022 }
2023 fflush(stdout);
2024 /* Exchange messages with the server */
2025 if( http_exchange(&send, &recv, (syncFlags & SYNC_CLONE)==0 || nCycle>0,
2026 MAX_REDIRECTS) ){
 
 
 
 
 
2027 nErr++;
2028 go = 2;
2029 break;
2030 }
2031
2032
--- src/xfer.c
+++ src/xfer.c
@@ -1120,11 +1120,11 @@
1120 ** of application/x-fossil or application/x-fossil-debug to this page,
1121 ** regardless of what path was specified in the HTTP header. This allows
1122 ** clone clients to specify a URL that omits default pathnames, such
1123 ** as "http://fossil-scm.org/" instead of "http://fossil-scm.org/index.cgi".
1124 **
1125 ** WEBPAGE: xfer raw-content
1126 **
1127 ** This is the transfer handler on the server side. The transfer
1128 ** message has been uncompressed and placed in the g.cgiIn blob.
1129 ** Process this message and form an appropriate reply.
1130 */
@@ -1783,10 +1783,11 @@
1783 int nUvFileRcvd = 0; /* Number of uvfile cards received on this cycle */
1784 sqlite3_int64 mtime; /* Modification time on a UV file */
1785 int autopushFailed = 0; /* Autopush following commit failed if true */
1786 const char *zCkinLock; /* Name of check-in to lock. NULL for none */
1787 const char *zClientId; /* A unique identifier for this check-out */
1788 unsigned int mHttpFlags;/* Flags for the http_exchange() subsystem */
1789
1790 if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
1791 if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED))==0
1792 && configRcvMask==0 && configSendMask==0 ) return 0;
1793 if( syncFlags & SYNC_FROMPARENT ){
@@ -2020,12 +2021,17 @@
2021 if( syncFlags & SYNC_VERBOSE ){
2022 fossil_print("waiting for server...");
2023 }
2024 fflush(stdout);
2025 /* Exchange messages with the server */
2026 if( (syncFlags & SYNC_CLONE)!=0 && nCycle==0 ){
2027 /* Do not send a login card on the first round-trip of a clone */
2028 mHttpFlags = 0;
2029 }else{
2030 mHttpFlags = HTTP_USE_LOGIN;
2031 }
2032 if( http_exchange(&send, &recv, mHttpFlags, MAX_REDIRECTS, 0) ){
2033 nErr++;
2034 go = 2;
2035 break;
2036 }
2037
2038
+10 -4
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
2828
2929
SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -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_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB
3030
3131
SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -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_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
3232
33
-SRC = add_.c alerts_.c allrepo_.c attach_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.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 deltafunc_.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 forum_.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 repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.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 webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
33
+SRC = add_.c alerts_.c allrepo_.c attach_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.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 deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c finfo_.c foci_.c forum_.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 repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.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 webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
3434
35
-OBJ = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backoffice$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)\capabilities$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)\deltafunc$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)\forum$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)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$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)\webmail$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
35
+OBJ = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backoffice$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)\capabilities$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)\deltafunc$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)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$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)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$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)\webmail$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
3636
3737
3838
RC=$(DMDIR)\bin\rcc
3939
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
4040
@@ -49,11 +49,11 @@
4949
5050
$(OBJDIR)\fossil.res: $B\win\fossil.rc
5151
$(RC) $(RCFLAGS) -o$@ $**
5252
5353
$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54
- +echo add alerts allrepo attach backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi checkin checkout clearsign clone comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export file finfo foci forum 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 repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile webmail wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
54
+ +echo add alerts allrepo attach backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi checkin checkout clearsign clone comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file finfo foci forum 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 repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile webmail wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
5555
+echo fossil >> $@
5656
+echo fossil >> $@
5757
+echo $(LIBS) >> $@
5858
+echo. >> $@
5959
+echo fossil >> $@
@@ -350,10 +350,16 @@
350350
$(OBJDIR)\export$O : export_.c export.h
351351
$(TCC) -o$@ -c export_.c
352352
353353
export_.c : $(SRCDIR)\export.c
354354
+translate$E $** > $@
355
+
356
+$(OBJDIR)\extcgi$O : extcgi_.c extcgi.h
357
+ $(TCC) -o$@ -c extcgi_.c
358
+
359
+extcgi_.c : $(SRCDIR)\extcgi.c
360
+ +translate$E $** > $@
355361
356362
$(OBJDIR)\file$O : file_.c file.h
357363
$(TCC) -o$@ -c file_.c
358364
359365
file_.c : $(SRCDIR)\file.c
@@ -952,7 +958,7 @@
952958
953959
zip_.c : $(SRCDIR)\zip.c
954960
+translate$E $** > $@
955961
956962
headers: makeheaders$E page_index.h builtin_data.h default_css.h VERSION.h
957
- +makeheaders$E add_.c:add.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backoffice_.c:backoffice.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 capabilities_.c:capabilities.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 deltafunc_.c:deltafunc.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 forum_.c:forum.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 repolist_.c:repolist.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 setupuser_.c:setupuser.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 smtp_.c:smtp.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 webmail_.c:webmail.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
963
+ +makeheaders$E add_.c:add.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backoffice_.c:backoffice.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 capabilities_.c:capabilities.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 deltafunc_.c:deltafunc.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 extcgi_.c:extcgi.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.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 repolist_.c:repolist.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 setupuser_.c:setupuser.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 smtp_.c:smtp.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 webmail_.c:webmail.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
958964
@copy /Y nul: headers
959965
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
28
29 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -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_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB
30
31 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -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_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c alerts_.c allrepo_.c attach_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.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 deltafunc_.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 forum_.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 repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.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 webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backoffice$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)\capabilities$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)\deltafunc$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)\forum$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)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$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)\webmail$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
36
37
38 RC=$(DMDIR)\bin\rcc
39 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
40
@@ -49,11 +49,11 @@
49
50 $(OBJDIR)\fossil.res: $B\win\fossil.rc
51 $(RC) $(RCFLAGS) -o$@ $**
52
53 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54 +echo add alerts allrepo attach backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi checkin checkout clearsign clone comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export file finfo foci forum 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 repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile webmail wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
55 +echo fossil >> $@
56 +echo fossil >> $@
57 +echo $(LIBS) >> $@
58 +echo. >> $@
59 +echo fossil >> $@
@@ -350,10 +350,16 @@
350 $(OBJDIR)\export$O : export_.c export.h
351 $(TCC) -o$@ -c export_.c
352
353 export_.c : $(SRCDIR)\export.c
354 +translate$E $** > $@
 
 
 
 
 
 
355
356 $(OBJDIR)\file$O : file_.c file.h
357 $(TCC) -o$@ -c file_.c
358
359 file_.c : $(SRCDIR)\file.c
@@ -952,7 +958,7 @@
952
953 zip_.c : $(SRCDIR)\zip.c
954 +translate$E $** > $@
955
956 headers: makeheaders$E page_index.h builtin_data.h default_css.h VERSION.h
957 +makeheaders$E add_.c:add.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backoffice_.c:backoffice.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 capabilities_.c:capabilities.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 deltafunc_.c:deltafunc.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 forum_.c:forum.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 repolist_.c:repolist.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 setupuser_.c:setupuser.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 smtp_.c:smtp.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 webmail_.c:webmail.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
958 @copy /Y nul: headers
959
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
28
29 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -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_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB
30
31 SHELL_OPTIONS = -DNDEBUG=1 -DSQLITE_DQS=0 -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_DBSTAT_VTAB -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_STMTVTAB -DSQLITE_HAVE_ZLIB -DSQLITE_INTROSPECTION_PRAGMAS -DSQLITE_ENABLE_DBPAGE_VTAB -Dmain=sqlite3_shell -DSQLITE_SHELL_IS_UTF8=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=sqlcmd_get_dbname -DSQLITE_SHELL_INIT_PROC=sqlcmd_init_proc -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c alerts_.c allrepo_.c attach_.c backoffice_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c capabilities_.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 deltafunc_.c descendants_.c diff_.c diffcmd_.c dispatch_.c doc_.c encode_.c etag_.c event_.c export_.c extcgi_.c file_.c finfo_.c foci_.c forum_.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 repolist_.c report_.c rss_.c schema_.c search_.c security_audit_.c setup_.c setupuser_.c sha1_.c sha1hard_.c sha3_.c shun_.c sitemap_.c skins_.c smtp_.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 webmail_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\alerts$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\backoffice$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)\capabilities$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)\deltafunc$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)\extcgi$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\forum$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)\repolist$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\security_audit$O $(OBJDIR)\setup$O $(OBJDIR)\setupuser$O $(OBJDIR)\sha1$O $(OBJDIR)\sha1hard$O $(OBJDIR)\sha3$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\smtp$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)\webmail$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
36
37
38 RC=$(DMDIR)\bin\rcc
39 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
40
@@ -49,11 +49,11 @@
49
50 $(OBJDIR)\fossil.res: $B\win\fossil.rc
51 $(RC) $(RCFLAGS) -o$@ $**
52
53 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54 +echo add alerts allrepo attach backoffice bag bisect blob branch browse builtin bundle cache capabilities captcha cgi checkin checkout clearsign clone comformat configure content cookies db delta deltacmd deltafunc descendants diff diffcmd dispatch doc encode etag event export extcgi file finfo foci forum 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 repolist report rss schema search security_audit setup setupuser sha1 sha1hard sha3 shun sitemap skins smtp sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode unversioned update url user utf8 util verify vfile webmail wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
55 +echo fossil >> $@
56 +echo fossil >> $@
57 +echo $(LIBS) >> $@
58 +echo. >> $@
59 +echo fossil >> $@
@@ -350,10 +350,16 @@
350 $(OBJDIR)\export$O : export_.c export.h
351 $(TCC) -o$@ -c export_.c
352
353 export_.c : $(SRCDIR)\export.c
354 +translate$E $** > $@
355
356 $(OBJDIR)\extcgi$O : extcgi_.c extcgi.h
357 $(TCC) -o$@ -c extcgi_.c
358
359 extcgi_.c : $(SRCDIR)\extcgi.c
360 +translate$E $** > $@
361
362 $(OBJDIR)\file$O : file_.c file.h
363 $(TCC) -o$@ -c file_.c
364
365 file_.c : $(SRCDIR)\file.c
@@ -952,7 +958,7 @@
958
959 zip_.c : $(SRCDIR)\zip.c
960 +translate$E $** > $@
961
962 headers: makeheaders$E page_index.h builtin_data.h default_css.h VERSION.h
963 +makeheaders$E add_.c:add.h alerts_.c:alerts.h allrepo_.c:allrepo.h attach_.c:attach.h backoffice_.c:backoffice.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 capabilities_.c:capabilities.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 deltafunc_.c:deltafunc.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 extcgi_.c:extcgi.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h forum_.c:forum.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 repolist_.c:repolist.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 setupuser_.c:setupuser.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 smtp_.c:smtp.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 webmail_.c:webmail.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
964 @copy /Y nul: headers
965
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -473,10 +473,11 @@
473473
$(SRCDIR)/doc.c \
474474
$(SRCDIR)/encode.c \
475475
$(SRCDIR)/etag.c \
476476
$(SRCDIR)/event.c \
477477
$(SRCDIR)/export.c \
478
+ $(SRCDIR)/extcgi.c \
478479
$(SRCDIR)/file.c \
479480
$(SRCDIR)/finfo.c \
480481
$(SRCDIR)/foci.c \
481482
$(SRCDIR)/forum.c \
482483
$(SRCDIR)/fshell.c \
@@ -686,10 +687,11 @@
686687
$(OBJDIR)/doc_.c \
687688
$(OBJDIR)/encode_.c \
688689
$(OBJDIR)/etag_.c \
689690
$(OBJDIR)/event_.c \
690691
$(OBJDIR)/export_.c \
692
+ $(OBJDIR)/extcgi_.c \
691693
$(OBJDIR)/file_.c \
692694
$(OBJDIR)/finfo_.c \
693695
$(OBJDIR)/foci_.c \
694696
$(OBJDIR)/forum_.c \
695697
$(OBJDIR)/fshell_.c \
@@ -825,10 +827,11 @@
825827
$(OBJDIR)/doc.o \
826828
$(OBJDIR)/encode.o \
827829
$(OBJDIR)/etag.o \
828830
$(OBJDIR)/event.o \
829831
$(OBJDIR)/export.o \
832
+ $(OBJDIR)/extcgi.o \
830833
$(OBJDIR)/file.o \
831834
$(OBJDIR)/finfo.o \
832835
$(OBJDIR)/foci.o \
833836
$(OBJDIR)/forum.o \
834837
$(OBJDIR)/fshell.o \
@@ -1184,10 +1187,11 @@
11841187
$(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
11851188
$(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
11861189
$(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
11871190
$(OBJDIR)/event_.c:$(OBJDIR)/event.h \
11881191
$(OBJDIR)/export_.c:$(OBJDIR)/export.h \
1192
+ $(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \
11891193
$(OBJDIR)/file_.c:$(OBJDIR)/file.h \
11901194
$(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
11911195
$(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
11921196
$(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \
11931197
$(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
@@ -1588,10 +1592,18 @@
15881592
15891593
$(OBJDIR)/export.o: $(OBJDIR)/export_.c $(OBJDIR)/export.h $(SRCDIR)/config.h
15901594
$(XTCC) -o $(OBJDIR)/export.o -c $(OBJDIR)/export_.c
15911595
15921596
$(OBJDIR)/export.h: $(OBJDIR)/headers
1597
+
1598
+$(OBJDIR)/extcgi_.c: $(SRCDIR)/extcgi.c $(TRANSLATE)
1599
+ $(TRANSLATE) $(SRCDIR)/extcgi.c >$@
1600
+
1601
+$(OBJDIR)/extcgi.o: $(OBJDIR)/extcgi_.c $(OBJDIR)/extcgi.h $(SRCDIR)/config.h
1602
+ $(XTCC) -o $(OBJDIR)/extcgi.o -c $(OBJDIR)/extcgi_.c
1603
+
1604
+$(OBJDIR)/extcgi.h: $(OBJDIR)/headers
15931605
15941606
$(OBJDIR)/file_.c: $(SRCDIR)/file.c $(TRANSLATE)
15951607
$(TRANSLATE) $(SRCDIR)/file.c >$@
15961608
15971609
$(OBJDIR)/file.o: $(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h
15981610
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -473,10 +473,11 @@
473 $(SRCDIR)/doc.c \
474 $(SRCDIR)/encode.c \
475 $(SRCDIR)/etag.c \
476 $(SRCDIR)/event.c \
477 $(SRCDIR)/export.c \
 
478 $(SRCDIR)/file.c \
479 $(SRCDIR)/finfo.c \
480 $(SRCDIR)/foci.c \
481 $(SRCDIR)/forum.c \
482 $(SRCDIR)/fshell.c \
@@ -686,10 +687,11 @@
686 $(OBJDIR)/doc_.c \
687 $(OBJDIR)/encode_.c \
688 $(OBJDIR)/etag_.c \
689 $(OBJDIR)/event_.c \
690 $(OBJDIR)/export_.c \
 
691 $(OBJDIR)/file_.c \
692 $(OBJDIR)/finfo_.c \
693 $(OBJDIR)/foci_.c \
694 $(OBJDIR)/forum_.c \
695 $(OBJDIR)/fshell_.c \
@@ -825,10 +827,11 @@
825 $(OBJDIR)/doc.o \
826 $(OBJDIR)/encode.o \
827 $(OBJDIR)/etag.o \
828 $(OBJDIR)/event.o \
829 $(OBJDIR)/export.o \
 
830 $(OBJDIR)/file.o \
831 $(OBJDIR)/finfo.o \
832 $(OBJDIR)/foci.o \
833 $(OBJDIR)/forum.o \
834 $(OBJDIR)/fshell.o \
@@ -1184,10 +1187,11 @@
1184 $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
1185 $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
1186 $(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
1187 $(OBJDIR)/event_.c:$(OBJDIR)/event.h \
1188 $(OBJDIR)/export_.c:$(OBJDIR)/export.h \
 
1189 $(OBJDIR)/file_.c:$(OBJDIR)/file.h \
1190 $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
1191 $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
1192 $(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \
1193 $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
@@ -1588,10 +1592,18 @@
1588
1589 $(OBJDIR)/export.o: $(OBJDIR)/export_.c $(OBJDIR)/export.h $(SRCDIR)/config.h
1590 $(XTCC) -o $(OBJDIR)/export.o -c $(OBJDIR)/export_.c
1591
1592 $(OBJDIR)/export.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1593
1594 $(OBJDIR)/file_.c: $(SRCDIR)/file.c $(TRANSLATE)
1595 $(TRANSLATE) $(SRCDIR)/file.c >$@
1596
1597 $(OBJDIR)/file.o: $(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h
1598
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -473,10 +473,11 @@
473 $(SRCDIR)/doc.c \
474 $(SRCDIR)/encode.c \
475 $(SRCDIR)/etag.c \
476 $(SRCDIR)/event.c \
477 $(SRCDIR)/export.c \
478 $(SRCDIR)/extcgi.c \
479 $(SRCDIR)/file.c \
480 $(SRCDIR)/finfo.c \
481 $(SRCDIR)/foci.c \
482 $(SRCDIR)/forum.c \
483 $(SRCDIR)/fshell.c \
@@ -686,10 +687,11 @@
687 $(OBJDIR)/doc_.c \
688 $(OBJDIR)/encode_.c \
689 $(OBJDIR)/etag_.c \
690 $(OBJDIR)/event_.c \
691 $(OBJDIR)/export_.c \
692 $(OBJDIR)/extcgi_.c \
693 $(OBJDIR)/file_.c \
694 $(OBJDIR)/finfo_.c \
695 $(OBJDIR)/foci_.c \
696 $(OBJDIR)/forum_.c \
697 $(OBJDIR)/fshell_.c \
@@ -825,10 +827,11 @@
827 $(OBJDIR)/doc.o \
828 $(OBJDIR)/encode.o \
829 $(OBJDIR)/etag.o \
830 $(OBJDIR)/event.o \
831 $(OBJDIR)/export.o \
832 $(OBJDIR)/extcgi.o \
833 $(OBJDIR)/file.o \
834 $(OBJDIR)/finfo.o \
835 $(OBJDIR)/foci.o \
836 $(OBJDIR)/forum.o \
837 $(OBJDIR)/fshell.o \
@@ -1184,10 +1187,11 @@
1187 $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \
1188 $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \
1189 $(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \
1190 $(OBJDIR)/event_.c:$(OBJDIR)/event.h \
1191 $(OBJDIR)/export_.c:$(OBJDIR)/export.h \
1192 $(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \
1193 $(OBJDIR)/file_.c:$(OBJDIR)/file.h \
1194 $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \
1195 $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \
1196 $(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \
1197 $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \
@@ -1588,10 +1592,18 @@
1592
1593 $(OBJDIR)/export.o: $(OBJDIR)/export_.c $(OBJDIR)/export.h $(SRCDIR)/config.h
1594 $(XTCC) -o $(OBJDIR)/export.o -c $(OBJDIR)/export_.c
1595
1596 $(OBJDIR)/export.h: $(OBJDIR)/headers
1597
1598 $(OBJDIR)/extcgi_.c: $(SRCDIR)/extcgi.c $(TRANSLATE)
1599 $(TRANSLATE) $(SRCDIR)/extcgi.c >$@
1600
1601 $(OBJDIR)/extcgi.o: $(OBJDIR)/extcgi_.c $(OBJDIR)/extcgi.h $(SRCDIR)/config.h
1602 $(XTCC) -o $(OBJDIR)/extcgi.o -c $(OBJDIR)/extcgi_.c
1603
1604 $(OBJDIR)/extcgi.h: $(OBJDIR)/headers
1605
1606 $(OBJDIR)/file_.c: $(SRCDIR)/file.c $(TRANSLATE)
1607 $(TRANSLATE) $(SRCDIR)/file.c >$@
1608
1609 $(OBJDIR)/file.o: $(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h
1610
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -379,10 +379,11 @@
379379
doc_.c \
380380
encode_.c \
381381
etag_.c \
382382
event_.c \
383383
export_.c \
384
+ extcgi_.c \
384385
file_.c \
385386
finfo_.c \
386387
foci_.c \
387388
forum_.c \
388389
fshell_.c \
@@ -591,10 +592,11 @@
591592
$(OX)\doc$O \
592593
$(OX)\encode$O \
593594
$(OX)\etag$O \
594595
$(OX)\event$O \
595596
$(OX)\export$O \
597
+ $(OX)\extcgi$O \
596598
$(OX)\file$O \
597599
$(OX)\finfo$O \
598600
$(OX)\foci$O \
599601
$(OX)\forum$O \
600602
$(OX)\fshell$O \
@@ -792,10 +794,11 @@
792794
echo $(OX)\doc.obj >> $@
793795
echo $(OX)\encode.obj >> $@
794796
echo $(OX)\etag.obj >> $@
795797
echo $(OX)\event.obj >> $@
796798
echo $(OX)\export.obj >> $@
799
+ echo $(OX)\extcgi.obj >> $@
797800
echo $(OX)\file.obj >> $@
798801
echo $(OX)\finfo.obj >> $@
799802
echo $(OX)\foci.obj >> $@
800803
echo $(OX)\forum.obj >> $@
801804
echo $(OX)\fshell.obj >> $@
@@ -1236,10 +1239,16 @@
12361239
$(OX)\export$O : export_.c export.h
12371240
$(TCC) /Fo$@ -c export_.c
12381241
12391242
export_.c : $(SRCDIR)\export.c
12401243
translate$E $** > $@
1244
+
1245
+$(OX)\extcgi$O : extcgi_.c extcgi.h
1246
+ $(TCC) /Fo$@ -c extcgi_.c
1247
+
1248
+extcgi_.c : $(SRCDIR)\extcgi.c
1249
+ translate$E $** > $@
12411250
12421251
$(OX)\file$O : file_.c file.h
12431252
$(TCC) /Fo$@ -c file_.c
12441253
12451254
file_.c : $(SRCDIR)\file.c
@@ -1878,10 +1887,11 @@
18781887
doc_.c:doc.h \
18791888
encode_.c:encode.h \
18801889
etag_.c:etag.h \
18811890
event_.c:event.h \
18821891
export_.c:export.h \
1892
+ extcgi_.c:extcgi.h \
18831893
file_.c:file.h \
18841894
finfo_.c:finfo.h \
18851895
foci_.c:foci.h \
18861896
forum_.c:forum.h \
18871897
fshell_.c:fshell.h \
18881898
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -379,10 +379,11 @@
379 doc_.c \
380 encode_.c \
381 etag_.c \
382 event_.c \
383 export_.c \
 
384 file_.c \
385 finfo_.c \
386 foci_.c \
387 forum_.c \
388 fshell_.c \
@@ -591,10 +592,11 @@
591 $(OX)\doc$O \
592 $(OX)\encode$O \
593 $(OX)\etag$O \
594 $(OX)\event$O \
595 $(OX)\export$O \
 
596 $(OX)\file$O \
597 $(OX)\finfo$O \
598 $(OX)\foci$O \
599 $(OX)\forum$O \
600 $(OX)\fshell$O \
@@ -792,10 +794,11 @@
792 echo $(OX)\doc.obj >> $@
793 echo $(OX)\encode.obj >> $@
794 echo $(OX)\etag.obj >> $@
795 echo $(OX)\event.obj >> $@
796 echo $(OX)\export.obj >> $@
 
797 echo $(OX)\file.obj >> $@
798 echo $(OX)\finfo.obj >> $@
799 echo $(OX)\foci.obj >> $@
800 echo $(OX)\forum.obj >> $@
801 echo $(OX)\fshell.obj >> $@
@@ -1236,10 +1239,16 @@
1236 $(OX)\export$O : export_.c export.h
1237 $(TCC) /Fo$@ -c export_.c
1238
1239 export_.c : $(SRCDIR)\export.c
1240 translate$E $** > $@
 
 
 
 
 
 
1241
1242 $(OX)\file$O : file_.c file.h
1243 $(TCC) /Fo$@ -c file_.c
1244
1245 file_.c : $(SRCDIR)\file.c
@@ -1878,10 +1887,11 @@
1878 doc_.c:doc.h \
1879 encode_.c:encode.h \
1880 etag_.c:etag.h \
1881 event_.c:event.h \
1882 export_.c:export.h \
 
1883 file_.c:file.h \
1884 finfo_.c:finfo.h \
1885 foci_.c:foci.h \
1886 forum_.c:forum.h \
1887 fshell_.c:fshell.h \
1888
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -379,10 +379,11 @@
379 doc_.c \
380 encode_.c \
381 etag_.c \
382 event_.c \
383 export_.c \
384 extcgi_.c \
385 file_.c \
386 finfo_.c \
387 foci_.c \
388 forum_.c \
389 fshell_.c \
@@ -591,10 +592,11 @@
592 $(OX)\doc$O \
593 $(OX)\encode$O \
594 $(OX)\etag$O \
595 $(OX)\event$O \
596 $(OX)\export$O \
597 $(OX)\extcgi$O \
598 $(OX)\file$O \
599 $(OX)\finfo$O \
600 $(OX)\foci$O \
601 $(OX)\forum$O \
602 $(OX)\fshell$O \
@@ -792,10 +794,11 @@
794 echo $(OX)\doc.obj >> $@
795 echo $(OX)\encode.obj >> $@
796 echo $(OX)\etag.obj >> $@
797 echo $(OX)\event.obj >> $@
798 echo $(OX)\export.obj >> $@
799 echo $(OX)\extcgi.obj >> $@
800 echo $(OX)\file.obj >> $@
801 echo $(OX)\finfo.obj >> $@
802 echo $(OX)\foci.obj >> $@
803 echo $(OX)\forum.obj >> $@
804 echo $(OX)\fshell.obj >> $@
@@ -1236,10 +1239,16 @@
1239 $(OX)\export$O : export_.c export.h
1240 $(TCC) /Fo$@ -c export_.c
1241
1242 export_.c : $(SRCDIR)\export.c
1243 translate$E $** > $@
1244
1245 $(OX)\extcgi$O : extcgi_.c extcgi.h
1246 $(TCC) /Fo$@ -c extcgi_.c
1247
1248 extcgi_.c : $(SRCDIR)\extcgi.c
1249 translate$E $** > $@
1250
1251 $(OX)\file$O : file_.c file.h
1252 $(TCC) /Fo$@ -c file_.c
1253
1254 file_.c : $(SRCDIR)\file.c
@@ -1878,10 +1887,11 @@
1887 doc_.c:doc.h \
1888 encode_.c:encode.h \
1889 etag_.c:etag.h \
1890 event_.c:event.h \
1891 export_.c:export.h \
1892 extcgi_.c:extcgi.h \
1893 file_.c:file.h \
1894 finfo_.c:finfo.h \
1895 foci_.c:foci.h \
1896 forum_.c:forum.h \
1897 fshell_.c:fshell.h \
1898
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,11 +1,19 @@
11
<title>Change Log</title>
22
33
<a name='v2_10'></a>
44
<h2>Changes for Version 2.10 (pending)</h2>
55
6
+ * Added support for [./serverext.wiki|CGI-based Server Extensions].
7
+ * Added the [/help?cmd=repolist-skin|repolist-skin] setting used to
8
+ add style to repository list pages.
9
+ * Enhance the hierarchical display of Forum threads to do less
10
+ indentation and to provide links back to the previous message
11
+ in the thread. Provide sequential numbers for all messages in
12
+ a forum thread.
613
* Change the default [./hashpolicy.wiki|hash policy] to SHA3.
14
+ * Documentation improvements
715
816
<a name='v2_9'></a>
917
<h2>Changes for Version 2.9 (2019-07-13)</h2>
1018
1119
* Added the [/help?cmd=git|fossil git export] command and instructions
1220
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,11 +1,19 @@
1 <title>Change Log</title>
2
3 <a name='v2_10'></a>
4 <h2>Changes for Version 2.10 (pending)</h2>
5
 
 
 
 
 
 
 
6 * Change the default [./hashpolicy.wiki|hash policy] to SHA3.
 
7
8 <a name='v2_9'></a>
9 <h2>Changes for Version 2.9 (2019-07-13)</h2>
10
11 * Added the [/help?cmd=git|fossil git export] command and instructions
12
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,11 +1,19 @@
1 <title>Change Log</title>
2
3 <a name='v2_10'></a>
4 <h2>Changes for Version 2.10 (pending)</h2>
5
6 * Added support for [./serverext.wiki|CGI-based Server Extensions].
7 * Added the [/help?cmd=repolist-skin|repolist-skin] setting used to
8 add style to repository list pages.
9 * Enhance the hierarchical display of Forum threads to do less
10 indentation and to provide links back to the previous message
11 in the thread. Provide sequential numbers for all messages in
12 a forum thread.
13 * Change the default [./hashpolicy.wiki|hash policy] to SHA3.
14 * Documentation improvements
15
16 <a name='v2_9'></a>
17 <h2>Changes for Version 2.9 (2019-07-13)</h2>
18
19 * Added the [/help?cmd=git|fossil git export] command and instructions
20
+4 -2
--- www/env-opts.md
+++ www/env-opts.md
@@ -31,12 +31,11 @@
3131
3232
`--chdir DIRECTORY`: Change to the named directory before processing
3333
any commands.
3434
3535
36
-`--comfmtflags NUMBER`
37
-`--comment-format NUMBER`: Specify flags that control how check-in comments
36
+`--comfmtflags NUMBER`: Specify flags that control how check-in comments
3837
and certain other text outputs are formatted for display. The flags are
3938
individual bits in `NUMBER`, which must be specified in base 10:
4039
4140
* _0_ &mdash; Uses the revised algorithm with no special handling.
4241
@@ -56,10 +55,13 @@
5655
5756
* _16_ &mdash; Looks for the original comment text within the text being
5857
printed. Upon matching, a new line will be emitted, thus
5958
preserving more of the pre-existing formatting.
6059
60
+
61
+`--comment-format NUMBER`: Alias for `--comfmtflags NUMBER`.
62
+
6163
6264
`--errorlog ERRLOG`: Name a file to which fossil will log panics,
6365
errors, and warnings.
6466
6567
6668
--- www/env-opts.md
+++ www/env-opts.md
@@ -31,12 +31,11 @@
31
32 `--chdir DIRECTORY`: Change to the named directory before processing
33 any commands.
34
35
36 `--comfmtflags NUMBER`
37 `--comment-format NUMBER`: Specify flags that control how check-in comments
38 and certain other text outputs are formatted for display. The flags are
39 individual bits in `NUMBER`, which must be specified in base 10:
40
41 * _0_ &mdash; Uses the revised algorithm with no special handling.
42
@@ -56,10 +55,13 @@
56
57 * _16_ &mdash; Looks for the original comment text within the text being
58 printed. Upon matching, a new line will be emitted, thus
59 preserving more of the pre-existing formatting.
60
 
 
 
61
62 `--errorlog ERRLOG`: Name a file to which fossil will log panics,
63 errors, and warnings.
64
65
66
--- www/env-opts.md
+++ www/env-opts.md
@@ -31,12 +31,11 @@
31
32 `--chdir DIRECTORY`: Change to the named directory before processing
33 any commands.
34
35
36 `--comfmtflags NUMBER`: Specify flags that control how check-in comments
 
37 and certain other text outputs are formatted for display. The flags are
38 individual bits in `NUMBER`, which must be specified in base 10:
39
40 * _0_ &mdash; Uses the revised algorithm with no special handling.
41
@@ -56,10 +55,13 @@
55
56 * _16_ &mdash; Looks for the original comment text within the text being
57 printed. Upon matching, a new line will be emitted, thus
58 preserving more of the pre-existing formatting.
59
60
61 `--comment-format NUMBER`: Alias for `--comfmtflags NUMBER`.
62
63
64 `--errorlog ERRLOG`: Name a file to which fossil will log panics,
65 errors, and warnings.
66
67
68
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -13,16 +13,10 @@
1313
Keep in mind that you are reading this on a Fossil website, and though
1414
we try to be fair, the information here
1515
might be biased in favor of Fossil. Ask around for second opinions from
1616
people who have used <em>both</em> Fossil and Git.
1717
18
-&#185;<small><i>Git does not include a
19
-wiki, a ticket tracker, a forum, or a tech-note feature, so those elements will not transfer when
20
-exporting from Fossil to Git. GitHub adds some of these to stock Git,
21
-but because they're not part of Git proper, [./mirrortogithub.md|exporting a Fossil
22
-repository to GitHub] will still not include them; Fossil tickets do not
23
-become GitHub issues, for example.</i></small>
2418
2519
<h2>2.0 Differences Between Fossil And Git</h2>
2620
2721
Differences between Fossil and Git are summarized by the following table,
2822
with further description in the text that follows.
@@ -121,21 +115,19 @@
121115
122116
123117
<h3 id="vs-linux">2.3 Linux vs. SQLite</h3>
124118
125119
Fossil and Git promote different development styles because each one was
126
-specifically designed to support the primary authors' main software
120
+specifically designed to support the creator's main software
127121
development project: [https://en.wikipedia.org/wiki/Linus_Torvalds|Linus
128122
Torvalds] designed Git to support development of
129123
[https://www.kernel.org/|the Linux kernel], and
130124
[https://en.wikipedia.org/wiki/D._Richard_Hipp|D. Richard Hipp] designed
131125
Fossil to support the development of [https://sqlite.org/|SQLite].
132
-SQLite is much more widely deployed than the Linux kernel, but for
133
-Linux-based systems, the kernel is the more fundamental component.
134126
Both projects must rank high on any objective list of "most
135127
important FOSS projects," yet these two projects are almost entirely unlike
136
-one another.
128
+one another. So, too, are these two DVCSes.
137129
138130
In the following sections, we will explain how three key differences
139131
between Linux and SQLite dictated the design of each DVCS's low-friction
140132
usage path.
141133
@@ -177,44 +169,63 @@
177169
178170
<ul>
179171
<li><p><b>Personal engagement:</b> SQLite's developers know each
180172
other by name and work together daily on the project.</p></li>
181173
182
- <li><p><b>Trust over hierarchy:</b> Fossil supports developers given
183
- direct commit capability on the repository rather than support a
184
- hierarchical "dictator and lieutenants" contribution style. D.
174
+ <li><p><b>Trust over hierarchy:</b> SQLite's developers check
175
+ changes into their local repository, and these are immediately and
176
+ automatically sync'd up to the central repository; there is no
177
+ "[https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows#_dictator_and_lieutenants_workflow|dictator
178
+ and lieutenants]" hierarchy as with Linux kernel contributions. D.
185179
Richard Hipp rarely overrides decisions made by those he has trusted
186
- with commit access on his repositories.
187
- [/doc/trunk/www/admin-v-setup.md|Some users] have more power over
188
- what they can do with the repository, but Fossil does not otherwise
180
+ with commit access on his repositories. Fossil allows you to give
181
+ [/doc/trunk/www/admin-v-setup.md|some users] more power over what
182
+ they can do with the repository, but Fossil does not otherwise
189183
directly support the enforcement of a development organization's
190
- social hierarchy. Fossil is a great fit for
184
+ social and power hierarchies. Fossil is a great fit for
191185
[https://en.wikipedia.org/wiki/Flat_organization|flat
192186
organizations].</p></li>
193187
194
- <li><p><b>Anonymous contribution discouraged:</b> Anonymous
195
- contribution is possible in a Fossil project, but there is no
196
- low-friction path to it, as in Git. Fossil's closest equivalent to
197
- Git pull requests is the [/help?cmd=bundle|bundle], which requires
198
- higher engagement than firing off a PR. Both Fossil and Git also
199
- support <tt>patch(1)</tt> files, but that's a lossy contribution
200
- path in both systems.</p></li>
201
-
202
- <li><p><b>No rebasing:</b> When a remote clone syncs changes up to
203
- its parent repository, the changes are sent exactly as they were
204
- committed to the local repository. [#history|There is no rebasing
205
- mechanism, on purpose.]</p></li>
188
+ <li><p><b>No easy drive-by contributions:</b> Git
189
+ [https://www.git-scm.com/docs/git-request-pull|pull requests] offer
190
+ a low-friction path to accepting
191
+ [https://www.jonobacon.com/2012/07/25/building-strong-community-structural-integrity/|drive-by
192
+ contributions]. Fossil's closest equivalent is its unique
193
+ [/help?cmd=bundle|bundle] feature, which requires higher engagement
194
+ than firing off a PR.² This difference comes directly from the
195
+ initial designed purpose for each tool: the SQLite project doesn't
196
+ accept outside contributions from previously-unknown developers, but
197
+ the Linux kernel does.</p></li>
198
+
199
+ <li><p><b>No rebasing:</b> When your local repo clone syncs changes
200
+ up to its parent, those changes are sent exactly as they were
201
+ committed locally. [#history|There is no rebasing mechanism in
202
+ Fossil, on purpose.]</p></li>
206203
207204
<li><p><b>Sync over push:</b> Explicit pushes are uncommon in
208
- Fossil-based projects; the default is to rely on
205
+ Fossil-based projects: the default is to rely on
209206
[/help?cmd=autosync|autosync mode] instead, in which each commit
210
- normally syncs immediately to its parent repository, so that
211
- explicit pushes are not needed.</p></li>
207
+ syncs immediately to its parent repository. This is a mode so you
208
+ can turn it off temporarily when needed, such as when working
209
+ offline. Fossil is still a truly distributed version control system;
210
+ it's just that its starting default is to assume you're rarely out
211
+ of communication with the parent repo.
212
+ <br><br>
213
+ This is not merely a reflection of modern always-connected computing
214
+ environments. It is a conscious decision in direct support of
215
+ SQLite's cathedral development model: we don't want developers going
216
+ dark, then showing up weeks later with a massive bolus of changes
217
+ for us to integrate all at once.
218
+ [https://en.wikipedia.org/wiki/Jim_McCarthy_(author)|Jim McCarthy]
219
+ put it well in his book on software project management,
220
+ <i>[https://www.amazon.com/dp/0735623198/|Dynamics of Software
221
+ Development]</i>: "[https://www.youtube.com/watch?v=oY6BCHqEbyc|Beware
222
+ of a guy in a room]."</p></li>
212223
213224
<li><p><b>Branch names sync:</b> Unlike in Git, branch names are not
214225
purely local labels. They sync along with everything else, so
215
- everyone everyone sees the same set of branch names.</p></li>
226
+ everyone sees the same set of branch names.</p></li>
216227
217228
<li><p><b>Private branches are rare:</b>
218229
[/doc/trunk/www/private.wiki|Private branches exist in Fossil], but
219230
they're normally used to handle rare exception cases, whereas in
220231
many Git projects, they're part of the straight-line development
@@ -224,19 +235,15 @@
224235
keep local clones identical to the repository it cloned
225236
from.</p></li>
226237
</ul>
227238
228239
Where Git encourages siloed development, Fossil fights against it.
229
-[https://en.wikipedia.org/wiki/Jim_McCarthy_(author)|Jim McCarthy] put
230
-it well in his book on software project management,
231
-[https://www.amazon.com/dp/0735623198/|Dynamics of Software
232
-Development]: "[https://www.youtube.com/watch?v=oY6BCHqEbyc|Beware of a
233
-guy in a room]." Fossil places a lot of emphasis on synchronizing
234
-everyone's work and on reporting on the state of the project and the
235
-work of its developers, so that everyone — especially the project leader
236
-— can maintain a better mental picture of what is happening, leading to
237
-better situational awareness.
240
+Fossil places a lot of emphasis on synchronizing everyone's work and on
241
+reporting on the state of the project and the work of its developers, so
242
+that everyone — especially the project leader — can maintain a better
243
+mental picture of what is happening, leading to better situational
244
+awareness.
238245
239246
Each DVCS can be used in the opposite style, but doing so works against
240247
their low-friction paths.
241248
242249
@@ -504,5 +511,28 @@
504511
The [/help?cmd=push|fossil push], [/help?cmd=pull|fossil pull], and
505512
[/help?cmd=sync|fossil sync] commands do not provide the capability to
506513
push or pull individual branches. Pushing and pulling in Fossil is
507514
all or nothing. This is in keeping with Fossil's emphasis on maintaining
508515
a complete record and on sharing everything between all developers.
516
+
517
+<hr/>
518
+
519
+<h3>Asides and Digressions</h3>
520
+
521
+<i><small><ol>
522
+ <li><p>Git does not include a wiki, a ticket tracker, a forum, or a
523
+ tech-note feature, so those elements will not transfer when
524
+ exporting from Fossil to Git. GitHub adds some of these to stock
525
+ Git, but because they're not part of Git proper,
526
+ [./mirrortogithub.md|exporting a Fossil repository to GitHub] will
527
+ still not include them; Fossil tickets do not become GitHub issues,
528
+ for example.</p></li>
529
+
530
+ <li><p>Both Fossil and Git support
531
+ [https://en.wikipedia.org/wiki/Patch_(Unix)|<tt>patch(1)</tt>
532
+ files], a common way to allow drive-by contributions, but it's a
533
+ lossy contribution path for both systems. Unlike Git PRs and Fossil
534
+ bundles, patch files collapse mulitple checkins together, they don't
535
+ include check-in comments, and they cannot encode changes made above
536
+ the individual file content layer: you lose branching decisisions,
537
+ tag changes, file renames, and more when using patch files.</p></li>
538
+</ol></i></small>
509539
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -13,16 +13,10 @@
13 Keep in mind that you are reading this on a Fossil website, and though
14 we try to be fair, the information here
15 might be biased in favor of Fossil. Ask around for second opinions from
16 people who have used <em>both</em> Fossil and Git.
17
18 &#185;<small><i>Git does not include a
19 wiki, a ticket tracker, a forum, or a tech-note feature, so those elements will not transfer when
20 exporting from Fossil to Git. GitHub adds some of these to stock Git,
21 but because they're not part of Git proper, [./mirrortogithub.md|exporting a Fossil
22 repository to GitHub] will still not include them; Fossil tickets do not
23 become GitHub issues, for example.</i></small>
24
25 <h2>2.0 Differences Between Fossil And Git</h2>
26
27 Differences between Fossil and Git are summarized by the following table,
28 with further description in the text that follows.
@@ -121,21 +115,19 @@
121
122
123 <h3 id="vs-linux">2.3 Linux vs. SQLite</h3>
124
125 Fossil and Git promote different development styles because each one was
126 specifically designed to support the primary authors' main software
127 development project: [https://en.wikipedia.org/wiki/Linus_Torvalds|Linus
128 Torvalds] designed Git to support development of
129 [https://www.kernel.org/|the Linux kernel], and
130 [https://en.wikipedia.org/wiki/D._Richard_Hipp|D. Richard Hipp] designed
131 Fossil to support the development of [https://sqlite.org/|SQLite].
132 SQLite is much more widely deployed than the Linux kernel, but for
133 Linux-based systems, the kernel is the more fundamental component.
134 Both projects must rank high on any objective list of "most
135 important FOSS projects," yet these two projects are almost entirely unlike
136 one another.
137
138 In the following sections, we will explain how three key differences
139 between Linux and SQLite dictated the design of each DVCS's low-friction
140 usage path.
141
@@ -177,44 +169,63 @@
177
178 <ul>
179 <li><p><b>Personal engagement:</b> SQLite's developers know each
180 other by name and work together daily on the project.</p></li>
181
182 <li><p><b>Trust over hierarchy:</b> Fossil supports developers given
183 direct commit capability on the repository rather than support a
184 hierarchical "dictator and lieutenants" contribution style. D.
 
 
185 Richard Hipp rarely overrides decisions made by those he has trusted
186 with commit access on his repositories.
187 [/doc/trunk/www/admin-v-setup.md|Some users] have more power over
188 what they can do with the repository, but Fossil does not otherwise
189 directly support the enforcement of a development organization's
190 social hierarchy. Fossil is a great fit for
191 [https://en.wikipedia.org/wiki/Flat_organization|flat
192 organizations].</p></li>
193
194 <li><p><b>Anonymous contribution discouraged:</b> Anonymous
195 contribution is possible in a Fossil project, but there is no
196 low-friction path to it, as in Git. Fossil's closest equivalent to
197 Git pull requests is the [/help?cmd=bundle|bundle], which requires
198 higher engagement than firing off a PR. Both Fossil and Git also
199 support <tt>patch(1)</tt> files, but that's a lossy contribution
200 path in both systems.</p></li>
201
202 <li><p><b>No rebasing:</b> When a remote clone syncs changes up to
203 its parent repository, the changes are sent exactly as they were
204 committed to the local repository. [#history|There is no rebasing
205 mechanism, on purpose.]</p></li>
 
 
 
206
207 <li><p><b>Sync over push:</b> Explicit pushes are uncommon in
208 Fossil-based projects; the default is to rely on
209 [/help?cmd=autosync|autosync mode] instead, in which each commit
210 normally syncs immediately to its parent repository, so that
211 explicit pushes are not needed.</p></li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
213 <li><p><b>Branch names sync:</b> Unlike in Git, branch names are not
214 purely local labels. They sync along with everything else, so
215 everyone everyone sees the same set of branch names.</p></li>
216
217 <li><p><b>Private branches are rare:</b>
218 [/doc/trunk/www/private.wiki|Private branches exist in Fossil], but
219 they're normally used to handle rare exception cases, whereas in
220 many Git projects, they're part of the straight-line development
@@ -224,19 +235,15 @@
224 keep local clones identical to the repository it cloned
225 from.</p></li>
226 </ul>
227
228 Where Git encourages siloed development, Fossil fights against it.
229 [https://en.wikipedia.org/wiki/Jim_McCarthy_(author)|Jim McCarthy] put
230 it well in his book on software project management,
231 [https://www.amazon.com/dp/0735623198/|Dynamics of Software
232 Development]: "[https://www.youtube.com/watch?v=oY6BCHqEbyc|Beware of a
233 guy in a room]." Fossil places a lot of emphasis on synchronizing
234 everyone's work and on reporting on the state of the project and the
235 work of its developers, so that everyone — especially the project leader
236 — can maintain a better mental picture of what is happening, leading to
237 better situational awareness.
238
239 Each DVCS can be used in the opposite style, but doing so works against
240 their low-friction paths.
241
242
@@ -504,5 +511,28 @@
504 The [/help?cmd=push|fossil push], [/help?cmd=pull|fossil pull], and
505 [/help?cmd=sync|fossil sync] commands do not provide the capability to
506 push or pull individual branches. Pushing and pulling in Fossil is
507 all or nothing. This is in keeping with Fossil's emphasis on maintaining
508 a complete record and on sharing everything between all developers.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
509
--- www/fossil-v-git.wiki
+++ www/fossil-v-git.wiki
@@ -13,16 +13,10 @@
13 Keep in mind that you are reading this on a Fossil website, and though
14 we try to be fair, the information here
15 might be biased in favor of Fossil. Ask around for second opinions from
16 people who have used <em>both</em> Fossil and Git.
17
 
 
 
 
 
 
18
19 <h2>2.0 Differences Between Fossil And Git</h2>
20
21 Differences between Fossil and Git are summarized by the following table,
22 with further description in the text that follows.
@@ -121,21 +115,19 @@
115
116
117 <h3 id="vs-linux">2.3 Linux vs. SQLite</h3>
118
119 Fossil and Git promote different development styles because each one was
120 specifically designed to support the creator's main software
121 development project: [https://en.wikipedia.org/wiki/Linus_Torvalds|Linus
122 Torvalds] designed Git to support development of
123 [https://www.kernel.org/|the Linux kernel], and
124 [https://en.wikipedia.org/wiki/D._Richard_Hipp|D. Richard Hipp] designed
125 Fossil to support the development of [https://sqlite.org/|SQLite].
 
 
126 Both projects must rank high on any objective list of "most
127 important FOSS projects," yet these two projects are almost entirely unlike
128 one another. So, too, are these two DVCSes.
129
130 In the following sections, we will explain how three key differences
131 between Linux and SQLite dictated the design of each DVCS's low-friction
132 usage path.
133
@@ -177,44 +169,63 @@
169
170 <ul>
171 <li><p><b>Personal engagement:</b> SQLite's developers know each
172 other by name and work together daily on the project.</p></li>
173
174 <li><p><b>Trust over hierarchy:</b> SQLite's developers check
175 changes into their local repository, and these are immediately and
176 automatically sync'd up to the central repository; there is no
177 "[https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows#_dictator_and_lieutenants_workflow|dictator
178 and lieutenants]" hierarchy as with Linux kernel contributions. D.
179 Richard Hipp rarely overrides decisions made by those he has trusted
180 with commit access on his repositories. Fossil allows you to give
181 [/doc/trunk/www/admin-v-setup.md|some users] more power over what
182 they can do with the repository, but Fossil does not otherwise
183 directly support the enforcement of a development organization's
184 social and power hierarchies. Fossil is a great fit for
185 [https://en.wikipedia.org/wiki/Flat_organization|flat
186 organizations].</p></li>
187
188 <li><p><b>No easy drive-by contributions:</b> Git
189 [https://www.git-scm.com/docs/git-request-pull|pull requests] offer
190 a low-friction path to accepting
191 [https://www.jonobacon.com/2012/07/25/building-strong-community-structural-integrity/|drive-by
192 contributions]. Fossil's closest equivalent is its unique
193 [/help?cmd=bundle|bundle] feature, which requires higher engagement
194 than firing off a PR.² This difference comes directly from the
195 initial designed purpose for each tool: the SQLite project doesn't
196 accept outside contributions from previously-unknown developers, but
197 the Linux kernel does.</p></li>
198
199 <li><p><b>No rebasing:</b> When your local repo clone syncs changes
200 up to its parent, those changes are sent exactly as they were
201 committed locally. [#history|There is no rebasing mechanism in
202 Fossil, on purpose.]</p></li>
203
204 <li><p><b>Sync over push:</b> Explicit pushes are uncommon in
205 Fossil-based projects: the default is to rely on
206 [/help?cmd=autosync|autosync mode] instead, in which each commit
207 syncs immediately to its parent repository. This is a mode so you
208 can turn it off temporarily when needed, such as when working
209 offline. Fossil is still a truly distributed version control system;
210 it's just that its starting default is to assume you're rarely out
211 of communication with the parent repo.
212 <br><br>
213 This is not merely a reflection of modern always-connected computing
214 environments. It is a conscious decision in direct support of
215 SQLite's cathedral development model: we don't want developers going
216 dark, then showing up weeks later with a massive bolus of changes
217 for us to integrate all at once.
218 [https://en.wikipedia.org/wiki/Jim_McCarthy_(author)|Jim McCarthy]
219 put it well in his book on software project management,
220 <i>[https://www.amazon.com/dp/0735623198/|Dynamics of Software
221 Development]</i>: "[https://www.youtube.com/watch?v=oY6BCHqEbyc|Beware
222 of a guy in a room]."</p></li>
223
224 <li><p><b>Branch names sync:</b> Unlike in Git, branch names are not
225 purely local labels. They sync along with everything else, so
226 everyone sees the same set of branch names.</p></li>
227
228 <li><p><b>Private branches are rare:</b>
229 [/doc/trunk/www/private.wiki|Private branches exist in Fossil], but
230 they're normally used to handle rare exception cases, whereas in
231 many Git projects, they're part of the straight-line development
@@ -224,19 +235,15 @@
235 keep local clones identical to the repository it cloned
236 from.</p></li>
237 </ul>
238
239 Where Git encourages siloed development, Fossil fights against it.
240 Fossil places a lot of emphasis on synchronizing everyone's work and on
241 reporting on the state of the project and the work of its developers, so
242 that everyone — especially the project leader — can maintain a better
243 mental picture of what is happening, leading to better situational
244 awareness.
 
 
 
 
245
246 Each DVCS can be used in the opposite style, but doing so works against
247 their low-friction paths.
248
249
@@ -504,5 +511,28 @@
511 The [/help?cmd=push|fossil push], [/help?cmd=pull|fossil pull], and
512 [/help?cmd=sync|fossil sync] commands do not provide the capability to
513 push or pull individual branches. Pushing and pulling in Fossil is
514 all or nothing. This is in keeping with Fossil's emphasis on maintaining
515 a complete record and on sharing everything between all developers.
516
517 <hr/>
518
519 <h3>Asides and Digressions</h3>
520
521 <i><small><ol>
522 <li><p>Git does not include a wiki, a ticket tracker, a forum, or a
523 tech-note feature, so those elements will not transfer when
524 exporting from Fossil to Git. GitHub adds some of these to stock
525 Git, but because they're not part of Git proper,
526 [./mirrortogithub.md|exporting a Fossil repository to GitHub] will
527 still not include them; Fossil tickets do not become GitHub issues,
528 for example.</p></li>
529
530 <li><p>Both Fossil and Git support
531 [https://en.wikipedia.org/wiki/Patch_(Unix)|<tt>patch(1)</tt>
532 files], a common way to allow drive-by contributions, but it's a
533 lossy contribution path for both systems. Unlike Git PRs and Fossil
534 bundles, patch files collapse mulitple checkins together, they don't
535 include check-in comments, and they cannot encode changes made above
536 the individual file content layer: you lose branching decisisions,
537 tag changes, file renames, and more when using patch files.</p></li>
538 </ol></i></small>
539
+15 -5
--- www/server.wiki
+++ www/server.wiki
@@ -1,12 +1,22 @@
11
<title>How To Configure A Fossil Server</title>
22
3
-<h2>Introduction</h2>
3
+<h2>No Server Required</h2>
4
+
5
+<blockquote>
6
+Fossil does <em>not</em> require a central server.
7
+Data sharing and synchronization can be entirely peer-to-peer.
8
+Fossil uses [https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type|conflict-free replicated data types]
9
+to ensure that (in the limit) all participating peers see the exact same content.
10
+</blockquote>
11
+
12
+<h2>But, A Server Can Be Useful</h2>
413
514
<blockquote>
6
-A server is not necessary to use Fossil, but a server does help in collaborating with
7
-peers. A Fossil server also works well as a complete website for a project.
15
+Fossil does not require a a server,
16
+but a server does make collaboration easier.
17
+A Fossil server also works well as a complete website for a project.
818
For example, the complete [https://www.fossil-scm.org/] website, including the
919
page you are now reading,
1020
is just a Fossil server displaying the content of the
1121
self-hosting repository for Fossil.
1222
@@ -236,12 +246,12 @@
236246
237247
Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b>
238248
will serve up the repository "/home/fossil/repos/XYZ.fossil" (if it exists).
239249
240250
Additional options available to the CGI script are documented in the
241
-source code. As of 2017-07-02, the available options are described at
242
-[/artifact/9a52a07b?ln=1777-1824|main.c lines 1777 through 1824].
251
+source code. As of 2019-07-26, the available options are described at
252
+[/artifact/183cf5e5ad2ae111?ln=1912-1959|main.c lines 1912 through 1959].
243253
</blockquote>
244254
245255
<h2 id="scgi">Fossil as SCGI</h2>
246256
<blockquote>
247257
248258
249259
ADDED www/serverext.wiki
--- www/server.wiki
+++ www/server.wiki
@@ -1,12 +1,22 @@
1 <title>How To Configure A Fossil Server</title>
2
3 <h2>Introduction</h2>
 
 
 
 
 
 
 
 
 
4
5 <blockquote>
6 A server is not necessary to use Fossil, but a server does help in collaborating with
7 peers. A Fossil server also works well as a complete website for a project.
 
8 For example, the complete [https://www.fossil-scm.org/] website, including the
9 page you are now reading,
10 is just a Fossil server displaying the content of the
11 self-hosting repository for Fossil.
12
@@ -236,12 +246,12 @@
236
237 Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b>
238 will serve up the repository "/home/fossil/repos/XYZ.fossil" (if it exists).
239
240 Additional options available to the CGI script are documented in the
241 source code. As of 2017-07-02, the available options are described at
242 [/artifact/9a52a07b?ln=1777-1824|main.c lines 1777 through 1824].
243 </blockquote>
244
245 <h2 id="scgi">Fossil as SCGI</h2>
246 <blockquote>
247
248
249 DDED www/serverext.wiki
--- www/server.wiki
+++ www/server.wiki
@@ -1,12 +1,22 @@
1 <title>How To Configure A Fossil Server</title>
2
3 <h2>No Server Required</h2>
4
5 <blockquote>
6 Fossil does <em>not</em> require a central server.
7 Data sharing and synchronization can be entirely peer-to-peer.
8 Fossil uses [https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type|conflict-free replicated data types]
9 to ensure that (in the limit) all participating peers see the exact same content.
10 </blockquote>
11
12 <h2>But, A Server Can Be Useful</h2>
13
14 <blockquote>
15 Fossil does not require a a server,
16 but a server does make collaboration easier.
17 A Fossil server also works well as a complete website for a project.
18 For example, the complete [https://www.fossil-scm.org/] website, including the
19 page you are now reading,
20 is just a Fossil server displaying the content of the
21 self-hosting repository for Fossil.
22
@@ -236,12 +246,12 @@
246
247 Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b>
248 will serve up the repository "/home/fossil/repos/XYZ.fossil" (if it exists).
249
250 Additional options available to the CGI script are documented in the
251 source code. As of 2019-07-26, the available options are described at
252 [/artifact/183cf5e5ad2ae111?ln=1912-1959|main.c lines 1912 through 1959].
253 </blockquote>
254
255 <h2 id="scgi">Fossil as SCGI</h2>
256 <blockquote>
257
258
259 DDED www/serverext.wiki
--- a/www/serverext.wiki
+++ b/www/serverext.wiki
@@ -0,0 +1,13 @@
1
+<title>CGI tle>CGI Server Extension
2
+
3
+Ta <title>CGI Server Extension
4
+
5
+Ta [./server/|Fossil ser/h2>
6
+
7
+If you hchecklist application](/ext/checklist) on
8
+the [SQLite]()used to be. By
9
+ver Extension
10
+
11
+Ta [<title>CG()And pbas
12
+
13
+<h2>Extensions are offthus specified becomes the D
--- a/www/serverext.wiki
+++ b/www/serverext.wiki
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/www/serverext.wiki
+++ b/www/serverext.wiki
@@ -0,0 +1,13 @@
1 <title>CGI tle>CGI Server Extension
2
3 Ta <title>CGI Server Extension
4
5 Ta [./server/|Fossil ser/h2>
6
7 If you hchecklist application](/ext/checklist) on
8 the [SQLite]()used to be. By
9 ver Extension
10
11 Ta [<title>CG()And pbas
12
13 <h2>Extensions are offthus specified becomes the D

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button