f880f8b822d19c049867d38998c93a03566ba13f hiram Wed Aug 12 13:26:46 2026 -0700 fixing up errors found in code review refs #37946 diff --git src/hg/hubApi/apiUtils.c src/hg/hubApi/apiUtils.c index 9ddde8a37df..9896faba317 100644 --- src/hg/hubApi/apiUtils.c +++ src/hg/hubApi/apiUtils.c @@ -692,42 +692,66 @@ * When NO trackDb, can't tell at this point, will check that later */ { if (tdb) { if (tdbIsContainer(tdb) || tdbIsComposite(tdb) || tdbIsCompositeView(tdb) || tdbIsSuper(tdb)) return FALSE; else return TRUE; } else return TRUE; /* might be true */ } +static struct hash *dbExistsCache = NULL; /* memoize sqlDatabaseExists() below, + * protectedTrack() is called once per track in a listing */ + boolean protectedTrack(char *db, struct trackDb *tdb, char *tableName) /* determine if track is off-limits protected data */ { -// if the table is from hub, assume db should be from hub as well +// A hub track's table name always carries the hub_<id>_ prefix, but db only +// needs that same prefix reconstructed when db itself is an assembly hub +// genome (accessControlInit()/trackHubDatabase() look it up by its decorated +// name). When db is a real, existing database -- as it is for a hub track +// that merely overlays an existing genome, e.g. a hub track on hg19 -- db +// must be left alone, or accessControlInit()'s hAllocConn() aborts with +// "Unknown database". if (isHubTrack(tableName)) + { + if (dbExistsCache == NULL) + dbExistsCache = hashNew(0); + struct hashEl *hel = hashLookup(dbExistsCache, db); + boolean isRealDb; + if (hel == NULL) + { + isRealDb = sqlDatabaseExists(db); + hashAdd(dbExistsCache, db, isRealDb ? intToPt(1) : intToPt(0)); + } + else + isRealDb = ptToInt(hel->val); + + if (! isRealDb) { char buffer[4096]; safef(buffer, sizeof buffer, "hub_%d_%s",hubIdFromTrackName(tableName), db); db = cloneString(buffer); } + } return cartTrackDbIsAccessDenied(db, tableName) || cartTrackDbIsNoGenome(db, tableName); } boolean isWiggleDataTable(char *type) /* is this a wiggle data track table */ { if (startsWith("wig", type)) { if (startsWith("wigMaf", type)) return FALSE; else return TRUE; } else @@ -840,31 +864,31 @@ init = TRUE; } return host; } boolean inUcscEduDomain() /* Return TRUE if this machine is configured as belonging to the ucsc.edu * domain, per hg.conf's central.domain setting (the same setting used for * the cross-host login cookie domain). This is deployment config rather * than something derived from the machine's own OS hostname/DNS: a box's * local/cloud-assigned hostname and its UCSC-facing name (e.g. * genome-euro.ucsc.edu) can be unrelated DNS labels with no way to bridge * them via gethostname()/getaddrinfo(). */ { char *domain = cfgOption(CFG_CENTRAL_DOMAIN); -return (domain != NULL && strstr(domain, ".ucsc.edu") != NULL); +return (domain != NULL && endsWith(domain, ".ucsc.edu")); } boolean onGenomeRRMachine() /* Return TRUE if running on one of the genome.ucsc.edu round-robin * machines (hgw0, hgw1, hgw2, ...), which carry SQL grants on * hgcentral.gbMembers. Only meaningful within inUcscEduDomain(). */ { if (hIsPrivateHost()) // stay on localhost for hgwdev and hgwbeta return TRUE; char *hostName = thisHostName(); if (isEmpty(hostName)) return FALSE; if (startsWith("hgwbeta", hostName)) return TRUE; if (!startsWith("hgw", hostName)) @@ -986,36 +1010,44 @@ if (sd < 0) { dyStringFree(&url); return "error"; } char *redirectedUrl = NULL; if (!netSkipHttpHeaderLinesWithRedirect(sd, dyStringContents(url), &redirectedUrl)) { close(sd); dyStringFree(&url); return "error"; } dyStringFree(&url); struct dyString *body = netSlurpFile(sd); close(sd); + +char *status = "error"; +struct errCatch *errCatch = errCatchNew(); +if (errCatchStart(errCatch)) + { struct jsonElement *json = jsonParse(body->string); + char *statusField = jsonStringField(json, "status"); + if (isNotEmpty(statusField)) + status = cloneString(statusField); + } +errCatchEnd(errCatch); +errCatchFree(&errCatch); dyStringFree(&body); -if (json == NULL) - return "error"; -char *status = jsonStringField(json, "status"); -return isNotEmpty(status) ? cloneString(status) : "error"; +return status; } void apiSubmitOttoRequest(char *words[MAX_PATH_INFO]) /* Internal server-to-server endpoint: record a row in the ottoRequest table * on behalf of a hubApi host that lacks its own hgcentral write grants (see * relaySubmitOttoRequest()). Requires the shared hg.conf secret * 'hubApi.relaySecret' to match, since this performs the actual database * write without the bot-challenge cookie check that /liftRequest and * /assemblyRequest do locally -- that check already ran on the relaying * host before it got here. Always answers 200 + a JSON "status" field; * never apiErrAbort()s for a duplicate/rateLimited outcome, so the relay * caller can distinguish it from a hard failure. */ { char *secret = cfgOption("hubApi.relaySecret"); char *givenSecret = getenv("HTTP_X_RELAY_SECRET");