Fossil SCM

Upper-case query parameter, POST parameter, and cookie names are converted to lower-case prior to entering them into the parameter set. Before this change, upper-case names were silently rejected.

drh 2019-09-05 02:33 trunk merge
Commit 19bbd2c5eab9607d2899418323e3813915dbebebf4fc3b97256f004ea8125731
3 files changed +72 -16 +2 +1 -1
+72 -16
--- src/cgi.c
+++ src/cgi.c
@@ -489,10 +489,31 @@
489489
}
490490
491491
/*
492492
** Add another query parameter or cookie to the parameter set.
493493
** zName is the name of the query parameter or cookie and zValue
494
+** is its fully decoded value. zName will be modified to be an
495
+** all lowercase string.
496
+**
497
+** zName and zValue are not copied and must not change or be
498
+** deallocated after this routine returns. This routine changes
499
+** all ASCII alphabetic characters in zName to lower case. The
500
+** caller must not change them back.
501
+*/
502
+void cgi_set_parameter_nocopy_tolower(
503
+ char *zName,
504
+ const char *zValue,
505
+ int isQP
506
+){
507
+ int i;
508
+ for(i=0; zName[i]; i++){ zName[i] = fossil_tolower(zName[i]); }
509
+ cgi_set_parameter_nocopy(zName, zValue, isQP);
510
+}
511
+
512
+/*
513
+** Add another query parameter or cookie to the parameter set.
514
+** zName is the name of the query parameter or cookie and zValue
494515
** is its fully decoded value.
495516
**
496517
** Copies are made of both the zName and zValue parameters.
497518
*/
498519
void cgi_set_parameter(const char *zName, const char *zValue){
@@ -523,10 +544,15 @@
523544
assert( aParamQP[i].isQP );
524545
return;
525546
}
526547
}
527548
cgi_set_parameter_nocopy(zName, zValue, 1);
549
+}
550
+void cgi_replace_query_parameter_tolower(char *zName, const char *zValue){
551
+ int i;
552
+ for(i=0; zName[i]; i++){ zName[i] = fossil_tolower(zName[i]); }
553
+ cgi_replace_query_parameter(zName, zValue);
528554
}
529555
530556
/*
531557
** Delete a parameter.
532558
*/
@@ -561,11 +587,10 @@
561587
** must be made of zValue.
562588
*/
563589
void cgi_setenv(const char *zName, const char *zValue){
564590
cgi_set_parameter_nocopy(zName, mprintf("%s",zValue), 0);
565591
}
566
-
567592
568593
/*
569594
** Add a list of query parameters or cookies to the parameter set.
570595
**
571596
** Each parameter is of the form NAME=VALUE. Both the NAME and the
@@ -615,12 +640,16 @@
615640
dehttpize(zValue);
616641
}else{
617642
if( *z ){ *z++ = 0; }
618643
zValue = "";
619644
}
620
- if( fossil_islower(zName[0]) && fossil_no_strange_characters(zName+1) ){
621
- cgi_set_parameter_nocopy(zName, zValue, isQP);
645
+ if( zName[0] && fossil_no_strange_characters(zName+1) ){
646
+ if( fossil_islower(zName[0]) ){
647
+ cgi_set_parameter_nocopy(zName, zValue, isQP);
648
+ }else if( fossil_isupper(zName[0]) ){
649
+ cgi_set_parameter_nocopy_tolower(zName, zValue, isQP);
650
+ }
622651
}
623652
#ifdef FOSSIL_ENABLE_JSON
624653
json_setenv( zName, cson_value_new_string(zValue,strlen(zValue)) );
625654
#endif /* FOSSIL_ENABLE_JSON */
626655
}
@@ -759,15 +788,23 @@
759788
if( zBoundry==0 ) return;
760789
while( (zLine = get_line_from_string(&z, &len))!=0 ){
761790
if( zLine[0]==0 ){
762791
int nContent = 0;
763792
zValue = get_bounded_content(&z, &len, zBoundry, &nContent);
764
- if( zName && zValue && fossil_islower(zName[0]) ){
765
- cgi_set_parameter_nocopy(zName, zValue, 1);
766
- if( showBytes ){
767
- cgi_set_parameter_nocopy(mprintf("%s:bytes", zName),
768
- mprintf("%d",nContent), 1);
793
+ if( zName && zValue ){
794
+ if( fossil_islower(zName[0]) ){
795
+ cgi_set_parameter_nocopy(zName, zValue, 1);
796
+ if( showBytes ){
797
+ cgi_set_parameter_nocopy(mprintf("%s:bytes", zName),
798
+ mprintf("%d",nContent), 1);
799
+ }
800
+ }else if( fossil_isupper(zName[0]) ){
801
+ cgi_set_parameter_nocopy_tolower(zName, zValue, 1);
802
+ if( showBytes ){
803
+ cgi_set_parameter_nocopy_tolower(mprintf("%s:bytes", zName),
804
+ mprintf("%d",nContent), 1);
805
+ }
769806
}
770807
}
771808
zName = 0;
772809
showBytes = 0;
773810
}else{
@@ -779,18 +816,28 @@
779816
i++;
780817
}else if( c=='n' && sqlite3_strnicmp(azArg[i],"name=",n)==0 ){
781818
zName = azArg[++i];
782819
}else if( c=='f' && sqlite3_strnicmp(azArg[i],"filename=",n)==0 ){
783820
char *z = azArg[++i];
784
- if( zName && z && fossil_islower(zName[0]) ){
785
- cgi_set_parameter_nocopy(mprintf("%s:filename",zName), z, 1);
821
+ if( zName && z ){
822
+ if( fossil_islower(zName[0]) ){
823
+ cgi_set_parameter_nocopy(mprintf("%s:filename",zName), z, 1);
824
+ }else if( fossil_isupper(zName[0]) ){
825
+ cgi_set_parameter_nocopy_tolower(mprintf("%s:filename",zName),
826
+ z, 1);
827
+ }
786828
}
787829
showBytes = 1;
788830
}else if( c=='c' && sqlite3_strnicmp(azArg[i],"content-type:",n)==0 ){
789831
char *z = azArg[++i];
790
- if( zName && z && fossil_islower(zName[0]) ){
791
- cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z, 1);
832
+ if( zName && z ){
833
+ if( fossil_islower(zName[0]) ){
834
+ cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z, 1);
835
+ }else if( fossil_isupper(zName[0]) ){
836
+ cgi_set_parameter_nocopy_tolower(mprintf("%s:mimetype",zName),
837
+ z, 1);
838
+ }
792839
}
793840
}
794841
}
795842
}
796843
}
@@ -945,17 +992,19 @@
945992
** PATH_INFO when it is empty.
946993
*/
947994
void cgi_init(void){
948995
char *z;
949996
const char *zType;
997
+ char *zSemi;
950998
int len;
951999
const char *zRequestUri = cgi_parameter("REQUEST_URI",0);
9521000
const char *zScriptName = cgi_parameter("SCRIPT_NAME",0);
9531001
const char *zPathInfo = cgi_parameter("PATH_INFO",0);
9541002
9551003
#ifdef FOSSIL_ENABLE_JSON
956
- json_main_bootstrap();
1004
+ int noJson = P("no_json")!=0;
1005
+ if( noJson==0 ){ json_main_bootstrap(); }
9571006
#endif
9581007
g.isHTTP = 1;
9591008
cgi_destination(CGI_BODY);
9601009
if( zScriptName==0 ) malformed_request("missing SCRIPT_NAME");
9611010
if( zRequestUri==0 ){
@@ -990,21 +1039,28 @@
9901039
if( z ){
9911040
g.zIpAddr = mprintf("%s", z);
9921041
}
9931042
9941043
len = atoi(PD("CONTENT_LENGTH", "0"));
995
- g.zContentType = zType = P("CONTENT_TYPE");
1044
+ zType = P("CONTENT_TYPE");
1045
+ zSemi = zType ? strchr(zType, ';') : 0;
1046
+ if( zSemi ){
1047
+ g.zContentType = mprintf("%.*s", (int)(zSemi-zType), zType);
1048
+ zType = g.zContentType;
1049
+ }else{
1050
+ g.zContentType = zType;
1051
+ }
9961052
blob_zero(&g.cgiIn);
9971053
if( len>0 && zType ){
9981054
if( fossil_strcmp(zType, "application/x-fossil")==0 ){
9991055
blob_read_from_channel(&g.cgiIn, g.httpIn, len);
10001056
blob_uncompress(&g.cgiIn, &g.cgiIn);
10011057
}
10021058
#ifdef FOSSIL_ENABLE_JSON
1003
- else if( fossil_strcmp(zType, "application/json")==0
1059
+ else if( noJson==0 && (fossil_strcmp(zType, "application/json")==0
10041060
|| fossil_strcmp(zType,"text/plain")==0/*assume this MIGHT be JSON*/
1005
- || fossil_strcmp(zType,"application/javascript")==0){
1061
+ || fossil_strcmp(zType,"application/javascript")==0) ){
10061062
g.json.isJsonMode = 1;
10071063
cgi_parse_POST_JSON(g.httpIn, (unsigned int)len);
10081064
/* FIXMEs:
10091065
10101066
- See if fossil really needs g.cgiIn to be set for this purpose
10111067
--- src/cgi.c
+++ src/cgi.c
@@ -489,10 +489,31 @@
489 }
490
491 /*
492 ** Add another query parameter or cookie to the parameter set.
493 ** zName is the name of the query parameter or cookie and zValue
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
494 ** is its fully decoded value.
495 **
496 ** Copies are made of both the zName and zValue parameters.
497 */
498 void cgi_set_parameter(const char *zName, const char *zValue){
@@ -523,10 +544,15 @@
523 assert( aParamQP[i].isQP );
524 return;
525 }
526 }
527 cgi_set_parameter_nocopy(zName, zValue, 1);
 
 
 
 
 
528 }
529
530 /*
531 ** Delete a parameter.
532 */
@@ -561,11 +587,10 @@
561 ** must be made of zValue.
562 */
563 void cgi_setenv(const char *zName, const char *zValue){
564 cgi_set_parameter_nocopy(zName, mprintf("%s",zValue), 0);
565 }
566
567
568 /*
569 ** Add a list of query parameters or cookies to the parameter set.
570 **
571 ** Each parameter is of the form NAME=VALUE. Both the NAME and the
@@ -615,12 +640,16 @@
615 dehttpize(zValue);
616 }else{
617 if( *z ){ *z++ = 0; }
618 zValue = "";
619 }
620 if( fossil_islower(zName[0]) && fossil_no_strange_characters(zName+1) ){
621 cgi_set_parameter_nocopy(zName, zValue, isQP);
 
 
 
 
622 }
623 #ifdef FOSSIL_ENABLE_JSON
624 json_setenv( zName, cson_value_new_string(zValue,strlen(zValue)) );
625 #endif /* FOSSIL_ENABLE_JSON */
626 }
@@ -759,15 +788,23 @@
759 if( zBoundry==0 ) return;
760 while( (zLine = get_line_from_string(&z, &len))!=0 ){
761 if( zLine[0]==0 ){
762 int nContent = 0;
763 zValue = get_bounded_content(&z, &len, zBoundry, &nContent);
764 if( zName && zValue && fossil_islower(zName[0]) ){
765 cgi_set_parameter_nocopy(zName, zValue, 1);
766 if( showBytes ){
767 cgi_set_parameter_nocopy(mprintf("%s:bytes", zName),
768 mprintf("%d",nContent), 1);
 
 
 
 
 
 
 
 
769 }
770 }
771 zName = 0;
772 showBytes = 0;
773 }else{
@@ -779,18 +816,28 @@
779 i++;
780 }else if( c=='n' && sqlite3_strnicmp(azArg[i],"name=",n)==0 ){
781 zName = azArg[++i];
782 }else if( c=='f' && sqlite3_strnicmp(azArg[i],"filename=",n)==0 ){
783 char *z = azArg[++i];
784 if( zName && z && fossil_islower(zName[0]) ){
785 cgi_set_parameter_nocopy(mprintf("%s:filename",zName), z, 1);
 
 
 
 
 
786 }
787 showBytes = 1;
788 }else if( c=='c' && sqlite3_strnicmp(azArg[i],"content-type:",n)==0 ){
789 char *z = azArg[++i];
790 if( zName && z && fossil_islower(zName[0]) ){
791 cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z, 1);
 
 
 
 
 
792 }
793 }
794 }
795 }
796 }
@@ -945,17 +992,19 @@
945 ** PATH_INFO when it is empty.
946 */
947 void cgi_init(void){
948 char *z;
949 const char *zType;
 
950 int len;
951 const char *zRequestUri = cgi_parameter("REQUEST_URI",0);
952 const char *zScriptName = cgi_parameter("SCRIPT_NAME",0);
953 const char *zPathInfo = cgi_parameter("PATH_INFO",0);
954
955 #ifdef FOSSIL_ENABLE_JSON
956 json_main_bootstrap();
 
957 #endif
958 g.isHTTP = 1;
959 cgi_destination(CGI_BODY);
960 if( zScriptName==0 ) malformed_request("missing SCRIPT_NAME");
961 if( zRequestUri==0 ){
@@ -990,21 +1039,28 @@
990 if( z ){
991 g.zIpAddr = mprintf("%s", z);
992 }
993
994 len = atoi(PD("CONTENT_LENGTH", "0"));
995 g.zContentType = zType = P("CONTENT_TYPE");
 
 
 
 
 
 
 
996 blob_zero(&g.cgiIn);
997 if( len>0 && zType ){
998 if( fossil_strcmp(zType, "application/x-fossil")==0 ){
999 blob_read_from_channel(&g.cgiIn, g.httpIn, len);
1000 blob_uncompress(&g.cgiIn, &g.cgiIn);
1001 }
1002 #ifdef FOSSIL_ENABLE_JSON
1003 else if( fossil_strcmp(zType, "application/json")==0
1004 || fossil_strcmp(zType,"text/plain")==0/*assume this MIGHT be JSON*/
1005 || fossil_strcmp(zType,"application/javascript")==0){
1006 g.json.isJsonMode = 1;
1007 cgi_parse_POST_JSON(g.httpIn, (unsigned int)len);
1008 /* FIXMEs:
1009
1010 - See if fossil really needs g.cgiIn to be set for this purpose
1011
--- src/cgi.c
+++ src/cgi.c
@@ -489,10 +489,31 @@
489 }
490
491 /*
492 ** Add another query parameter or cookie to the parameter set.
493 ** zName is the name of the query parameter or cookie and zValue
494 ** is its fully decoded value. zName will be modified to be an
495 ** all lowercase string.
496 **
497 ** zName and zValue are not copied and must not change or be
498 ** deallocated after this routine returns. This routine changes
499 ** all ASCII alphabetic characters in zName to lower case. The
500 ** caller must not change them back.
501 */
502 void cgi_set_parameter_nocopy_tolower(
503 char *zName,
504 const char *zValue,
505 int isQP
506 ){
507 int i;
508 for(i=0; zName[i]; i++){ zName[i] = fossil_tolower(zName[i]); }
509 cgi_set_parameter_nocopy(zName, zValue, isQP);
510 }
511
512 /*
513 ** Add another query parameter or cookie to the parameter set.
514 ** zName is the name of the query parameter or cookie and zValue
515 ** is its fully decoded value.
516 **
517 ** Copies are made of both the zName and zValue parameters.
518 */
519 void cgi_set_parameter(const char *zName, const char *zValue){
@@ -523,10 +544,15 @@
544 assert( aParamQP[i].isQP );
545 return;
546 }
547 }
548 cgi_set_parameter_nocopy(zName, zValue, 1);
549 }
550 void cgi_replace_query_parameter_tolower(char *zName, const char *zValue){
551 int i;
552 for(i=0; zName[i]; i++){ zName[i] = fossil_tolower(zName[i]); }
553 cgi_replace_query_parameter(zName, zValue);
554 }
555
556 /*
557 ** Delete a parameter.
558 */
@@ -561,11 +587,10 @@
587 ** must be made of zValue.
588 */
589 void cgi_setenv(const char *zName, const char *zValue){
590 cgi_set_parameter_nocopy(zName, mprintf("%s",zValue), 0);
591 }
 
592
593 /*
594 ** Add a list of query parameters or cookies to the parameter set.
595 **
596 ** Each parameter is of the form NAME=VALUE. Both the NAME and the
@@ -615,12 +640,16 @@
640 dehttpize(zValue);
641 }else{
642 if( *z ){ *z++ = 0; }
643 zValue = "";
644 }
645 if( zName[0] && fossil_no_strange_characters(zName+1) ){
646 if( fossil_islower(zName[0]) ){
647 cgi_set_parameter_nocopy(zName, zValue, isQP);
648 }else if( fossil_isupper(zName[0]) ){
649 cgi_set_parameter_nocopy_tolower(zName, zValue, isQP);
650 }
651 }
652 #ifdef FOSSIL_ENABLE_JSON
653 json_setenv( zName, cson_value_new_string(zValue,strlen(zValue)) );
654 #endif /* FOSSIL_ENABLE_JSON */
655 }
@@ -759,15 +788,23 @@
788 if( zBoundry==0 ) return;
789 while( (zLine = get_line_from_string(&z, &len))!=0 ){
790 if( zLine[0]==0 ){
791 int nContent = 0;
792 zValue = get_bounded_content(&z, &len, zBoundry, &nContent);
793 if( zName && zValue ){
794 if( fossil_islower(zName[0]) ){
795 cgi_set_parameter_nocopy(zName, zValue, 1);
796 if( showBytes ){
797 cgi_set_parameter_nocopy(mprintf("%s:bytes", zName),
798 mprintf("%d",nContent), 1);
799 }
800 }else if( fossil_isupper(zName[0]) ){
801 cgi_set_parameter_nocopy_tolower(zName, zValue, 1);
802 if( showBytes ){
803 cgi_set_parameter_nocopy_tolower(mprintf("%s:bytes", zName),
804 mprintf("%d",nContent), 1);
805 }
806 }
807 }
808 zName = 0;
809 showBytes = 0;
810 }else{
@@ -779,18 +816,28 @@
816 i++;
817 }else if( c=='n' && sqlite3_strnicmp(azArg[i],"name=",n)==0 ){
818 zName = azArg[++i];
819 }else if( c=='f' && sqlite3_strnicmp(azArg[i],"filename=",n)==0 ){
820 char *z = azArg[++i];
821 if( zName && z ){
822 if( fossil_islower(zName[0]) ){
823 cgi_set_parameter_nocopy(mprintf("%s:filename",zName), z, 1);
824 }else if( fossil_isupper(zName[0]) ){
825 cgi_set_parameter_nocopy_tolower(mprintf("%s:filename",zName),
826 z, 1);
827 }
828 }
829 showBytes = 1;
830 }else if( c=='c' && sqlite3_strnicmp(azArg[i],"content-type:",n)==0 ){
831 char *z = azArg[++i];
832 if( zName && z ){
833 if( fossil_islower(zName[0]) ){
834 cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z, 1);
835 }else if( fossil_isupper(zName[0]) ){
836 cgi_set_parameter_nocopy_tolower(mprintf("%s:mimetype",zName),
837 z, 1);
838 }
839 }
840 }
841 }
842 }
843 }
@@ -945,17 +992,19 @@
992 ** PATH_INFO when it is empty.
993 */
994 void cgi_init(void){
995 char *z;
996 const char *zType;
997 char *zSemi;
998 int len;
999 const char *zRequestUri = cgi_parameter("REQUEST_URI",0);
1000 const char *zScriptName = cgi_parameter("SCRIPT_NAME",0);
1001 const char *zPathInfo = cgi_parameter("PATH_INFO",0);
1002
1003 #ifdef FOSSIL_ENABLE_JSON
1004 int noJson = P("no_json")!=0;
1005 if( noJson==0 ){ json_main_bootstrap(); }
1006 #endif
1007 g.isHTTP = 1;
1008 cgi_destination(CGI_BODY);
1009 if( zScriptName==0 ) malformed_request("missing SCRIPT_NAME");
1010 if( zRequestUri==0 ){
@@ -990,21 +1039,28 @@
1039 if( z ){
1040 g.zIpAddr = mprintf("%s", z);
1041 }
1042
1043 len = atoi(PD("CONTENT_LENGTH", "0"));
1044 zType = P("CONTENT_TYPE");
1045 zSemi = zType ? strchr(zType, ';') : 0;
1046 if( zSemi ){
1047 g.zContentType = mprintf("%.*s", (int)(zSemi-zType), zType);
1048 zType = g.zContentType;
1049 }else{
1050 g.zContentType = zType;
1051 }
1052 blob_zero(&g.cgiIn);
1053 if( len>0 && zType ){
1054 if( fossil_strcmp(zType, "application/x-fossil")==0 ){
1055 blob_read_from_channel(&g.cgiIn, g.httpIn, len);
1056 blob_uncompress(&g.cgiIn, &g.cgiIn);
1057 }
1058 #ifdef FOSSIL_ENABLE_JSON
1059 else if( noJson==0 && (fossil_strcmp(zType, "application/json")==0
1060 || fossil_strcmp(zType,"text/plain")==0/*assume this MIGHT be JSON*/
1061 || fossil_strcmp(zType,"application/javascript")==0) ){
1062 g.json.isJsonMode = 1;
1063 cgi_parse_POST_JSON(g.httpIn, (unsigned int)len);
1064 /* FIXMEs:
1065
1066 - See if fossil really needs g.cgiIn to be set for this purpose
1067
--- src/dispatch.c
+++ src/dispatch.c
@@ -196,10 +196,12 @@
196196
if( *z ){ *z++ = 0; }
197197
zValue = "";
198198
}
199199
if( fossil_islower(zName[0]) ){
200200
cgi_replace_query_parameter(zName, zValue);
201
+ }else if( fossil_isupper(zName[0]) ){
202
+ cgi_replace_query_parameter_tolower(zName, zValue);
201203
}
202204
}
203205
return 0;
204206
}
205207
206208
--- src/dispatch.c
+++ src/dispatch.c
@@ -196,10 +196,12 @@
196 if( *z ){ *z++ = 0; }
197 zValue = "";
198 }
199 if( fossil_islower(zName[0]) ){
200 cgi_replace_query_parameter(zName, zValue);
 
 
201 }
202 }
203 return 0;
204 }
205
206
--- src/dispatch.c
+++ src/dispatch.c
@@ -196,10 +196,12 @@
196 if( *z ){ *z++ = 0; }
197 zValue = "";
198 }
199 if( fossil_islower(zName[0]) ){
200 cgi_replace_query_parameter(zName, zValue);
201 }else if( fossil_isupper(zName[0]) ){
202 cgi_replace_query_parameter_tolower(zName, zValue);
203 }
204 }
205 return 0;
206 }
207
208
+1 -1
--- src/doc.c
+++ src/doc.c
@@ -595,11 +595,11 @@
595595
if( wiki_find_title(pBody, &title, &tail) ){
596596
style_header("%s", blob_str(&title));
597597
Th_Render(blob_str(&tail));
598598
blob_reset(&tail);
599599
}else{
600
- style_header("%h", zDefaultTitle);
600
+ style_header("%h", zFilename);
601601
Th_Render(blob_str(pBody));
602602
}
603603
}else{
604604
Th_Render(blob_str(pBody));
605605
}
606606
--- src/doc.c
+++ src/doc.c
@@ -595,11 +595,11 @@
595 if( wiki_find_title(pBody, &title, &tail) ){
596 style_header("%s", blob_str(&title));
597 Th_Render(blob_str(&tail));
598 blob_reset(&tail);
599 }else{
600 style_header("%h", zDefaultTitle);
601 Th_Render(blob_str(pBody));
602 }
603 }else{
604 Th_Render(blob_str(pBody));
605 }
606
--- src/doc.c
+++ src/doc.c
@@ -595,11 +595,11 @@
595 if( wiki_find_title(pBody, &title, &tail) ){
596 style_header("%s", blob_str(&title));
597 Th_Render(blob_str(&tail));
598 blob_reset(&tail);
599 }else{
600 style_header("%h", zFilename);
601 Th_Render(blob_str(pBody));
602 }
603 }else{
604 Th_Render(blob_str(pBody));
605 }
606

Keyboard Shortcuts

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