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/hgTracks.js src/hg/js/hgTracks.js
index 54a5607..951d9f7 100644
--- src/hg/js/hgTracks.js
+++ src/hg/js/hgTracks.js
@@ -478,30 +478,55 @@
changeAssemblies: function (ele) // UNUSED? Larry's experimental code
{ // code to update page when user changes assembly select list.
$.ajax({
type: "GET",
url: "../cgi-bin/hgApi",
data: cart.varsToUrlData({ 'cmd': 'defaultPos', 'db': getDb() }),
dataType: "html",
trueSuccess: genomePos.handleChange,
success: catchErrorOrDispatch,
error: errorHandler,
cache: true
});
return false;
},
+
+ inlineJs : "",
+
+ getInlineJs: function (response, status)
+ {
+ //alert("genomePos.getInlineJs called!"); // DEBUG REMOVE
+ genomePos.inlineJs = response;
+ },
+
+ fetchInlineJs: function (url)
+ { // code to fetch temp file with inline js in it. // OBSOLETE CSP1
+ $.ajax({
+ type: "GET",
+ async: false, // wait for result
+ url: url,
+ dataType: "html",
+ trueSuccess: genomePos.getInlineJs,
+ success: catchErrorOrDispatch,
+ error: errorHandler,
+ cache: false
+ });
+ return genomePos.inlineJs;
+ },
+
+
convertedVirtCoords : {chromStart : -1, chromEnd : -1},
handleConvertChromPosToVirtCoords: function (response, status)
{
var virtStart = -1, virtEnd = -1;
var newJson = scrapeVariable(response, "convertChromToVirtChrom");
if (!newJson) {
warn("convertChromToVirtChrom object is missing from the response");
} else {
virtStart = newJson.virtWinStart;
virtEnd = newJson.virtWinEnd;
}
genomePos.convertedVirtCoords = {chromStart : virtStart, chromEnd : virtEnd};
},
@@ -3087,48 +3112,53 @@
// remove an existing dialog box
var extToolDialog = $("#extToolDialog").remove();
// construct the contents
var htmlLines = ["
"];
var winSize = hgTracks.winEnd - hgTracks.winStart;
for (i = 0; i < extTools.length; i++) {
var tool = extTools[i];
var toolId = tool[0];
var shortLabel = tool[1];
var longLabel = tool[2];
var maxSize = tool[3];
if ((maxSize===0) || (winSize < maxSize))
{
var url = "hgTracks?hgsid="+getHgsid()+"&hgt.redirectTool="+toolId;
- var onclick = "$('#extToolDialog').dialog('close');";
- htmlLines.push("- "+shortLabel+": "+longLabel+"
");
+ //var onclick = "$('#extToolDialog').dialog('close');";
+ //htmlLines.push("- "+shortLabel+": "+longLabel+"
");
+ // onclick js code moved to jsInline
+ htmlLines.push("- "+shortLabel+": "+longLabel+"
");
}
else
{
note = "
Needs zoom to < "+maxSize/1000+" kbp.";
htmlLines.push('- '+shortLabel+": "+longLabel+note);
}
}
htmlLines.push("
");
content = htmlLines.join("");
var title = hgTracks.chromName + ":" + (hgTracks.winStart+1) + "-" + hgTracks.winEnd;
if (hgTracks.nonVirtPosition)
title = hgTracks.nonVirtPosition;
title += " on another website";
$("body").append("");
+
// Strategy for popups with js:
// - jsFiles and CSS should not be included in html. Here they are shluped out.
// - The resulting files ought to be loadable dynamically (with getScript()),
// but this was not working nicely with the modal dialog
// Therefore include files must be included with hgTracks CGI !
// - embedded js should not be in the popup box.
// - Somethings should be in a popup.ready() function, and this is emulated below,
// as soon as the cleanHtml is added
// Since there are many possible popup cfg dialogs, the ready should be all inclusive.
// -- popup.ready() -- Here is the place to do things that might otherwise go
// into a $('#pop').ready() routine!
// Searching for some semblance of size suitability
var popMaxHeight = ($(window).height() - 40);
@@ -3276,32 +3308,33 @@
$('#hgTracksDialog').dialog('option' , 'title' , popUpHgt.title);
$('#hgTracksDialog').dialog('open');
}
};
// A function to show the keyboard help dialog box, bound to ? and called from the menu bar
function showHotkeyHelp() {
$("#hotkeyHelp").dialog({width:'600'});
}
// A function to add an entry for the keyboard help dialog box to the menubar
// and add text that indicates the shortcuts to many static menubar items as suggested by good old IBM CUA/SAA
function addKeyboardHelpEntries() {
- var html = 'Keyboard Shortcuts?';
+ var html = 'Keyboard Shortcuts?';
$('#help .last').before(html);
+ $("#keybShorts").onclick = function(){showHotKeyHelp(); return false;};
html = 's s';
$('#sessionsMenuLink').after(html);
html = 'p s';
$('#publicSessionsMenuLink').after(html);
html = 'c t';
$('#customTracksMenuLink').after(html);
html = 't h';
$('#trackHubsMenuLink').after(html);
html = 't b';
$('#blatMenuLink').after(html);
@@ -3455,37 +3488,40 @@
var urlData = cart.varsToUrlData(changedVars);
if (imageV2.mapIsUpdateable) {
imageV2.requestImgUpdate(trackName,urlData,"");
} else {
window.location = "../cgi-bin/hgTracks?" + urlData + "&hgsid=" + getHgsid();
}
}
}
}
},
uiDialog: function (response, status)
{
// Take html from hgTrackUi and put it up as a modal dialog.
+ //alert("Got here popUp.uiDialog"); // DEBUG REMOVE GALT
+
// make sure all links (e.g. help links) open up in a new window
response = response.replace(/"+ cleanHtml +"");
// Strategy for popups with js:
// - jsFiles and CSS should not be included in html. Here they are shluped out.
// - The resulting files ought to be loadable dynamically (with getScript()),
// but this was not working nicely with the modal dialog
// Therefore include files must be included with hgTracks CGI !
// - embedded js should not be in the popup box.
// - Somethings should be in a popup.ready() function, and this is emulated below,
// as soon as the cleanHtml is added
// Since there are many possible popup cfg dialogs, the ready should be all inclusive.
if ( ! popUp.trackDescriptionOnly ) {
// If subtrack then vis rules differ
var subtrack = tdbIsSubtrack(hgTracks.trackDb[popUp.trackName]) ? popUp.trackName :"";
@@ -3899,32 +3935,66 @@
}
window.location.assign(url);
return false;
}
document.TrackHeaderForm.submit();
},
updateImgAndMap: function (response, status)
{ // Handle ajax response with an updated trackMap image, map and optional ideogram.
// and maybe the redLines background too.
// this.cmd can be used to figure out which menu item triggered this.
// this.id === appropriate track if we are retrieving just a single track.
// update local hgTracks.trackDb to reflect possible side-effects of ajax request.
+ // alert("response=["+response+"]"); // DEBUG GALT REMOVE
+
var newJson = scrapeVariable(response, "hgTracks");
+ // added by GALT for CSP/XSS
+ if (!newJson) {
+ // OLD CSP1 way not using now?
+ var strippedJsFiles = {};
+ stripJsFiles(response, false, strippedJsFiles);
+ //alert(strippedJsFiles.toSource()); // DEBUG GALT FF ONLY
+ //alert("strippedJsFiles.jsFiles="+strippedJsFiles.jsFiles+""); // DEBUG GALT REMOVE
+ var inlinePath = "";
+ var i, len;
+ if (strippedJsFiles.jsFiles) {
+ for (i = 0, len = strippedJsFiles.jsFiles.length; i < len; ++i) {
+ //alert(strippedJsFiles.jsFiles[i]); // DEBUG REMOVE
+ var srcPattern="";
+ var reg = new RegExp(srcPattern);
+ var a = reg.exec(strippedJsFiles.jsFiles[i]);
+ if (a && a[1]) {
+ if (a[1].match("inline")) {
+ inlinePath = a[1];
+ //alert("SRC found: "+a[1]); // DEBUG REMOVE
+ }
+ }
+ }
+ }
+ if (inlinePath !== "") {
+ //alert("inlinePath found: "+inlinePath); // DEBUG REMOVE
+ var js = genomePos.fetchInlineJs(inlinePath);
+ //alert(js); // DEBUG REMOVE
+ response += ("");
+ newJson = scrapeVariable(response, "hgTracks");
+ }
+ }
+
//alert(JSON.stringify(newJson)); // DEBUG Example
var oldJson = hgTracks;
var valid = false;
if (!newJson) {
var stripped = {};
stripJsEmbedded(response, true, stripped);
if ( ! stripped.warnMsg )
warn("hgTracks object is missing from the response");
} else {
if (this.id) {
if (newJson.trackDb[this.id]) {
var visibility = vis.enumOrder[newJson.trackDb[this.id].visibility];
var limitedVis;
if (newJson.trackDb[this.id].limitedVis)