Fossil SCM
Back out check-in [5bb921dd0893a548] which was wrong - the REQUEST_URI CGI parameter should include the query string. Improve the CGI variable documentation in comments. Improve robustness to malformed CGI variables.
Commit
e514eeea8f8598a899a6c0e1f76fd9bb9c736f96fc1165e0dedf1fdb37f5a3e6
Parent
c9082b29711617c…
1 file changed
+25
-16
+25
-16
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -1174,10 +1174,14 @@ | ||
| 1174 | 1174 | ** |
| 1175 | 1175 | ** REQUEST_URI, PATH_INFO, and SCRIPT_NAME are related as follows: |
| 1176 | 1176 | ** |
| 1177 | 1177 | ** REQUEST_URI == SCRIPT_NAME + PATH_INFO |
| 1178 | 1178 | ** |
| 1179 | +** Or if QUERY_STRING is not empty: | |
| 1180 | +** | |
| 1181 | +** REQUEST_URI == SCRIPT_NAME + PATH_INFO + '?' + QUERY_STRING | |
| 1182 | +** | |
| 1179 | 1183 | ** Where "+" means concatenate. Fossil requires SCRIPT_NAME. If |
| 1180 | 1184 | ** REQUEST_URI is provided but PATH_INFO is not, then PATH_INFO is |
| 1181 | 1185 | ** computed from REQUEST_URI and SCRIPT_NAME. If PATH_INFO is provided |
| 1182 | 1186 | ** but REQUEST_URI is not, then compute REQUEST_URI from PATH_INFO and |
| 1183 | 1187 | ** SCRIPT_NAME. If neither REQUEST_URI nor PATH_INFO are provided, then |
| @@ -1192,18 +1196,20 @@ | ||
| 1192 | 1196 | ** SCGI typically omits PATH_INFO. CGI sometimes omits REQUEST_URI and |
| 1193 | 1197 | ** PATH_INFO when it is empty. |
| 1194 | 1198 | ** |
| 1195 | 1199 | ** CGI Parameter quick reference: |
| 1196 | 1200 | ** |
| 1197 | -** REQUEST_URI | |
| 1198 | -** _____________|____________ | |
| 1199 | -** / \ | |
| 1200 | -** https://www.fossil-scm.org/forum/info/12736b30c072551a?t=c | |
| 1201 | -** \________________/\____/\____________________/ \_/ | |
| 1202 | -** | | | | | |
| 1203 | -** HTTP_HOST | PATH_INFO QUERY_STRING | |
| 1204 | -** SCRIPT_NAME | |
| 1201 | +** REQUEST_URI | |
| 1202 | +** _____________|________________ | |
| 1203 | +** / \ | |
| 1204 | +** https://fossil-scm.org/forum/info/12736b30c072551a?t=c | |
| 1205 | +** \___/ \____________/\____/\____________________/ \_/ | |
| 1206 | +** | | | | | | |
| 1207 | +** | HTTP_HOST | PATH_INFO QUERY_STRING | |
| 1208 | +** | | | |
| 1209 | +** REQUEST_SCHEMA SCRIPT_NAME | |
| 1210 | +** | |
| 1205 | 1211 | */ |
| 1206 | 1212 | void cgi_init(void){ |
| 1207 | 1213 | char *z; |
| 1208 | 1214 | const char *zType; |
| 1209 | 1215 | char *zSemi; |
| @@ -1222,20 +1228,18 @@ | ||
| 1222 | 1228 | cgi_destination(CGI_BODY); |
| 1223 | 1229 | |
| 1224 | 1230 | /* We must have SCRIPT_NAME. If the web server did not supply it, try |
| 1225 | 1231 | ** to compute it from REQUEST_URI and PATH_INFO. */ |
| 1226 | 1232 | if( zScriptName==0 ){ |
| 1227 | - size_t nRU, nPI; | |
| 1228 | 1233 | if( zRequestUri==0 || zPathInfo==0 ){ |
| 1229 | 1234 | malformed_request("missing SCRIPT_NAME"); /* Does not return */ |
| 1230 | 1235 | } |
| 1231 | - nRU = strlen(zRequestUri); | |
| 1232 | - nPI = strlen(zPathInfo); | |
| 1233 | - if( nRU<nPI ){ | |
| 1234 | - malformed_request("PATH_INFO is longer than REQUEST_URI"); | |
| 1236 | + z = strstr(zRequestUri,zPathInfo); | |
| 1237 | + if( z==0 ){ | |
| 1238 | + malformed_request("PATH_INFO not found in REQUEST_URI"); | |
| 1235 | 1239 | } |
| 1236 | - zScriptName = fossil_strndup(zRequestUri,(int)(nRU-nPI)); | |
| 1240 | + zScriptName = fossil_strndup(zRequestUri,(int)(z-zRequestUri)); | |
| 1237 | 1241 | cgi_set_parameter("SCRIPT_NAME", zScriptName); |
| 1238 | 1242 | } |
| 1239 | 1243 | |
| 1240 | 1244 | #ifdef _WIN32 |
| 1241 | 1245 | /* The Microsoft IIS web server does not define REQUEST_URI, instead it uses |
| @@ -1251,15 +1255,20 @@ | ||
| 1251 | 1255 | cgi_replace_parameter("PATH_INFO", zPathInfo); |
| 1252 | 1256 | } |
| 1253 | 1257 | #endif |
| 1254 | 1258 | if( zRequestUri==0 ){ |
| 1255 | 1259 | const char *z = zPathInfo; |
| 1260 | + const char *zQS = cgi_parameter("QUERY_STRING",0); | |
| 1256 | 1261 | if( zPathInfo==0 ){ |
| 1257 | 1262 | malformed_request("missing PATH_INFO and/or REQUEST_URI"); |
| 1258 | 1263 | } |
| 1259 | 1264 | if( z[0]=='/' ) z++; |
| 1260 | - zRequestUri = mprintf("%s/%s", zScriptName, z); | |
| 1265 | + if( zQS && zQS[0] ){ | |
| 1266 | + zRequestUri = mprintf("%s/%s?%s", zScriptName, z, zQS); | |
| 1267 | + }else{ | |
| 1268 | + zRequestUri = mprintf("%s/%s", zScriptName, z); | |
| 1269 | + } | |
| 1261 | 1270 | cgi_set_parameter("REQUEST_URI", zRequestUri); |
| 1262 | 1271 | } |
| 1263 | 1272 | if( zPathInfo==0 ){ |
| 1264 | 1273 | int i, j; |
| 1265 | 1274 | for(i=0; zRequestUri[i]==zScriptName[i] && zRequestUri[i]; i++){} |
| @@ -1866,14 +1875,14 @@ | ||
| 1866 | 1875 | cgi_setenv("REQUEST_METHOD",zToken); |
| 1867 | 1876 | zToken = extract_token(z, &z); |
| 1868 | 1877 | if( zToken==0 ){ |
| 1869 | 1878 | malformed_request("malformed URL in HTTP header"); |
| 1870 | 1879 | } |
| 1880 | + cgi_setenv("REQUEST_URI", zToken); | |
| 1871 | 1881 | cgi_setenv("SCRIPT_NAME", ""); |
| 1872 | 1882 | for(i=0; zToken[i] && zToken[i]!='?'; i++){} |
| 1873 | 1883 | if( zToken[i] ) zToken[i++] = 0; |
| 1874 | - cgi_setenv("REQUEST_URI", zToken); | |
| 1875 | 1884 | cgi_setenv("PATH_INFO", zToken); |
| 1876 | 1885 | cgi_setenv("QUERY_STRING", &zToken[i]); |
| 1877 | 1886 | if( zIpAddr==0 ){ |
| 1878 | 1887 | zIpAddr = cgi_remote_ip(fileno(g.httpIn)); |
| 1879 | 1888 | } |
| 1880 | 1889 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1174,10 +1174,14 @@ | |
| 1174 | ** |
| 1175 | ** REQUEST_URI, PATH_INFO, and SCRIPT_NAME are related as follows: |
| 1176 | ** |
| 1177 | ** REQUEST_URI == SCRIPT_NAME + PATH_INFO |
| 1178 | ** |
| 1179 | ** Where "+" means concatenate. Fossil requires SCRIPT_NAME. If |
| 1180 | ** REQUEST_URI is provided but PATH_INFO is not, then PATH_INFO is |
| 1181 | ** computed from REQUEST_URI and SCRIPT_NAME. If PATH_INFO is provided |
| 1182 | ** but REQUEST_URI is not, then compute REQUEST_URI from PATH_INFO and |
| 1183 | ** SCRIPT_NAME. If neither REQUEST_URI nor PATH_INFO are provided, then |
| @@ -1192,18 +1196,20 @@ | |
| 1192 | ** SCGI typically omits PATH_INFO. CGI sometimes omits REQUEST_URI and |
| 1193 | ** PATH_INFO when it is empty. |
| 1194 | ** |
| 1195 | ** CGI Parameter quick reference: |
| 1196 | ** |
| 1197 | ** REQUEST_URI |
| 1198 | ** _____________|____________ |
| 1199 | ** / \ |
| 1200 | ** https://www.fossil-scm.org/forum/info/12736b30c072551a?t=c |
| 1201 | ** \________________/\____/\____________________/ \_/ |
| 1202 | ** | | | | |
| 1203 | ** HTTP_HOST | PATH_INFO QUERY_STRING |
| 1204 | ** SCRIPT_NAME |
| 1205 | */ |
| 1206 | void cgi_init(void){ |
| 1207 | char *z; |
| 1208 | const char *zType; |
| 1209 | char *zSemi; |
| @@ -1222,20 +1228,18 @@ | |
| 1222 | cgi_destination(CGI_BODY); |
| 1223 | |
| 1224 | /* We must have SCRIPT_NAME. If the web server did not supply it, try |
| 1225 | ** to compute it from REQUEST_URI and PATH_INFO. */ |
| 1226 | if( zScriptName==0 ){ |
| 1227 | size_t nRU, nPI; |
| 1228 | if( zRequestUri==0 || zPathInfo==0 ){ |
| 1229 | malformed_request("missing SCRIPT_NAME"); /* Does not return */ |
| 1230 | } |
| 1231 | nRU = strlen(zRequestUri); |
| 1232 | nPI = strlen(zPathInfo); |
| 1233 | if( nRU<nPI ){ |
| 1234 | malformed_request("PATH_INFO is longer than REQUEST_URI"); |
| 1235 | } |
| 1236 | zScriptName = fossil_strndup(zRequestUri,(int)(nRU-nPI)); |
| 1237 | cgi_set_parameter("SCRIPT_NAME", zScriptName); |
| 1238 | } |
| 1239 | |
| 1240 | #ifdef _WIN32 |
| 1241 | /* The Microsoft IIS web server does not define REQUEST_URI, instead it uses |
| @@ -1251,15 +1255,20 @@ | |
| 1251 | cgi_replace_parameter("PATH_INFO", zPathInfo); |
| 1252 | } |
| 1253 | #endif |
| 1254 | if( zRequestUri==0 ){ |
| 1255 | const char *z = zPathInfo; |
| 1256 | if( zPathInfo==0 ){ |
| 1257 | malformed_request("missing PATH_INFO and/or REQUEST_URI"); |
| 1258 | } |
| 1259 | if( z[0]=='/' ) z++; |
| 1260 | zRequestUri = mprintf("%s/%s", zScriptName, z); |
| 1261 | cgi_set_parameter("REQUEST_URI", zRequestUri); |
| 1262 | } |
| 1263 | if( zPathInfo==0 ){ |
| 1264 | int i, j; |
| 1265 | for(i=0; zRequestUri[i]==zScriptName[i] && zRequestUri[i]; i++){} |
| @@ -1866,14 +1875,14 @@ | |
| 1866 | cgi_setenv("REQUEST_METHOD",zToken); |
| 1867 | zToken = extract_token(z, &z); |
| 1868 | if( zToken==0 ){ |
| 1869 | malformed_request("malformed URL in HTTP header"); |
| 1870 | } |
| 1871 | cgi_setenv("SCRIPT_NAME", ""); |
| 1872 | for(i=0; zToken[i] && zToken[i]!='?'; i++){} |
| 1873 | if( zToken[i] ) zToken[i++] = 0; |
| 1874 | cgi_setenv("REQUEST_URI", zToken); |
| 1875 | cgi_setenv("PATH_INFO", zToken); |
| 1876 | cgi_setenv("QUERY_STRING", &zToken[i]); |
| 1877 | if( zIpAddr==0 ){ |
| 1878 | zIpAddr = cgi_remote_ip(fileno(g.httpIn)); |
| 1879 | } |
| 1880 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1174,10 +1174,14 @@ | |
| 1174 | ** |
| 1175 | ** REQUEST_URI, PATH_INFO, and SCRIPT_NAME are related as follows: |
| 1176 | ** |
| 1177 | ** REQUEST_URI == SCRIPT_NAME + PATH_INFO |
| 1178 | ** |
| 1179 | ** Or if QUERY_STRING is not empty: |
| 1180 | ** |
| 1181 | ** REQUEST_URI == SCRIPT_NAME + PATH_INFO + '?' + QUERY_STRING |
| 1182 | ** |
| 1183 | ** Where "+" means concatenate. Fossil requires SCRIPT_NAME. If |
| 1184 | ** REQUEST_URI is provided but PATH_INFO is not, then PATH_INFO is |
| 1185 | ** computed from REQUEST_URI and SCRIPT_NAME. If PATH_INFO is provided |
| 1186 | ** but REQUEST_URI is not, then compute REQUEST_URI from PATH_INFO and |
| 1187 | ** SCRIPT_NAME. If neither REQUEST_URI nor PATH_INFO are provided, then |
| @@ -1192,18 +1196,20 @@ | |
| 1196 | ** SCGI typically omits PATH_INFO. CGI sometimes omits REQUEST_URI and |
| 1197 | ** PATH_INFO when it is empty. |
| 1198 | ** |
| 1199 | ** CGI Parameter quick reference: |
| 1200 | ** |
| 1201 | ** REQUEST_URI |
| 1202 | ** _____________|________________ |
| 1203 | ** / \ |
| 1204 | ** https://fossil-scm.org/forum/info/12736b30c072551a?t=c |
| 1205 | ** \___/ \____________/\____/\____________________/ \_/ |
| 1206 | ** | | | | | |
| 1207 | ** | HTTP_HOST | PATH_INFO QUERY_STRING |
| 1208 | ** | | |
| 1209 | ** REQUEST_SCHEMA SCRIPT_NAME |
| 1210 | ** |
| 1211 | */ |
| 1212 | void cgi_init(void){ |
| 1213 | char *z; |
| 1214 | const char *zType; |
| 1215 | char *zSemi; |
| @@ -1222,20 +1228,18 @@ | |
| 1228 | cgi_destination(CGI_BODY); |
| 1229 | |
| 1230 | /* We must have SCRIPT_NAME. If the web server did not supply it, try |
| 1231 | ** to compute it from REQUEST_URI and PATH_INFO. */ |
| 1232 | if( zScriptName==0 ){ |
| 1233 | if( zRequestUri==0 || zPathInfo==0 ){ |
| 1234 | malformed_request("missing SCRIPT_NAME"); /* Does not return */ |
| 1235 | } |
| 1236 | z = strstr(zRequestUri,zPathInfo); |
| 1237 | if( z==0 ){ |
| 1238 | malformed_request("PATH_INFO not found in REQUEST_URI"); |
| 1239 | } |
| 1240 | zScriptName = fossil_strndup(zRequestUri,(int)(z-zRequestUri)); |
| 1241 | cgi_set_parameter("SCRIPT_NAME", zScriptName); |
| 1242 | } |
| 1243 | |
| 1244 | #ifdef _WIN32 |
| 1245 | /* The Microsoft IIS web server does not define REQUEST_URI, instead it uses |
| @@ -1251,15 +1255,20 @@ | |
| 1255 | cgi_replace_parameter("PATH_INFO", zPathInfo); |
| 1256 | } |
| 1257 | #endif |
| 1258 | if( zRequestUri==0 ){ |
| 1259 | const char *z = zPathInfo; |
| 1260 | const char *zQS = cgi_parameter("QUERY_STRING",0); |
| 1261 | if( zPathInfo==0 ){ |
| 1262 | malformed_request("missing PATH_INFO and/or REQUEST_URI"); |
| 1263 | } |
| 1264 | if( z[0]=='/' ) z++; |
| 1265 | if( zQS && zQS[0] ){ |
| 1266 | zRequestUri = mprintf("%s/%s?%s", zScriptName, z, zQS); |
| 1267 | }else{ |
| 1268 | zRequestUri = mprintf("%s/%s", zScriptName, z); |
| 1269 | } |
| 1270 | cgi_set_parameter("REQUEST_URI", zRequestUri); |
| 1271 | } |
| 1272 | if( zPathInfo==0 ){ |
| 1273 | int i, j; |
| 1274 | for(i=0; zRequestUri[i]==zScriptName[i] && zRequestUri[i]; i++){} |
| @@ -1866,14 +1875,14 @@ | |
| 1875 | cgi_setenv("REQUEST_METHOD",zToken); |
| 1876 | zToken = extract_token(z, &z); |
| 1877 | if( zToken==0 ){ |
| 1878 | malformed_request("malformed URL in HTTP header"); |
| 1879 | } |
| 1880 | cgi_setenv("REQUEST_URI", zToken); |
| 1881 | cgi_setenv("SCRIPT_NAME", ""); |
| 1882 | for(i=0; zToken[i] && zToken[i]!='?'; i++){} |
| 1883 | if( zToken[i] ) zToken[i++] = 0; |
| 1884 | cgi_setenv("PATH_INFO", zToken); |
| 1885 | cgi_setenv("QUERY_STRING", &zToken[i]); |
| 1886 | if( zIpAddr==0 ){ |
| 1887 | zIpAddr = cgi_remote_ip(fileno(g.httpIn)); |
| 1888 | } |
| 1889 |