905b9cb05eeaca7f2dcda42fc6abdb95a2d2da7f
max
Wed Sep 9 05:29:28 2026 -0700
no captcha for a command-line CGI run, and version the detailsScript module URL
Two small fixes to things noticed while adding the scatterPlot plot type.
A CGI run from the command line got the Cloudflare Turnstile challenge page
instead of the output the caller asked for, which makes "./hgc db=hg38 g=x" -
the quickest way to see what a CGI emits - useless without a hand-made hg.conf.
There is no browser to solve a captcha in that situation. printCaptcha() now
returns early when cgiWasSpoofed(). That flag cannot be set from an HTTP
request: cgiFromCommandLine() returns early and leaves it FALSE whenever the
web server has set REQUEST_METHOD. Checked that a plain argument-style run is
now clean, that a run which fakes the web environment with QUERY_STRING still
gets the captcha, and that an HTTP request behaves exactly as the unmodified
binary does.
The detailsScript module was loaded from a hardcoded import('../js/hgc.X.js'),
bypassing webTimeStampedLinkToResource(), so it was the one script on the page
with no ?v=<mtime>. That is the mechanism that flushes a browser's cache when
the CGI version changes and that keeps a mirror from pairing an old static file
with new CGIs, and without it a cached module could be handed newer bedDetails
JSON than it was written for. Now built through the helper, which also fixes the
already-shipped histogram type. The helper errAborts on a missing file and the
plot type comes from a hub, so a plot type with no module installed falls back to
the plain path: a silent failed import as before, rather than one bad hub setting
taking down the whole details page.
refs #35415
diff --git src/hg/lib/cart.c src/hg/lib/cart.c
index 7a6035e03ac..e6a36af1074 100644
--- src/hg/lib/cart.c
+++ src/hg/lib/cart.c
@@ -1687,30 +1687,38 @@
return res;
}
// hg.conf key with the cloud flare secret key, used twice here, so a global macro
#define CLOUDFLARESITEKEY "cloudFlareSiteKey"
static char *getSessionId()
/* Get session id if any from CGI. */
{
return cgiOptionalString("hgsid");
}
void printCaptcha()
/* print an html page that shows the captcha and on success, reloads the page with the token added as token=x */
{
+ // A CGI run from the command line has no browser to solve a captcha, so the
+ // challenge page would just replace the output the caller asked for. Only a
+ // real command-line run reaches here with wasSpoofed set: cgiFromCommandLine()
+ // returns early, leaving it FALSE, whenever the web server has set
+ // REQUEST_METHOD, so this cannot be reached from an HTTP request.
+ if (cgiWasSpoofed())
+ return;
+
char *cfSiteKey = cfgVal(CLOUDFLARESITEKEY);
if (!cfSiteKey)
return;
if (cfgOptionBooleanDefault("captchaDebug", FALSE))
fprintf(stderr, "CAPTCHA_PRINT %s\n", getSessionId());
cspWriteResponseHeader();
puts("Content-Type:text/html\n"); // puts outputs one newline. Header requires two newlines.
puts("<html><head>");
printf("<script nonce='%s'>\n", getNonce());
printf("function showWidget() { \n"
"turnstile.render('#myWidget', {\n"
"sitekey: '%s',\n"
"theme: 'light',\n"
"callback: function (token) {\n"