Parcourir la source

Escape strings and encode URIs to mitigate possible DOM XSS.

pull/101/head
Matthew Petroff il y a 9 ans
Parent
révision
e294e40b23
2 fichiers modifiés avec 34 ajouts et 24 suppressions
  1. +3
    -3
      src/js/libpannellum.js
  2. +31
    -21
      src/js/pannellum.js

+ 3
- 3
src/js/libpannellum.js Voir le fichier

@@ -175,9 +175,9 @@ function Renderer(container, image, imageType, video) {
faceImg.side = s;
faceImg.onload = onLoad;
if (imageType == 'multires') {
faceImg.src = path.replace('%s',sides[s]) + '.' + image.extension;
faceImg.src = encodeURI(path.replace('%s', sides[s]) + '.' + image.extension);
} else {
faceImg.src = image[s].src;
faceImg.src = encodeURI(image[s].src);
}
}
@@ -934,7 +934,7 @@ function Renderer(container, image, imageType, video) {
node.textureLoaded = true;
delete node.image;
};
node.image.src = node.path + '.' + image.extension;
node.image.src = encodeURI(node.path + '.' + image.extension);
}
}


+ 31
- 21
src/js/pannellum.js Voir le fichier

@@ -290,7 +290,7 @@ function init() {
if (config.basePath && !absoluteURL(p)) {
p = config.basePath + p;
}
panoImage[i].src = p;
panoImage[i].src = encodeURI(p);
}
} else if (config.type == 'multires') {
onImageLoad();
@@ -308,7 +308,7 @@ function init() {
for (i = 0; i < config.panoramas.length; i++) {
if (panoImage.canPlayType(config.panoramas[i].type).length > 0) {
panoImage.crossOrigin = 'anonymous';
panoImage.src = absoluteURL(config.panoramas[i].file) ? config.panoramas[i].file : p + config.panoramas[i].file;
panoImage.src = encodeURI(absoluteURL(config.panoramas[i].file) ? config.panoramas[i].file : p + config.panoramas[i].file);
break;
}
}
@@ -333,7 +333,7 @@ function init() {
if (xhr.status != 200) {
// Display error if image can't be loaded
var a = document.createElement('a');
a.href = p;
a.href = encodeURI(p);
a.innerHTML = a.href;
anError('The file ' + a.outerHTML + ' could not be accessed.');
}
@@ -1120,15 +1120,15 @@ function createHotSpots() {
});
config.hotSpots.forEach(function(hs) {
var div = document.createElement('div');
div.className = 'pnlm-hotspot pnlm-tooltip pnlm-sprite pnlm-' + hs.type;
div.className = 'pnlm-hotspot pnlm-tooltip pnlm-sprite pnlm-' + escapeHTML(hs.type);
var span = document.createElement('span');
span.innerHTML = hs.text;
span.innerHTML = escapeHTML(hs.text);
var a;
if (hs.URL) {
a = document.createElement('a');
a.setAttribute('href', hs.URL);
a.setAttribute('href', encodeURI(hs.URL));
a.setAttribute('target', '_blank');
renderContainer.appendChild(a);
div.style.cursor = 'pointer';
@@ -1136,19 +1136,19 @@ function createHotSpots() {
a.appendChild(div);
} else if (hs.video) {
var video = document.createElement('video');
video.setAttribute('src',hs.video);
video.setAttribute('controls',true);
video.setAttribute('style','width:' + hs.width + 'px');
video.setAttribute('src', encodeURI(hs.video));
video.setAttribute('controls', true);
video.setAttribute('style', 'width:' + hs.width + 'px');
renderContainer.appendChild(div);
span.appendChild(video);
} else if (hs.image) {
a = document.createElement('a');
a.setAttribute('href', hs.image);
a.setAttribute('href', encodeURI(hs.image));
a.setAttribute('target', '_blank');
span.appendChild(a);
var image = document.createElement('img');
image.setAttribute('src',hs.image);
image.setAttribute('style','width:' + hs.width + 'px');
image.setAttribute('src', encodeURI(hs.image));
image.setAttribute('style', 'width:' + hs.width + 'px');
renderContainer.appendChild(div);
a.appendChild(image);
@@ -1300,7 +1300,7 @@ function processOptions() {
preview = new Image();
preview.crossOrigin = 'anonymous';
preview.src = p;
preview.src = encodeURI(p);
preview.className = 'pnlm-preview-img';
renderContainer.appendChild(preview);
}
@@ -1310,17 +1310,17 @@ function processOptions() {
if (config.hasOwnProperty(key)) {
switch(key) {
case 'title':
infoDisplay.title.innerHTML = config[key];
infoDisplay.title.innerHTML = escapeHTML(config[key]);
infoDisplay.container.style.display = 'inline';
break;
case 'author':
infoDisplay.author.innerHTML = 'by ' + config[key];
infoDisplay.author.innerHTML = 'by ' + escapeHTML(config[key]);
infoDisplay.container.style.display = 'inline';
break;
case 'fallback':
infoDisplay.errorMsg.innerHTML = '<p>Your browser does not support WebGL.<br><a href="' + config[key] + '" target="_blank">Click here to view this panorama in an alternative viewer.</a></p>';
infoDisplay.errorMsg.innerHTML = '<p>Your browser does not support WebGL.<br><a href="' + encodeURI(config[key]) + '" target="_blank">Click here to view this panorama in an alternative viewer.</a></p>';
break;
case 'hfov':
@@ -1358,11 +1358,6 @@ function processOptions() {
config.autoRotateStopDelay = config[key];
break;
case 'header':
// Add contents to header
document.getElementsByTagName('head')[0].innerHTML += config[key];
break;
case 'showZoomCtrl':
if (config[key]) {
// Show zoom controls
@@ -1549,6 +1544,21 @@ function loadScene(sceneId, targetPitch, targetYaw) {
}

/**
* Escapes HTML string (to mitigate possible DOM XSS attacks).
* @private
* @param {string} s - String to escape
* @returns {string} Escaped string
*/
function escapeHTML(s) {
return String(s).replace(/&/g, '&amp;')
.replace('"', '&quot;')
.replace("'", '&#39;')
.replace('<', '&lt;')
.replace('>', '&gt;')
.replace('/', '&#x2f;');
}

/**
* Returns the pitch of the center of the view.
* @memberof Viewer
* @instance


Chargement…
Annuler
Enregistrer