f2d3014a3cc95116346eab4675817cf0c65f6d62
braney
Tue Aug 18 11:12:35 2026 -0700
hgc: encode item detail text consistently, refs #38123
diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c
index bb86647bed5..4222db1b9c7 100644
--- src/hg/hgc/hgc.c
+++ src/hg/hgc/hgc.c
@@ -296,30 +296,43 @@
char mousedb[] = "mm3";
#define NUMTRACKS 9
int prevColor[NUMTRACKS]; /* used to optimize color change html commands */
int currentColor[NUMTRACKS]; /* used to optimize color change html commands */
int maxShade = 9; /* Highest shade in a color gradient. */
Color shadesOfGray[10+1]; /* 10 shades of gray from white to black */
Color shadesOfRed[16];
boolean exprBedColorsMade = FALSE; /* Have the shades of red been made? */
int maxRGBShade = 16;
struct bed *sageExpList = NULL;
char ncbiOmimUrl[255] = {"https://www.ncbi.nlm.nih.gov/omim/"};
+char *hubEncode(struct trackDb *tdb, char *text)
+/* Return text escaped for HTML if it belongs to a track hub, otherwise return it unchanged.
+ * A hub's trackDb, autoSql schema and data file are all written by a stranger, so anything
+ * from them has to be escaped before it goes in the page. Our own tracks are a
+ * different case: they put real HTML in fields on purpose - ClinVar's review-status stars,
+ * the CRISPR track's links in an extra column, the
in the Denisova schema comments -
+ * and escaping those would print the markup instead of rendering it. */
+{
+if (text != NULL && tdb != NULL && isHubTrack(tdb->track))
+ return htmlEncode(text);
+return text;
+}
+
struct palInfo
{
char *chrom;
int left;
int right;
char *rnaName;
};
/* See this NCBI web doc for more info about entrezFormat:
* https://www.ncbi.nlm.nih.gov/entrez/query/static/linking.html */
char *entrezFormat = "https://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Search&db=%s&term=%s&doptcmdl=%s&tool=genome.ucsc.edu";
char *entrezPureSearchFormat = "https://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=PureSearch&db=%s&details_term=%s[%s] ";
char *ncbiGeneFormat = "https://www.ncbi.nlm.nih.gov/gene/%s";
char *entrezUidFormat = "https://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=%s&list_uids=%d&dopt=%s&tool=genome.ucsc.edu";
@@ -819,38 +832,39 @@
// its bed-compatible leading fields (only the first bedSize fields are read).
// At -O3 GCC's -Warray-bounds flags those casts because the real object is
// smaller than struct bed; the accesses are safe by the bed-layout convention.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
void bedPrintPos(struct bed *bed, int bedSize, struct trackDb *tdb)
/* Print first bedSize fields of a bed type structure in
* standard format. */
{
char *strand = NULL;
if (bedSize >= 4 && bed->name[0] != 0)
{
char *label = "Item", *tdbLabel = NULL;
if (tdb && ((tdbLabel = trackDbSetting(tdb, "bedNameLabel")) != NULL))
label = tdbLabel;
- printf("%s: %s
\n", label, bed->name);
+ // bedNameLabel is a trackDb setting and the name comes from the data file
+ printf("%s: %s
\n", hubEncode(tdb, label), hubEncode(tdb, bed->name));
}
if (bedSize >= 5)
{
if (!tdb || !trackDbSetting(tdb, "noScoreFilter"))
{
char *scoreLabel = trackDbSettingOrDefault(tdb, "scoreLabel", "Score");
- printf("%s: %d
\n", scoreLabel, bed->score);
+ printf("%s: %d
\n", hubEncode(tdb, scoreLabel), bed->score);
}
}
if (bedSize >= 6)
{
strand = bed->strand;
}
printPos(bed->chrom, bed->chromStart, bed->chromEnd, strand, TRUE, bed->name);
}
#pragma GCC diagnostic pop
void genericHeader(struct trackDb *tdb, char *item)
/* Put up generic track info. */
{
if (item != NULL && item[0] != 0)
@@ -987,50 +1001,53 @@
char *eUrl = replaceInUrl(url, itemName, cart, database, seqName, winStart, winEnd, tdb->track,
encode, fields);
if (eUrl==NULL)
return;
/* create the url label setting for trackDb from the url
setting prefix */
safef(urlLabelSetting, sizeof(urlLabelSetting), "%sLabel", urlSetting);
char *linkLabel = trackDbSettingOrDefault(tdb, urlLabelSetting, "Outside Link:");
char *eLinkLabel = replaceInUrl(linkLabel, itemName, cart, database, seqName, winStart, winEnd, tdb->track,
encode, fields);
// if we got no item name from hgTracks or the item name does not appear in the URL
// there is no need to show the item name at all
+// the url and its label come from trackDb and the item name from the data file, both of
+// which a track hub supplies, so escape them
if (isEmpty(itemName) || !stringIn("$$", url))
{
- printf("%s
",eUrl, eLinkLabel);
+ printf("%s
",hubEncode(tdb, eUrl),
+ hubEncode(tdb, eLinkLabel));
return;
}
-printf("%s ",eLinkLabel);
+printf("%s ",hubEncode(tdb, eLinkLabel));
-printf("", eUrl);
+printf("", hubEncode(tdb, eUrl));
if (sameWord(tdb->table, "npredGene"))
{
printf("%s (%s)
\n", itemName, "NCBI MapView");
}
else
{
char *label = itemName;
if (isNotEmpty(itemLabel) && differentString(itemName, itemLabel))
label = itemLabel;
- printf("%s
\n", label);
+ printf("%s
\n", hubEncode(tdb, label));
}
//freeMem(&eUrl); small memory leak
}
void printCustomUrlWithFields(struct trackDb *tdb, char *itemName, char *itemLabel, boolean encode, struct slPair *fields)
/* Wrapper to call printCustomUrlWithLabel with additional fields to substitute */
{
char urlSetting[10];
safef(urlSetting, sizeof(urlSetting), "url");
printCustomUrlWithLabel(tdb, itemName, itemLabel, urlSetting, encode, fields);
}
void printCustomUrl(struct trackDb *tdb, char *itemName, boolean encode)
/* Wrapper to call printCustomUrlWithLabel using the url setting in trackDb */
@@ -1460,31 +1477,31 @@
return idNames;
}
void printIdOrLinks(struct asColumn *col, struct hash *fieldToUrl, struct trackDb *tdb, char *idList)
/* if trackDb does not contain a "urls" entry for current column name, just print idList as it is.
* Otherwise treat idList as a comma-sep list of IDs and print one row per id, with a link to url,
* ($$ in url is OK, wildcards like $P, $p, are also OK)
* */
{
// try to find a fieldName=url setting in the "urls" tdb statement, print id if not found
char *url = NULL;
if (fieldToUrl != NULL)
url = (char*)hashFindVal(fieldToUrl, col->name);
if (url == NULL)
{
- printf("
\n
| \n"); else if (col->isList || col->isArray || col->lowType->stringy || asTypesIsInt(col->lowType->type)) printIdOrLinks(col, fieldToUrl, tdb, fields[ix]); else if (asTypesIsFloating(col->lowType->type)) { double valDouble = strtod(fields[ix],NULL); if (errno == 0 && valDouble != 0) printf(" | %g | \n", valDouble); else - printf("%s | \n", fields[ix]); // decided not to print error + printf("%s | \n", hubEncode(tdb, fields[ix])); // decided not to print error } else - printf("%s | \n", fields[ix]); + printf("%s | \n", hubEncode(tdb, fields[ix])); printCount++; } if (skipIds) slFreeList(skipIds); if (sepFields) slFreeList(sepFields); if (embeddedTblFields) { printf("