Fossil SCM
More robust handling of missing CGI parameters. See discussion at [https://www.fossil-scm.org/forum/forumpost/e2e75f8aec|forum thread e2e75f8aec].
Commit
d6f69343ca4673d5128f40be011d6d16bca6f33f5bcdaeaca45eec544f8a4447
Parent
5182a1bfbf43e94…
1 file changed
+32
-6
+32
-6
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -1053,29 +1053,56 @@ | ||
| 1053 | 1053 | ** assume that PATH_INFO is an empty string and set REQUEST_URI equal |
| 1054 | 1054 | ** to PATH_INFO. |
| 1055 | 1055 | ** |
| 1056 | 1056 | ** SCGI typically omits PATH_INFO. CGI sometimes omits REQUEST_URI and |
| 1057 | 1057 | ** PATH_INFO when it is empty. |
| 1058 | +** | |
| 1059 | +** CGI Parameter quick reference: | |
| 1060 | +** | |
| 1061 | +** REQUEST_URI | |
| 1062 | +** _____________|____________ | |
| 1063 | +** / \ | |
| 1064 | +** https://www.fossil-scm.org/forum/info/12736b30c072551a?t=c | |
| 1065 | +** \________________/\____/\____________________/ \_/ | |
| 1066 | +** | | | | | |
| 1067 | +** HTTP_HOST | PATH_INFO QUERY_STRING | |
| 1068 | +** SCRIPT_NAME | |
| 1058 | 1069 | */ |
| 1059 | 1070 | void cgi_init(void){ |
| 1060 | 1071 | char *z; |
| 1061 | 1072 | const char *zType; |
| 1062 | 1073 | char *zSemi; |
| 1063 | 1074 | int len; |
| 1064 | 1075 | const char *zRequestUri = cgi_parameter("REQUEST_URI",0); |
| 1065 | - const char *zScriptName = cgi_parameter("SCRIPT_NAME",0); | |
| 1066 | - const char *zPathInfo = cgi_parameter("PATH_INFO",0); | |
| 1076 | + const char *zScriptName = cgi_parameter("SCRIPT_NAME",""); | |
| 1077 | + const char *zPathInfo = cgi_parameter("PATH_INFO",""); | |
| 1067 | 1078 | #ifdef _WIN32 |
| 1068 | 1079 | const char *zServerSoftware = cgi_parameter("SERVER_SOFTWARE",0); |
| 1069 | 1080 | #endif |
| 1070 | 1081 | |
| 1071 | 1082 | #ifdef FOSSIL_ENABLE_JSON |
| 1072 | 1083 | const int noJson = P("no_json")!=0; |
| 1073 | 1084 | #endif |
| 1074 | 1085 | g.isHTTP = 1; |
| 1075 | 1086 | cgi_destination(CGI_BODY); |
| 1076 | - if( zScriptName==0 ) malformed_request("missing SCRIPT_NAME"); | |
| 1087 | + | |
| 1088 | + /* We must have SCRIPT_NAME. If the web server did not supply it, try | |
| 1089 | + ** to compute it from REQUEST_URI and PATH_INFO. */ | |
| 1090 | + if( zScriptName==0 ){ | |
| 1091 | + size_t nRU, nPI; | |
| 1092 | + if( zRequestUri==0 || zPathInfo==0 ){ | |
| 1093 | + malformed_request("missing SCRIPT_NAME"); /* Does not return */ | |
| 1094 | + } | |
| 1095 | + nRU = strlen(zRequestUri); | |
| 1096 | + nPI = strlen(zPathInfo); | |
| 1097 | + if( nRU<nPI ){ | |
| 1098 | + malformed_request("PATH_INFO is longer than REQUEST_URI"); | |
| 1099 | + } | |
| 1100 | + zScriptName = mprintf("%.*s", (int)(nRU-nPI), zRequestUri); | |
| 1101 | + cgi_set_parameter("SCRIPT_NAME", zScriptName); | |
| 1102 | + } | |
| 1103 | + | |
| 1077 | 1104 | #ifdef _WIN32 |
| 1078 | 1105 | /* The Microsoft IIS web server does not define REQUEST_URI, instead it uses |
| 1079 | 1106 | ** PATH_INFO for virtually the same purpose. Define REQUEST_URI the same as |
| 1080 | 1107 | ** PATH_INFO and redefine PATH_INFO with SCRIPT_NAME removed from the |
| 1081 | 1108 | ** beginning. */ |
| @@ -1257,16 +1284,15 @@ | ||
| 1257 | 1284 | } |
| 1258 | 1285 | } |
| 1259 | 1286 | |
| 1260 | 1287 | /* If no match is found and the name begins with an upper-case |
| 1261 | 1288 | ** letter, then check to see if there is an environment variable |
| 1262 | - ** with the given name. Handle environment variables with empty values | |
| 1263 | - ** the same as non-existent environment variables. | |
| 1289 | + ** with the given name. | |
| 1264 | 1290 | */ |
| 1265 | 1291 | if( fossil_isupper(zName[0]) ){ |
| 1266 | 1292 | const char *zValue = fossil_getenv(zName); |
| 1267 | - if( zValue && zValue[0] ){ | |
| 1293 | + if( zValue ){ | |
| 1268 | 1294 | cgi_set_parameter_nocopy(zName, zValue, 0); |
| 1269 | 1295 | CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue)); |
| 1270 | 1296 | return zValue; |
| 1271 | 1297 | } |
| 1272 | 1298 | } |
| 1273 | 1299 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1053,29 +1053,56 @@ | |
| 1053 | ** assume that PATH_INFO is an empty string and set REQUEST_URI equal |
| 1054 | ** to PATH_INFO. |
| 1055 | ** |
| 1056 | ** SCGI typically omits PATH_INFO. CGI sometimes omits REQUEST_URI and |
| 1057 | ** PATH_INFO when it is empty. |
| 1058 | */ |
| 1059 | void cgi_init(void){ |
| 1060 | char *z; |
| 1061 | const char *zType; |
| 1062 | char *zSemi; |
| 1063 | int len; |
| 1064 | const char *zRequestUri = cgi_parameter("REQUEST_URI",0); |
| 1065 | const char *zScriptName = cgi_parameter("SCRIPT_NAME",0); |
| 1066 | const char *zPathInfo = cgi_parameter("PATH_INFO",0); |
| 1067 | #ifdef _WIN32 |
| 1068 | const char *zServerSoftware = cgi_parameter("SERVER_SOFTWARE",0); |
| 1069 | #endif |
| 1070 | |
| 1071 | #ifdef FOSSIL_ENABLE_JSON |
| 1072 | const int noJson = P("no_json")!=0; |
| 1073 | #endif |
| 1074 | g.isHTTP = 1; |
| 1075 | cgi_destination(CGI_BODY); |
| 1076 | if( zScriptName==0 ) malformed_request("missing SCRIPT_NAME"); |
| 1077 | #ifdef _WIN32 |
| 1078 | /* The Microsoft IIS web server does not define REQUEST_URI, instead it uses |
| 1079 | ** PATH_INFO for virtually the same purpose. Define REQUEST_URI the same as |
| 1080 | ** PATH_INFO and redefine PATH_INFO with SCRIPT_NAME removed from the |
| 1081 | ** beginning. */ |
| @@ -1257,16 +1284,15 @@ | |
| 1257 | } |
| 1258 | } |
| 1259 | |
| 1260 | /* If no match is found and the name begins with an upper-case |
| 1261 | ** letter, then check to see if there is an environment variable |
| 1262 | ** with the given name. Handle environment variables with empty values |
| 1263 | ** the same as non-existent environment variables. |
| 1264 | */ |
| 1265 | if( fossil_isupper(zName[0]) ){ |
| 1266 | const char *zValue = fossil_getenv(zName); |
| 1267 | if( zValue && zValue[0] ){ |
| 1268 | cgi_set_parameter_nocopy(zName, zValue, 0); |
| 1269 | CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue)); |
| 1270 | return zValue; |
| 1271 | } |
| 1272 | } |
| 1273 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1053,29 +1053,56 @@ | |
| 1053 | ** assume that PATH_INFO is an empty string and set REQUEST_URI equal |
| 1054 | ** to PATH_INFO. |
| 1055 | ** |
| 1056 | ** SCGI typically omits PATH_INFO. CGI sometimes omits REQUEST_URI and |
| 1057 | ** PATH_INFO when it is empty. |
| 1058 | ** |
| 1059 | ** CGI Parameter quick reference: |
| 1060 | ** |
| 1061 | ** REQUEST_URI |
| 1062 | ** _____________|____________ |
| 1063 | ** / \ |
| 1064 | ** https://www.fossil-scm.org/forum/info/12736b30c072551a?t=c |
| 1065 | ** \________________/\____/\____________________/ \_/ |
| 1066 | ** | | | | |
| 1067 | ** HTTP_HOST | PATH_INFO QUERY_STRING |
| 1068 | ** SCRIPT_NAME |
| 1069 | */ |
| 1070 | void cgi_init(void){ |
| 1071 | char *z; |
| 1072 | const char *zType; |
| 1073 | char *zSemi; |
| 1074 | int len; |
| 1075 | const char *zRequestUri = cgi_parameter("REQUEST_URI",0); |
| 1076 | const char *zScriptName = cgi_parameter("SCRIPT_NAME",""); |
| 1077 | const char *zPathInfo = cgi_parameter("PATH_INFO",""); |
| 1078 | #ifdef _WIN32 |
| 1079 | const char *zServerSoftware = cgi_parameter("SERVER_SOFTWARE",0); |
| 1080 | #endif |
| 1081 | |
| 1082 | #ifdef FOSSIL_ENABLE_JSON |
| 1083 | const int noJson = P("no_json")!=0; |
| 1084 | #endif |
| 1085 | g.isHTTP = 1; |
| 1086 | cgi_destination(CGI_BODY); |
| 1087 | |
| 1088 | /* We must have SCRIPT_NAME. If the web server did not supply it, try |
| 1089 | ** to compute it from REQUEST_URI and PATH_INFO. */ |
| 1090 | if( zScriptName==0 ){ |
| 1091 | size_t nRU, nPI; |
| 1092 | if( zRequestUri==0 || zPathInfo==0 ){ |
| 1093 | malformed_request("missing SCRIPT_NAME"); /* Does not return */ |
| 1094 | } |
| 1095 | nRU = strlen(zRequestUri); |
| 1096 | nPI = strlen(zPathInfo); |
| 1097 | if( nRU<nPI ){ |
| 1098 | malformed_request("PATH_INFO is longer than REQUEST_URI"); |
| 1099 | } |
| 1100 | zScriptName = mprintf("%.*s", (int)(nRU-nPI), zRequestUri); |
| 1101 | cgi_set_parameter("SCRIPT_NAME", zScriptName); |
| 1102 | } |
| 1103 | |
| 1104 | #ifdef _WIN32 |
| 1105 | /* The Microsoft IIS web server does not define REQUEST_URI, instead it uses |
| 1106 | ** PATH_INFO for virtually the same purpose. Define REQUEST_URI the same as |
| 1107 | ** PATH_INFO and redefine PATH_INFO with SCRIPT_NAME removed from the |
| 1108 | ** beginning. */ |
| @@ -1257,16 +1284,15 @@ | |
| 1284 | } |
| 1285 | } |
| 1286 | |
| 1287 | /* If no match is found and the name begins with an upper-case |
| 1288 | ** letter, then check to see if there is an environment variable |
| 1289 | ** with the given name. |
| 1290 | */ |
| 1291 | if( fossil_isupper(zName[0]) ){ |
| 1292 | const char *zValue = fossil_getenv(zName); |
| 1293 | if( zValue ){ |
| 1294 | cgi_set_parameter_nocopy(zName, zValue, 0); |
| 1295 | CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue)); |
| 1296 | return zValue; |
| 1297 | } |
| 1298 | } |
| 1299 |