e4c2e97b5eb35b8f9b7b71eb13a4c24e6c1ece22 max Mon Sep 14 09:19:02 2026 -0700 hui, hgTrackUi: encode trackDb setting and cart text in HTML attributes, refs #38123 diff --git src/hg/lib/hui.c src/hg/lib/hui.c index 33024787b93..593ca22fca2 100644 --- src/hg/lib/hui.c +++ src/hg/lib/hui.c @@ -544,31 +544,32 @@ static void printDownloadUrl(char *downloadUrl, char *database, char *track) /* given a string <label><space><url>, print a nice download link */ { char *parts[2]; int partCount = chopByWhiteRespectDoubleQuotes(downloadUrl, parts, 2); if (partCount!=2) { puts("<b>Internal Error:</b> The downloadUrl trackDb statement needs exactly two arguments, the file type and the URL."); return; } char* fileType = parts[0]; stripString(fileType, "\""); // Remove double quotes, weird that chopByWhiteRespectDoubleQuotes doesn't do this char* url = parts[1]; char *newUrl = replaceInUrl(url, "", NULL, database, "", 0, 0, track, FALSE, NULL); -printf("<br>Download: <a href=\"%s\">%s</a>", newUrl, fileType); +// downloadUrl may be hub supplied +printf("<br>Download: <a href=\"%s\">%s</a>", htmlEncode(newUrl), htmlEncode(fileType)); } static void makeFileDownloads(struct trackDb *tdb, char *db) /* given either downloadUrl or downloadUrl.1/.2/... in trackDb, print links to these files. * File can be anywhere on the internet, useful e.g. for GTF files for gene tracks */ { char *downloadUrl = trackDbSetting(tdb, "downloadUrl"); struct slName* tdbNames = trackDbSettingsWildMatch(tdb, "downloadUrl.*"); if (downloadUrl) printDownloadUrl(downloadUrl, db, tdb->track); while (tdbNames != NULL) { struct slName *tdbName = slPopHead(&tdbNames); printDownloadUrl(trackDbSetting(tdb, tdbName->name), db, tdb->track); @@ -4349,43 +4350,43 @@ if (filterBy->useIndex) { safef(varName, sizeof(varName), "%d",ix); name = varName; label = slValue->name; } else { label = (filterBy->valueAndLabel? slValue->name + strlen(slValue->name)+1: slValue->name); name = slValue->name; } printf("<OPTION"); if (filterBy->slChoices != NULL && slNameInList(filterBy->slChoices,name)) printf(" SELECTED"); if (filterBy->useIndex || filterBy->valueAndLabel) - printf(" value='%s'",name); + printf(" value='%s'",htmlEncode(name)); // filterValues are hub supplied if (filterBy->styleFollows) { char *styler = label + strlen(label)+1; if (*styler != '\0') { if (*styler == '#') // Legacy: just the color that follows - printf(" style='color: %s;'",styler); + printf(" style='color: %s;'",htmlEncode(styler)); else - printf(" style='%s'",styler); + printf(" style='%s'",htmlEncode(styler)); } } -printf(">%s</OPTION>\n",label); +printf(">%s</OPTION>\n",htmlEncode(label)); // filterValues are hub supplied } static boolean filterByColumnIsMultiple(struct cart *cart, struct trackDb *tdb, char *setting) /* Is this filter setting expecting multiple items (e.g. has checkboxes in the UI) */ { return (sameString(setting, FILTERBY_MULTIPLE) || sameString(setting, FILTERBY_MULTIPLE_LIST_OR) || sameString(setting, FILTERBY_MULTIPLE_LIST_ONLY_OR) || sameString(setting, FILTERBY_MULTIPLE_LIST_ONLY_AND) || sameString(setting, FILTERBY_MULTIPLE_LIST_AND)); } static boolean advancedFilter(struct cart *cart, struct trackDb *tdb, char *setting) { if (!tdbIsBigBed(tdb)) @@ -4523,33 +4524,33 @@ label = (filterBy->valueAndLabel ? slValue->name + strlen(slValue->name)+1 : slValue->name); name = slValue->name; } printf("<OPTION"); if (filterBy->slChoices != NULL && slNameInList(filterBy->slChoices,name)) printf(" SELECTED"); if (filterBy->useIndex || filterBy->valueAndLabel) printf(" value='%s'",htmlEncode(name)); // filterValues are hub supplied if (filterBy->styleFollows) { char *styler = label + strlen(label)+1; if (*styler != '\0') { if (*styler == '#') // Legacy: just the color that follows - printf(" style='color: %s;'",styler); + printf(" style='color: %s;'",htmlEncode(styler)); else - printf(" style='%s'",styler); + printf(" style='%s'",htmlEncode(styler)); } } printf(">%s</OPTION>\n",htmlEncode(label)); // filterValues are hub supplied } printf("</SELECT>\n"); puts("</td>"); } puts("</TR></TABLE>"); } void filterBySetCfgUi(struct cart *cart, struct trackDb *tdb, filterBy_t *filterBySet, boolean onOneLine, char *prefix) /* Does the filter UI for a list of filterBy structure */ { @@ -8539,31 +8540,32 @@ safef(option, sizeof(option), "%s.%s", name, BASE_COLORS_VAR); puts(" Alternate colors every"); cgiMakeIntVar(option, cartCgiUsualInt(cart, option, 0), 1); puts("bases<BR>"); safef(option, sizeof(option), "%s.%s", name, BASE_COLORS_OFFSET_VAR); puts(" Offset alternate colors by"); cgiMakeIntVar(option, cartCgiUsualInt(cart, option, 0), 1); puts("bases<BR>"); #endif } } treeImage = trackDbSetting(tdb, "treeImage"); if (treeImage) - printf("</TD><TD VALIGN=\"TOP\"><IMG SRC=\"../images/%s\"></TD></TR></TABLE>", treeImage); + printf("</TD><TD VALIGN=\"TOP\"><IMG SRC=\"../images/%s\"></TD></TR></TABLE>", + htmlEncode(treeImage)); // treeImage may be hub supplied else puts("</TD></TR></TABLE>"); if (trackDbSetting(tdb, CONS_WIGGLE) != NULL) { wigCfgUi(cart,tdb,name,"Conservation graph:",FALSE); } cfgEndBox(boxed); } static char *grayLabels[] = { "alignment quality", "base qualities", "unpaired ends", }; @@ -9626,31 +9628,32 @@ } } } if (dimensionX && cntX>MATRIX_RIGHT_BUTTONS_AFTER) matrixYheadings(db,parentTdb, membersForAll,ixY,FALSE); puts("</TR>\n"); } } if (dimensionY && cntY>MATRIX_BOTTOM_BUTTONS_AFTER) matrixXheadings(db,parentTdb,membersForAll,FALSE); puts("</TABLE>"); // if there is a treeImage, put it beside the matrix if (treeImage != NULL) - printf("</TD><TD><IMG SRC=\"%s\"></TD></TABLE>", treeImage); + printf("</TD><TD><IMG SRC=\"%s\"></TD></TABLE>", + htmlEncode(treeImage)); // treeImage may be hub supplied // If any filter additional filter composites, they can be added at the end. compositeUiByFilter(db, cart, parentTdb, formName); fastMatixToSubtrackMap(); return TRUE; } static boolean compositeUiAllButtons(char *db, struct cart *cart, struct trackDb *parentTdb, char *formName) // UI for composite tracks: all/none buttons only (as opposed to matrix or lots of buttons { if (trackDbCountDescendantLeaves(parentTdb) <= 1) return FALSE; @@ -10275,31 +10278,32 @@ src = htmlEncode(buffer); } if (setting) { url = nextWord(&setting); if (setting) { hint = htmlEncode(stripEnclosingDoubleQuotes(setting)); } } struct dyString *ds = dyStringNew(0); // generate markup if (url) - dyStringPrintf(ds, "<a class='pennantIconText' href='%s' target='ucscHelp' ", url); + dyStringPrintf(ds, "<a class='pennantIconText' href='%s' target='ucscHelp' ", + htmlEncode(url)); // pennantIcon may be hub supplied else if (isTextIcon) dyStringAppend(ds, "<span class='pennantIconText' "); if (isTextIcon) dyStringPrintf(ds, "style='color: %s;' ", color); if (hint) dyStringPrintf(ds, "title='%s' ", hint); if (url || isTextIcon) dyStringAppend(ds, ">"); // add text or image if (isTextIcon) dyStringPrintf(ds, "%s", src); else dyStringPrintf(ds, "<img height='16' width='16' src='%s'>", src);