| ︙ | | |
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
|
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
|
-
+
|
for( zTok = strtok_r(zBuf, ",\"",&zPos);
zTok && fossil_stricmp(zTok,zETag);
zTok = strtok_r(0, ",\"",&zPos)){}
fossil_free(zBuf);
if(zTok) return 1;
}
}
return 0;
}
#endif
/*
** Return true if the response should be sent with Content-Encoding: gzip.
*/
|
| ︙ | | |
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
|
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
|
-
+
|
/*
** Add a query parameter. The zName portion is fixed but a copy
** must be made of zValue.
*/
void cgi_setenv(const char *zName, const char *zValue){
cgi_set_parameter_nocopy(zName, mprintf("%s",zValue), 0);
}
/*
** Add a list of query parameters or cookies to the parameter set.
**
** Each parameter is of the form NAME=VALUE. Both the NAME and the
** VALUE may be url-encoded ("+" for space, "%HH" for other special
** characters). But this routine assumes that NAME contains no
|
| ︙ | | |
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
|
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
|
-
+
|
*pnContent = i;
i += nBoundry;
break;
}
}
*pz = &z[i];
get_line_from_string(pz, pLen);
return z;
return z;
}
/*
** Tokenize a line of text into as many as nArg tokens. Make
** azArg[] point to the start of each token.
**
** Tokens consist of space or semi-colon delimited words or
|
| ︙ | | |
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
|
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
|
-
+
|
char *z = azArg[++i];
if( zName && z && fossil_islower(zName[0]) ){
cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z, 1);
}
}
}
}
}
}
}
#ifdef FOSSIL_ENABLE_JSON
/*
** Internal helper for cson_data_source_FILE_n().
*/
|
| ︙ | | |
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
|
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
|
-
+
|
*/
void cgi_init(void){
char *z;
const char *zType;
int len;
const char *zRequestUri = cgi_parameter("REQUEST_URI",0);
const char *zScriptName = cgi_parameter("SCRIPT_NAME",0);
const char *zPathInfo = cgi_parameter("PATH_INFO","");
const char *zPathInfo = cgi_parameter("PATH_INFO",0);
#ifdef FOSSIL_ENABLE_JSON
json_main_bootstrap();
#endif
g.isHTTP = 1;
cgi_destination(CGI_BODY);
if( zScriptName==0 ) malformed_request("missing SCRIPT_NAME");
|
| ︙ | | |
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
|
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
|
-
+
-
+
|
}
z = (char*)P("HTTP_COOKIE");
if( z ){
z = mprintf("%s",z);
add_param_list(z, ';');
}
z = (char*)P("QUERY_STRING");
if( z ){
z = mprintf("%s",z);
add_param_list(z, '&');
}
z = (char*)P("REMOTE_ADDR");
if( z ){
g.zIpAddr = mprintf("%s", z);
}
len = atoi(PD("CONTENT_LENGTH", "0"));
g.zContentType = zType = P("CONTENT_TYPE");
blob_zero(&g.cgiIn);
if( len>0 && zType ){
if( fossil_strcmp(zType,"application/x-www-form-urlencoded")==0
if( fossil_strcmp(zType,"application/x-www-form-urlencoded")==0
|| strncmp(zType,"multipart/form-data",19)==0 ){
z = fossil_malloc( len+1 );
len = fread(z, 1, len, g.httpIn);
z[len] = 0;
cgi_trace(z);
if( zType[0]=='a' ){
add_param_list(z, '&');
|
| ︙ | | |
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
|
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
|
-
+
|
g.json.isJsonMode = 1;
cgi_parse_POST_JSON(g.httpIn, (unsigned int)len);
/* FIXMEs:
- See if fossil really needs g.cgiIn to be set for this purpose
(i don't think it does). If it does then fill g.cgiIn and
refactor to parse the JSON from there.
- After parsing POST JSON, copy the "first layer" of keys/values
to cgi_setenv(), honoring the upper-case distinction used
in add_param_list(). However...
- If we do that then we might get a disconnect in precedence of
GET/POST arguments. i prefer for GET entries to take precedence
over like-named POST entries, but in order for that to happen we
|
| ︙ | | |
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
|
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
|
-
+
|
** Return a pointer to a string containing the real IP address, or a
** NULL pointer to stick with the IP address previously computed and
** loaded into g.zIpAddr.
*/
static const char *cgi_accept_forwarded_for(const char *z){
int i;
if( fossil_strcmp(g.zIpAddr, "127.0.0.1")!=0 ) return 0;
i = strlen(z)-1;
while( i>=0 && z[i]!=',' && !fossil_isspace(z[i]) ) i--;
return &z[++i];
}
/*
** Remove the first space-delimited token from a string and return
|
| ︙ | | |
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
|
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
|
-
+
|
}
cgi_setenv("REQUEST_URI", zToken);
cgi_setenv("SCRIPT_NAME", "");
for(i=0; zToken[i] && zToken[i]!='?'; i++){}
if( zToken[i] ) zToken[i++] = 0;
cgi_setenv("PATH_INFO", zToken);
cgi_setenv("QUERY_STRING", &zToken[i]);
/* Get all the optional fields that follow the first line.
*/
while( fgets(zLine,sizeof(zLine),g.httpIn) ){
char *zFieldName;
char *zVal;
cgi_trace(zLine);
|
| ︙ | | |
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
|
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
|
-
-
-
-
-
-
-
-
-
-
-
|
cgi_setenv("HTTPS", zVal);
}else if( fossil_strcmp(zFieldName,"host:")==0 ){
cgi_setenv("HTTP_HOST", zVal);
}else if( fossil_strcmp(zFieldName,"if-none-match:")==0 ){
cgi_setenv("HTTP_IF_NONE_MATCH", zVal);
}else if( fossil_strcmp(zFieldName,"if-modified-since:")==0 ){
cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal);
}else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){
char* p = zVal;
/*
** x-forwarded-for header is a list of comma-separated addresses,
** with leftmost address corresponding to the client
*/
while(*p && *p != ',') p++;
*p = '\0';
zIpAddr = mprintf( "%s", zVal );
#if 0
}else if( fossil_strcmp(zFieldName,"referer:")==0 ){
cgi_setenv("HTTP_REFERER", zVal);
#endif
}else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){
cgi_setenv("HTTP_USER_AGENT", zVal);
}else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){
const char *zIpAddr = cgi_accept_forwarded_for(zVal);
if( zIpAddr!=0 ){
g.zIpAddr = mprintf("%s", zIpAddr);
cgi_replace_parameter("REMOTE_ADDR", g.zIpAddr);
|
| ︙ | | |
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
|
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
|
-
+
|
static char *zCmd = 0;
char *z, *zToken;
const char *zType = 0;
int i, content_length = 0;
char zLine[2000]; /* A single line of input. */
if( zIpAddr ){
if( nCycles==0 ){
if( nCycles==0 ){
cgi_setenv("REMOTE_ADDR", zIpAddr);
g.zIpAddr = mprintf("%s", zIpAddr);
}
}else{
fossil_panic("missing SSH IP address");
}
if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){
|
| ︙ | | |
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
|
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
|
-
+
|
for(i=0; zToken[i] && zToken[i]!='?'; i++){}
if( zToken[i] ) zToken[i++] = 0;
if( nCycles==0 ){
cgi_setenv("PATH_INFO", zToken);
}else{
cgi_replace_parameter("PATH_INFO", mprintf("%s",zToken));
}
/* Get all the optional fields that follow the first line.
*/
while( fgets(zLine,sizeof(zLine),g.httpIn) ){
char *zFieldName;
char *zVal;
cgi_trace(zLine);
|
| ︙ | | |
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
|
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
|
-
+
|
fossil_free(zToFree);
fgetc(g.httpIn); /* Read past the "," separating header from content */
cgi_init();
}
#if INTERFACE
/*
/*
** Bitmap values for the flags parameter to cgi_http_server().
*/
#define HTTP_SERVER_LOCALHOST 0x0001 /* Bind to 127.0.0.1 only */
#define HTTP_SERVER_SCGI 0x0002 /* SCGI instead of HTTP */
#endif /* INTERFACE */
|
| ︙ | | |
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
|
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
|
-
-
-
-
+
+
+
-
|
}else{
fossil_fatal("unable to open listening socket on any"
" port in the range %d..%d", mnPort, mxPort);
}
}
if( iPort>mxPort ) return 1;
listen(listener,10);
if( iPort>mnPort ){
fossil_print("Listening for %s requests on TCP port %d\n",
(flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
fflush(stdout);
fossil_print("Listening for %s requests on TCP port %d\n",
(flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
fflush(stdout);
}
if( zBrowser ){
zBrowser = mprintf(zBrowser, iPort);
#if defined(__CYGWIN__)
/* On Cygwin, we can do better than "echo" */
if( memcmp(zBrowser, "echo ", 5)==0 ){
wchar_t *wUrl = fossil_utf8_to_unicode(zBrowser+5);
wUrl[wcslen(wUrl)-2] = 0; /* Strip terminating " &" */
|
| ︙ | | |
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
|
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
|
-
+
|
}
}
/* Bury dead children */
while( waitpid(0, 0, WNOHANG)>0 ){
nchildren--;
}
}
/* NOT REACHED */
/* NOT REACHED */
fossil_exit(1);
#endif // WIN32
/* NOT REACHED */
return 0;
}
|
| ︙ | | |
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
|
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
|
-
+
|
}else if( p->tm_mon>11 ){
p->tm_year += p->tm_mon/12;
p->tm_mon %= 12;
}
isLeapYr = p->tm_year%4==0 && (p->tm_year%100!=0 || (p->tm_year+300)%400==0);
p->tm_yday = priorDays[p->tm_mon] + p->tm_mday - 1;
if( isLeapYr && p->tm_mon>1 ) p->tm_yday++;
nDay = (p->tm_year-70)*365 + (p->tm_year-69)/4 -p->tm_year/100 +
nDay = (p->tm_year-70)*365 + (p->tm_year-69)/4 -p->tm_year/100 +
(p->tm_year+300)/400 + p->tm_yday;
t = ((nDay*24 + p->tm_hour)*60 + p->tm_min)*60 + p->tm_sec;
return t;
}
/*
** Check the objectTime against the If-Modified-Since request header. If the
|
| ︙ | | |