a53b9958fa734f73aeffb9ddfe2fbad1ca65f90c
galt
Mon Jan 30 16:18:41 2017 -0800
Check-in of CSP2 Content-Security-Policy work. All C-language CGIs should now support CSP2 in browser to stop major forms of XSS javascript injection. Javascript on pages is gathered together, and then emitted in a single script block at the end with a nonce that tells the browser, this is js that we generated instead of being injected by a hacker. Both inline script from script blocks and inline js event handlers had to be pulled out and separated. You will not see js sprinkled through-out the page now. Older browsers that support CSP1 or that do not understand CSP at all will still work, just without protection. External js libraries loaded at runtime need to be added to the CSP policy header in src/lib/htmshell.c.
diff --git src/hg/lib/hui.c src/hg/lib/hui.c
index 77ff269..2b37af1 100644
--- src/hg/lib/hui.c
+++ src/hg/lib/hui.c
@@ -42,42 +42,52 @@
#include "pgSnp.h"
#include "memgfx.h"
#include "trackHub.h"
#include "gtexUi.h"
#include "genbank.h"
#include "htmlPage.h"
#include "longRange.h"
#include "tagRepo.h"
#define SMALLBUF 256
#define MAX_SUBGROUP 9
#define ADD_BUTTON_LABEL "add"
#define CLEAR_BUTTON_LABEL "clear"
#define JBUFSIZE 2048
-#define PM_BUTTON "\n"
-#define DEF_BUTTON "\n"
+
+#define DEF_BUTTON "\n"
+#define DEF_BUTTON_JS "setCheckBoxesThatContain('%s',true,false,'%s','','%s');" \
+ "setCheckBoxesThatContain('%s',false,false,'%s','_defOff','%s');"
#define DEFAULT_BUTTON(nameOrId,anc,beg,contains) \
- printf(DEF_BUTTON,(nameOrId),(beg),(contains),(nameOrId),(beg),(contains),(anc), \
- "defaults_sm.png","default")
+ printf(DEF_BUTTON,(anc),"defaults_sm.png","default"); \
+ safef(id, sizeof id, "btn_%s", (anc)); \
+ safef(javascript, sizeof javascript, DEF_BUTTON_JS,(nameOrId),(beg),(contains),(nameOrId),(beg),(contains)); \
+ jsOnEventById("click", id, javascript);
+
+#define PM_BUTTON "\n"
+#define PM_BUTTON_JS "setCheckBoxesThatContain('%s',%s,true,'%s','','%s');"
#define PLUS_BUTTON(nameOrId,anc,beg,contains) \
- printf(PM_BUTTON, (nameOrId),"true", (beg),(contains),(anc),"add_sm.gif", "+")
+ printf(PM_BUTTON, (anc), "add_sm.gif", "+"); \
+ safef(id, sizeof id, "btn_%s", (anc)); \
+ safef(javascript, sizeof javascript, PM_BUTTON_JS, (nameOrId),"true", (beg),(contains)); \
+ jsOnEventById("click", id, javascript);
#define MINUS_BUTTON(nameOrId,anc,beg,contains) \
- printf(PM_BUTTON, (nameOrId),"false",(beg),(contains),(anc),"remove_sm.gif","-")
+ printf(PM_BUTTON, (anc), "remove_sm.gif", "-"); \
+ safef(id, sizeof id, "btn_%s", (anc)); \
+ safef(javascript, sizeof javascript, PM_BUTTON_JS, (nameOrId),"false", (beg),(contains)); \
+ jsOnEventById("click", id, javascript);
boolean isEncode2(char *database)
// Return true for ENCODE2 assemblies
{
return (sameString(database, "hg18") || sameString(database, "hg19") || sameString(database, "mm9"));
}
static char *htmlStringForDownloadsLink(char *database, struct trackDb *tdb,
char *name,boolean nameIsFile)
// Returns an HTML string for a downloads link
{
// If has fileSortOrder, then link to new hgFileUi
if (!nameIsFile && trackDbSetting(tdb, FILE_SORT_ORDER) != NULL)
{
char * link = needMem(PATH_LEN); // 512 should be enough
@@ -303,34 +313,39 @@
return dyStringCannibalize(&dyTable);
}
boolean compositeMetadataToggle(char *db,struct trackDb *tdb,char *title,
boolean embeddedInText,boolean showLongLabel)
// If metadata from metaTbl exists, create a link that will allow toggling it's display
{
char *tagStormFile = trackDbSetting(tdb, "metaDb");
if (tagStormFile == NULL)
{
const struct mdbObj *safeObj = metadataForTable(db,tdb,NULL);
if (safeObj == NULL || safeObj->vars == NULL)
return FALSE;
}
-printf("%strack);
+printf("%s%s",
- (embeddedInText?" ":"
", useDragAndDrop ? " id='noDrag' class='nodrop nodrag'" : "");
// First table row contains the display "selected/visible" or "all" radio buttons
// NOTE: list subtrack radio buttons are inside tracklist table header if
// there are no sort columns. The reason is to ensure spacing of lines
// column headers when the only column header is "Restricted Until"
printf("
");
columnCount = colspan;
}
// Add column headers which are sort button links
if (sortOrder != NULL)
{
printf("
\n",
sortOrder->htmlId, sortOrder->sortOrder); // keeing track of sortOrder
columnCount++;
if (!tdbIsMultiTrack(parentTdb)) // An extra column for subVis/wrench so dragAndDrop works
{
printf("
\n");
columnCount++;
}
// Columns in tdb order (unchanging), sort in cart order (changed by user action)
int sIx=0;
for (sIx=0;sIxcount;sIx++)
{
if (sameString(SORT_ON_TRACK_NAME,sortOrder->column[sIx]))
break; // All wrangler requested sort orders have been done.
if (sameString(SORT_ON_RESTRICTED,sortOrder->column[sIx]))
break; // All wrangler requested sort orders have been done.
- printf("
"); // schema column
columnCount++;
// Finally there may be a restricted until column
if (settings->restrictions)
{
if (sortOrder != NULL)
{
int sIx=sortOrder->count-1;
assert(sameString(SORT_ON_RESTRICTED,sortOrder->column[sIx]));
- printf("
");
// If sortable, then there must be a column per sortable dimension
if (sortOrder != NULL)
{
int sIx=0;
for (sIx=0; sIx count; sIx++)
{
char *col = sortOrder->column[sIx];
ix = stringArrayIx(col, membership->subgroups, membership->count);
// TODO: Sort needs to expand from subGroups to labels as well
if (ix >= 0)
{
@@ -4701,40 +4733,40 @@
boolean displayAll = sameString(displaySubs, "all");
// Table wraps around entire list so that "Top" link can float to the correct place.
cgiDown(0.7);
printf("
");
printf("");
if (sortOrder != NULL)
{
// First table row contains the display "selected/visible" or "all" radio buttons
// NOTE: list subtrack radio buttons are inside tracklist table header if
// there are no sort columns. The reason is to ensure spacing of lines
// column headers when the only column header is "Restricted Until"
printf("List subtracks: ");
char javascript[JBUFSIZE];
safef(javascript, sizeof(javascript),
- "class='allOrOnly' onclick='showOrHideSelectedSubtracks(true);'");
+ "showOrHideSelectedSubtracks(true);");
if (subCount > LARGE_COMPOSITE_CUTOFF)
safef(buffer,SMALLBUF,"%s.displaySubtracks",parentTdb->track);
else
safecpy(buffer,SMALLBUF,"displaySubtracks");
- cgiMakeOnClickRadioButton(buffer, "selected", !displayAll,javascript);
+cgiMakeOnEventRadioButtonWithClass(buffer, "selected", !displayAll, "allOrOnly", "click", javascript);
puts("only selected/visible ");
safef(javascript, sizeof(javascript),
- "class='allOrOnly' onclick='showOrHideSelectedSubtracks(false);'");
- cgiMakeOnClickRadioButton(buffer, "all", displayAll,javascript);
+ "showOrHideSelectedSubtracks(false);");
+cgiMakeOnEventRadioButtonWithClass(buffer, "all", displayAll, "allOrOnly", "click", javascript);
printf("all");
if (slCount(subtrackRefList) > 5)
printf(" ()");
if (membersHaveMatrix(membersForAll))
makeTopLink(parentTdb);
printf("
");
}
else
{
if (membersHaveMatrix(membersForAll))
makeTopLink(parentTdb);
}
// Get info for subtrack list
struct subtrackConfigSettings *settings = NULL;
@@ -4804,49 +4836,52 @@
subtrack->longLabel);
}
else if (hSameTrackDbType(primaryType, subtrack->type))
{
puts("
\n", style);
// we need to fool the wiggle dialog into defaulting to autoscale and maximum
char *origType = tdb->type;
tdb->type = "bedGraph";
if (hashFindVal(tdb->settingsHash, AUTOSCALE) == NULL)
hashAdd(tdb->settingsHash, AUTOSCALE, "on");
if (hashFindVal(tdb->settingsHash, WINDOWINGFUNCTION) == NULL)
hashAdd(tdb->settingsHash, WINDOWINGFUNCTION, wiggleWindowingEnumToString( wiggleWindowingMax));
wigCfgUi(cart,tdb,name,title,TRUE);
tdb->type = origType;
printf("
\n\n");
-printf("\n\n");
+char javascript[1024];
+safef(javascript, sizeof javascript, "$(\"input[name='%s']\").click( function() { $('#densGraphOptions').toggle();} );\n"
+ , varName); // XSS FILTER?
+jsInline(javascript);
}
void wiggleScaleDropDownJavascript(char *name)
/* print some js that deactivates the min/max range if autoscaling is activated */
{
-printf("\n");
+struct dyString *dy = dyStringNew(1024);
+dyStringPrintf(dy, " $(\"[name='%s.autoScale']\").change(function()\n", name);
+dyStringPrintf(dy, " {\n");
+dyStringPrintf(dy, " val= $(this).find(':selected').val(); \n");
+dyStringPrintf(dy, " if (val==\"auto-scale to data view\")\n");
+dyStringPrintf(dy, " {\n");
+dyStringPrintf(dy, " $(\"[name='%s.minY']\")[0].disabled=true;\n", name);
+dyStringPrintf(dy, " $(\"[name='%s.maxY']\")[0].disabled=true;\n", name);
+dyStringPrintf(dy, " $(\".%sAutoScaleDesc\").attr('style', 'color:grey;');\n", name);
+dyStringPrintf(dy, " }\n");
+dyStringPrintf(dy, " else\n");
+dyStringPrintf(dy, " {\n");
+dyStringPrintf(dy, " $(\"[name='%s.minY']\")[0].disabled=false;\n", name);
+dyStringPrintf(dy, " $(\"[name='%s.maxY']\")[0].disabled=false;\n", name);
+dyStringPrintf(dy, " $(\".%sAutoScaleDesc\").attr('style', 'color:black;');\n", name);
+dyStringPrintf(dy, " }\n");
+dyStringPrintf(dy, " });\n");
+dyStringPrintf(dy, "\n");
+dyStringPrintf(dy, " $( document ).ready(function()\n");
+dyStringPrintf(dy, " {\n");
+dyStringPrintf(dy, " val= $(\"[name='%s.autoScale']\").find(':selected').val(); \n", name);
+dyStringPrintf(dy, " if (val==\"auto-scale to data view\")\n");
+dyStringPrintf(dy, " {\n");
+dyStringPrintf(dy, " $(\"[name='%s.minY']\")[0].disabled=true;\n", name);
+dyStringPrintf(dy, " $(\"[name='%s.maxY']\")[0].disabled=true;\n", name);
+dyStringPrintf(dy, " $(\".%sAutoScaleDesc\").attr('style', 'color:grey;');\n", name);
+dyStringPrintf(dy, " }\n");
+dyStringPrintf(dy, " });\n");
+jsInline(dy->string);
+dyStringFree(&dy);
}
void wigCfgUi(struct cart *cart, struct trackDb *tdb, char *name, char *title, boolean boxed)
/* UI for the wiggle track */
{
char *typeLine = NULL; /* to parse the trackDb type line */
char *words[8]; /* to parse the trackDb type line */
int wordCount = 0; /* to parse the trackDb type line */
char option[256];
double minY; /* from trackDb or cart */
double maxY; /* from trackDb or cart */
double tDbMinY; /* data range limits from trackDb type line */
double tDbMaxY; /* data range limits from trackDb type line */
int defaultHeight; /* pixels per item */
char *horizontalGrid = NULL; /* Grid lines, off by default */
@@ -5069,32 +5106,35 @@
printf(" at y =");
safef(option, sizeof(option), "%s.%s", name, YLINEMARK );
cgiMakeDoubleVarInRange(option, yLineMark, "Indicator at Y", 0, NULL, NULL);
safef(option, sizeof(option), "%s.%s", name, YLINEONOFF );
wiggleYLineMarkDropDown(option, yLineMarkOnOff);
printf("");
if (boxed)
puts("");
else
{
puts("");
printf("Graph configuration help",WIGGLE_HELP_PAGE);
}
// add a little javascript call to make sure we don't get whiskers with stacks in multiwigs
+
+char javascript[1024];
+safef(javascript, sizeof javascript, "$(function () { multiWigSetupOnChange('%s'); });\n", name);
if (didAggregate)
- printf("\n", name);
+ jsInline(javascript);
cfgEndBox(boxed);
}
void filterButtons(char *filterTypeVar, char *filterTypeVal, boolean none)
/* Put up some filter buttons. */
{
printf("Filter: ");
radioButton(filterTypeVar, filterTypeVal, "red");
radioButton(filterTypeVar, filterTypeVal, "green");
radioButton(filterTypeVar, filterTypeVal, "blue");
radioButton(filterTypeVar, filterTypeVal, "exclude");
radioButton(filterTypeVar, filterTypeVal, "include");
if (none)
@@ -5199,41 +5239,30 @@
// maxShade is used to access the array.
int maxShade = 9;
int scoreMinGrayLevel = scoreMin * maxShade/scoreMax;
if (scoreMinGrayLevel <= 0) scoreMinGrayLevel = 1;
char *setting = trackDbSettingClosestToHome(tdb, MIN_GRAY_LEVEL);
int minGrayLevel = cartUsualIntClosestToHome(cart, tdb, parentLevel, MIN_GRAY_LEVEL,
setting ? atoi(setting) : scoreMinGrayLevel);
if (minGrayLevel <= 0) minGrayLevel = 1;
if (minGrayLevel > maxShade) minGrayLevel = maxShade;
puts("\nShade of lowest-scoring items: ");
// Add javascript to select so that its color is consistent with option colors:
int level = 255 - (255*minGrayLevel / maxShade);
printf("\n");
}
}
@@ -6317,74 +6346,76 @@
boolean lineBreakJustPrinted;
char trackName[255];
char query[256];
char **row;
struct sqlConnection *conn;
struct sqlResult *sr;
char *words[MAX_SP_SIZE];
int defaultOffSpeciesCnt = 0;
if (cartOptionalString(cart, "ajax") == NULL)
jsIncludeFile("utils.js",NULL);
//jsInit();
puts("\n
Species selection: ");
cgiContinueHiddenVar("g");
-PLUS_BUTTON( "id", "plus_pw","cb_maf_","_maf_");
-MINUS_BUTTON("id","minus_pw","cb_maf_","_maf_");
+char id[256];
+char javascript[1024];
+PLUS_BUTTON( "id", "plus_pw","cb_maf_","_maf_")
+MINUS_BUTTON("id","minus_pw","cb_maf_","_maf_")
char prefix[512];
safef(prefix, sizeof prefix, "%s.", name);
char *defaultOffSpecies = trackDbSetting(tdb, "speciesDefaultOff");
struct hash *offHash = NULL;
if (defaultOffSpecies)
{
offHash = newHash(5);
- DEFAULT_BUTTON( "id", "default_pw","cb_maf_","_maf_");
+ DEFAULT_BUTTON( "id", "default_pw","cb_maf_","_maf_") // DEBUG RESTORE
int wordCt = chopLine(defaultOffSpecies, words);
defaultOffSpeciesCnt = wordCt;
/* build hash of species that should be off */
int ii;
for(ii=0; ii < wordCt; ii++)
hashAdd(offHash, words[ii], NULL);
}
if (groupCt == 1)
puts("\n
");
group = -1;
lineBreakJustPrinted = FALSE;
for (wmSpecies = wmSpeciesList, i = 0, j = 0; wmSpecies != NULL;
wmSpecies = wmSpecies->next, i++)
{
char *label;
prevGroup = group;
group = wmSpecies->group;
if (groupCt != 1 && group != prevGroup)
{
i = 0;
j = 0;
if (group != 0)
puts("
\n");
/* replace underscores in group names */
subChar(groups[group], '_', ' ');
printf("
");
}
if (hIsGsidServer())
numberPerRow = 6;
else
numberPerRow = 5;
/* new logic to decide if line break should be displayed here */
if ((j != 0 && (j % numberPerRow) == 0) && (lineBreakJustPrinted == FALSE))
{
puts("
");
lineBreakJustPrinted = TRUE;
}
@@ -6628,39 +6659,40 @@
cfgEndBox(boxed);
}
static char *grayLabels[] =
{ "alignment quality",
"base qualities",
"unpaired ends",
};
static char *grayValues[] =
{ BAM_GRAY_MODE_ALI_QUAL,
BAM_GRAY_MODE_BASE_QUAL,
BAM_GRAY_MODE_UNPAIRED,
};
// When a child input of a radio set is changed, click its radio button:
-#define UPDATE_RADIO_FORMAT "%s=\"\
+
+#define UPDATE_RADIO_FORMAT_JS "\
var inputs = document.getElementsByName('%s'); \
if (inputs) { \
for (var i=0; i < inputs.length; i++) { \
if (inputs[i].type == 'radio') { \
inputs[i].checked = (inputs[i].value == '%s'); \
} \
} \
- }\""
+ }"
void bamCfgUi(struct cart *cart, struct trackDb *tdb, char *name, char *title, boolean boxed)
/* BAM: short-read-oriented alignment file format. */
{
boxed = cfgBeginBoxAndTitle(tdb, boxed, title);
char cartVarName[1024];
printf("
\n");
// Make row of vis drop downs
for (ix = 0; ix < membersOfView->count; ix++)
{
char *viewName = membersOfView->tags[ix];
if (matchedViewTracks[ix] != NULL)
{
printf("
", dimensionX->groupTitle);
}
@@ -7095,72 +7149,70 @@
}
cntX++;
}
}
// If dimension is big enough, then add Y buttons to right as well
if (cntX>MATRIX_RIGHT_BUTTONS_AFTER)
{
if (dimensionY)
{
if (squeeze)
printf("
\n");
}
static void matrixXheadingsRow2(struct trackDb *parentTdb, boolean squeeze,
membersForAll_t* membersForAll)
// prints the 2nd row of a matrix: Y title; X buttons; title Y
{
members_t *dimensionX = membersForAll->members[dimX];
members_t *dimensionY = membersForAll->members[dimY];
// If there are both X and Y dimensions, then there is a row of buttons in X
if (dimensionX && dimensionY)
{
int ixX,cntX=0;
printf("
%s
",
dimensionY->groupTitle);
for (ixX = 0; ixX < dimensionX->count; ixX++) // Special row of +- +- +-
{
if (dimensionX->subtrackList
&& dimensionX->subtrackList[ixX]
&& dimensionX->subtrackList[ixX]->val)
{
- char objName[SMALLBUF];
printf("
");
cntX++;
}
}
// If dimension is big enough, then add Y buttons to right as well
if (cntX>MATRIX_RIGHT_BUTTONS_AFTER)
printf("
%s
", dimensionY->groupTitle);
puts("
\n");
}
}
static boolean matrixXheadings(char *db,struct trackDb *parentTdb, membersForAll_t* membersForAll,
boolean top)
// UI for X headings in matrix
{
@@ -7181,47 +7233,45 @@
int ixY,boolean left)
// prints the column of Y labels and buttons
{
members_t *dimensionX = membersForAll->members[dimX];
members_t *dimensionY = membersForAll->members[dimY];
struct trackDb *childTdb = NULL;
if (dimensionY
&& dimensionY->subtrackList
&& dimensionY->subtrackList[ixY]
&& dimensionY->subtrackList[ixY]->val)
childTdb = dimensionY->subtrackList[ixY]->val;
if (dimensionX && dimensionY && childTdb != NULL) // Both X and Y, then column of buttons
{
- char objName[SMALLBUF];
printf("
\n",dimensionY->tags[ixY],
compositeLabelWithVocabLink(db,parentTdb,childTdb,dimensionY->groupTag,
dimensionY->titles[ixY]));
}
static int displayABCdimensions(char *db,struct cart *cart, struct trackDb *parentTdb,
struct slRef *subtrackRefList, membersForAll_t* membersForAll)
// This will walk through all declared nonX&Y dimensions (X and Y is the 2D matrix of CBs.
// NOTE: ABC dims are only supported if there are X & Y both.
// Also expected number should be passed in
{
int count=0,ix;
@@ -7234,39 +7284,40 @@
count++;
if (count==1) // First time set up a table
puts("
");
printf("
%s:
",
membersForAll->members[ix]->groupTitle);
int aIx;
for (aIx=0;aIxmembers[ix]->count;aIx++)
{
if (membersForAll->members[ix]->tags[aIx] != NULL)
{
assert(membersForAll->members[ix]->subtrackList[aIx]->val != NULL);
printf("