52cee2eff9e953d4584a415b8a9b84bd2326d3cd
braney
  Tue Aug 18 11:14:37 2026 -0700
hgTables: encode track menu and schema text consistently, refs #38123

diff --git src/hg/hgTables/hgTables.c src/hg/hgTables/hgTables.c
index 6d06af47db7..bda35aa64a4 100644
--- src/hg/hgTables/hgTables.c
+++ src/hg/hgTables/hgTables.c
@@ -110,30 +110,42 @@
     while (c == '<' && c != 0)
 	{
 	s = strchr(s,'>');
 	if (s != NULL)
 	    {
 	    if (*s == '>') ++s; /* skip closing bracket > */
 	    c = *s++;		/* next char after the closing bracket > */
 	    }
 	else
 	    c = 0;	/* no closing bracket > found, end of string */
 	}
     *e++ = c;	/*	copies all text outside tags, including ending NULL */
     }
 }
 
+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 autoSql schema and data file are written by a stranger, so text from them has to be
+ * escaped before it goes in the page.  Our own tracks are a different case: some of them
+ * put real HTML in a field or a schema comment on purpose, and escaping that would print the
+ * markup instead of rendering it. */
+{
+if (text != NULL && tdb != NULL && isHubTrack(tdb->track))
+    return htmlEncode(text);
+return text;
+}
+
 void writeHtmlCell(char *text)
 /* Write out a cell in an HTML table, making text not too big,
  * and stripping html tags and breaking spaces.... */
 {
 int maxLen = 128;
 int len = strlen(text);
 char *extra = "";
 if (len > maxLen)
     {
     len = maxLen;
     extra = "&nbsp;...";
     }
 char *s = cloneStringZ(text,len);
 char *r;
 stripHtmlTags(s);