9ad04e0a0b06ec3c4f09ef1b6c3ce6be79b61c68
braney
  Sun Aug 16 11:56:56 2026 -0700
cart: validate file names read back out of the cart

Several cart variables hold the name of a file the server created for a user.
Route them through one shared check, isServerUserFilePath(), which accepts the
trash directory, the session-data directories and myVariantsDataDir, and apply
it both where values enter the cart and where the file names are used.

A few of these variables may instead hold a remote URL.  Those get their own
list and isServerUserFileOrUrl(), because the code that reads them chooses
between a fetch and a local open by looking for a protocol.

Consolidates two hand-rolled copies of the same test in blatShare.c and
customFactory.c, and drops the weaker private copy in sessionData.c.

Adds hg/utils/cartFileVarCatalog, a registry that scans the tree for a cart
value reaching a file call and reconciles what it finds against the lists in
cart.c, so a new one of these cannot be added without somebody noticing.  Its
--reconcile is quiet enough for the nightly cron the other catalogs use, and it
is what turned up seven of the names now on those lists.

refs #37623

diff --git src/hg/lib/customFactory.c src/hg/lib/customFactory.c
index 58dfe192696..a98d4584811 100644
--- src/hg/lib/customFactory.c
+++ src/hg/lib/customFactory.c
@@ -164,35 +164,31 @@
 return same;
 }
 
 boolean isValidBigDataUrl(char *url, boolean doAbort, char *db, boolean allowLocals)
 /* return True if the URL is a valid bigDataUrl.
  * It can be a local filename if this is allowed by udc.localDir
  * or is localFile for curated genomes /gbdb/$db
  */
 {
 if ((startsWith("http://", url)
    || startsWith("https://", url)
    || startsWith("ftp://", url)))
     return TRUE;
 
 // we allow bigDataUrl's to point to trash (or sessionDataDir, if configured)
-char *sessionDataDir = cfgOption("sessionDataDir");
-char *sessionDataDirOld = cfgOption("sessionDataDirOld");
-if (startsWith(trashDir(), url) ||
-    (isNotEmpty(sessionDataDir) && startsWith(sessionDataDir, url)) ||
-    (isNotEmpty(sessionDataDirOld) && startsWith(sessionDataDirOld, url)))
+if (isTrashOrSessionDataPath(url))
     return TRUE;
 
 if (udcIsResolvable(url))
     return TRUE;
 
 if (allowLocals)
     {
     if (startsWith("/gbdb/genark/", url))
 	{
 	char gbdbSection[256];
 	safef(gbdbSection, sizeof gbdbSection, "/%s/", trackHubSkipHubName(db));
 	if (strstr(url, gbdbSection))
 	    return TRUE;
 	}
     char gbdbPrefix[256];