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.

drh 2022-02-13 19:16 trunk merge
Commit e514eeea8f8598a899a6c0e1f76fd9bb9c736f96fc1165e0dedf1fdb37f5a3e6
1 file changed +25 -16
+25 -16
--- src/cgi.c
+++ src/cgi.c
@@ -1174,10 +1174,14 @@
11741174
**
11751175
** REQUEST_URI, PATH_INFO, and SCRIPT_NAME are related as follows:
11761176
**
11771177
** REQUEST_URI == SCRIPT_NAME + PATH_INFO
11781178
**
1179
+** Or if QUERY_STRING is not empty:
1180
+**
1181
+** REQUEST_URI == SCRIPT_NAME + PATH_INFO + '?' + QUERY_STRING
1182
+**
11791183
** Where "+" means concatenate. Fossil requires SCRIPT_NAME. If
11801184
** REQUEST_URI is provided but PATH_INFO is not, then PATH_INFO is
11811185
** computed from REQUEST_URI and SCRIPT_NAME. If PATH_INFO is provided
11821186
** but REQUEST_URI is not, then compute REQUEST_URI from PATH_INFO and
11831187
** SCRIPT_NAME. If neither REQUEST_URI nor PATH_INFO are provided, then
@@ -1192,18 +1196,20 @@
11921196
** SCGI typically omits PATH_INFO. CGI sometimes omits REQUEST_URI and
11931197
** PATH_INFO when it is empty.
11941198
**
11951199
** CGI Parameter quick reference:
11961200
**
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
+**
12051211
*/
12061212
void cgi_init(void){
12071213
char *z;
12081214
const char *zType;
12091215
char *zSemi;
@@ -1222,20 +1228,18 @@
12221228
cgi_destination(CGI_BODY);
12231229
12241230
/* We must have SCRIPT_NAME. If the web server did not supply it, try
12251231
** to compute it from REQUEST_URI and PATH_INFO. */
12261232
if( zScriptName==0 ){
1227
- size_t nRU, nPI;
12281233
if( zRequestUri==0 || zPathInfo==0 ){
12291234
malformed_request("missing SCRIPT_NAME"); /* Does not return */
12301235
}
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");
12351239
}
1236
- zScriptName = fossil_strndup(zRequestUri,(int)(nRU-nPI));
1240
+ zScriptName = fossil_strndup(zRequestUri,(int)(z-zRequestUri));
12371241
cgi_set_parameter("SCRIPT_NAME", zScriptName);
12381242
}
12391243
12401244
#ifdef _WIN32
12411245
/* The Microsoft IIS web server does not define REQUEST_URI, instead it uses
@@ -1251,15 +1255,20 @@
12511255
cgi_replace_parameter("PATH_INFO", zPathInfo);
12521256
}
12531257
#endif
12541258
if( zRequestUri==0 ){
12551259
const char *z = zPathInfo;
1260
+ const char *zQS = cgi_parameter("QUERY_STRING",0);
12561261
if( zPathInfo==0 ){
12571262
malformed_request("missing PATH_INFO and/or REQUEST_URI");
12581263
}
12591264
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
+ }
12611270
cgi_set_parameter("REQUEST_URI", zRequestUri);
12621271
}
12631272
if( zPathInfo==0 ){
12641273
int i, j;
12651274
for(i=0; zRequestUri[i]==zScriptName[i] && zRequestUri[i]; i++){}
@@ -1866,14 +1875,14 @@
18661875
cgi_setenv("REQUEST_METHOD",zToken);
18671876
zToken = extract_token(z, &z);
18681877
if( zToken==0 ){
18691878
malformed_request("malformed URL in HTTP header");
18701879
}
1880
+ cgi_setenv("REQUEST_URI", zToken);
18711881
cgi_setenv("SCRIPT_NAME", "");
18721882
for(i=0; zToken[i] && zToken[i]!='?'; i++){}
18731883
if( zToken[i] ) zToken[i++] = 0;
1874
- cgi_setenv("REQUEST_URI", zToken);
18751884
cgi_setenv("PATH_INFO", zToken);
18761885
cgi_setenv("QUERY_STRING", &zToken[i]);
18771886
if( zIpAddr==0 ){
18781887
zIpAddr = cgi_remote_ip(fileno(g.httpIn));
18791888
}
18801889
--- 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

Keyboard Shortcuts

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