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/hgc/bigBedClick.c src/hg/hgc/bigBedClick.c
index fdac6c12423..0eb19d930e3 100644
--- src/hg/hgc/bigBedClick.c
+++ src/hg/hgc/bigBedClick.c
@@ -716,35 +716,58 @@
jsonWriteObjectEnd(jw);
}
}
jsonWriteObjectEnd(jw);
}
jsonWriteListEnd(jw);
}
jsonWriteObjectEnd(jw); // scripts
jsonWriteObjectEnd(jw); // root
// Emit as inline JavaScript
struct dyString *ds = dyStringNew(1024);
dyStringPrintf(ds, "var bedDetails = %s;\n", jw->dy->string);
- // Dynamically import and call each plot type's module
+ // Dynamically import and call each plot type's module. The URL carries
+ // ?v=<mtime>, as every other js file does, so that a browser cannot serve a
+ // cached module against newer bedDetails JSON and a mirror cannot pair an old
+ // module with new CGIs. webTimeStampedLinkToResource() errAborts on a missing
+ // file and plotType comes from a hub, so a plotType with no module installed
+ // falls back to the plain path: that leaves a silent failed import as before,
+ // rather than taking the whole details page down over one bad hub setting.
for (hel = helList; hel != NULL; hel = hel->next)
+ {
+ char modFile[PATH_LEN];
+ safef(modFile, sizeof modFile, "hgc.%s.js", hel->name);
+ char fallBack[PATH_LEN];
+ safef(fallBack, sizeof fallBack, "../js/%s", modFile);
+ char *modUrl = fallBack;
+ char *docRoot = hDocumentRoot();
+ if (docRoot != NULL)
+ {
+ char onDisk[PATH_LEN];
+ safef(onDisk, sizeof onDisk, "%s/js/%s", docRoot, modFile);
+ if (fileExists(onDisk))
+ modUrl = webTimeStampedLinkToResource(modFile, FALSE);
+ }
dyStringPrintf(ds, "$(document).ready(function() {\n"
- " import('../js/hgc.%s.js').then(function(mod) { mod.%s(bedDetails); });\n"
- "});\n", hel->name, hel->name);
+ " import('%s').then(function(mod) { mod.%s(bedDetails); });\n"
+ "});\n", modUrl, hel->name);
+ if (modUrl != fallBack)
+ freeMem(modUrl);
+ }
jsInline(dyStringCannibalize(&ds));
jsonWriteFree(&jw);
hashElFreeList(&helList);
hashFree(&plotTypeHash);
}
}
if (!found)
{
printf("No item %s starting at %d\n", emptyForNull(item), start);
}
lmCleanup(&lm);
bbiFileClose(&bbi);
}