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/hgGenome/mainPage.c src/hg/hgGenome/mainPage.c index 7b982f9..1b3bed8 100644 --- src/hg/hgGenome/mainPage.c +++ src/hg/hgGenome/mainPage.c @@ -1,692 +1,695 @@ /* mainPage - draws the main hgGenome page, including some controls * on the top and the graphic. */ /* Copyright (C) 2013 The Regents of the University of California * See README in this or parent directory for licensing information. */ #include "common.h" #include "psGfx.h" #include "pscmGfx.h" #include "linefile.h" #include "hash.h" #include "cheapcgi.h" #include "htmshell.h" #include "cart.h" #include "hui.h" #include "dbDb.h" #include "ra.h" #include "hdb.h" #include "web.h" #include "portable.h" #include "hgColors.h" #include "trackLayout.h" #include "chromInfo.h" #include "hvGfx.h" #include "genoLay.h" #include "cytoBand.h" #include "hCytoBand.h" #include "errCatch.h" #include "chromGraph.h" #include "customTrack.h" #include "hPrint.h" #include "jsHelper.h" #include "hgGenome.h" #include "trashDir.h" static char *allColors[] = { "black", "blue", "purple", "red", "orange", "yellow", "green", "gray", }; static char *defaultColors[maxLinesOfGraphs][maxGraphsPerLine] = { {"blue", "red", "black", "yellow", }, {"gray", "purple", "green", "orange",}, {"blue", "red", "black", "yellow", }, {"gray", "purple", "green", "orange",}, {"blue", "red", "black", "yellow", }, {"gray", "purple", "green", "orange",}, }; char *graphColorAt(int row, int col) /* Return graph color at given row/column, NULL if nonw. */ { char *varName = graphColorVarName(row, col); char *color = cartUsualString(cart, varName, defaultColors[row][col]); if (color == NULL) color = defaultColors[0][0]; return color; } Color colorFromAscii(struct hvGfx *hvg, char *asciiColor) /* Get color index for a named color. */ { if (sameWord("red", asciiColor)) return MG_RED; else if (sameWord("blue", asciiColor)) return MG_BLUE; else if (sameWord("yellow", asciiColor)) return hvGfxFindColorIx(hvg, 220, 220, 0); else if (sameWord("purple", asciiColor)) return hvGfxFindColorIx(hvg, 150, 0, 200); else if (sameWord("orange", asciiColor)) return hvGfxFindColorIx(hvg, 230, 120, 0); else if (sameWord("green", asciiColor)) return hvGfxFindColorIx(hvg, 0, 180, 0); else if (sameWord("gray", asciiColor)) return MG_GRAY; else return MG_BLACK; } /* Page drawing stuff. */ void drawChromGraph(struct hvGfx *hvg, struct sqlConnection *conn, struct genoLay *gl, char *chromGraph, int yOff, int height, Color color, boolean leftLabel, boolean rightLabel, boolean firstInRow) /* Draw chromosome graph on all chromosomes in layout at given * y offset and height. */ { boolean yellowMissing = getYellowMissing(); struct genoGraph *gg = hashFindVal(ggHash, chromGraph); if (gg != NULL) { /* Get binary data source and scaling info etc. */ struct chromGraphBin *cgb = gg->cgb; struct chromGraphSettings *cgs = gg->settings; int maxGapToFill = cgs->maxGapToFill; static struct rgbColor missingDataColor = { 180, 180, 120}; Color missingColor = hvGfxFindRgb(hvg, &missingDataColor); double pixelsPerBase = 1.0/gl->basesPerPixel; double gMin = cgs->minVal, gMax = cgs->maxVal, gScale; gScale = height/(gMax-gMin); /* Draw significance threshold as a light blue line */ if (leftLabel) { static struct rgbColor guidelineColor = { 220, 220, 255}; Color lightBlue = hvGfxFindRgb(hvg, &guidelineColor); struct slRef *ref; struct genoLayChrom *chrom; int rightX = gl->picWidth - gl->rightLabelWidth - gl->margin; int leftX = gl->leftLabelWidth + gl->margin; int width = rightX - leftX; double threshold = getThreshold(); if (threshold >= gMin && threshold <= gMax) { int y = height - ((threshold - gMin)*gScale) + yOff; for (ref = gl->leftList; ref != NULL; ref = ref->next) { chrom = ref->val; hvGfxBox(hvg, leftX, y + chrom->y, width, 1, lightBlue); } ref = gl->bottomList; if (ref != NULL) { chrom = ref->val; hvGfxBox(hvg, leftX, y + chrom->y, width, 1, lightBlue); } } } /* Draw graphs on each chromosome */ chromGraphBinRewind(cgb); while (chromGraphBinNextChrom(cgb)) { struct genoLayChrom *chrom = hashFindVal(gl->chromHash, cgb->chrom); if (chrom) { int chromX = chrom->x, chromY = chrom->y; int minY = chromY + yOff; int maxY = chromY + yOff + height - 1; if (chromGraphBinNextVal(cgb)) { /* Set clipping so can't scribble outside of box. */ hvGfxSetClip(hvg, chromX, chromY, chrom->width+1, chrom->height); /* Handle first point as special case here, so don't * have to test for first point in inner loop. */ double x,lastX; int y,start,lastStart,lastY; start = lastStart = cgb->chromStart; x = lastX = pixelsPerBase*start + chromX; y = lastY = (height - ((cgb->val - gMin)*gScale)) + chromY+yOff; if (y < minY) y = minY; else if (y > maxY) y = maxY; struct pscmGfx *pscm = NULL; if (hvg->pixelBased) { hvGfxDot(hvg, x, y, color); } else { pscm = (struct pscmGfx *)hvg->vg->data; pscmSetColor(pscm, color); psFillEllipse(pscm->ps, x, y, 0.01, 0.01); psSetLineWidth(pscm->ps, 0.01); } /* Draw rest of points, connecting with line to previous point * if not too far off. */ while (chromGraphBinNextVal(cgb)) { start = cgb->chromStart; x = pixelsPerBase*start + chromX; if (hvg->pixelBased) x = (int) x; y = (height - ((cgb->val - gMin)*gScale)) + chromY+yOff; if (y < minY) y = minY; else if (y > maxY) y = maxY; if (x != lastX || y != lastY) { if (start - lastStart <= maxGapToFill) { if (hvg->pixelBased) hvGfxLine(hvg, lastX, lastY, x, y, color); else { pscmSetColor(pscm, color); psDrawLine(pscm->ps, lastX, lastY, x, y); } } else { if (yellowMissing && leftLabel) { int width = x - lastX - 1; if (width > 0) hvGfxBox(hvg, lastX+1, minY, width, height, missingColor); } if (hvg->pixelBased) { hvGfxDot(hvg, x, y, color); } else { pscmSetColor(pscm, color); psFillEllipse(pscm->ps, x, y, 0.01, 0.01); } } } lastX = x; lastY = y; lastStart = start; } if (!hvg->pixelBased) { psSetLineWidth(pscm->ps, 1); } hvGfxUnclip(hvg); } } else { /* Just read and discard data. */ while (chromGraphBinNextVal(cgb)) ; } } /* Draw labels. */ if (withLabels && (leftLabel || rightLabel)) { int lineY = yOff; int i,j; int spaceWidth = tl.nWidth; int tickWidth = spaceWidth*2/3; int fontPixelHeight = mgFontPixelHeight(gl->font); for (i=0; ilineCount; ++i) { hvGfxSetClip(hvg, 0, lineY, gl->picWidth, gl->lineHeight); for (j=0; j< cgs->linesAtCount; ++j) { double lineAt = cgs->linesAt[j]; int y = (height - ((lineAt - gMin)*gScale)) + lineY; int textTop = y - fontPixelHeight/2+1; int textBottom = textTop + fontPixelHeight; char label[24]; safef(label, sizeof(label), "%g", lineAt); if (leftLabel) { hvGfxBox(hvg, gl->margin + gl->leftLabelWidth - tickWidth-1, y, tickWidth, 1, color); if (textTop >= lineY && textBottom < lineY + height) { hvGfxTextRight(hvg, gl->margin, textTop, gl->leftLabelWidth-spaceWidth, fontPixelHeight, color, gl->font, label); } } if (rightLabel) { hvGfxBox(hvg, gl->picWidth - gl->margin - gl->rightLabelWidth+1, y, tickWidth, 1, color); if (textTop >= lineY && textBottom < lineY + height) { hvGfxText(hvg, gl->picWidth - gl->margin - gl->rightLabelWidth + spaceWidth, textTop, color, gl->font, label); } } } lineY += gl->lineHeight; hvGfxUnclip(hvg); } } } } void genomeGif(struct sqlConnection *conn, struct genoLay *gl, int graphRows, int graphCols, int oneRowHeight, char *psOutput) /* Create genome GIF file and HTML that includes it. */ { struct hvGfx *hvg; struct tempName gifTn; Color shadesOfGray[10]; int maxShade = ArraySize(shadesOfGray)-1; int spacing = 1; int yOffset = 2*spacing; int innerHeight = oneRowHeight - 3*spacing; int i,j; if (psOutput) { hvg = hvGfxOpenPostScript(gl->picWidth, gl->picHeight, psOutput); } else { /* Create gif file and make reference to it in html. */ trashDirFile(&gifTn, "hgg", "ideo", ".png"); hvg = hvGfxOpenPng(gl->picWidth, gl->picHeight, gifTn.forCgi, FALSE); hPrintf("", gifTn.forHtml, gl->picWidth, gl->picHeight, hggClick); } /* Get our grayscale. */ hMakeGrayShades(hvg, shadesOfGray, maxShade); /* Draw the labels and then the chromosomes. */ genoLayDrawChromLabels(gl, hvg, MG_BLACK); genoLayDrawBandedChroms(gl, hvg, database, conn, shadesOfGray, maxShade, MG_BLACK); /* Draw chromosome graphs. */ for (i=0; i=0; --j) { char *graph = graphSourceAt(i,j); if (graph != NULL && graph[0] != 0) { Color color = colorFromAscii(hvg, graphColorAt(i,j)); drawChromGraph(hvg, conn, gl, graph, gl->betweenChromOffsetY + yOffset, innerHeight, color, j==0, j==1, firstInRow); firstInRow = FALSE; } } yOffset += oneRowHeight; } hvGfxBox(hvg, 0, 0, gl->picWidth, 1, MG_GRAY); hvGfxBox(hvg, 0, gl->picHeight-1, gl->picWidth, 1, MG_GRAY); hvGfxBox(hvg, 0, 0, 1, gl->picHeight, MG_GRAY); hvGfxBox(hvg, gl->picWidth-1, 0, 1, gl->picHeight, MG_GRAY); hvGfxClose(&hvg); } -void graphDropdown(struct sqlConnection *conn, char *varName, char *curVal, char *js) +void graphDropdown(struct sqlConnection *conn, char *varName, char *curVal, char *event, char *js) /* Make a drop-down with available chrom graphs */ { int totalCount = 1; char **menu, **values; int i = 0; struct slRef *ref; for (ref = ggList; ref != NULL; ref = ref->next) { struct genoGraph *gg = ref->val; if (gg->isComposite == FALSE) totalCount++; } AllocArray(menu, totalCount); AllocArray(values, totalCount); menu[0] = "-- nothing --"; values[0] = ""; for (ref = ggList; ref != NULL; ref = ref->next) { struct genoGraph *gg = ref->val; if (gg->isComposite == FALSE) { ++i; menu[i] = gg->shortLabel; values[i] = gg->name; } } -cgiMakeDropListFull(varName, menu, values, totalCount, curVal, js); +cgiMakeDropListFull(varName, menu, values, totalCount, curVal, event, js); freez(&menu); freez(&values); } -void colorDropdown(int row, int col, char *js) +void colorDropdown(int row, int col, char *event, char *js) /* Put up color drop down menu. */ { char *varName = graphColorVarName(row, col); char *curVal = graphColorAt(row, col); -cgiMakeDropListFull(varName, allColors, allColors, ArraySize(allColors), curVal, js); +cgiMakeDropListFull(varName, allColors, allColors, ArraySize(allColors), curVal, event, js); } static void addThresholdGraphCarries(struct dyString *dy, int graphRows, int graphCols, boolean cgaOnly) /* Add javascript that carries over threshold and graph vars * to new form. */ { if (cgaOnly) return; jsTextCarryOver(dy, getThresholdName()); int i,j; for (i=0; i