03550a41a3b40299ba1405770fdf548dd48a63a7 braney Mon Apr 13 15:51:11 2026 -0700 Deduplicate and htmlEncode alias list in printAliases() refs #29201 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c index 10f38be4c45..e383b57baf8 100644 --- src/hg/hgTracks/hgTracks.c +++ src/hg/hgTracks/hgTracks.c @@ -8837,52 +8837,57 @@ puts(" <button id='hgtIgv' type='button' " "title='Add an IGV.js window below the UCSC Browser, to open files from " "your local harddisk or server' >Add IGV Tracks</button>"); //jsInline("document.getElementById('hgtIgv').addEventListener('click', onIgvClick);"); } } static void printAliases(char *nativeName, char *displayName) /* Print out the alternative names for this sequence next to the position. */ { struct slName *aliases = chromAliasFindAliases(nativeName); if (aliases == NULL) return; +slSort(&aliases, slNameCmp); +slUniqify(&aliases, slNameCmp, slNameFree); + // Build comma-separated list of aliases, skipping the display name and native name struct dyString *dy = dyStringNew(256); struct slName *a; for (a = aliases; a != NULL; a = a->next) { if (isEmpty(a->name)) continue; if (sameString(a->name, displayName) || sameString(a->name, nativeName)) continue; if (dy->stringSize > 0) dyStringAppend(dy, ", "); dyStringAppend(dy, a->name); } if (dy->stringSize == 0) { dyStringFree(&dy); return; } +char *encoded = htmlEncode(dy->string); printf("<span id='chromAliases' title='Also known as: %s'>" - "<a>ⓘ Aliases</a></span>", dy->string); + "<a>ⓘ Aliases</a></span>", encoded); +freeMem(encoded); dyStringFree(&dy); } unsigned getParaLoadTimeout() // get the parallel load timeout in seconds (defaults to 90) { char *paraLoadTimeoutStr = cartOptionalString(cart, "parallelFetch.timeout"); if (paraLoadTimeoutStr == NULL) paraLoadTimeoutStr = cfgOptionDefault("parallelFetch.timeout", "90"); // wait up to default 90 seconds. unsigned paraLoadTimeout = sqlUnsigned(paraLoadTimeoutStr); return paraLoadTimeout; }