Fossil SCM
Merge in updates from trunk.
Commit
7e7258b3ed91ea05aabcbe9abfb0c2f542c81175a29a91f1d53e14f29b55cfd0
Parent
ef40a0be4060ad9…
28 files changed
+3
-1
+4
+33
-21
+21
+1
-1
+1
+77
-60
+3
+133
-30
+6
-6
-7
+10
-6
+25
-4
+12
+1
+3
+12
-2
+99
-38
+1
-1
+9
-3
+10
-4
+12
+10
+8
+4
-2
+72
-42
+15
-5
+13
~
src/alerts.c
~
src/capabilities.c
~
src/cgi.c
~
src/db.c
~
src/default_css.txt
~
src/dispatch.c
~
src/doc.c
~
src/extcgi.c
~
src/http.c
~
src/http_transport.c
~
src/json_user.c
~
src/login.c
~
src/main.c
~
src/main.mk
~
src/makemake.tcl
~
src/mkindex.c
~
src/popen.c
~
src/repolist.c
~
src/setupuser.c
~
src/xfer.c
~
win/Makefile.dmc
~
win/Makefile.mingw
~
win/Makefile.msc
~
www/changes.wiki
~
www/env-opts.md
~
www/fossil-v-git.wiki
~
www/server.wiki
~
www/serverext.wiki
+3
-1
| --- src/alerts.c | ||
| +++ src/alerts.c | ||
| @@ -804,11 +804,13 @@ | ||
| 804 | 804 | }else{ |
| 805 | 805 | blob_init(&all, 0, 0); |
| 806 | 806 | pOut = &all; |
| 807 | 807 | } |
| 808 | 808 | 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 ){ | |
| 810 | 812 | blob_appendf(pOut, "From: %s <%s@%s>\r\n", |
| 811 | 813 | zFromName, alert_mailbox_name(zFromName), alert_hostname(p->zFrom)); |
| 812 | 814 | blob_appendf(pOut, "X-Fossil-From: <%s>\r\n", p->zFrom); |
| 813 | 815 | }else{ |
| 814 | 816 | blob_appendf(pOut, "From: <%s>\r\n", p->zFrom); |
| 815 | 817 |
| --- 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 |
+4
| --- src/capabilities.c | ||
| +++ src/capabilities.c | ||
| @@ -100,10 +100,11 @@ | ||
| 100 | 100 | void capability_expand(CapabilityString *pIn){ |
| 101 | 101 | static char *zNobody = 0; |
| 102 | 102 | static char *zAnon = 0; |
| 103 | 103 | static char *zReader = 0; |
| 104 | 104 | static char *zDev = 0; |
| 105 | + static char *zAdmin = "bcdefghijklmnopqrtwxz234567AD"; | |
| 105 | 106 | int doneV = 0; |
| 106 | 107 | |
| 107 | 108 | if( pIn==0 ){ |
| 108 | 109 | fossil_free(zNobody); zNobody = 0; |
| 109 | 110 | fossil_free(zAnon); zAnon = 0; |
| @@ -117,10 +118,13 @@ | ||
| 117 | 118 | zReader = db_text(0, "SELECT cap FROM user WHERE login='reader'"); |
| 118 | 119 | zDev = db_text(0, "SELECT cap FROM user WHERE login='developer'"); |
| 119 | 120 | } |
| 120 | 121 | pIn = capability_add(pIn, zAnon); |
| 121 | 122 | pIn = capability_add(pIn, zNobody); |
| 123 | + if( pIn->x['a'] || pIn->x['s'] ){ | |
| 124 | + pIn = capability_add(pIn, zAdmin); | |
| 125 | + } | |
| 122 | 126 | if( pIn->x['v'] ){ |
| 123 | 127 | pIn = capability_add(pIn, zDev); |
| 124 | 128 | doneV = 1; |
| 125 | 129 | } |
| 126 | 130 | if( pIn->x['u'] ){ |
| 127 | 131 |
| --- 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 @@ | ||
| 13 | 13 | ** [email protected] |
| 14 | 14 | ** http://www.hwaci.com/drh/ |
| 15 | 15 | ** |
| 16 | 16 | ******************************************************************************* |
| 17 | 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. | |
| 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. | |
| 23 | 28 | */ |
| 24 | 29 | #include "config.h" |
| 25 | 30 | #ifdef _WIN32 |
| 26 | 31 | # if !defined(_WIN32_WINNT) |
| 27 | 32 | # define _WIN32_WINNT 0x0501 |
| @@ -981,28 +986,13 @@ | ||
| 981 | 986 | |
| 982 | 987 | len = atoi(PD("CONTENT_LENGTH", "0")); |
| 983 | 988 | g.zContentType = zType = P("CONTENT_TYPE"); |
| 984 | 989 | blob_zero(&g.cgiIn); |
| 985 | 990 | 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 ){ | |
| 998 | 992 | blob_read_from_channel(&g.cgiIn, g.httpIn, len); |
| 999 | 993 | 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 | 994 | } |
| 1005 | 995 | #ifdef FOSSIL_ENABLE_JSON |
| 1006 | 996 | else if( fossil_strcmp(zType, "application/json") |
| 1007 | 997 | || fossil_strcmp(zType,"text/plain")/*assume this MIGHT be JSON*/ |
| 1008 | 998 | || fossil_strcmp(zType,"application/javascript")){ |
| @@ -1024,12 +1014,34 @@ | ||
| 1024 | 1014 | need to process QUERY_STRING _after_ reading the POST data. |
| 1025 | 1015 | */ |
| 1026 | 1016 | cgi_set_content_type(json_guess_content_type()); |
| 1027 | 1017 | } |
| 1028 | 1018 | #endif /* FOSSIL_ENABLE_JSON */ |
| 1019 | + else{ | |
| 1020 | + blob_read_from_channel(&g.cgiIn, g.httpIn, len); | |
| 1021 | + } | |
| 1029 | 1022 | } |
| 1023 | +} | |
| 1030 | 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 | + } | |
| 1031 | 1043 | } |
| 1032 | 1044 | |
| 1033 | 1045 | /* |
| 1034 | 1046 | ** This is the comparison function used to sort the aParamQP[] array of |
| 1035 | 1047 | ** query parameters and cookies. |
| 1036 | 1048 |
| --- 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 |
M
src/db.c
+21
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -3422,10 +3422,31 @@ | ||
| 3422 | 3422 | ** SETTING: repo-cksum boolean default=on |
| 3423 | 3423 | ** Compute checksums over all files in each checkout as a double-check |
| 3424 | 3424 | ** of correctness. Disable this on large repositories for a performance |
| 3425 | 3425 | ** improvement. |
| 3426 | 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 | +*/ | |
| 3427 | 3448 | /* |
| 3428 | 3449 | ** SETTING: self-register boolean default=off |
| 3429 | 3450 | ** Allow users to register themselves through the HTTP UI. |
| 3430 | 3451 | ** This is useful if you want to see other names than |
| 3431 | 3452 | ** "Anonymous" in e.g. ticketing system. On the other hand |
| 3432 | 3453 |
| --- 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 |
+1
-1
| --- src/default_css.txt | ||
| +++ src/default_css.txt | ||
| @@ -777,11 +777,11 @@ | ||
| 777 | 777 | margin: -2px .24em 0 0; |
| 778 | 778 | padding: 0; |
| 779 | 779 | border: 0; |
| 780 | 780 | vertical-align: middle; |
| 781 | 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"); | |
| 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 | 783 | background-repeat: no-repeat; |
| 784 | 784 | background-position: center; |
| 785 | 785 | cursor: pointer; |
| 786 | 786 | } |
| 787 | 787 | .copy-button-flipped { |
| 788 | 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='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 |
+1
| --- src/dispatch.c | ||
| +++ src/dispatch.c | ||
| @@ -47,10 +47,11 @@ | ||
| 47 | 47 | #define CMDFLAG_COMMAND 0x0010 /* A command */ |
| 48 | 48 | #define CMDFLAG_SETTING 0x0020 /* A setting */ |
| 49 | 49 | #define CMDFLAG_VERSIONABLE 0x0040 /* A versionable setting */ |
| 50 | 50 | #define CMDFLAG_BLOCKTEXT 0x0080 /* Multi-line text setting */ |
| 51 | 51 | #define CMDFLAG_BOOLEAN 0x0100 /* A boolean setting */ |
| 52 | +#define CMDFLAG_RAWCONTENT 0x0200 /* Do not interpret POST content */ | |
| 52 | 53 | /**************************************************************************/ |
| 53 | 54 | |
| 54 | 55 | /* Values for the 2nd parameter to dispatch_name_search() */ |
| 55 | 56 | #define CMDFLAG_ANY 0x0038 /* Match anything */ |
| 56 | 57 | #define CMDFLAG_PREFIX 0x0200 /* Prefix match is ok */ |
| 57 | 58 |
| --- 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 @@ | ||
| 529 | 529 | base = i+5; |
| 530 | 530 | } |
| 531 | 531 | } |
| 532 | 532 | blob_append(cgi_output_blob(), &z[base], i-base); |
| 533 | 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 | + | |
| 534 | 609 | |
| 535 | 610 | /* |
| 536 | 611 | ** WEBPAGE: uv |
| 537 | 612 | ** WEBPAGE: doc |
| 538 | 613 | ** URL: /uv/FILE |
| @@ -618,10 +693,11 @@ | ||
| 618 | 693 | zCheckin = "tip"; |
| 619 | 694 | } |
| 620 | 695 | } |
| 621 | 696 | if( nMiss==count(azSuffix) ){ |
| 622 | 697 | zName = "404.md"; |
| 698 | + zDfltTitle = "Not Found"; | |
| 623 | 699 | }else if( zName[i]==0 ){ |
| 624 | 700 | assert( nMiss>=0 && nMiss<count(azSuffix) ); |
| 625 | 701 | zName = azSuffix[nMiss]; |
| 626 | 702 | }else if( !isUV ){ |
| 627 | 703 | zName += i; |
| @@ -690,70 +766,11 @@ | ||
| 690 | 766 | Th_Store("doc_version", db_text(0, "SELECT '[' || substr(uuid,1,10) || ']'" |
| 691 | 767 | " FROM blob WHERE rid=%d", vid)); |
| 692 | 768 | Th_Store("doc_date", db_text(0, "SELECT datetime(mtime) FROM event" |
| 693 | 769 | " WHERE objid=%d AND type='ci'", vid)); |
| 694 | 770 | } |
| 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); | |
| 755 | 772 | if( nMiss>=count(azSuffix) ) cgi_set_status(404, "Not Found"); |
| 756 | 773 | db_end_transaction(0); |
| 757 | 774 | return; |
| 758 | 775 | |
| 759 | 776 | /* Jump here when unable to locate the document */ |
| 760 | 777 | |
| 761 | 778 | 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 |
+3
| --- 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 @@ | ||
| 29 | 29 | #ifndef fileno |
| 30 | 30 | #define fileno(s) _fileno(s) |
| 31 | 31 | #endif |
| 32 | 32 | #endif |
| 33 | 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 | + | |
| 34 | 45 | /* Maximum number of HTTP Authorization attempts */ |
| 35 | 46 | #define MAX_HTTP_AUTH 2 |
| 36 | 47 | |
| 37 | 48 | /* Keep track of HTTP Basic Authorization failures */ |
| 38 | 49 | static int fSeenHttpAuth = 0; |
| @@ -97,22 +108,21 @@ | ||
| 97 | 108 | /* |
| 98 | 109 | ** Construct an appropriate HTTP request header. Write the header |
| 99 | 110 | ** into pHdr. This routine initializes the pHdr blob. pPayload is |
| 100 | 111 | ** the complete payload (including the login card) already compressed. |
| 101 | 112 | */ |
| 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; | |
| 105 | 119 | |
| 106 | 120 | 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 ? "/" : ""); | |
| 114 | 124 | if( g.url.proxyAuth ){ |
| 115 | 125 | blob_appendf(pHdr, "Proxy-Authorization: %s\r\n", g.url.proxyAuth); |
| 116 | 126 | } |
| 117 | 127 | if( g.zHttpAuth && g.zHttpAuth[0] ){ |
| 118 | 128 | const char *zCredentials = g.zHttpAuth; |
| @@ -121,16 +131,21 @@ | ||
| 121 | 131 | fossil_free(zEncoded); |
| 122 | 132 | } |
| 123 | 133 | blob_appendf(pHdr, "Host: %s\r\n", g.url.hostname); |
| 124 | 134 | blob_appendf(pHdr, "User-Agent: %s\r\n", get_user_agent()); |
| 125 | 135 | 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)); | |
| 130 | 145 | } |
| 131 | - blob_appendf(pHdr, "Content-Length: %d\r\n\r\n", blob_size(pPayload)); | |
| 146 | + blob_append(pHdr, "\r\n", 2); | |
| 132 | 147 | } |
| 133 | 148 | |
| 134 | 149 | /* |
| 135 | 150 | ** Use Fossil credentials for HTTP Basic Authorization prompt |
| 136 | 151 | */ |
| @@ -200,11 +215,17 @@ | ||
| 200 | 215 | ** |
| 201 | 216 | ** The server address is contain in the "g" global structure. The |
| 202 | 217 | ** url_parse() routine should have been called prior to this routine |
| 203 | 218 | ** in order to fill this structure appropriately. |
| 204 | 219 | */ |
| 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 | +){ | |
| 206 | 227 | Blob login; /* The login card */ |
| 207 | 228 | Blob payload; /* The complete payload including login card */ |
| 208 | 229 | Blob hdr; /* The HTTP request header */ |
| 209 | 230 | int closeConnection; /* True to close the connection when done */ |
| 210 | 231 | int iLength; /* Expected length of the reply payload */ |
| @@ -220,22 +241,26 @@ | ||
| 220 | 241 | fossil_warning("%s", transport_errmsg(&g.url)); |
| 221 | 242 | return 1; |
| 222 | 243 | } |
| 223 | 244 | |
| 224 | 245 | /* 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); | |
| 230 | 248 | }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 | + } | |
| 233 | 258 | } |
| 234 | 259 | |
| 235 | 260 | /* Construct the HTTP request header */ |
| 236 | - http_build_header(&payload, &hdr); | |
| 261 | + http_build_header(&payload, &hdr, zAltMimetype); | |
| 237 | 262 | |
| 238 | 263 | /* When tracing, write the transmitted HTTP message both to standard |
| 239 | 264 | ** output and into a file. The file can then be used to drive the |
| 240 | 265 | ** server-side like this: |
| 241 | 266 | ** |
| @@ -261,10 +286,15 @@ | ||
| 261 | 286 | } |
| 262 | 287 | |
| 263 | 288 | /* |
| 264 | 289 | ** Send the request to the server. |
| 265 | 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 | + } | |
| 266 | 296 | transport_send(&g.url, &hdr); |
| 267 | 297 | transport_send(&g.url, &payload); |
| 268 | 298 | blob_reset(&hdr); |
| 269 | 299 | blob_reset(&payload); |
| 270 | 300 | transport_flip(&g.url); |
| @@ -273,21 +303,24 @@ | ||
| 273 | 303 | ** Read and interpret the server reply |
| 274 | 304 | */ |
| 275 | 305 | closeConnection = 1; |
| 276 | 306 | iLength = -1; |
| 277 | 307 | 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 | + } | |
| 279 | 311 | if( fossil_strnicmp(zLine, "http/1.", 7)==0 ){ |
| 280 | 312 | if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err; |
| 281 | 313 | if( rc==401 ){ |
| 282 | 314 | if( fSeenHttpAuth++ < MAX_HTTP_AUTH ){ |
| 283 | 315 | if( g.zHttpAuth ){ |
| 284 | 316 | if( g.zHttpAuth ) free(g.zHttpAuth); |
| 285 | 317 | } |
| 286 | 318 | g.zHttpAuth = prompt_for_httpauth_creds(); |
| 287 | 319 | transport_close(&g.url); |
| 288 | - return http_exchange(pSend, pReply, useLogin, maxRedirect); | |
| 320 | + return http_exchange(pSend, pReply, mHttpFlags, | |
| 321 | + maxRedirect, zAltMimetype); | |
| 289 | 322 | } |
| 290 | 323 | } |
| 291 | 324 | if( rc!=200 && rc!=301 && rc!=302 && rc!=307 && rc!=308 ){ |
| 292 | 325 | int ii; |
| 293 | 326 | for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} |
| @@ -323,10 +356,11 @@ | ||
| 323 | 356 | closeConnection = 0; |
| 324 | 357 | } |
| 325 | 358 | }else if( ( rc==301 || rc==302 || rc==307 || rc==308 ) && |
| 326 | 359 | fossil_strnicmp(zLine, "location:", 9)==0 ){ |
| 327 | 360 | int i, j; |
| 361 | + int wasHttps; | |
| 328 | 362 | |
| 329 | 363 | if ( --maxRedirect == 0){ |
| 330 | 364 | fossil_warning("redirect limit exceeded"); |
| 331 | 365 | goto write_err; |
| 332 | 366 | } |
| @@ -338,27 +372,39 @@ | ||
| 338 | 372 | j = strlen(zLine) - 1; |
| 339 | 373 | while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){ |
| 340 | 374 | j -= 4; |
| 341 | 375 | zLine[j] = 0; |
| 342 | 376 | } |
| 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; | |
| 344 | 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 | + } | |
| 345 | 386 | transport_close(&g.url); |
| 346 | 387 | transport_global_shutdown(&g.url); |
| 347 | 388 | fSeenHttpAuth = 0; |
| 348 | 389 | if( g.zHttpAuth ) free(g.zHttpAuth); |
| 349 | 390 | g.zHttpAuth = get_httpauth(); |
| 350 | 391 | 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); | |
| 352 | 394 | }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){ |
| 353 | 395 | if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){ |
| 354 | 396 | isCompressed = 0; |
| 355 | 397 | }else if( fossil_strnicmp(&zLine[14], |
| 356 | 398 | "application/x-fossil-uncompressed", -1)==0 ){ |
| 357 | 399 | 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 | + } | |
| 360 | 406 | } |
| 361 | 407 | } |
| 362 | 408 | } |
| 363 | 409 | if( iLength<0 ){ |
| 364 | 410 | fossil_warning("server did not reply"); |
| @@ -419,5 +465,62 @@ | ||
| 419 | 465 | */ |
| 420 | 466 | write_err: |
| 421 | 467 | transport_close(&g.url); |
| 422 | 468 | return 1; |
| 423 | 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 | +} | |
| 424 | 527 |
| --- 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 |
+6
-6
| --- src/http_transport.c | ||
| +++ src/http_transport.c | ||
| @@ -140,11 +140,11 @@ | ||
| 140 | 140 | fossil_panic("ssh:// URI does not specify a path to the repository"); |
| 141 | 141 | } |
| 142 | 142 | if( g.fSshTrace ){ |
| 143 | 143 | fossil_print("%s\n", blob_str(&zCmd)); /* Show the whole SSH command */ |
| 144 | 144 | } |
| 145 | - popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid); | |
| 145 | + popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid, 0); | |
| 146 | 146 | if( sshPid==0 ){ |
| 147 | 147 | socket_set_errmsg("cannot start ssh tunnel using [%b]", &zCmd); |
| 148 | 148 | } |
| 149 | 149 | blob_reset(&zCmd); |
| 150 | 150 | return sshPid==0; |
| @@ -165,17 +165,17 @@ | ||
| 165 | 165 | if( transport.isOpen==0 ){ |
| 166 | 166 | if( pUrlData->isSsh ){ |
| 167 | 167 | rc = transport_ssh_open(pUrlData); |
| 168 | 168 | if( rc==0 ) transport.isOpen = 1; |
| 169 | 169 | }else if( pUrlData->isHttps ){ |
| 170 | - #ifdef FOSSIL_ENABLE_SSL | |
| 170 | +#ifdef FOSSIL_ENABLE_SSL | |
| 171 | 171 | rc = ssl_open(pUrlData); |
| 172 | 172 | if( rc==0 ) transport.isOpen = 1; |
| 173 | - #else | |
| 173 | +#else | |
| 174 | 174 | socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support"); |
| 175 | 175 | rc = 1; |
| 176 | - #endif | |
| 176 | +#endif | |
| 177 | 177 | }else if( pUrlData->isFile ){ |
| 178 | 178 | sqlite3_uint64 iRandId; |
| 179 | 179 | sqlite3_randomness(sizeof(iRandId), &iRandId); |
| 180 | 180 | transport.zOutFile = mprintf("%s-%llu-out.http", |
| 181 | 181 | g.zRepositoryName, iRandId); |
| @@ -239,19 +239,19 @@ | ||
| 239 | 239 | transport.nSent += n; |
| 240 | 240 | if( pUrlData->isSsh ){ |
| 241 | 241 | fwrite(z, 1, n, sshOut); |
| 242 | 242 | fflush(sshOut); |
| 243 | 243 | }else if( pUrlData->isHttps ){ |
| 244 | - #ifdef FOSSIL_ENABLE_SSL | |
| 244 | +#ifdef FOSSIL_ENABLE_SSL | |
| 245 | 245 | int sent; |
| 246 | 246 | while( n>0 ){ |
| 247 | 247 | sent = ssl_send(0, z, n); |
| 248 | 248 | /* printf("Sent %d of %d bytes\n", sent, n); fflush(stdout); */ |
| 249 | 249 | if( sent<=0 ) break; |
| 250 | 250 | n -= sent; |
| 251 | 251 | } |
| 252 | - #endif | |
| 252 | +#endif | |
| 253 | 253 | }else if( pUrlData->isFile ){ |
| 254 | 254 | fwrite(z, 1, n, transport.pFile); |
| 255 | 255 | }else{ |
| 256 | 256 | int sent; |
| 257 | 257 | while( n>0 ){ |
| 258 | 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); |
| 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 |
-7
| --- src/json_user.c | ||
| +++ src/json_user.c | ||
| @@ -186,17 +186,10 @@ | ||
| 186 | 186 | char const tgtHasSetup = zCap && (NULL!=strchr(zCap, 's')); |
| 187 | 187 | char tgtHadSetup = 0; |
| 188 | 188 | Blob sql = empty_blob; |
| 189 | 189 | Stmt q = empty_Stmt; |
| 190 | 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 | 191 | if(uid<=0 && (!zName||!*zName)){ |
| 199 | 192 | return json_set_err(FSL_JSON_E_MISSING_ARGS, |
| 200 | 193 | "One of 'uid' or 'name' is required."); |
| 201 | 194 | }else if(uid>0){ |
| 202 | 195 | zNameFree = db_text(NULL, "SELECT login FROM user WHERE uid=%d",uid); |
| 203 | 196 |
| --- 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 @@ | ||
| 434 | 434 | if( sqlite3_strglob("*Safari/537.36Mozilla/5.0*", zAgent)==0 ) return 0; |
| 435 | 435 | |
| 436 | 436 | if( sqlite3_strglob("*Firefox/[1-9]*", zAgent)==0 ) return 1; |
| 437 | 437 | if( sqlite3_strglob("*Chrome/[1-9]*", zAgent)==0 ) return 1; |
| 438 | 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+ */ | |
| 439 | + if( sqlite3_strglob("*Trident/[1-9]*;?rv:[1-9]*", zAgent)==0 ){ | |
| 440 | + return 1; /* IE11+ */ | |
| 441 | + } | |
| 440 | 442 | if( sqlite3_strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent)==0 ) return 1; |
| 441 | 443 | return 0; |
| 442 | 444 | } |
| 443 | 445 | if( strncmp(zAgent, "Opera/", 6)==0 ) return 1; |
| 444 | 446 | if( strncmp(zAgent, "Safari/", 7)==0 ) return 1; |
| @@ -897,22 +899,24 @@ | ||
| 897 | 899 | |
| 898 | 900 | /* |
| 899 | 901 | ** Attempt to use Basic Authentication to establish the user. Return the |
| 900 | 902 | ** (non-zero) uid if successful. Return 0 if it does not work. |
| 901 | 903 | */ |
| 902 | -static int logic_basic_authentication(const char *zIpAddr){ | |
| 904 | +static int login_basic_authentication(const char *zIpAddr){ | |
| 903 | 905 | const char *zAuth = PD("HTTP_AUTHORIZATION", 0); |
| 904 | 906 | int i; |
| 905 | 907 | int uid = 0; |
| 906 | 908 | int nDecode = 0; |
| 907 | 909 | char *zDecode = 0; |
| 908 | 910 | const char *zUsername = 0; |
| 909 | 911 | const char *zPasswd = 0; |
| 910 | 912 | |
| 911 | - if( zAuth==0 ) return 0; /* Fail: No Authentication: header */ | |
| 913 | + if( zAuth==0 ) return 0; /* Fail: No Authentication: header */ | |
| 912 | 914 | 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 | + } | |
| 914 | 918 | |
| 915 | 919 | /* Parse out the username and password, separated by a ":" */ |
| 916 | 920 | zAuth += 6; |
| 917 | 921 | while( fossil_isspace(zAuth[0]) ) zAuth++; |
| 918 | 922 | zDecode = decode64(zAuth, &nDecode); |
| @@ -1069,11 +1073,11 @@ | ||
| 1069 | 1073 | /* If the request didn't provide a login cookie or the login cookie didn't |
| 1070 | 1074 | ** match a known valid user, check the HTTP "Authorization" header and |
| 1071 | 1075 | ** see if those credentials are valid for a known user. |
| 1072 | 1076 | */ |
| 1073 | 1077 | if( uid==0 && db_get_boolean("http_authentication_ok",0) ){ |
| 1074 | - uid = logic_basic_authentication(zIpAddr); | |
| 1078 | + uid = login_basic_authentication(zIpAddr); | |
| 1075 | 1079 | } |
| 1076 | 1080 | |
| 1077 | 1081 | /* If no user found yet, try to log in as "nobody" */ |
| 1078 | 1082 | if( uid==0 ){ |
| 1079 | 1083 | uid = db_int(0, "SELECT uid FROM user WHERE login='nobody'"); |
| @@ -1226,11 +1230,11 @@ | ||
| 1226 | 1230 | p->TktFmt = p->Attach = p->ApndTkt = |
| 1227 | 1231 | p->ModWiki = p->ModTkt = p->Delete = |
| 1228 | 1232 | p->RdForum = p->WrForum = p->ModForum = |
| 1229 | 1233 | p->WrTForum = p->AdminForum = |
| 1230 | 1234 | p->EmailAlert = p->Announce = p->Debug = |
| 1231 | - p->WrUnver = p->Private = 1; | |
| 1235 | + p->Private = 1; | |
| 1232 | 1236 | /* Fall thru into Read/Write */ |
| 1233 | 1237 | case 'i': p->Read = p->Write = 1; break; |
| 1234 | 1238 | case 'o': p->Read = 1; break; |
| 1235 | 1239 | case 'z': p->Zip = 1; break; |
| 1236 | 1240 | |
| 1237 | 1241 |
| --- 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 @@ | ||
| 173 | 173 | char *zPath; /* Name of webpage being served */ |
| 174 | 174 | char *zExtra; /* Extra path information past the webpage name */ |
| 175 | 175 | char *zBaseURL; /* Full text of the URL being served */ |
| 176 | 176 | char *zHttpsURL; /* zBaseURL translated to https: */ |
| 177 | 177 | char *zTop; /* Parent directory of zPath */ |
| 178 | + const char *zExtRoot; /* Document root for the /ext sub-website */ | |
| 178 | 179 | const char *zContentType; /* The content type of the input HTTP request */ |
| 179 | 180 | int iErrPriority; /* Priority of current error message */ |
| 180 | 181 | char *zErrMsg; /* Text of an error message */ |
| 181 | 182 | int sslNotAvailable; /* SSL is not available. Do not redirect to https: */ |
| 182 | 183 | Blob cgiIn; /* Input to an xfer www method */ |
| @@ -1193,11 +1194,11 @@ | ||
| 1193 | 1194 | ** The g.zBaseURL is normally set based on HTTP_HOST and SCRIPT_NAME |
| 1194 | 1195 | ** environment variables. However, if zAltBase is not NULL then it |
| 1195 | 1196 | ** is the argument to the --baseurl option command-line option and |
| 1196 | 1197 | ** g.zBaseURL and g.zTop is set from that instead. |
| 1197 | 1198 | */ |
| 1198 | -static void set_base_url(const char *zAltBase){ | |
| 1199 | +void set_base_url(const char *zAltBase){ | |
| 1199 | 1200 | int i; |
| 1200 | 1201 | const char *zHost; |
| 1201 | 1202 | const char *zMode; |
| 1202 | 1203 | const char *zCur; |
| 1203 | 1204 | |
| @@ -1783,10 +1784,13 @@ | ||
| 1783 | 1784 | @ <h1>Server Configuration Error</h1> |
| 1784 | 1785 | @ <p>The database schema on the server is out-of-date. Please ask |
| 1785 | 1786 | @ the administrator to run <b>fossil rebuild</b>.</p> |
| 1786 | 1787 | } |
| 1787 | 1788 | }else{ |
| 1789 | + if( (pCmd->eCmdFlags & CMDFLAG_RAWCONTENT)==0 ){ | |
| 1790 | + cgi_decode_post_parameters(); | |
| 1791 | + } | |
| 1788 | 1792 | if( g.fCgiTrace ){ |
| 1789 | 1793 | fossil_trace("######## Calling %s #########\n", pCmd->zName); |
| 1790 | 1794 | cgi_print_all(1, 1); |
| 1791 | 1795 | } |
| 1792 | 1796 | #ifdef FOSSIL_ENABLE_TH1_HOOKS |
| @@ -1941,10 +1945,13 @@ | ||
| 1941 | 1945 | ** |
| 1942 | 1946 | ** debug: FILE Causing debugging information to be written |
| 1943 | 1947 | ** into FILE. |
| 1944 | 1948 | ** |
| 1945 | 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. | |
| 1946 | 1953 | ** |
| 1947 | 1954 | ** redirect: REPO URL Extract the "name" query parameter and search |
| 1948 | 1955 | ** REPO for a check-in or ticket that matches the |
| 1949 | 1956 | ** value of "name", then redirect to URL. There |
| 1950 | 1957 | ** can be multiple "redirect:" lines that are |
| @@ -2087,10 +2094,19 @@ | ||
| 2087 | 2094 | ** to FILENAME. |
| 2088 | 2095 | */ |
| 2089 | 2096 | g.zErrlog = mprintf("%s", blob_str(&value)); |
| 2090 | 2097 | blob_reset(&value); |
| 2091 | 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; | |
| 2092 | 2108 | } |
| 2093 | 2109 | if( blob_eq(&key, "HOME:") && blob_token(&line, &value) ){ |
| 2094 | 2110 | /* HOME: VALUE |
| 2095 | 2111 | ** |
| 2096 | 2112 | ** Set CGI parameter "HOME" to VALUE. This is legacy. Use |
| @@ -2240,16 +2256,17 @@ | ||
| 2240 | 2256 | ** for requests coming from localhost, if the "localauth" setting is not |
| 2241 | 2257 | ** enabled. |
| 2242 | 2258 | ** |
| 2243 | 2259 | ** Options: |
| 2244 | 2260 | ** --baseurl URL base URL (useful with reverse proxies) |
| 2261 | +** --extroot DIR document root for the /ext extension mechanism | |
| 2245 | 2262 | ** --files GLOB comma-separate glob patterns for static file to serve |
| 2246 | -** --localauth enable automatic login for local connections | |
| 2247 | 2263 | ** --host NAME specify hostname of the server |
| 2248 | 2264 | ** --https signal a request coming in via https |
| 2249 | 2265 | ** --in FILE Take input from FILE instead of standard input |
| 2250 | 2266 | ** --ipaddr ADDR Assume the request comes from the given IP address |
| 2267 | +** --localauth enable automatic login for local connections | |
| 2251 | 2268 | ** --nocompress do not compress HTTP replies |
| 2252 | 2269 | ** --nodelay omit backoffice processing if it would delay process exit |
| 2253 | 2270 | ** --nojail drop root privilege but do not enter the chroot jail |
| 2254 | 2271 | ** --nossl signal that no SSL connections are available |
| 2255 | 2272 | ** --notfound URL use URL as "HTTP 404, object not found" page. |
| @@ -2297,10 +2314,11 @@ | ||
| 2297 | 2314 | noJail = find_option("nojail",0,0)!=0; |
| 2298 | 2315 | allowRepoList = find_option("repolist",0,0)!=0; |
| 2299 | 2316 | g.useLocalauth = find_option("localauth", 0, 0)!=0; |
| 2300 | 2317 | g.sslNotAvailable = find_option("nossl", 0, 0)!=0; |
| 2301 | 2318 | g.fNoHttpCompress = find_option("nocompress",0,0)!=0; |
| 2319 | + g.zExtRoot = find_option("extroot",0,1); | |
| 2302 | 2320 | zInFile = find_option("in",0,1); |
| 2303 | 2321 | if( zInFile ){ |
| 2304 | 2322 | backoffice_disable(); |
| 2305 | 2323 | g.httpIn = fossil_fopen(zInFile, "rb"); |
| 2306 | 2324 | if( g.httpIn==0 ) fossil_fatal("cannot open \"%s\" for reading", zInFile); |
| @@ -2391,10 +2409,11 @@ | ||
| 2391 | 2409 | Th_InitTraceLog(); |
| 2392 | 2410 | login_set_capabilities("sx", 0); |
| 2393 | 2411 | g.useLocalauth = 1; |
| 2394 | 2412 | g.httpIn = stdin; |
| 2395 | 2413 | g.httpOut = stdout; |
| 2414 | + g.zExtRoot = find_option("extroot",0,1); | |
| 2396 | 2415 | find_server_repository(2, 0); |
| 2397 | 2416 | g.cgiOutput = 1; |
| 2398 | 2417 | g.fNoHttpCompress = 1; |
| 2399 | 2418 | g.fullHttpReply = 1; |
| 2400 | 2419 | zIpAddr = cgi_ssh_remote_addr(0); |
| @@ -2402,11 +2421,11 @@ | ||
| 2402 | 2421 | g.fSshClient |= CGI_SSH_CLIENT; |
| 2403 | 2422 | ssh_request_loop(zIpAddr, 0); |
| 2404 | 2423 | }else{ |
| 2405 | 2424 | cgi_set_parameter("REMOTE_ADDR", "127.0.0.1"); |
| 2406 | 2425 | cgi_handle_http_request(0); |
| 2407 | - process_one_web_page(0, 0, 0); | |
| 2426 | + process_one_web_page(0, 0, 1); | |
| 2408 | 2427 | } |
| 2409 | 2428 | } |
| 2410 | 2429 | |
| 2411 | 2430 | #if !defined(_WIN32) |
| 2412 | 2431 | #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__) |
| @@ -2484,11 +2503,11 @@ | ||
| 2484 | 2503 | ** by default. |
| 2485 | 2504 | ** |
| 2486 | 2505 | ** Options: |
| 2487 | 2506 | ** --baseurl URL Use URL as the base (useful for reverse proxies) |
| 2488 | 2507 | ** --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 | |
| 2490 | 2509 | ** --files GLOBLIST Comma-separated list of glob patterns for static files |
| 2491 | 2510 | ** --localauth enable automatic login for requests from localhost |
| 2492 | 2511 | ** --localhost listen on 127.0.0.1 only (always true for "ui") |
| 2493 | 2512 | ** --https Indicates that the input is coming through a reverse |
| 2494 | 2513 | ** proxy that has already translated HTTPS into HTTP. |
| @@ -2497,10 +2516,11 @@ | ||
| 2497 | 2516 | ** --nocompress Do not compress HTTP replies |
| 2498 | 2517 | ** --nojail Drop root privileges but do not enter the chroot jail |
| 2499 | 2518 | ** --nossl signal that no SSL connections are available (Always |
| 2500 | 2519 | ** set by default for the "ui" command) |
| 2501 | 2520 | ** --notfound URL Redirect |
| 2521 | +** --page PAGE Start "ui" on PAGE. ex: --page "timeline?y=ci" | |
| 2502 | 2522 | ** -P|--port TCPPORT listen to request on port TCPPORT |
| 2503 | 2523 | ** --th-trace trace TH1 execution (for debugging purposes) |
| 2504 | 2524 | ** --repolist If REPOSITORY is dir, URL "/" lists repos. |
| 2505 | 2525 | ** --scgi Accept SCGI rather than HTTP |
| 2506 | 2526 | ** --skin LABEL Use override skin LABEL |
| @@ -2537,10 +2557,11 @@ | ||
| 2537 | 2557 | #endif |
| 2538 | 2558 | |
| 2539 | 2559 | if( g.zErrlog==0 ){ |
| 2540 | 2560 | g.zErrlog = "-"; |
| 2541 | 2561 | } |
| 2562 | + g.zExtRoot = find_option("extroot",0,1); | |
| 2542 | 2563 | zFileGlob = find_option("files-urlenc",0,1); |
| 2543 | 2564 | if( zFileGlob ){ |
| 2544 | 2565 | char *z = mprintf("%s", zFileGlob); |
| 2545 | 2566 | dehttpize(z); |
| 2546 | 2567 | zFileGlob = z; |
| 2547 | 2568 |
| --- 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 @@ | ||
| 51 | 51 | $(SRCDIR)/doc.c \ |
| 52 | 52 | $(SRCDIR)/encode.c \ |
| 53 | 53 | $(SRCDIR)/etag.c \ |
| 54 | 54 | $(SRCDIR)/event.c \ |
| 55 | 55 | $(SRCDIR)/export.c \ |
| 56 | + $(SRCDIR)/extcgi.c \ | |
| 56 | 57 | $(SRCDIR)/file.c \ |
| 57 | 58 | $(SRCDIR)/finfo.c \ |
| 58 | 59 | $(SRCDIR)/foci.c \ |
| 59 | 60 | $(SRCDIR)/forum.c \ |
| 60 | 61 | $(SRCDIR)/fshell.c \ |
| @@ -264,10 +265,11 @@ | ||
| 264 | 265 | $(OBJDIR)/doc_.c \ |
| 265 | 266 | $(OBJDIR)/encode_.c \ |
| 266 | 267 | $(OBJDIR)/etag_.c \ |
| 267 | 268 | $(OBJDIR)/event_.c \ |
| 268 | 269 | $(OBJDIR)/export_.c \ |
| 270 | + $(OBJDIR)/extcgi_.c \ | |
| 269 | 271 | $(OBJDIR)/file_.c \ |
| 270 | 272 | $(OBJDIR)/finfo_.c \ |
| 271 | 273 | $(OBJDIR)/foci_.c \ |
| 272 | 274 | $(OBJDIR)/forum_.c \ |
| 273 | 275 | $(OBJDIR)/fshell_.c \ |
| @@ -403,10 +405,11 @@ | ||
| 403 | 405 | $(OBJDIR)/doc.o \ |
| 404 | 406 | $(OBJDIR)/encode.o \ |
| 405 | 407 | $(OBJDIR)/etag.o \ |
| 406 | 408 | $(OBJDIR)/event.o \ |
| 407 | 409 | $(OBJDIR)/export.o \ |
| 410 | + $(OBJDIR)/extcgi.o \ | |
| 408 | 411 | $(OBJDIR)/file.o \ |
| 409 | 412 | $(OBJDIR)/finfo.o \ |
| 410 | 413 | $(OBJDIR)/foci.o \ |
| 411 | 414 | $(OBJDIR)/forum.o \ |
| 412 | 415 | $(OBJDIR)/fshell.o \ |
| @@ -740,10 +743,11 @@ | ||
| 740 | 743 | $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \ |
| 741 | 744 | $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ |
| 742 | 745 | $(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \ |
| 743 | 746 | $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ |
| 744 | 747 | $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ |
| 748 | + $(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \ | |
| 745 | 749 | $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ |
| 746 | 750 | $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ |
| 747 | 751 | $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ |
| 748 | 752 | $(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \ |
| 749 | 753 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| @@ -1142,10 +1146,18 @@ | ||
| 1142 | 1146 | |
| 1143 | 1147 | $(OBJDIR)/export.o: $(OBJDIR)/export_.c $(OBJDIR)/export.h $(SRCDIR)/config.h |
| 1144 | 1148 | $(XTCC) -o $(OBJDIR)/export.o -c $(OBJDIR)/export_.c |
| 1145 | 1149 | |
| 1146 | 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 | |
| 1147 | 1159 | |
| 1148 | 1160 | $(OBJDIR)/file_.c: $(SRCDIR)/file.c $(OBJDIR)/translate |
| 1149 | 1161 | $(OBJDIR)/translate $(SRCDIR)/file.c >$@ |
| 1150 | 1162 | |
| 1151 | 1163 | $(OBJDIR)/file.o: $(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h |
| 1152 | 1164 |
| --- 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 |
+1
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -61,10 +61,11 @@ | ||
| 61 | 61 | dispatch |
| 62 | 62 | doc |
| 63 | 63 | encode |
| 64 | 64 | etag |
| 65 | 65 | event |
| 66 | + extcgi | |
| 66 | 67 | export |
| 67 | 68 | file |
| 68 | 69 | finfo |
| 69 | 70 | foci |
| 70 | 71 | forum |
| 71 | 72 |
| --- 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 |
+3
| --- src/mkindex.c | ||
| +++ src/mkindex.c | ||
| @@ -89,10 +89,11 @@ | ||
| 89 | 89 | #define CMDFLAG_COMMAND 0x0010 /* A command */ |
| 90 | 90 | #define CMDFLAG_SETTING 0x0020 /* A setting */ |
| 91 | 91 | #define CMDFLAG_VERSIONABLE 0x0040 /* A versionable setting */ |
| 92 | 92 | #define CMDFLAG_BLOCKTEXT 0x0080 /* Multi-line text setting */ |
| 93 | 93 | #define CMDFLAG_BOOLEAN 0x0100 /* A boolean setting */ |
| 94 | +#define CMDFLAG_RAWCONTENT 0x0200 /* Do not interpret webpage content */ | |
| 94 | 95 | /**************************************************************************/ |
| 95 | 96 | |
| 96 | 97 | /* |
| 97 | 98 | ** Each entry looks like this: |
| 98 | 99 | */ |
| @@ -236,10 +237,12 @@ | ||
| 236 | 237 | aEntry[nUsed].eType &= ~(CMDFLAG_1ST_TIER|CMDFLAG_TEST); |
| 237 | 238 | aEntry[nUsed].eType |= CMDFLAG_2ND_TIER; |
| 238 | 239 | }else if( j==4 && strncmp(&zLine[i], "test", j)==0 ){ |
| 239 | 240 | aEntry[nUsed].eType &= ~(CMDFLAG_1ST_TIER|CMDFLAG_2ND_TIER); |
| 240 | 241 | aEntry[nUsed].eType |= CMDFLAG_TEST; |
| 242 | + }else if( j==11 && strncmp(&zLine[i], "raw-content", j)==0 ){ | |
| 243 | + aEntry[nUsed].eType |= CMDFLAG_RAWCONTENT; | |
| 241 | 244 | }else if( j==7 && strncmp(&zLine[i], "boolean", j)==0 ){ |
| 242 | 245 | aEntry[nUsed].eType &= ~(CMDFLAG_BLOCKTEXT); |
| 243 | 246 | aEntry[nUsed].iWidth = 0; |
| 244 | 247 | aEntry[nUsed].eType |= CMDFLAG_BOOLEAN; |
| 245 | 248 | }else if( j==10 && strncmp(&zLine[i], "block-text", j)==0 ){ |
| 246 | 249 |
| --- 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 @@ | ||
| 121 | 121 | ** Note that *ppIn is an unbuffered file descriptor, not a FILE. |
| 122 | 122 | ** The process ID of the child is written into *pChildPid. |
| 123 | 123 | ** |
| 124 | 124 | ** Return the number of errors. |
| 125 | 125 | */ |
| 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 | +){ | |
| 127 | 133 | #ifdef _WIN32 |
| 128 | 134 | HANDLE hStdinRd, hStdinWr, hStdoutRd, hStdoutWr, hStderr; |
| 129 | 135 | SECURITY_ATTRIBUTES saAttr; |
| 130 | 136 | DWORD childPid = 0; |
| 131 | 137 | int fd; |
| @@ -189,11 +195,15 @@ | ||
| 189 | 195 | close(1); |
| 190 | 196 | fd = dup(pin[1]); |
| 191 | 197 | if( fd!=1 ) nErr++; |
| 192 | 198 | close(pin[0]); |
| 193 | 199 | 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 | + } | |
| 195 | 205 | return 1; |
| 196 | 206 | }else{ |
| 197 | 207 | /* This is the parent process */ |
| 198 | 208 | close(pin[1]); |
| 199 | 209 | *pfdIn = pin[0]; |
| 200 | 210 |
| --- 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 @@ | ||
| 27 | 27 | ** input. All other fields are outputs. |
| 28 | 28 | */ |
| 29 | 29 | struct RepoInfo { |
| 30 | 30 | char *zRepoName; /* Name of the repository file */ |
| 31 | 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. */ | |
| 32 | 35 | char *zProjName; /* Project Name. Memory from fossil_malloc() */ |
| 33 | 36 | double rMTime; /* Last update. Julian day number */ |
| 34 | 37 | }; |
| 35 | 38 | #endif |
| 36 | 39 | |
| 37 | 40 | /* |
| 38 | 41 | ** 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. | |
| 40 | 44 | */ |
| 41 | -void remote_repo_info(RepoInfo *pRepo){ | |
| 45 | +static void remote_repo_info(RepoInfo *pRepo){ | |
| 42 | 46 | sqlite3 *db; |
| 43 | 47 | sqlite3_stmt *pStmt; |
| 44 | 48 | int rc; |
| 45 | 49 | |
| 50 | + pRepo->isRepolistSkin = 0; | |
| 46 | 51 | pRepo->isValid = 0; |
| 47 | 52 | pRepo->zProjName = 0; |
| 48 | 53 | pRepo->rMTime = 0.0; |
| 49 | 54 | |
| 50 | 55 | g.dbIgnoreErrors++; |
| 51 | 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); | |
| 52 | 66 | if( rc ) goto finish_repo_list; |
| 53 | 67 | rc = sqlite3_prepare_v2(db, "SELECT value FROM config" |
| 54 | 68 | " WHERE name='project-name'", |
| 55 | 69 | -1, &pStmt, 0); |
| 56 | 70 | if( rc ) goto finish_repo_list; |
| @@ -85,15 +99,20 @@ | ||
| 85 | 99 | ** |
| 86 | 100 | ** Or, if no repositories can be located beneath g.zRepositoryName, |
| 87 | 101 | ** return 0. |
| 88 | 102 | */ |
| 89 | 103 | 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 */ | |
| 93 | 111 | |
| 94 | 112 | assert( g.db==0 ); |
| 113 | + blob_init(&html, 0, 0); | |
| 95 | 114 | if( fossil_strcmp(g.zRepositoryName,"/")==0 && !g.fJail ){ |
| 96 | 115 | /* For the special case of the "repository directory" being "/", |
| 97 | 116 | ** show all of the repositories named in the ~/.fossil database. |
| 98 | 117 | ** |
| 99 | 118 | ** On unix systems, then entries are of the form "repo:/home/..." |
| @@ -118,28 +137,24 @@ | ||
| 118 | 137 | db_multi_exec("CREATE TABLE vfile(pathname);"); |
| 119 | 138 | vfile_scan(&base, blob_size(&base), 0, 0, 0); |
| 120 | 139 | db_multi_exec("DELETE FROM sfile WHERE pathname NOT GLOB '*[^/].fossil'"); |
| 121 | 140 | allRepo = 0; |
| 122 | 141 | } |
| 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 | 142 | 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{ | |
| 132 | 147 | Stmt q; |
| 133 | 148 | 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"); | |
| 141 | 156 | db_prepare(&q, "SELECT pathname" |
| 142 | 157 | " FROM sfile ORDER BY pathname COLLATE nocase;"); |
| 143 | 158 | rNow = db_double(0, "SELECT julianday('now')"); |
| 144 | 159 | while( db_step(&q)==SQLITE_ROW ){ |
| 145 | 160 | const char *zName = db_column_text(&q, 0); |
| @@ -162,51 +177,97 @@ | ||
| 162 | 177 | }else{ |
| 163 | 178 | zFull = mprintf("%s/%s", g.zRepositoryName, zName); |
| 164 | 179 | } |
| 165 | 180 | x.zRepoName = zFull; |
| 166 | 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 | + } | |
| 167 | 188 | fossil_free(zFull); |
| 168 | 189 | if( !x.isValid ){ |
| 169 | 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; | |
| 170 | 196 | } |
| 171 | 197 | iAge = (rNow - x.rMTime)*86400; |
| 172 | 198 | if( iAge<0 ) x.rMTime = rNow; |
| 173 | 199 | zAge = human_readable_age(rNow - x.rMTime); |
| 174 | - @ <tr><td valign="top">\ | |
| 200 | + blob_append_sql(&html, "<tr><td valign='top'>"); | |
| 175 | 201 | if( sqlite3_strglob("*.fossil", zName)!=0 ){ |
| 176 | 202 | /* The "fossil server DIRECTORY" and "fossil ui DIRECTORY" commands |
| 177 | 203 | ** do not work for repositories whose names do not end in ".fossil". |
| 178 | 204 | ** So do not hyperlink those cases. */ |
| 179 | - @ %h(zName) | |
| 205 | + blob_append_sql(&html,"%h",zName); | |
| 180 | 206 | } 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); | |
| 183 | 209 | } 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); | |
| 185 | 213 | }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); | |
| 187 | 217 | } |
| 188 | 218 | if( x.zProjName ){ |
| 189 | - @ <td></td><td>%h(x.zProjName)</td> | |
| 219 | + blob_append_sql(&html, "<td></td><td>%h</td>\n", x.zProjName); | |
| 190 | 220 | fossil_free(x.zProjName); |
| 191 | 221 | }else{ |
| 192 | - @ <td></td><td></td> | |
| 222 | + blob_append_sql(&html, "<td></td><td></td>\n"); | |
| 193 | 223 | } |
| 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); | |
| 195 | 227 | fossil_free(zAge); |
| 196 | 228 | sqlite3_free(zUrl); |
| 197 | 229 | } |
| 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(); | |
| 199 | 251 | }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(); | |
| 208 | 269 | return n; |
| 209 | 270 | } |
| 210 | 271 | |
| 211 | 272 | /* |
| 212 | 273 | ** COMMAND: test-list-page |
| 213 | 274 |
| --- 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 @@ | ||
| 337 | 337 | char zCap[70], zNm[4]; |
| 338 | 338 | zNm[0] = 'a'; |
| 339 | 339 | zNm[2] = 0; |
| 340 | 340 | for(i=0, c='a'; c<='z'; c++){ |
| 341 | 341 | 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; | |
| 343 | 343 | if( a[c&0x7f] ) zCap[i++] = c; |
| 344 | 344 | } |
| 345 | 345 | for(c='0'; c<='9'; c++){ |
| 346 | 346 | zNm[1] = c; |
| 347 | 347 | a[c&0x7f] = P(zNm)!=0; |
| 348 | 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' || 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 @@ | ||
| 1120 | 1120 | ** of application/x-fossil or application/x-fossil-debug to this page, |
| 1121 | 1121 | ** regardless of what path was specified in the HTTP header. This allows |
| 1122 | 1122 | ** clone clients to specify a URL that omits default pathnames, such |
| 1123 | 1123 | ** as "http://fossil-scm.org/" instead of "http://fossil-scm.org/index.cgi". |
| 1124 | 1124 | ** |
| 1125 | -** WEBPAGE: xfer | |
| 1125 | +** WEBPAGE: xfer raw-content | |
| 1126 | 1126 | ** |
| 1127 | 1127 | ** This is the transfer handler on the server side. The transfer |
| 1128 | 1128 | ** message has been uncompressed and placed in the g.cgiIn blob. |
| 1129 | 1129 | ** Process this message and form an appropriate reply. |
| 1130 | 1130 | */ |
| @@ -1783,10 +1783,11 @@ | ||
| 1783 | 1783 | int nUvFileRcvd = 0; /* Number of uvfile cards received on this cycle */ |
| 1784 | 1784 | sqlite3_int64 mtime; /* Modification time on a UV file */ |
| 1785 | 1785 | int autopushFailed = 0; /* Autopush following commit failed if true */ |
| 1786 | 1786 | const char *zCkinLock; /* Name of check-in to lock. NULL for none */ |
| 1787 | 1787 | const char *zClientId; /* A unique identifier for this check-out */ |
| 1788 | + unsigned int mHttpFlags;/* Flags for the http_exchange() subsystem */ | |
| 1788 | 1789 | |
| 1789 | 1790 | if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH; |
| 1790 | 1791 | if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE|SYNC_UNVERSIONED))==0 |
| 1791 | 1792 | && configRcvMask==0 && configSendMask==0 ) return 0; |
| 1792 | 1793 | if( syncFlags & SYNC_FROMPARENT ){ |
| @@ -2020,12 +2021,17 @@ | ||
| 2020 | 2021 | if( syncFlags & SYNC_VERBOSE ){ |
| 2021 | 2022 | fossil_print("waiting for server..."); |
| 2022 | 2023 | } |
| 2023 | 2024 | fflush(stdout); |
| 2024 | 2025 | /* 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) ){ | |
| 2027 | 2033 | nErr++; |
| 2028 | 2034 | go = 2; |
| 2029 | 2035 | break; |
| 2030 | 2036 | } |
| 2031 | 2037 | |
| 2032 | 2038 |
| --- 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 @@ | ||
| 28 | 28 | |
| 29 | 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 | 30 | |
| 31 | 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 | 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 | |
| 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 | 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 | |
| 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 | 36 | |
| 37 | 37 | |
| 38 | 38 | RC=$(DMDIR)\bin\rcc |
| 39 | 39 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 40 | 40 | |
| @@ -49,11 +49,11 @@ | ||
| 49 | 49 | |
| 50 | 50 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 51 | 51 | $(RC) $(RCFLAGS) -o$@ $** |
| 52 | 52 | |
| 53 | 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 > $@ | |
| 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 | 55 | +echo fossil >> $@ |
| 56 | 56 | +echo fossil >> $@ |
| 57 | 57 | +echo $(LIBS) >> $@ |
| 58 | 58 | +echo. >> $@ |
| 59 | 59 | +echo fossil >> $@ |
| @@ -350,10 +350,16 @@ | ||
| 350 | 350 | $(OBJDIR)\export$O : export_.c export.h |
| 351 | 351 | $(TCC) -o$@ -c export_.c |
| 352 | 352 | |
| 353 | 353 | export_.c : $(SRCDIR)\export.c |
| 354 | 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 $** > $@ | |
| 355 | 361 | |
| 356 | 362 | $(OBJDIR)\file$O : file_.c file.h |
| 357 | 363 | $(TCC) -o$@ -c file_.c |
| 358 | 364 | |
| 359 | 365 | file_.c : $(SRCDIR)\file.c |
| @@ -952,7 +958,7 @@ | ||
| 952 | 958 | |
| 953 | 959 | zip_.c : $(SRCDIR)\zip.c |
| 954 | 960 | +translate$E $** > $@ |
| 955 | 961 | |
| 956 | 962 | 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 | |
| 958 | 964 | @copy /Y nul: headers |
| 959 | 965 |
| --- 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 |
+12
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -473,10 +473,11 @@ | ||
| 473 | 473 | $(SRCDIR)/doc.c \ |
| 474 | 474 | $(SRCDIR)/encode.c \ |
| 475 | 475 | $(SRCDIR)/etag.c \ |
| 476 | 476 | $(SRCDIR)/event.c \ |
| 477 | 477 | $(SRCDIR)/export.c \ |
| 478 | + $(SRCDIR)/extcgi.c \ | |
| 478 | 479 | $(SRCDIR)/file.c \ |
| 479 | 480 | $(SRCDIR)/finfo.c \ |
| 480 | 481 | $(SRCDIR)/foci.c \ |
| 481 | 482 | $(SRCDIR)/forum.c \ |
| 482 | 483 | $(SRCDIR)/fshell.c \ |
| @@ -686,10 +687,11 @@ | ||
| 686 | 687 | $(OBJDIR)/doc_.c \ |
| 687 | 688 | $(OBJDIR)/encode_.c \ |
| 688 | 689 | $(OBJDIR)/etag_.c \ |
| 689 | 690 | $(OBJDIR)/event_.c \ |
| 690 | 691 | $(OBJDIR)/export_.c \ |
| 692 | + $(OBJDIR)/extcgi_.c \ | |
| 691 | 693 | $(OBJDIR)/file_.c \ |
| 692 | 694 | $(OBJDIR)/finfo_.c \ |
| 693 | 695 | $(OBJDIR)/foci_.c \ |
| 694 | 696 | $(OBJDIR)/forum_.c \ |
| 695 | 697 | $(OBJDIR)/fshell_.c \ |
| @@ -825,10 +827,11 @@ | ||
| 825 | 827 | $(OBJDIR)/doc.o \ |
| 826 | 828 | $(OBJDIR)/encode.o \ |
| 827 | 829 | $(OBJDIR)/etag.o \ |
| 828 | 830 | $(OBJDIR)/event.o \ |
| 829 | 831 | $(OBJDIR)/export.o \ |
| 832 | + $(OBJDIR)/extcgi.o \ | |
| 830 | 833 | $(OBJDIR)/file.o \ |
| 831 | 834 | $(OBJDIR)/finfo.o \ |
| 832 | 835 | $(OBJDIR)/foci.o \ |
| 833 | 836 | $(OBJDIR)/forum.o \ |
| 834 | 837 | $(OBJDIR)/fshell.o \ |
| @@ -1184,10 +1187,11 @@ | ||
| 1184 | 1187 | $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h \ |
| 1185 | 1188 | $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ |
| 1186 | 1189 | $(OBJDIR)/etag_.c:$(OBJDIR)/etag.h \ |
| 1187 | 1190 | $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ |
| 1188 | 1191 | $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ |
| 1192 | + $(OBJDIR)/extcgi_.c:$(OBJDIR)/extcgi.h \ | |
| 1189 | 1193 | $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ |
| 1190 | 1194 | $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ |
| 1191 | 1195 | $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ |
| 1192 | 1196 | $(OBJDIR)/forum_.c:$(OBJDIR)/forum.h \ |
| 1193 | 1197 | $(OBJDIR)/fshell_.c:$(OBJDIR)/fshell.h \ |
| @@ -1588,10 +1592,18 @@ | ||
| 1588 | 1592 | |
| 1589 | 1593 | $(OBJDIR)/export.o: $(OBJDIR)/export_.c $(OBJDIR)/export.h $(SRCDIR)/config.h |
| 1590 | 1594 | $(XTCC) -o $(OBJDIR)/export.o -c $(OBJDIR)/export_.c |
| 1591 | 1595 | |
| 1592 | 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 | |
| 1593 | 1605 | |
| 1594 | 1606 | $(OBJDIR)/file_.c: $(SRCDIR)/file.c $(TRANSLATE) |
| 1595 | 1607 | $(TRANSLATE) $(SRCDIR)/file.c >$@ |
| 1596 | 1608 | |
| 1597 | 1609 | $(OBJDIR)/file.o: $(OBJDIR)/file_.c $(OBJDIR)/file.h $(SRCDIR)/config.h |
| 1598 | 1610 |
| --- 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 |
+10
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -379,10 +379,11 @@ | ||
| 379 | 379 | doc_.c \ |
| 380 | 380 | encode_.c \ |
| 381 | 381 | etag_.c \ |
| 382 | 382 | event_.c \ |
| 383 | 383 | export_.c \ |
| 384 | + extcgi_.c \ | |
| 384 | 385 | file_.c \ |
| 385 | 386 | finfo_.c \ |
| 386 | 387 | foci_.c \ |
| 387 | 388 | forum_.c \ |
| 388 | 389 | fshell_.c \ |
| @@ -591,10 +592,11 @@ | ||
| 591 | 592 | $(OX)\doc$O \ |
| 592 | 593 | $(OX)\encode$O \ |
| 593 | 594 | $(OX)\etag$O \ |
| 594 | 595 | $(OX)\event$O \ |
| 595 | 596 | $(OX)\export$O \ |
| 597 | + $(OX)\extcgi$O \ | |
| 596 | 598 | $(OX)\file$O \ |
| 597 | 599 | $(OX)\finfo$O \ |
| 598 | 600 | $(OX)\foci$O \ |
| 599 | 601 | $(OX)\forum$O \ |
| 600 | 602 | $(OX)\fshell$O \ |
| @@ -792,10 +794,11 @@ | ||
| 792 | 794 | echo $(OX)\doc.obj >> $@ |
| 793 | 795 | echo $(OX)\encode.obj >> $@ |
| 794 | 796 | echo $(OX)\etag.obj >> $@ |
| 795 | 797 | echo $(OX)\event.obj >> $@ |
| 796 | 798 | echo $(OX)\export.obj >> $@ |
| 799 | + echo $(OX)\extcgi.obj >> $@ | |
| 797 | 800 | echo $(OX)\file.obj >> $@ |
| 798 | 801 | echo $(OX)\finfo.obj >> $@ |
| 799 | 802 | echo $(OX)\foci.obj >> $@ |
| 800 | 803 | echo $(OX)\forum.obj >> $@ |
| 801 | 804 | echo $(OX)\fshell.obj >> $@ |
| @@ -1236,10 +1239,16 @@ | ||
| 1236 | 1239 | $(OX)\export$O : export_.c export.h |
| 1237 | 1240 | $(TCC) /Fo$@ -c export_.c |
| 1238 | 1241 | |
| 1239 | 1242 | export_.c : $(SRCDIR)\export.c |
| 1240 | 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 $** > $@ | |
| 1241 | 1250 | |
| 1242 | 1251 | $(OX)\file$O : file_.c file.h |
| 1243 | 1252 | $(TCC) /Fo$@ -c file_.c |
| 1244 | 1253 | |
| 1245 | 1254 | file_.c : $(SRCDIR)\file.c |
| @@ -1878,10 +1887,11 @@ | ||
| 1878 | 1887 | doc_.c:doc.h \ |
| 1879 | 1888 | encode_.c:encode.h \ |
| 1880 | 1889 | etag_.c:etag.h \ |
| 1881 | 1890 | event_.c:event.h \ |
| 1882 | 1891 | export_.c:export.h \ |
| 1892 | + extcgi_.c:extcgi.h \ | |
| 1883 | 1893 | file_.c:file.h \ |
| 1884 | 1894 | finfo_.c:finfo.h \ |
| 1885 | 1895 | foci_.c:foci.h \ |
| 1886 | 1896 | forum_.c:forum.h \ |
| 1887 | 1897 | fshell_.c:fshell.h \ |
| 1888 | 1898 |
| --- 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 |
+8
| --- www/changes.wiki | ||
| +++ www/changes.wiki | ||
| @@ -1,11 +1,19 @@ | ||
| 1 | 1 | <title>Change Log</title> |
| 2 | 2 | |
| 3 | 3 | <a name='v2_10'></a> |
| 4 | 4 | <h2>Changes for Version 2.10 (pending)</h2> |
| 5 | 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. | |
| 6 | 13 | * Change the default [./hashpolicy.wiki|hash policy] to SHA3. |
| 14 | + * Documentation improvements | |
| 7 | 15 | |
| 8 | 16 | <a name='v2_9'></a> |
| 9 | 17 | <h2>Changes for Version 2.9 (2019-07-13)</h2> |
| 10 | 18 | |
| 11 | 19 | * Added the [/help?cmd=git|fossil git export] command and instructions |
| 12 | 20 |
| --- 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 @@ | ||
| 31 | 31 | |
| 32 | 32 | `--chdir DIRECTORY`: Change to the named directory before processing |
| 33 | 33 | any commands. |
| 34 | 34 | |
| 35 | 35 | |
| 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 | |
| 38 | 37 | and certain other text outputs are formatted for display. The flags are |
| 39 | 38 | individual bits in `NUMBER`, which must be specified in base 10: |
| 40 | 39 | |
| 41 | 40 | * _0_ — Uses the revised algorithm with no special handling. |
| 42 | 41 | |
| @@ -56,10 +55,13 @@ | ||
| 56 | 55 | |
| 57 | 56 | * _16_ — Looks for the original comment text within the text being |
| 58 | 57 | printed. Upon matching, a new line will be emitted, thus |
| 59 | 58 | preserving more of the pre-existing formatting. |
| 60 | 59 | |
| 60 | + | |
| 61 | +`--comment-format NUMBER`: Alias for `--comfmtflags NUMBER`. | |
| 62 | + | |
| 61 | 63 | |
| 62 | 64 | `--errorlog ERRLOG`: Name a file to which fossil will log panics, |
| 63 | 65 | errors, and warnings. |
| 64 | 66 | |
| 65 | 67 | |
| 66 | 68 |
| --- 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_ — Uses the revised algorithm with no special handling. |
| 42 | |
| @@ -56,10 +55,13 @@ | |
| 56 | |
| 57 | * _16_ — 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_ — Uses the revised algorithm with no special handling. |
| 41 | |
| @@ -56,10 +55,13 @@ | |
| 55 | |
| 56 | * _16_ — 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 |
+72
-42
| --- www/fossil-v-git.wiki | ||
| +++ www/fossil-v-git.wiki | ||
| @@ -13,16 +13,10 @@ | ||
| 13 | 13 | Keep in mind that you are reading this on a Fossil website, and though |
| 14 | 14 | we try to be fair, the information here |
| 15 | 15 | might be biased in favor of Fossil. Ask around for second opinions from |
| 16 | 16 | people who have used <em>both</em> Fossil and Git. |
| 17 | 17 | |
| 18 | -¹<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 | 18 | |
| 25 | 19 | <h2>2.0 Differences Between Fossil And Git</h2> |
| 26 | 20 | |
| 27 | 21 | Differences between Fossil and Git are summarized by the following table, |
| 28 | 22 | with further description in the text that follows. |
| @@ -121,21 +115,19 @@ | ||
| 121 | 115 | |
| 122 | 116 | |
| 123 | 117 | <h3 id="vs-linux">2.3 Linux vs. SQLite</h3> |
| 124 | 118 | |
| 125 | 119 | 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 | |
| 127 | 121 | development project: [https://en.wikipedia.org/wiki/Linus_Torvalds|Linus |
| 128 | 122 | Torvalds] designed Git to support development of |
| 129 | 123 | [https://www.kernel.org/|the Linux kernel], and |
| 130 | 124 | [https://en.wikipedia.org/wiki/D._Richard_Hipp|D. Richard Hipp] designed |
| 131 | 125 | 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 | 126 | Both projects must rank high on any objective list of "most |
| 135 | 127 | important FOSS projects," yet these two projects are almost entirely unlike |
| 136 | -one another. | |
| 128 | +one another. So, too, are these two DVCSes. | |
| 137 | 129 | |
| 138 | 130 | In the following sections, we will explain how three key differences |
| 139 | 131 | between Linux and SQLite dictated the design of each DVCS's low-friction |
| 140 | 132 | usage path. |
| 141 | 133 | |
| @@ -177,44 +169,63 @@ | ||
| 177 | 169 | |
| 178 | 170 | <ul> |
| 179 | 171 | <li><p><b>Personal engagement:</b> SQLite's developers know each |
| 180 | 172 | other by name and work together daily on the project.</p></li> |
| 181 | 173 | |
| 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. | |
| 185 | 179 | 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 | |
| 189 | 183 | 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 | |
| 191 | 185 | [https://en.wikipedia.org/wiki/Flat_organization|flat |
| 192 | 186 | organizations].</p></li> |
| 193 | 187 | |
| 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> | |
| 206 | 203 | |
| 207 | 204 | <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 | |
| 209 | 206 | [/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> | |
| 212 | 223 | |
| 213 | 224 | <li><p><b>Branch names sync:</b> Unlike in Git, branch names are not |
| 214 | 225 | 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> | |
| 216 | 227 | |
| 217 | 228 | <li><p><b>Private branches are rare:</b> |
| 218 | 229 | [/doc/trunk/www/private.wiki|Private branches exist in Fossil], but |
| 219 | 230 | they're normally used to handle rare exception cases, whereas in |
| 220 | 231 | many Git projects, they're part of the straight-line development |
| @@ -224,19 +235,15 @@ | ||
| 224 | 235 | keep local clones identical to the repository it cloned |
| 225 | 236 | from.</p></li> |
| 226 | 237 | </ul> |
| 227 | 238 | |
| 228 | 239 | 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. | |
| 238 | 245 | |
| 239 | 246 | Each DVCS can be used in the opposite style, but doing so works against |
| 240 | 247 | their low-friction paths. |
| 241 | 248 | |
| 242 | 249 | |
| @@ -504,5 +511,28 @@ | ||
| 504 | 511 | The [/help?cmd=push|fossil push], [/help?cmd=pull|fossil pull], and |
| 505 | 512 | [/help?cmd=sync|fossil sync] commands do not provide the capability to |
| 506 | 513 | push or pull individual branches. Pushing and pulling in Fossil is |
| 507 | 514 | all or nothing. This is in keeping with Fossil's emphasis on maintaining |
| 508 | 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> | |
| 509 | 539 |
| --- 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 | ¹<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 @@ | ||
| 1 | 1 | <title>How To Configure A Fossil Server</title> |
| 2 | 2 | |
| 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> | |
| 4 | 13 | |
| 5 | 14 | <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. | |
| 8 | 18 | For example, the complete [https://www.fossil-scm.org/] website, including the |
| 9 | 19 | page you are now reading, |
| 10 | 20 | is just a Fossil server displaying the content of the |
| 11 | 21 | self-hosting repository for Fossil. |
| 12 | 22 | |
| @@ -236,12 +246,12 @@ | ||
| 236 | 246 | |
| 237 | 247 | Once deployed, a URL like: <b>http://mydomain.org/cgi-bin/repo/XYZ</b> |
| 238 | 248 | will serve up the repository "/home/fossil/repos/XYZ.fossil" (if it exists). |
| 239 | 249 | |
| 240 | 250 | 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]. | |
| 243 | 253 | </blockquote> |
| 244 | 254 | |
| 245 | 255 | <h2 id="scgi">Fossil as SCGI</h2> |
| 246 | 256 | <blockquote> |
| 247 | 257 | |
| 248 | 258 | |
| 249 | 259 | 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 |
+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 |
| --- 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 |