1d95bea96bc2a652fe77b22c0639eaa888fe858f max Fri Oct 24 05:34:54 2025 -0700 adding CGI var logging option for hg.conf, refs #36533 diff --git src/lib/cheapcgi.c src/lib/cheapcgi.c index 1e0cccf6ba5..07788267d9e 100644 --- src/lib/cheapcgi.c +++ src/lib/cheapcgi.c @@ -1,29 +1,30 @@ /* Routines for getting variables passed in from web page * forms via CGI. * * This file is copyright 2002 Jim Kent, but license is hereby * granted for all use - public, private or commercial. */ #include "common.h" #include "hash.h" #include "cheapcgi.h" #include "portable.h" #include "linefile.h" #include "errAbort.h" #include "filePath.h" #include "htmshell.h" +#include "dystring.h" #ifndef GBROWSE #include "mime.h" #endif /* GBROWSE */ #include <signal.h> //============ javascript inline-separation routines =============== // One of the main services that CSP (Content Security Policy) provides // is protecting from reflected and stored XSS attacks by disabling all inline javacript, // both in script tags, and in inline event handlers. The separated javascript // can be either added back to the end of the html page with a nonce or sha hashid, // or it can be saved to a temp file in trash and then included as a non-inline, off-page .js. struct dyString *jsInlineLines = NULL; @@ -227,30 +228,33 @@ //============ END of javascript inline-separation routines =============== /* These three variables hold the parsed version of cgi variables. */ static char *inputString = NULL; static unsigned long inputSize; static struct hash *inputHash = NULL; static struct cgiVar *inputList = NULL; static boolean haveCookiesHash = FALSE; static struct hash *cookieHash = NULL; static struct cgiVar *cookieList = NULL; +// maximum length of CGI variables to dump to stderr, 0 = switch off +static int logCgiVarMaxLen = 0; + /* should cheapcgi use temp files to store uploaded files */ static boolean doUseTempFile = FALSE; void dumpCookieList() /* Print out the cookie list. */ { struct cgiVar *v; for (v=cookieList; v != NULL; v = v->next) printf("%s=%s (%d)\n", v->name, v->val, v->saved); } void useTempFile() /* tell cheapcgi to use temp files */ { doUseTempFile = TRUE; @@ -892,71 +896,95 @@ { end = val + strlen(val); *pInput = NULL; } else { *pInput = end+1; *end = 0; } *retVar = var; *retVal = val; cgiDecode(val,val,end-val); return TRUE; } +void cgiSetMaxLogLen(int l) +/* set the size of variable values that are dumped to stderr. Default is 0, which means no logging */ +{ +logCgiVarMaxLen = l; +} + void cgiParseInputAbort(char *input, struct hash **retHash, struct cgiVar **retList) /* Parse cgi-style input into a hash table and list. This will alter * the input data. The hash table will contain references back * into input, so please don't free input until you're done with * the hash. Prints message aborts if there's an error. * To clean up - slFreeList, hashFree, and only then free input. */ { char *namePt, *dataPt, *nextNamePt; struct hash *hash = *retHash; struct cgiVar *list = *retList, *el; if (!hash) hash = newHash(6); slReverse(&list); +struct dyString *logMsg = NULL; +if (logCgiVarMaxLen > 0) + logMsg = dyStringNew(1024); + namePt = input; while (namePt != NULL && namePt[0] != 0) { dataPt = strchr(namePt, '='); if (dataPt == NULL) { errAbort("Mangled CGI input string %s", namePt); } *dataPt++ = 0; nextNamePt = strchr(dataPt, '&'); if (nextNamePt == NULL) nextNamePt = strchr(dataPt, ';'); /* Accomodate DAS. */ if (nextNamePt != NULL) *nextNamePt++ = 0; + + if (logMsg && dataPt && strlen(dataPt) < logCgiVarMaxLen) + dyStringPrintf(logMsg, "%s=%s ", namePt, dataPt); // if dataPt is empty string, still print it, could be important + cgiDecode(namePt,namePt,strlen(namePt)); /* for unusual ct names */ cgiDecode(dataPt,dataPt,strlen(dataPt)); AllocVar(el); el->val = dataPt; slAddHead(&list, el); hashAddSaveName(hash, namePt, el, &el->name); namePt = nextNamePt; + + } + +if (logMsg) + { + char *logStr = dyStringCannibalize(&logMsg); + fprintf(stderr, "CGIVARS %s\n", logStr); + freez(&logStr); } + slReverse(&list); *retList = list; *retHash = hash; + } static jmp_buf cgiParseRecover; static void cgiParseAbort() /* Abort cgi parsing. */ { longjmp(cgiParseRecover, -1); } boolean cgiParseInput(char *input, struct hash **retHash, struct cgiVar **retList) /* Parse cgi-style input into a hash table and list. This will alter * the input data. The hash table will contain references back * into input, so please don't free input until you're done with