00001
00002
00003
00004
00005
00006
00007 #include "common.h"
00008 #include "hash.h"
00009 #include "cheapcgi.h"
00010 #include "portable.h"
00011 #include "linefile.h"
00012 #include "errabort.h"
00013 #include "mime.h"
00014
00015 static char const rcsid[] = "$Id: cheapcgi.c,v 1.85 2006/12/19 18:49:52 kent Exp $";
00016
00017
00018 static char *inputString = NULL;
00019 static unsigned long inputSize;
00020 static struct hash *inputHash = NULL;
00021 static struct cgiVar *inputList = NULL;
00022
00023 static boolean haveCookiesHash = FALSE;
00024 static struct hash *cookieHash = NULL;
00025 static struct cgiVar *cookieList = NULL;
00026
00027
00028 static boolean doUseTempFile = FALSE;
00029
00030 void dumpCookieList()
00031
00032 {
00033 struct cgiVar *v;
00034 for (v=cookieList; v != NULL; v = v->next)
00035 printf("%s=%s (%d)\n", v->name, v->val, v->saved);
00036 }
00037
00038 void useTempFile()
00039
00040 {
00041 doUseTempFile = TRUE;
00042 }
00043
00044 boolean cgiIsOnWeb()
00045
00046 {
00047 return getenv("REQUEST_METHOD") != NULL;
00048 }
00049
00050 char *cgiScriptName()
00051
00052 {
00053 return getenv("SCRIPT_NAME");
00054 }
00055
00056 char *cgiServerName()
00057
00058 {
00059 return getenv("SERVER_NAME");
00060 }
00061
00062 char *_cgiRawInput()
00063
00064 {
00065 return inputString;
00066 }
00067
00068 static void getQueryInput()
00069
00070 {
00071 inputString = getenv("QUERY_STRING");
00072 if (inputString == NULL)
00073 errAbort("No QUERY_STRING in environment.");
00074 inputString = cloneString(inputString);
00075 }
00076
00077 static void getPostInput()
00078
00079 {
00080 char *s;
00081 long i;
00082 int r;
00083
00084 s = getenv("CONTENT_LENGTH");
00085 if (s == NULL)
00086 errAbort("No CONTENT_LENGTH in environment.");
00087 if (sscanf(s, "%lu", &inputSize) != 1)
00088 errAbort("CONTENT_LENGTH isn't a number.");
00089 s = getenv("CONTENT_TYPE");
00090 if (s != NULL && startsWith("multipart/form-data", s))
00091 {
00092
00093 inputString = "";
00094 return;
00095 }
00096 inputString = needMem((size_t)inputSize+1);
00097 for (i=0; i<inputSize; ++i)
00098 {
00099 r = getc(stdin);
00100 if (r == EOF)
00101 errAbort("Short POST input.");
00102 inputString[i] = r;
00103 }
00104 inputString[inputSize] = 0;
00105 }
00106
00107 #define memmem(hay, haySize, needle, needleSize) \
00108 memMatch(needle, needleSize, hay, haySize)
00109
00110 static void cgiParseMultipart(struct hash **retHash, struct cgiVar **retList)
00111
00112 {
00113 char h[1024];
00114 char *s = NULL, *ct = NULL;
00115 struct dyString *dy = newDyString(256);
00116 struct mimeBuf *mb = NULL;
00117 struct mimePart *mp = NULL;
00118 char **env = NULL;
00119 struct hash *hash = newHash(6);
00120 struct cgiVar *list = NULL, *el;
00121 extern char **environ;
00122
00123
00124
00125
00126
00127
00128
00129 for(env=environ; *env; env++)
00130 if (startsWith("CONTENT_",*env))
00131 {
00132
00133
00134 safef(h,sizeof(h),"%s",*env);
00135 s = strchr(h,'_');
00136 if (!s)
00137 errAbort("expecting '_' parsing env var %s for MIME alt header", *env);
00138 *s = '-';
00139 s = strchr(h,'=');
00140 if (!s)
00141 errAbort("expecting '=' parsing env var %s for MIME alt header", *env);
00142 *s = ':';
00143 dyStringPrintf(dy,"%s\r\n",h);
00144 }
00145 dyStringAppend(dy,"\r\n");
00146
00147
00148
00149
00150 mb = initMimeBuf(STDIN_FILENO);
00151
00152
00153
00154 mp = parseMultiParts(mb, cloneString(dy->string));
00155 freeDyString(&dy);
00156 if(!mp->multi)
00157 errAbort("Malformatted multipart-form.");
00158
00159
00160
00161
00162
00163 ct = hashFindVal(mp->hdr,"content-type");
00164
00165
00166
00167 if (!startsWith("multipart/form-data",ct))
00168 errAbort("main content-type expected starts with [multipart/form-data], found [%s]",ct);
00169
00170 for(mp=mp->multi;mp;mp=mp->next)
00171 {
00172 char *cd = NULL, *cdMain = NULL, *cdName = NULL, *cdFileName = NULL, *ct = NULL;
00173 cd = hashFindVal(mp->hdr,"content-disposition");
00174 ct = hashFindVal(mp->hdr,"content-type");
00175
00176
00177
00178
00179 cdMain=getMimeHeaderMainVal(cd);
00180 cdName=getMimeHeaderFieldVal(cd,"name");
00181 cdFileName=getMimeHeaderFieldVal(cd,"filename");
00182
00183
00184
00185 if (!sameString(cdMain,"form-data"))
00186 errAbort("main content-type expected [form-data], found [%s]",cdMain);
00187
00188
00189
00190
00191
00192
00193
00194
00195 if(cdFileName)
00196 {
00197 char varNameFilename[256];
00198 safef(varNameFilename, sizeof(varNameFilename), "%s__filename", cdName);
00199 AllocVar(el);
00200 el->val = cloneString(cdFileName);
00201 slAddHead(&list, el);
00202 hashAddSaveName(hash, varNameFilename, el, &el->name);
00203 }
00204
00205 if (mp->data)
00206 {
00207 if (mp->binary)
00208 {
00209 char varNameBinary[256];
00210 char addrSizeBuf[40];
00211 safef(varNameBinary,sizeof(varNameBinary),"%s__binary",cdName);
00212 safef(addrSizeBuf,sizeof(addrSizeBuf),"%lu %llu",
00213 (unsigned long)mp->data,
00214 (unsigned long long)mp->size);
00215 AllocVar(el);
00216 el->val = cloneString(addrSizeBuf);
00217 slAddHead(&list, el);
00218 hashAddSaveName(hash, varNameBinary, el, &el->name);
00219 }
00220 else
00221 {
00222 AllocVar(el);
00223 el->val = mp->data;
00224 slAddHead(&list, el);
00225 hashAddSaveName(hash, cdName, el, &el->name);
00226 }
00227 }
00228 else if (mp->fileName)
00229 {
00230 char varNameData[256];
00231 safef(varNameData, sizeof(varNameData), "%s__data", cdName);
00232 AllocVar(el);
00233 el->val = mp->fileName;
00234 slAddHead(&list, el);
00235 hashAddSaveName(hash, varNameData, el, &el->name);
00236
00237
00238
00239 }
00240 else if (mp->multi)
00241 {
00242 warn("unexpected nested MIME structures");
00243 }
00244 else
00245 {
00246 errAbort("mp-> type not data,fileName, or multi - unexpected MIME structure");
00247 }
00248
00249 freez(&cdMain);
00250 freez(&cdName);
00251 freez(&cdFileName);
00252 }
00253
00254 slReverse(&list);
00255 *retList = list;
00256 *retHash = hash;
00257 }
00258
00259
00260
00261
00262 static void parseCookies(struct hash **retHash, struct cgiVar **retList)
00263
00264 {
00265 char* str;
00266 char *namePt, *dataPt, *nextNamePt;
00267 struct hash *hash;
00268 struct cgiVar *list = NULL, *el;
00269
00270
00271 if(haveCookiesHash == TRUE)
00272 return;
00273
00274 str = cloneString(getenv("HTTP_COOKIE"));
00275 if(str == NULL)
00276 return;
00277
00278 hash = newHash(6);
00279
00280 namePt = str;
00281 while (namePt != NULL)
00282 {
00283 dataPt = strchr(namePt, '=');
00284 if (dataPt == NULL)
00285 errAbort("Mangled Cookie input string %s", namePt);
00286 *dataPt++ = 0;
00287 nextNamePt = strchr(dataPt, ';');
00288 if (nextNamePt != NULL)
00289 {
00290 *nextNamePt++ = 0;
00291 nextNamePt++;
00292 }
00293 cgiDecode(dataPt,dataPt,strlen(dataPt));
00294 AllocVar(el);
00295 el->val = dataPt;
00296 slAddHead(&list, el);
00297 hashAddSaveName(hash, namePt, el, &el->name);
00298 namePt = nextNamePt;
00299 }
00300
00301 haveCookiesHash = TRUE;
00302
00303 slReverse(&list);
00304 *retList = list;
00305 *retHash = hash;
00306 }
00307
00308 char *findCookieData(char *varName)
00309
00310 {
00311 struct cgiVar *var;
00312
00313
00314 parseCookies(&cookieHash, &cookieList);
00315 if (cookieHash == NULL)
00316 return NULL;
00317 if ((var = hashFindVal(cookieHash, varName)) == NULL)
00318 return NULL;
00319 return var->val;
00320 }
00321
00322 static char *cgiInputSource(char *s)
00323
00324 {
00325 char *qs;
00326 if (s != NULL)
00327 return s;
00328 qs = getenv("QUERY_STRING");
00329 if (qs == NULL)
00330 return "POST";
00331 if (qs[0] == 0)
00332 {
00333 char *cl = getenv("CONTENT_LENGTH");
00334 if (cl != NULL && atoi(cl) > 0)
00335 return "POST";
00336 }
00337 return "QUERY";
00338 }
00339
00340 static void _cgiFindInput(char *method)
00341
00342
00343 {
00344 if (inputString == NULL)
00345 {
00346 method = cgiInputSource(method);
00347 if (sameWord(method, "POST"))
00348 getPostInput();
00349 else if (sameWord(method, "QUERY") || sameWord(method, "GET"))
00350 getQueryInput();
00351 else
00352 errAbort("Unknown form method");
00353 }
00354 }
00355
00356 static void cgiParseInputAbort(char *input, struct hash **retHash,
00357 struct cgiVar **retList)
00358
00359
00360
00361
00362 {
00363 char *namePt, *dataPt, *nextNamePt;
00364 struct hash *hash = newHash(6);
00365 struct cgiVar *list = NULL, *el;
00366
00367 namePt = input;
00368 while (namePt != NULL && namePt[0] != 0)
00369 {
00370 dataPt = strchr(namePt, '=');
00371 if (dataPt == NULL)
00372 {
00373 errAbort("Mangled CGI input string %s", namePt);
00374 }
00375 *dataPt++ = 0;
00376 nextNamePt = strchr(dataPt, '&');
00377 if (nextNamePt == NULL)
00378 nextNamePt = strchr(dataPt, ';');
00379 if (nextNamePt != NULL)
00380 *nextNamePt++ = 0;
00381 cgiDecode(namePt,namePt,strlen(namePt));
00382 cgiDecode(dataPt,dataPt,strlen(dataPt));
00383 AllocVar(el);
00384 el->val = dataPt;
00385 slAddHead(&list, el);
00386 hashAddSaveName(hash, namePt, el, &el->name);
00387 namePt = nextNamePt;
00388 }
00389 slReverse(&list);
00390 *retList = list;
00391 *retHash = hash;
00392 }
00393
00394 static jmp_buf cgiParseRecover;
00395
00396 static void cgiParseAbort()
00397
00398 {
00399 longjmp(cgiParseRecover, -1);
00400 }
00401
00402 boolean cgiParseInput(char *input, struct hash **retHash,
00403 struct cgiVar **retList)
00404
00405
00406
00407
00408 {
00409 boolean ok = TRUE;
00410 int status = setjmp(cgiParseRecover);
00411 if (status == 0)
00412 {
00413 pushAbortHandler(cgiParseAbort);
00414 cgiParseInputAbort(input, retHash, retList);
00415 }
00416 else
00417 {
00418 ok = FALSE;
00419 }
00420 popAbortHandler();
00421 return ok;
00422 }
00423
00424 static void initCgiInput()
00425
00426
00427
00428 {
00429 char* s;
00430
00431 if (inputString != NULL)
00432 return;
00433 _cgiFindInput(NULL);
00434
00435
00436 s = getenv("CONTENT_TYPE");
00437 if (s != NULL && startsWith("multipart/form-data", s))
00438 {
00439 cgiParseMultipart(&inputHash, &inputList);
00440 }
00441 else
00442 {
00443 cgiParseInputAbort(inputString, &inputHash, &inputList);
00444 }
00445
00446
00447 parseCookies(&cookieHash, &cookieList);
00448
00449
00450 s = cgiOptionalString("JKSQL_TRACE");
00451 if (s != NULL)
00452 envUpdate("JKSQL_TRACE", s);
00453 s = cgiOptionalString("JKSQL_PROF");
00454 if (s != NULL)
00455 envUpdate("JKSQL_PROF", s);
00456
00457 }
00458
00459 struct cgiVar *cgiVarList()
00460
00461 {
00462 initCgiInput();
00463 return inputList;
00464 }
00465
00466 static char *findVarData(char *varName)
00467
00468 {
00469 struct cgiVar *var;
00470
00471 initCgiInput();
00472 if ((var = hashFindVal(inputHash, varName)) == NULL)
00473 return NULL;
00474 return var->val;
00475 }
00476
00477 void cgiBadVar(char *varName)
00478
00479 {
00480 if (varName == NULL) varName = "";
00481 errAbort("Sorry, didn't find input variable %s\n"
00482 "Probably the web page didn't mean to call this program.",
00483 varName);
00484 }
00485
00486 static char *mustFindVarData(char *varName)
00487
00488 {
00489 char *res = findVarData(varName);
00490 if (res == NULL)
00491 cgiBadVar(varName);
00492 return res;
00493 }
00494
00495 void cgiDecode(char *in, char *out, int inLength)
00496
00497
00498
00499 {
00500 char c;
00501 int i;
00502 for (i=0; i<inLength;++i)
00503 {
00504 c = *in++;
00505 if (c == '+')
00506 *out++ = ' ';
00507 else if (c == '%')
00508 {
00509 int code;
00510 if (sscanf(in, "%2x", &code) != 1)
00511 code = '?';
00512 in += 2;
00513 i += 2;
00514 *out++ = code;
00515 }
00516 else
00517 *out++ = c;
00518 }
00519 *out++ = 0;
00520 }
00521
00522 char *cgiEncode(char *inString)
00523
00524
00525
00526 {
00527 char c;
00528 int outSize = 0;
00529 char *outString, *out, *in;
00530
00531 if (inString == NULL)
00532 return(cloneString(""));
00533
00534
00535 in = inString;
00536 while ((c = *in++) != 0)
00537 {
00538 if (isalnum(c) || c == ' ' || c == '.' || c == '_')
00539 outSize += 1;
00540 else
00541 outSize += 3;
00542 }
00543 outString = needMem(outSize+1);
00544
00545
00546 in = inString;
00547 out = outString;
00548 while ((c = *in++) != 0)
00549 {
00550 if (isalnum(c) || c == '.' || c == '_')
00551 *out++ = c;
00552 else if (c == ' ')
00553 *out++ = '+';
00554 else
00555 {
00556 unsigned char uc = c;
00557 char buf[4];
00558 *out++ = '%';
00559 safef(buf, sizeof(buf), "%02X", uc);
00560 *out++ = buf[0];
00561 *out++ = buf[1];
00562 }
00563 }
00564 *out++ = 0;
00565 return outString;
00566 }
00567
00568 char *cgiEncodeFull(char *inString)
00569
00570
00571
00572 {
00573 char c;
00574 int outSize = 0;
00575 char *outString, *out, *in;
00576
00577 if (inString == NULL)
00578 return(cloneString(""));
00579
00580
00581 in = inString;
00582 while ((c = *in++) != 0)
00583 {
00584 if (isalnum(c) || c == '.' || c == '_')
00585 outSize += 1;
00586 else
00587 outSize += 3;
00588 }
00589 outString = needMem(outSize+1);
00590
00591
00592 in = inString;
00593 out = outString;
00594 while ((c = *in++) != 0)
00595 {
00596 if (isalnum(c) || c == '.' || c == '_')
00597 *out++ = c;
00598 else
00599 {
00600 unsigned char uc = c;
00601 char buf[4];
00602 *out++ = '%';
00603 safef(buf, sizeof(buf), "%02X", uc);
00604 *out++ = buf[0];
00605 *out++ = buf[1];
00606 }
00607 }
00608 *out++ = 0;
00609 return outString;
00610 }
00611
00612 char *cgiOptionalString(char *varName)
00613
00614 {
00615 return findVarData(varName);
00616 }
00617
00618
00619 char *cgiString(char *varName)
00620
00621 {
00622 return mustFindVarData(varName);
00623 }
00624
00625 char *cgiUsualString(char *varName, char *usual)
00626
00627
00628 {
00629 char *pt;
00630 pt = findVarData(varName);
00631 if (pt == NULL)
00632 pt = usual;
00633 return pt;
00634 }
00635
00636 struct slName *cgiStringList(char *varName)
00637
00638
00639 {
00640 struct hashEl *hel;
00641 struct slName *stringList = NULL, *string;
00642
00643 initCgiInput();
00644 for (hel = hashLookup(inputHash, varName); hel != NULL; hel = hel->next)
00645 {
00646 if (sameString(hel->name, varName))
00647 {
00648 struct cgiVar *var = hel->val;
00649 string = newSlName(var->val);
00650 slAddHead(&stringList, string);
00651 }
00652 }
00653 return stringList;
00654 }
00655
00656
00657 int cgiInt(char *varName)
00658
00659 {
00660 char *data;
00661 char c;
00662
00663 data = mustFindVarData(varName);
00664 data = skipLeadingSpaces(data);
00665 c = data[0];
00666 if (!(isdigit(c) || (c == '-' && isdigit(data[1]))))
00667 errAbort("Expecting number in %s, got \"%s\"\n", varName, data);
00668 return atoi(data);
00669 }
00670
00671 int cgiIntExp(char *varName)
00672
00673
00674 {
00675 return intExp(cgiString(varName));
00676 }
00677
00678 int cgiOptionalInt(char *varName, int defaultVal)
00679
00680
00681 {
00682 char *s = cgiOptionalString(varName);
00683 s = skipLeadingSpaces(s);
00684 if (isEmpty(s))
00685 return defaultVal;
00686 return cgiInt(varName);
00687 }
00688
00689 double cgiDouble(char *varName)
00690
00691 {
00692 char *data;
00693 double x;
00694
00695 data = mustFindVarData(varName);
00696 if (sscanf(data, "%lf", &x)<1)
00697 errAbort("Expecting real number in %s, got \"%s\"\n", varName, data);
00698 return x;
00699 }
00700
00701 double cgiOptionalDouble(char *varName, double defaultVal)
00702
00703 {
00704 if (!cgiVarExists(varName))
00705 return defaultVal;
00706 return cgiDouble(varName);
00707 }
00708
00709 boolean cgiVarExists(char *varName)
00710
00711 {
00712 initCgiInput();
00713 return hashLookup(inputHash, varName) != NULL;
00714 }
00715
00716 boolean cgiBoolean(char *varName)
00717 {
00718 return cgiVarExists(varName);
00719 }
00720
00721 int cgiOneChoice(char *varName, struct cgiChoice *choices, int choiceSize)
00722
00723 {
00724 char *key = cgiString(varName);
00725 int i;
00726 int val = -1;
00727
00728 for (i=0; i<choiceSize; ++i)
00729 {
00730 if (sameWord(choices[i].name, key))
00731 {
00732 val = choices[i].value;
00733 return val;
00734 }
00735 }
00736 errAbort("Unknown key %s for variable %s\n", key, varName);
00737 return val;
00738 }
00739
00740 void cgiMakeSubmitButton()
00741
00742 {
00743 cgiMakeButton("Submit", "Submit");
00744 }
00745
00746 void cgiMakeResetButton()
00747
00748 {
00749 printf("<INPUT TYPE=RESET NAME=\"Reset\" VALUE=\" Reset \">");
00750 }
00751
00752 void cgiMakeClearButton(char *form, char *field)
00753
00754 {
00755 char javascript[1024];
00756
00757 safef(javascript, sizeof(javascript),
00758 "document.%s.%s.value = ''; document.%s.submit();", form, field, form);
00759 cgiMakeOnClickButton(javascript, " Clear ");
00760 }
00761
00762 void cgiMakeButtonWithMsg(char *name, char *value, char *msg)
00763
00764 {
00765 printf("<INPUT TYPE=SUBMIT NAME=\"%s\" VALUE=\"%s\" %s%s%s>",
00766 name, value,
00767 (msg ? " TITLE=\"" : ""), (msg ? msg : ""), (msg ? "\"" : "" ));
00768 }
00769
00770 void cgiMakeButton(char *name, char *value)
00771
00772 {
00773 cgiMakeButtonWithMsg(name, value, NULL);
00774 }
00775
00776 void cgiMakeOnClickButton(char *command, char *value)
00777
00778 {
00779 printf("<INPUT TYPE=\"button\" VALUE=\"%s\" onClick=\"%s\">", value, command);
00780 }
00781
00782 void cgiMakeOptionalButton(char *name, char *value, boolean disabled)
00783
00784 {
00785 printf("<INPUT TYPE=SUBMIT NAME=\"%s\" VALUE=\"%s\"", name, value);
00786 if (disabled)
00787 printf(" DISABLED");
00788 printf(">");
00789 }
00790
00791 void cgiMakeFileEntry(char *name)
00792
00793 {
00794 printf("<INPUT TYPE=FILE NAME=\"%s\">", name);
00795 }
00796
00797 void cgiSimpleTableStart()
00798
00799
00800 {
00801 printf("<TABLE>\n");
00802 }
00803
00804 void cgiTableEnd()
00805
00806 {
00807 printf("</TABLE>\n");
00808 }
00809
00810 void cgiSimpleTableRowStart()
00811
00812 {
00813 printf("<TR>\n");
00814 }
00815
00816 void cgiTableRowEnd()
00817
00818 {
00819 printf("</TR>\n");
00820 }
00821
00822 void cgiSimpleTableFieldStart()
00823
00824 {
00825 printf("<TD>");
00826 }
00827
00828 void cgiTableFieldEnd()
00829
00830 {
00831 printf("</TD>\n");
00832 }
00833
00834 void cgiTableField(char *text)
00835
00836 {
00837 printf("<TD> %s </TD>\n", text);
00838 }
00839
00840 void cgiTableFieldWithMsg(char *text, char *msg)
00841
00842 {
00843 printf("<TD %s%s%s> %s </TD>\n",
00844 (msg ? " TITLE=\"" : ""), (msg ? msg : ""), (msg ? "\"" : "" ),
00845 text);
00846 }
00847
00848 void cgiParagraph(char *text)
00849
00850 {
00851 printf("<P> %s\n", text);
00852 }
00853
00854 void cgiMakeRadioButton(char *name, char *value, boolean checked)
00855
00856
00857
00858 {
00859 printf("<INPUT TYPE=RADIO NAME=\"%s\" VALUE=\"%s\" %s>", name, value,
00860 (checked ? "CHECKED" : ""));
00861 }
00862
00863 void cgiMakeOnClickRadioButton(char *name, char *value, boolean checked,
00864 char *command)
00865
00866
00867
00868
00869 {
00870 printf("<INPUT TYPE=RADIO NAME=\"%s\" VALUE=\"%s\" %s %s>",
00871 name, value, command, (checked ? "CHECKED" : ""));
00872 }
00873
00874 char *cgiBooleanShadowPrefix()
00875
00876 {
00877 return "boolshad.";
00878 }
00879
00880 boolean cgiBooleanDefined(char *name)
00881
00882
00883 {
00884 char buf[256];
00885 safef(buf, sizeof(buf), "%s%s", cgiBooleanShadowPrefix(), name);
00886 return cgiVarExists(buf);
00887 }
00888
00889 void cgiMakeCheckBoxWithMsg(char *name, boolean checked, char *msg)
00890
00891
00892
00893 {
00894 char buf[256];
00895
00896 printf("<INPUT TYPE=CHECKBOX NAME=\"%s\" VALUE=on %s%s%s %s>", name,
00897 (msg ? " TITLE=\"" : ""), (msg ? msg : ""), (msg ? "\"" : "" ),
00898 (checked ? " CHECKED" : ""));
00899 safef(buf, sizeof(buf), "%s%s", cgiBooleanShadowPrefix(), name);
00900 cgiMakeHiddenVar(buf, "1");
00901 }
00902
00903 void cgiMakeCheckBox(char *name, boolean checked)
00904
00905 {
00906 cgiMakeCheckBoxWithMsg(name, checked, NULL);
00907 }
00908
00909 void cgiMakeHiddenBoolean(char *name, boolean on)
00910
00911
00912
00913 {
00914 char buf[256];
00915 cgiMakeHiddenVar(name, on ? "on" : "off");
00916 safef(buf, sizeof(buf), "%s%s", cgiBooleanShadowPrefix(), name);
00917 cgiMakeHiddenVar(buf, "1");
00918 }
00919
00920 void cgiMakeTextArea(char *varName, char *initialVal, int rowCount, int columnCount)
00921
00922 {
00923 cgiMakeTextAreaDisableable(varName, initialVal, rowCount, columnCount, FALSE);
00924 }
00925
00926 void cgiMakeTextAreaDisableable(char *varName, char *initialVal, int rowCount, int columnCount, boolean disabled)
00927
00928
00929 {
00930 printf("<TEXTAREA NAME=\"%s\" ROWS=%d COLS=%d %s>%s</TEXTAREA>", varName,
00931 rowCount, columnCount, disabled ? "DISABLED" : "",
00932 (initialVal != NULL ? initialVal : ""));
00933 }
00934
00935 void cgiMakeTextVar(char *varName, char *initialVal, int charSize)
00936
00937
00938 {
00939 if (initialVal == NULL)
00940 initialVal = "";
00941 if (charSize == 0) charSize = strlen(initialVal);
00942 if (charSize == 0) charSize = 8;
00943
00944 printf("<INPUT TYPE=TEXT NAME=\"%s\" SIZE=%d VALUE=\"%s\">", varName,
00945 charSize, initialVal);
00946 }
00947
00948 void cgiMakeIntVar(char *varName, int initialVal, int maxDigits)
00949
00950 {
00951 if (maxDigits == 0) maxDigits = 4;
00952
00953 printf("<INPUT TYPE=TEXT NAME=\"%s\" SIZE=%d VALUE=%d>", varName,
00954 maxDigits, initialVal);
00955 }
00956
00957 void cgiMakeDoubleVar(char *varName, double initialVal, int maxDigits)
00958
00959 {
00960 if (maxDigits == 0) maxDigits = 4;
00961
00962 printf("<INPUT TYPE=TEXT NAME=\"%s\" SIZE=%d VALUE=%g>", varName,
00963 maxDigits, initialVal);
00964 }
00965
00966
00967
00968 void cgiMakeDropList(char *name, char *menu[], int menuSize, char *checked)
00969
00970
00971 {
00972 cgiMakeDropListClass(name, menu, menuSize, checked, "normalText");
00973 }
00974
00975
00976 void cgiMakeDropListClass(char *name, char *menu[],
00977 int menuSize, char *checked, char *class)
00978
00979 {
00980 int i;
00981 char *selString;
00982 if (checked == NULL) checked = menu[0];
00983 printf("<SELECT NAME=\"%s\" class=%s>\n", name, class);
00984 for (i=0; i<menuSize; ++i)
00985 {
00986 if (sameWord(menu[i], checked))
00987 selString = " SELECTED";
00988 else
00989 selString = "";
00990 printf("<OPTION%s>%s</OPTION>\n", selString, menu[i]);
00991 }
00992 printf("</SELECT>\n");
00993 }
00994
00995 void cgiMakeMultList(char *name, char *menu[], int menuSize, char *checked, int length)
00996
00997
00998
00999 {
01000 int i;
01001 char *selString;
01002 if (checked == NULL) checked = menu[0];
01003 printf("<SELECT MULTIPLE SIZE=%d ALIGN=CENTER NAME=\"%s\">\n", length, name);
01004 for (i=0; i<menuSize; ++i)
01005 {
01006 if (sameWord(menu[i], checked))
01007 selString = " SELECTED";
01008 else
01009 selString = "";
01010 printf("<OPTION%s>%s</OPTION>\n", selString, menu[i]);
01011 }
01012 printf("</SELECT>\n");
01013 }
01014
01015 void cgiMakeDropListFull(char *name, char *menu[], char *values[],
01016 int menuSize, char *checked, char *extraAttribs)
01017
01018 {
01019 int i;
01020 char *selString;
01021 if (checked == NULL) checked = menu[0];
01022
01023 if (NULL != extraAttribs)
01024 {
01025 printf("<SELECT NAME=\"%s\" %s>\n", name, extraAttribs);
01026 }
01027 else
01028 {
01029 printf("<SELECT NAME=\"%s\">\n", name);
01030 }
01031
01032 for (i=0; i<menuSize; ++i)
01033 {
01034 if (sameWord(values[i], checked))
01035 selString = " SELECTED";
01036 else
01037 selString = "";
01038 printf("<OPTION%s VALUE=\"%s\">%s</OPTION>\n", selString, values[i], menu[i]);
01039 }
01040 printf("</SELECT>\n");
01041 }
01042
01043 void cgiMakeDropListWithVals(char *name, char *menu[], char *values[],
01044 int menuSize, char *checked)
01045
01046
01047 {
01048 int i;
01049 char *selString;
01050 if (checked == NULL) checked = values[0];
01051
01052 printf("<SELECT NAME=\"%s\">\n", name);
01053 for (i=0; i<menuSize; ++i)
01054 {
01055 if (sameWord(values[i], checked))
01056 selString = " SELECTED";
01057 else
01058 selString = "";
01059 printf("<OPTION%s VALUE=\"%s\">%s</OPTION>\n", selString, values[i], menu[i]);
01060 }
01061 printf("</SELECT>\n");
01062 }
01063
01064 void cgiMakeHiddenVar(char *varName, char *string)
01065
01066 {
01067 printf("<INPUT TYPE=HIDDEN NAME=\"%s\" VALUE=\"%s\">", varName, string);
01068 }
01069
01070 void cgiContinueHiddenVar(char *varName)
01071
01072 {
01073 if (cgiVarExists(varName))
01074 cgiMakeHiddenVar(varName, cgiString(varName));
01075 }
01076
01077 void cgiVarExclude(char *varName)
01078
01079 {
01080 if (cgiVarExists(varName))
01081 {
01082 struct cgiVar *cv = hashRemove(inputHash, varName);
01083 slRemoveEl(&inputList, cv);
01084 }
01085 }
01086
01087 void cgiVarExcludeExcept(char **varNames)
01088
01089
01090
01091 {
01092 struct hashEl *list, *el;
01093 struct hash *exclude = newHash(8);
01094 char *s;
01095
01096
01097 if (varNames != NULL)
01098 {
01099 while ((s = *varNames++) != NULL)
01100 hashAdd(exclude, s, NULL);
01101 }
01102
01103
01104
01105 initCgiInput();
01106 list = hashElListHash(inputHash);
01107 for (el = list; el != NULL; el = el->next)
01108 {
01109 if (!hashLookup(exclude, el->name))
01110 cgiVarExclude(el->name);
01111 }
01112 hashElFreeList(&list);
01113 freeHash(&exclude);
01114 }
01115
01116 void cgiVarSet(char *varName, char *val)
01117
01118 {
01119 struct cgiVar *var;
01120 initCgiInput();
01121 AllocVar(var);
01122 var->val = cloneString(val);
01123 hashAddSaveName(inputHash, varName, var, &var->name);
01124 }
01125
01126 struct dyString *cgiUrlString()
01127
01128 {
01129 struct dyString *dy = newDyString(0);
01130 struct cgiVar *cv;
01131 char *e;
01132
01133
01134 for (cv = inputList; cv != NULL; cv = cv->next)
01135 {
01136 if (cv != inputList)
01137 dyStringAppend(dy, "&");
01138 e = cgiEncode(cv->val);
01139 dyStringPrintf(dy, "%s=", cv->name);
01140 dyStringAppend(dy, e);
01141 freez(&e);
01142 }
01143 return dy;
01144 }
01145
01146 void cgiContinueAllVars()
01147
01148 {
01149 struct cgiVar *cv;
01150 for (cv = inputList; cv != NULL; cv = cv->next)
01151 cgiMakeHiddenVar(cv->name, cv->val);
01152 }
01153
01154
01155 boolean cgiFromCommandLine(int *pArgc, char *argv[], boolean preferWeb)
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168 {
01169 int argc = *pArgc;
01170 int i;
01171 int argcLeft = argc;
01172 char *name;
01173 static char queryString[4096];
01174 char *q = queryString;
01175 boolean needAnd = TRUE;
01176 boolean gotAny = FALSE;
01177 boolean startDash;
01178 boolean gotEq;
01179 static char hostLine[512];
01180
01181 if (preferWeb && cgiIsOnWeb())
01182 return TRUE;
01183 q += safef(q, queryString + sizeof(queryString) - q,
01184 "%s", "QUERY_STRING=cgiSpoof=on");
01185 for (i=0; i<argcLeft; )
01186 {
01187 name = argv[i];
01188 if ((startDash = (name[0] == '-')))
01189 ++name;
01190 gotEq = (strchr(name, '=') != NULL);
01191 if (gotEq || startDash)
01192 {
01193 if (needAnd)
01194 *q++ = '&';
01195 q += safef(q, queryString + sizeof(queryString) - q, "%s", name);
01196 if (!gotEq || strchr(name, '&') == NULL)
01197 needAnd = TRUE;
01198 if (!gotEq)
01199 q += safef(q, queryString + sizeof(queryString) - q, "=on");
01200 memcpy(&argv[i], &argv[i+1], sizeof(argv[i]) * (argcLeft-i-1));
01201 argcLeft -= 1;
01202 gotAny = TRUE;
01203 }
01204 else
01205 i++;
01206 }
01207 if (gotAny)
01208 {
01209 *pArgc = argcLeft;
01210 }
01211 putenv("REQUEST_METHOD=GET");
01212 putenv(queryString);
01213 safef(hostLine, sizeof(hostLine), "SERVER_NAME=%s", getenv("HOST"));
01214 putenv(hostLine);
01215 initCgiInput();
01216 return gotAny;
01217 }
01218
01219 boolean cgiSpoof(int *pArgc, char *argv[])
01220
01221
01222
01223 {
01224 return cgiFromCommandLine(pArgc, argv, TRUE);
01225 }
01226
01227 boolean cgiFromFile(char *fileName)
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238 {
01239 char **argv = NULL;
01240 int argc = 0;
01241 int maxArgc = 10;
01242 int i;
01243 struct lineFile *lf = lineFileOpen(fileName, TRUE);
01244 char *line;
01245 boolean spoof= FALSE;
01246 AllocArray(argv, maxArgc);
01247
01248
01249 argc = 1;
01250 argv[0] = cloneString(fileName);
01251 for(;;)
01252 {
01253
01254 if(!lineFileNext(lf, &line, NULL))
01255 break;
01256
01257 if (line[0] == '#' || sameString(line, ""))
01258 continue;
01259
01260 if((argc+1) >= maxArgc)
01261 {
01262 ExpandArray(argv, maxArgc, 2*maxArgc);
01263 maxArgc *= 2;
01264 }
01265
01266 argv[argc++] = cloneString(line);
01267 }
01268 spoof = cgiSpoof(&argc, argv);
01269
01270 lineFileClose(&lf);
01271 for(i=0; i<argc; i++)
01272 freez(&argv[i]);
01273 freez(&argv);
01274 return spoof;
01275 }