| | @@ -404,10 +404,11 @@ |
| 404 | 404 | static int seqQP = 0; /* Sequence numbers */ |
| 405 | 405 | static struct QParam { /* One entry for each query parameter or cookie */ |
| 406 | 406 | const char *zName; /* Parameter or cookie name */ |
| 407 | 407 | const char *zValue; /* Value of the query parameter or cookie */ |
| 408 | 408 | int seq; /* Order of insertion */ |
| 409 | + int isQP; /* True for query parameters */ |
| 409 | 410 | } *aParamQP; /* An array of all parameters and cookies */ |
| 410 | 411 | |
| 411 | 412 | /* |
| 412 | 413 | ** Add another query parameter or cookie to the parameter set. |
| 413 | 414 | ** zName is the name of the query parameter or cookie and zValue |
| | @@ -414,11 +415,11 @@ |
| 414 | 415 | ** is its fully decoded value. |
| 415 | 416 | ** |
| 416 | 417 | ** zName and zValue are not copied and must not change or be |
| 417 | 418 | ** deallocated after this routine returns. |
| 418 | 419 | */ |
| 419 | | -void cgi_set_parameter_nocopy(const char *zName, const char *zValue){ |
| 420 | +void cgi_set_parameter_nocopy(const char *zName, const char *zValue, int isQP){ |
| 420 | 421 | if( nAllocQP<=nUsedQP ){ |
| 421 | 422 | nAllocQP = nAllocQP*2 + 10; |
| 422 | 423 | if( nAllocQP>1000 ){ |
| 423 | 424 | /* Prevent a DOS service attack against the framework */ |
| 424 | 425 | fossil_fatal("Too many query parameters"); |
| | @@ -429,10 +430,11 @@ |
| 429 | 430 | aParamQP[nUsedQP].zValue = zValue; |
| 430 | 431 | if( g.fHttpTrace ){ |
| 431 | 432 | fprintf(stderr, "# cgi: %s = [%s]\n", zName, zValue); |
| 432 | 433 | } |
| 433 | 434 | aParamQP[nUsedQP].seq = seqQP++; |
| 435 | + aParamQP[nUsedQP].isQP = isQP; |
| 434 | 436 | nUsedQP++; |
| 435 | 437 | sortQP = 1; |
| 436 | 438 | } |
| 437 | 439 | |
| 438 | 440 | /* |
| | @@ -441,11 +443,11 @@ |
| 441 | 443 | ** is its fully decoded value. |
| 442 | 444 | ** |
| 443 | 445 | ** Copies are made of both the zName and zValue parameters. |
| 444 | 446 | */ |
| 445 | 447 | void cgi_set_parameter(const char *zName, const char *zValue){ |
| 446 | | - cgi_set_parameter_nocopy(mprintf("%s",zName), mprintf("%s",zValue)); |
| 448 | + cgi_set_parameter_nocopy(mprintf("%s",zName), mprintf("%s",zValue), 0); |
| 447 | 449 | } |
| 448 | 450 | |
| 449 | 451 | /* |
| 450 | 452 | ** Replace a parameter with a new value. |
| 451 | 453 | */ |
| | @@ -455,19 +457,19 @@ |
| 455 | 457 | if( fossil_strcmp(aParamQP[i].zName,zName)==0 ){ |
| 456 | 458 | aParamQP[i].zValue = zValue; |
| 457 | 459 | return; |
| 458 | 460 | } |
| 459 | 461 | } |
| 460 | | - cgi_set_parameter_nocopy(zName, zValue); |
| 462 | + cgi_set_parameter_nocopy(zName, zValue, 0); |
| 461 | 463 | } |
| 462 | 464 | |
| 463 | 465 | /* |
| 464 | 466 | ** Add a query parameter. The zName portion is fixed but a copy |
| 465 | 467 | ** must be made of zValue. |
| 466 | 468 | */ |
| 467 | 469 | void cgi_setenv(const char *zName, const char *zValue){ |
| 468 | | - cgi_set_parameter_nocopy(zName, mprintf("%s",zValue)); |
| 470 | + cgi_set_parameter_nocopy(zName, mprintf("%s",zValue), 0); |
| 469 | 471 | } |
| 470 | 472 | |
| 471 | 473 | |
| 472 | 474 | /* |
| 473 | 475 | ** Add a list of query parameters or cookies to the parameter set. |
| | @@ -493,10 +495,11 @@ |
| 493 | 495 | ** The input string "z" is modified but no copies is made. "z" |
| 494 | 496 | ** should not be deallocated or changed again after this routine |
| 495 | 497 | ** returns or it will corrupt the parameter table. |
| 496 | 498 | */ |
| 497 | 499 | static void add_param_list(char *z, int terminator){ |
| 500 | + int isQP = terminator=='&'; |
| 498 | 501 | while( *z ){ |
| 499 | 502 | char *zName; |
| 500 | 503 | char *zValue; |
| 501 | 504 | while( fossil_isspace(*z) ){ z++; } |
| 502 | 505 | zName = z; |
| | @@ -514,11 +517,11 @@ |
| 514 | 517 | }else{ |
| 515 | 518 | if( *z ){ *z++ = 0; } |
| 516 | 519 | zValue = ""; |
| 517 | 520 | } |
| 518 | 521 | if( fossil_islower(zName[0]) ){ |
| 519 | | - cgi_set_parameter_nocopy(zName, zValue); |
| 522 | + cgi_set_parameter_nocopy(zName, zValue, isQP); |
| 520 | 523 | } |
| 521 | 524 | #ifdef FOSSIL_ENABLE_JSON |
| 522 | 525 | json_setenv( zName, cson_value_new_string(zValue,strlen(zValue)) ); |
| 523 | 526 | #endif /* FOSSIL_ENABLE_JSON */ |
| 524 | 527 | } |
| | @@ -658,14 +661,14 @@ |
| 658 | 661 | while( (zLine = get_line_from_string(&z, &len))!=0 ){ |
| 659 | 662 | if( zLine[0]==0 ){ |
| 660 | 663 | int nContent = 0; |
| 661 | 664 | zValue = get_bounded_content(&z, &len, zBoundry, &nContent); |
| 662 | 665 | if( zName && zValue && fossil_islower(zName[0]) ){ |
| 663 | | - cgi_set_parameter_nocopy(zName, zValue); |
| 666 | + cgi_set_parameter_nocopy(zName, zValue, 1); |
| 664 | 667 | if( showBytes ){ |
| 665 | 668 | cgi_set_parameter_nocopy(mprintf("%s:bytes", zName), |
| 666 | | - mprintf("%d",nContent)); |
| 669 | + mprintf("%d",nContent), 1); |
| 667 | 670 | } |
| 668 | 671 | } |
| 669 | 672 | zName = 0; |
| 670 | 673 | showBytes = 0; |
| 671 | 674 | }else{ |
| | @@ -678,17 +681,17 @@ |
| 678 | 681 | }else if( c=='n' && sqlite3_strnicmp(azArg[i],"name=",n)==0 ){ |
| 679 | 682 | zName = azArg[++i]; |
| 680 | 683 | }else if( c=='f' && sqlite3_strnicmp(azArg[i],"filename=",n)==0 ){ |
| 681 | 684 | char *z = azArg[++i]; |
| 682 | 685 | if( zName && z && fossil_islower(zName[0]) ){ |
| 683 | | - cgi_set_parameter_nocopy(mprintf("%s:filename",zName), z); |
| 686 | + cgi_set_parameter_nocopy(mprintf("%s:filename",zName), z, 1); |
| 684 | 687 | } |
| 685 | 688 | showBytes = 1; |
| 686 | 689 | }else if( c=='c' && sqlite3_strnicmp(azArg[i],"content-type:",n)==0 ){ |
| 687 | 690 | char *z = azArg[++i]; |
| 688 | 691 | if( zName && z && fossil_islower(zName[0]) ){ |
| 689 | | - cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z); |
| 692 | + cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z, 1); |
| 690 | 693 | } |
| 691 | 694 | } |
| 692 | 695 | } |
| 693 | 696 | } |
| 694 | 697 | } |
| | @@ -980,11 +983,11 @@ |
| 980 | 983 | ** with the given name. |
| 981 | 984 | */ |
| 982 | 985 | if( fossil_isupper(zName[0]) ){ |
| 983 | 986 | const char *zValue = fossil_getenv(zName); |
| 984 | 987 | if( zValue ){ |
| 985 | | - cgi_set_parameter_nocopy(zName, zValue); |
| 988 | + cgi_set_parameter_nocopy(zName, zValue, 0); |
| 986 | 989 | CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue)); |
| 987 | 990 | return zValue; |
| 988 | 991 | } |
| 989 | 992 | } |
| 990 | 993 | CGIDEBUG(("no-match [%s]\n", zName)); |
| | @@ -1081,10 +1084,25 @@ |
| 1081 | 1084 | if( fossil_strnicmp("fossil-",zName,7)==0 ) continue; |
| 1082 | 1085 | } |
| 1083 | 1086 | cgi_printf("%h = %h <br />\n", zName, aParamQP[i].zValue); |
| 1084 | 1087 | } |
| 1085 | 1088 | } |
| 1089 | + |
| 1090 | +/* |
| 1091 | +** Export all query parameters (but not cookies or environment variables) |
| 1092 | +** as hidden values of a form. |
| 1093 | +*/ |
| 1094 | +void cgi_query_parameters_to_hidden(void){ |
| 1095 | + int i; |
| 1096 | + const char *zN, *zV; |
| 1097 | + for(i=0; i<nUsedQP; i++){ |
| 1098 | + if( aParamQP[i].isQP==0 ) continue; |
| 1099 | + zN = aParamQP[i].zName; |
| 1100 | + zV = aParamQP[i].zValue; |
| 1101 | + @ <input type="hidden" name="%h(zN)" value="%h(zV)"> |
| 1102 | + } |
| 1103 | +} |
| 1086 | 1104 | |
| 1087 | 1105 | /* |
| 1088 | 1106 | ** This routine works like "printf" except that it has the |
| 1089 | 1107 | ** extra formatting capabilities such as %h and %t. |
| 1090 | 1108 | */ |
| 1091 | 1109 | |