Fossil SCM
Defer decoding POST parameters until after the webpage name is located. Do not do the decode if the webpage has the new "raw-content" property. Set that property on /ext so that is can relay the encoded content to sub-cgi.
Commit
e4849f58e467b68aa107d7ae7c2ee6e55fd89cafde6eff2c69439c576a277222
Parent
cc21a4389e1c1c7…
5 files changed
+20
-12
+1
+1
-1
+3
+3
+20
-12
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -986,22 +986,11 @@ | ||
| 986 | 986 | |
| 987 | 987 | len = atoi(PD("CONTENT_LENGTH", "0")); |
| 988 | 988 | g.zContentType = zType = P("CONTENT_TYPE"); |
| 989 | 989 | blob_zero(&g.cgiIn); |
| 990 | 990 | if( len>0 && zType ){ |
| 991 | - if( fossil_strcmp(zType,"application/x-www-form-urlencoded")==0 | |
| 992 | - || strncmp(zType,"multipart/form-data",19)==0 ){ | |
| 993 | - z = fossil_malloc( len+1 ); | |
| 994 | - len = fread(z, 1, len, g.httpIn); | |
| 995 | - z[len] = 0; | |
| 996 | - cgi_trace(z); | |
| 997 | - if( zType[0]=='a' ){ | |
| 998 | - add_param_list(z, '&'); | |
| 999 | - }else{ | |
| 1000 | - process_multipart_form_data(z, len); | |
| 1001 | - } | |
| 1002 | - }else if( fossil_strcmp(zType, "application/x-fossil")==0 ){ | |
| 991 | + if( fossil_strcmp(zType, "application/x-fossil")==0 ){ | |
| 1003 | 992 | blob_read_from_channel(&g.cgiIn, g.httpIn, len); |
| 1004 | 993 | blob_uncompress(&g.cgiIn, &g.cgiIn); |
| 1005 | 994 | } |
| 1006 | 995 | #ifdef FOSSIL_ENABLE_JSON |
| 1007 | 996 | else if( fossil_strcmp(zType, "application/json") |
| @@ -1029,11 +1018,30 @@ | ||
| 1029 | 1018 | #endif /* FOSSIL_ENABLE_JSON */ |
| 1030 | 1019 | else{ |
| 1031 | 1020 | blob_read_from_channel(&g.cgiIn, g.httpIn, len); |
| 1032 | 1021 | } |
| 1033 | 1022 | } |
| 1023 | +} | |
| 1034 | 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 | + } | |
| 1042 | + blob_init(&g.cgiIn, 0, 0); | |
| 1035 | 1043 | } |
| 1036 | 1044 | |
| 1037 | 1045 | /* |
| 1038 | 1046 | ** This is the comparison function used to sort the aParamQP[] array of |
| 1039 | 1047 | ** query parameters and cookies. |
| 1040 | 1048 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -986,22 +986,11 @@ | |
| 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-www-form-urlencoded")==0 |
| 992 | || strncmp(zType,"multipart/form-data",19)==0 ){ |
| 993 | z = fossil_malloc( len+1 ); |
| 994 | len = fread(z, 1, len, g.httpIn); |
| 995 | z[len] = 0; |
| 996 | cgi_trace(z); |
| 997 | if( zType[0]=='a' ){ |
| 998 | add_param_list(z, '&'); |
| 999 | }else{ |
| 1000 | process_multipart_form_data(z, len); |
| 1001 | } |
| 1002 | }else if( fossil_strcmp(zType, "application/x-fossil")==0 ){ |
| 1003 | blob_read_from_channel(&g.cgiIn, g.httpIn, len); |
| 1004 | blob_uncompress(&g.cgiIn, &g.cgiIn); |
| 1005 | } |
| 1006 | #ifdef FOSSIL_ENABLE_JSON |
| 1007 | else if( fossil_strcmp(zType, "application/json") |
| @@ -1029,11 +1018,30 @@ | |
| 1029 | #endif /* FOSSIL_ENABLE_JSON */ |
| 1030 | else{ |
| 1031 | blob_read_from_channel(&g.cgiIn, g.httpIn, len); |
| 1032 | } |
| 1033 | } |
| 1034 | |
| 1035 | } |
| 1036 | |
| 1037 | /* |
| 1038 | ** This is the comparison function used to sort the aParamQP[] array of |
| 1039 | ** query parameters and cookies. |
| 1040 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -986,22 +986,11 @@ | |
| 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") |
| @@ -1029,11 +1018,30 @@ | |
| 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 | } |
| 1042 | blob_init(&g.cgiIn, 0, 0); |
| 1043 | } |
| 1044 | |
| 1045 | /* |
| 1046 | ** This is the comparison function used to sort the aParamQP[] array of |
| 1047 | ** query parameters and cookies. |
| 1048 |
+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 |
+1
-1
| --- src/extcgi.c | ||
| +++ src/extcgi.c | ||
| @@ -74,11 +74,11 @@ | ||
| 74 | 74 | "SERVER_PORT", |
| 75 | 75 | "SERVER_PROTOCOL", |
| 76 | 76 | }; |
| 77 | 77 | |
| 78 | 78 | /* |
| 79 | -** WEBPAGE: ext | |
| 79 | +** WEBPAGE: ext raw-content | |
| 80 | 80 | ** |
| 81 | 81 | ** Relay an HTTP request to secondary CGI after first checking the |
| 82 | 82 | ** login credentials and setting auxiliary environment variables |
| 83 | 83 | ** so that the secondary CGI can be aware of the credentials and |
| 84 | 84 | ** capabilities of the Fossil user. |
| 85 | 85 |
| --- src/extcgi.c | |
| +++ src/extcgi.c | |
| @@ -74,11 +74,11 @@ | |
| 74 | "SERVER_PORT", |
| 75 | "SERVER_PROTOCOL", |
| 76 | }; |
| 77 | |
| 78 | /* |
| 79 | ** WEBPAGE: ext |
| 80 | ** |
| 81 | ** Relay an HTTP request to secondary CGI after first checking the |
| 82 | ** login credentials and setting auxiliary environment variables |
| 83 | ** so that the secondary CGI can be aware of the credentials and |
| 84 | ** capabilities of the Fossil user. |
| 85 |
| --- src/extcgi.c | |
| +++ src/extcgi.c | |
| @@ -74,11 +74,11 @@ | |
| 74 | "SERVER_PORT", |
| 75 | "SERVER_PROTOCOL", |
| 76 | }; |
| 77 | |
| 78 | /* |
| 79 | ** WEBPAGE: ext raw-content |
| 80 | ** |
| 81 | ** Relay an HTTP request to secondary CGI after first checking the |
| 82 | ** login credentials and setting auxiliary environment variables |
| 83 | ** so that the secondary CGI can be aware of the credentials and |
| 84 | ** capabilities of the Fossil user. |
| 85 |
+3
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -1784,10 +1784,13 @@ | ||
| 1784 | 1784 | @ <h1>Server Configuration Error</h1> |
| 1785 | 1785 | @ <p>The database schema on the server is out-of-date. Please ask |
| 1786 | 1786 | @ the administrator to run <b>fossil rebuild</b>.</p> |
| 1787 | 1787 | } |
| 1788 | 1788 | }else{ |
| 1789 | + if( (pCmd->eCmdFlags & CMDFLAG_RAWCONTENT)==0 ){ | |
| 1790 | + cgi_decode_post_parameters(); | |
| 1791 | + } | |
| 1789 | 1792 | if( g.fCgiTrace ){ |
| 1790 | 1793 | fossil_trace("######## Calling %s #########\n", pCmd->zName); |
| 1791 | 1794 | cgi_print_all(1, 1); |
| 1792 | 1795 | } |
| 1793 | 1796 | #ifdef FOSSIL_ENABLE_TH1_HOOKS |
| 1794 | 1797 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -1784,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( g.fCgiTrace ){ |
| 1790 | fossil_trace("######## Calling %s #########\n", pCmd->zName); |
| 1791 | cgi_print_all(1, 1); |
| 1792 | } |
| 1793 | #ifdef FOSSIL_ENABLE_TH1_HOOKS |
| 1794 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -1784,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 |
| 1797 |
+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 |