aca9143822a9c12b16b33d479a5abb6495b6b4f0
braney
  Wed Aug 19 06:59:39 2026 -0700
lib, hgc, hgTables, hgHubConnect: share hubEncode, refs #38123

hgc.c and hgTables.c each had their own copy of hubEncode().  The two
bodies were identical, so move the function to hubConnect.c next to
isHubTrack() and let both CGIs call the one definition.

Also use cgiEncode() rather than htmlEncode() for the db= value in the
hgHubConnect assembly list.  That value goes in a query string, so
cgiEncode() is the right function there.  Genome names are already
limited to a safe character set, so this changes no output today.

diff --git src/hg/lib/hubConnect.c src/hg/lib/hubConnect.c
index 567bf75da9f..844cb2ee82c 100644
--- src/hg/lib/hubConnect.c
+++ src/hg/lib/hubConnect.c
@@ -15,53 +15,67 @@
 #include "jksql.h"
 #include "hdb.h"
 #include "net.h"
 #include "trackHub.h"
 #include "hubConnect.h"
 #include "hui.h"
 #include "errCatch.h"
 #include "obscure.h"
 #include "hgConfig.h"
 #include "grp.h"
 #include "udc.h"
 #include "hubPublic.h"
 #include "genark.h"
 #include "asmAlias.h"
 #include "cheapcgi.h"
+#include "htmshell.h"
 #include "quickLift.h"
 
 boolean hubsCanAddGroups()
 /* can track hubs have their own groups? */
 {
 static boolean canHubs = FALSE;
 static boolean canHubsSet = FALSE;
 
 if (!canHubsSet)
     {
     canHubs = cfgOptionBooleanDefault("trackHubsCanAddGroups", TRUE);
     canHubsSet = TRUE;
     }
 
 return canHubs;
 }
 
 boolean isHubTrack(char *trackName)
 /* Return TRUE if it's a hub track. */
 {
 return startsWith(hubTrackPrefix, trackName);
 }
 
+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 <BR> 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;
+}
+
 static char *hubStatusTableName = NULL;
 static char *_hubPublicTableName = NULL;
 
 static char *getHubStatusTableName()
 /* return the hubStatus table name from the environment, 
  * or hg.conf, or use the default.  Cache the result */
 {
 if (hubStatusTableName == NULL)
     hubStatusTableName = cfgOptionEnvDefault("HGDB_HUB_STATUS_TABLE",
 	    hubStatusTableConfVariable, defaultHubStatusTableName);
 
 return hubStatusTableName;
 }
 
 char *hubPublicTableName()