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/js/alleles.js src/hg/js/alleles.js index 0badd1b..c14fb8f 100644 --- src/hg/js/alleles.js +++ src/hg/js/alleles.js @@ -1,424 +1,441 @@ // JavaScript Especially for the Gene Haplotype Alleles section of hgGene CGI // Don't complain about line break before '||' etc: /* jshint -W014 */ // Alleles supports gene haplotype alleles section var alleles = (function() { var sectionName = "haplotypes"; // This define is used throughout var seqCharsPerPos = 1; // These globals should only need to be calculated once var seqPxPerPos = 7; var ajaxUpdates = 0; // persistence between ajax calls var persistRareHapsShown = false; var persistScoresShown = false; var persistSortReverse = false; var persistSortColId = ''; function initSortTable() { // Initialize the sortable table var allelesTable = $('table#alleles.sortable'); if (allelesTable.length === 1) { sortTable.initialize(allelesTable[0],false); sortTable.sortCaseSensitive(true); } } function update(content, status) { // Update the geneAlleles section based upon ajax request hideLoadingImage(this.loadingId); // Do this first + var pageNonce = getNonce(); + + var ajaxNonce = stripNonce(content, false); + + var jsNonce = stripJsNonce(content, ajaxNonce, false);// DEBUG msg with true + var geneAlleles = $('div#' + sectionName); if (geneAlleles.length > 0) { var cleanHtml = content; //cleanHtml = stripJsFiles(cleanHtml,true); // DEBUG msg with true //cleanHtml = stripCssFiles(cleanHtml,true); // DEBUG msg with true //cleanHtml = stripJsEmbedded(cleanHtml,true);// DEBUG msg with true var sectionBegin = ""; var sectionEnd = ""; var ix = cleanHtml.indexOf(sectionBegin); if (ix > 0) cleanHtml = cleanHtml.substring(ix); ix = cleanHtml.indexOf(sectionEnd); if (ix > 0) cleanHtml = cleanHtml.substring(0,ix + sectionEnd.length); if (cleanHtml.length > 0) { + ajaxUpdates++; $(geneAlleles[0]).html( cleanHtml ); hiliteRemove(); + + // append ajax js blocks with nonce + for (i=0; i 0) thisUrl = "../" + thisUrl.substring(ix); $.ajax({ type: "GET", url: thisUrl, data: "ajax=1&" + data + "&ajaxSection=" + sectionName, dataType: "html", trueSuccess: update, success: catchErrorOrDispatch, error: errorHandler, //async: false, //cmd: cmd, loadingId: showLoadingImage(sectionName), cache: false }); } function afterSort(obj) { // The sort table is controlled by utls.js, but this is some allele specific stuff var thisId = $(obj).attr('id'); if (persistSortColId !== thisId) persistSortColId = thisId; else persistSortReverse = ( !persistSortReverse ); // Sorted variant is hilited special if ($(obj).hasClass('var')) { hiliteId = thisId; hiliteSpecial( hiliteId ); } } function persistThroughUpdates() { // When an ajax update occurs, restore the non-ajax settings state // See if table was sorted previously if (persistSortColId !== '') { var col = $('table#alleles').find('TH#' + persistSortColId); if (col && col.length !== 0) { var colIx = Number( $(col).attr('cellIndex') ); $(col).click(); if (persistSortReverse) {// click twice if reverse order! persistSortReverse = false; // Needed so that it is set again setTimeout(function() { $('table#alleles').find('TH#' + persistSortColId).click(); }, 50); } } } // Make sure that sort command saves the coumn for persistence $('table#alleles').find('TH').click(function (e) { afterSort(this); }); // Persist on lighlite as red if (hiliteId !== '') hiliteSpecial( hiliteId ); } function propgateTitle(obj) { // Adds this objects title to all other objs with the same class // Relies upon a span and fixed width text // Find pointer position within text // Is there a title? var theTitle = obj.title; if (!theTitle || theTitle.length === 0) return; var varId = $( obj ).attr('id'); $('table#alleles').find('TD.' + varId).not("[title]").attr('title', theTitle); } var hilites = []; // Hold on to all the hilite ids that are currently displayed var hiliteId = ''; function hiliteTag(xPx, widthPx) { // returns an id based upon dimensions return "hilite" + xPx.toFixed(0) + "-" + widthPx.toFixed(0); } function hiliteAdd(xPx, widthPx, yPx, heightPx) { // Adds a hilite div with the specific dimensions. // Returns the div for further customization if (xPx === 0) return; // make sure it doesn't already exist! var hId = hiliteTag(xPx,widthPx); if (hilites.indexOf(hId) !== -1) return hId; var tbl = $('table#alleles'); var tripleView = ($(tbl).find('TD.dnaToo').length > 0); if (yPx === undefined || yPx === null) { // number could be 0 so be explicit if (tripleView) yPx = $(tbl).position().top + 2; // span whole height of table else yPx = $(tbl).find('TH#seq').position().top; // skip first row of header } if (!heightPx || heightPx === 0) { if (tripleView) heightPx = $(tbl).height() - 8; // span whole height of table else heightPx = $(tbl).height() - (2 * $(tbl).find('TH#seq').height()) + 4; } var div = $("