forked from sheetjs/sheetjs
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d2f2e17963 | |||
| 789e2d6870 | |||
| 66cf8d2117 | |||
| ca62b33453 | |||
| 1782abbc39 |
@ -485,7 +485,7 @@ function parse_XLUnicodeStringNoCch(blob, cch, opts) {
|
||||
/* 2.5.294 XLUnicodeString */
|
||||
function parse_XLUnicodeString(blob, length, opts) {
|
||||
var cch = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
|
||||
if(cch === 0) { blob.l++; return ""; }
|
||||
if(cch === 0) { if(opts.biff <= 8) blob.l++; return ""; }
|
||||
return parse_XLUnicodeStringNoCch(blob, cch, opts);
|
||||
}
|
||||
/* BIFF5 override */
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
/* L.5.5.2 SpreadsheetML Comments + VML Schema */
|
||||
function parse_vml(data/*:string*/, sheet, comments) {
|
||||
var cidx = 0;
|
||||
(str_match_xml_ns_g(data, "shape")||[]).forEach(function(m) {
|
||||
/* see CT_Group for other possible elements */
|
||||
(str_match_xml_ns_g(data, "(?:shape|rect)")||[]).forEach(function(m) {
|
||||
var type = "";
|
||||
var hidden = true;
|
||||
var aidx = -1;
|
||||
|
||||
@ -417,7 +417,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
|
||||
} else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
|
||||
// TODO: parse formula
|
||||
ftag = parsexmltag(cref[0]);
|
||||
var ___f = unescapexml(utf8read(cref[1]));
|
||||
var ___f = unescapexml(utf8read(cref[1]), true);
|
||||
if(!opts.xlfn) ___f = _xlfn(___f);
|
||||
sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r];
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HT
|
||||
if(cell.v != null) sp["data-v"] = escapehtml(cell.v instanceof Date ? cell.v.toISOString() : cell.v);
|
||||
if(cell.z != null) sp["data-z"] = cell.z;
|
||||
if(cell.f != null) sp["data-f"] = escapehtml(cell.f);
|
||||
if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + escapehtml(cell.l.Target) +'">' + w + '</a>';
|
||||
if(cell.l && (cell.l.Target || "#").charAt(0) != "#" && (!o.sanitizeLinks || (cell.l.Target || "").slice(0, 11).toLowerCase() != 'javascript:')) w = '<a href="' + escapehtml(cell.l.Target) +'">' + w + '</a>';
|
||||
}
|
||||
sp.id = (o.id || "sjs") + "-" + coord;
|
||||
oo.push(writextag('td', w, sp));
|
||||
|
||||
@ -116,6 +116,7 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
|
||||
case 0x7B: if(n[1] === 0x5C && n[2] === 0x72 && n[3] === 0x74) return rtf_to_workbook(d, o); break;
|
||||
case 0x0A: case 0x0D: case 0x20: return read_plaintext_raw(d, o);
|
||||
case 0x89: if(n[1] === 0x50 && n[2] === 0x4E && n[3] === 0x47) throw new Error("PNG Image File is not a spreadsheet"); break;
|
||||
case 0x25: if(n[1] === 0x50 && n[2] === 0x44 && n[3] === 0x46) throw new Error("PDF File is not a spreadsheet"); break;
|
||||
case 0x08: if(n[1] === 0xE7) throw new Error("Unsupported Multiplan 1.x file!"); break;
|
||||
case 0x0C:
|
||||
if(n[1] === 0xEC) throw new Error("Unsupported Multiplan 2.x file!");
|
||||
|
||||
15
test.js
15
test.js
@ -1529,6 +1529,21 @@ describe('write features', function() {
|
||||
var str = X.write(wb, {bookType:"html", type:"binary"});
|
||||
assert.ok(str.indexOf("<b>abc</b>") > 0);
|
||||
});
|
||||
it('should remove javascript: URLs when sanitizeLinks is true', function() {
|
||||
var sheet = X.utils.aoa_to_sheet([["Click me"]]);
|
||||
get_cell(sheet, "A1").l = { Target: "javascript:alert('xss')" };
|
||||
|
||||
assert.ok(X.utils.sheet_to_html(sheet).indexOf("javascript:alert") > -1, "javascript: should not be stripped by default");
|
||||
|
||||
assert.ok(X.utils.sheet_to_html(sheet, { sanitizeLinks: true }).indexOf("javascript:alert") === -1, "javascript: should be stripped with sanitizeLinks");
|
||||
});
|
||||
it('should preserve non-javascript URLs with sanitizeLinks', function() {
|
||||
var sheet = X.utils.aoa_to_sheet([["Link"]]);
|
||||
get_cell(sheet, "A1").l = { Target: "https://example.com" };
|
||||
|
||||
var str = X.utils.sheet_to_html(sheet, { sanitizeLinks: true });
|
||||
assert.ok(str.indexOf('href="https://example.com"') > -1);
|
||||
});
|
||||
});
|
||||
describe('sheet range limits', function() { [
|
||||
["biff2", "IV16384"],
|
||||
|
||||
15
test.mjs
generated
15
test.mjs
generated
@ -1533,6 +1533,21 @@ describe('write features', function() {
|
||||
var str = X.write(wb, {bookType:"html", type:"binary"});
|
||||
assert.ok(str.indexOf("<b>abc</b>") > 0);
|
||||
});
|
||||
it('should remove javascript: URLs when sanitizeLinks is true', function() {
|
||||
var sheet = X.utils.aoa_to_sheet([["Click me"]]);
|
||||
get_cell(sheet, "A1").l = { Target: "javascript:alert('xss')" };
|
||||
|
||||
assert.ok(X.utils.sheet_to_html(sheet).indexOf("javascript:alert") > -1, "javascript: should not be stripped by default");
|
||||
|
||||
assert.ok(X.utils.sheet_to_html(sheet, { sanitizeLinks: true }).indexOf("javascript:alert") === -1, "javascript: should be stripped with sanitizeLinks");
|
||||
});
|
||||
it('should preserve non-javascript URLs with sanitizeLinks', function() {
|
||||
var sheet = X.utils.aoa_to_sheet([["Link"]]);
|
||||
get_cell(sheet, "A1").l = { Target: "https://example.com" };
|
||||
|
||||
var str = X.utils.sheet_to_html(sheet, { sanitizeLinks: true });
|
||||
assert.ok(str.indexOf('href="https://example.com"') > -1);
|
||||
});
|
||||
});
|
||||
describe('sheet range limits', function() { [
|
||||
["biff2", "IV16384"],
|
||||
|
||||
15
test.mts
15
test.mts
@ -1480,6 +1480,21 @@ describe('write features', function() {
|
||||
var str = X.write(wb, {bookType:"html", type:"binary"});
|
||||
assert.ok(str.indexOf("<b>abc</b>") > 0);
|
||||
});
|
||||
it('should remove javascript: URLs when sanitizeLinks is true', function() {
|
||||
var sheet = X.utils.aoa_to_sheet([["Click me"]]);
|
||||
get_cell(sheet, "A1").l = { Target: "javascript:alert('xss')" };
|
||||
|
||||
assert.ok(X.utils.sheet_to_html(sheet).indexOf("javascript:alert") > -1, "javascript: should not be stripped by default");
|
||||
|
||||
assert.ok(X.utils.sheet_to_html(sheet, { sanitizeLinks: true }).indexOf("javascript:alert") === -1, "javascript: should be stripped with sanitizeLinks");
|
||||
});
|
||||
it('should preserve non-javascript URLs with sanitizeLinks', function() {
|
||||
var sheet = X.utils.aoa_to_sheet([["Link"]]);
|
||||
get_cell(sheet, "A1").l = { Target: "https://example.com" };
|
||||
|
||||
var str = X.utils.sheet_to_html(sheet, { sanitizeLinks: true });
|
||||
assert.ok(str.indexOf('href="https://example.com"') > -1);
|
||||
});
|
||||
});
|
||||
describe('sheet range limits', function() { var b = ([
|
||||
["biff2", "IV16384"],
|
||||
|
||||
15
test.test.mjs
generated
15
test.test.mjs
generated
@ -1533,6 +1533,21 @@ describe('write features', function() {
|
||||
var str = X.write(wb, {bookType:"html", type:"binary"});
|
||||
assert.ok(str.indexOf("<b>abc</b>") > 0);
|
||||
});
|
||||
it('should remove javascript: URLs when sanitizeLinks is true', function() {
|
||||
var sheet = X.utils.aoa_to_sheet([["Click me"]]);
|
||||
get_cell(sheet, "A1").l = { Target: "javascript:alert('xss')" };
|
||||
|
||||
assert.ok(X.utils.sheet_to_html(sheet).indexOf("javascript:alert") > -1, "javascript: should not be stripped by default");
|
||||
|
||||
assert.ok(X.utils.sheet_to_html(sheet, { sanitizeLinks: true }).indexOf("javascript:alert") === -1, "javascript: should be stripped with sanitizeLinks");
|
||||
});
|
||||
it('should preserve non-javascript URLs with sanitizeLinks', function() {
|
||||
var sheet = X.utils.aoa_to_sheet([["Link"]]);
|
||||
get_cell(sheet, "A1").l = { Target: "https://example.com" };
|
||||
|
||||
var str = X.utils.sheet_to_html(sheet, { sanitizeLinks: true });
|
||||
assert.ok(str.indexOf('href="https://example.com"') > -1);
|
||||
});
|
||||
});
|
||||
describe('sheet range limits', function() { [
|
||||
["biff2", "IV16384"],
|
||||
|
||||
15
test.ts
15
test.ts
@ -1480,6 +1480,21 @@ Deno.test('write features', async function(t) {
|
||||
var str = X.write(wb, {bookType:"html", type:"binary"});
|
||||
assert.assert(str.indexOf("<b>abc</b>") > 0);
|
||||
});
|
||||
await t.step('should remove javascript: URLs when sanitizeLinks is true', async function(t) {
|
||||
var sheet = X.utils.aoa_to_sheet([["Click me"]]);
|
||||
get_cell(sheet, "A1").l = { Target: "javascript:alert('xss')" };
|
||||
|
||||
assert.assert(X.utils.sheet_to_html(sheet).indexOf("javascript:alert") > -1, "javascript: should not be stripped by default");
|
||||
|
||||
assert.assert(X.utils.sheet_to_html(sheet, { sanitizeLinks: true }).indexOf("javascript:alert") === -1, "javascript: should be stripped with sanitizeLinks");
|
||||
});
|
||||
await t.step('should preserve non-javascript URLs with sanitizeLinks', async function(t) {
|
||||
var sheet = X.utils.aoa_to_sheet([["Link"]]);
|
||||
get_cell(sheet, "A1").l = { Target: "https://example.com" };
|
||||
|
||||
var str = X.utils.sheet_to_html(sheet, { sanitizeLinks: true });
|
||||
assert.assert(str.indexOf('href="https://example.com"') > -1);
|
||||
});
|
||||
});
|
||||
await t.step('sheet range limits', async function(t) { var b = ([
|
||||
["biff2", "IV16384"],
|
||||
|
||||
15
testnocp.ts
15
testnocp.ts
@ -1479,6 +1479,21 @@ Deno.test('write features', async function(t) {
|
||||
var str = X.write(wb, {bookType:"html", type:"binary"});
|
||||
assert.assert(str.indexOf("<b>abc</b>") > 0);
|
||||
});
|
||||
await t.step('should remove javascript: URLs when sanitizeLinks is true', async function(t) {
|
||||
var sheet = X.utils.aoa_to_sheet([["Click me"]]);
|
||||
get_cell(sheet, "A1").l = { Target: "javascript:alert('xss')" };
|
||||
|
||||
assert.assert(X.utils.sheet_to_html(sheet).indexOf("javascript:alert") > -1, "javascript: should not be stripped by default");
|
||||
|
||||
assert.assert(X.utils.sheet_to_html(sheet, { sanitizeLinks: true }).indexOf("javascript:alert") === -1, "javascript: should be stripped with sanitizeLinks");
|
||||
});
|
||||
await t.step('should preserve non-javascript URLs with sanitizeLinks', async function(t) {
|
||||
var sheet = X.utils.aoa_to_sheet([["Link"]]);
|
||||
get_cell(sheet, "A1").l = { Target: "https://example.com" };
|
||||
|
||||
var str = X.utils.sheet_to_html(sheet, { sanitizeLinks: true });
|
||||
assert.assert(str.indexOf('href="https://example.com"') > -1);
|
||||
});
|
||||
});
|
||||
await t.step('sheet range limits', async function(t) { var b = ([
|
||||
["biff2", "IV16384"],
|
||||
|
||||
15
tests/core.js
generated
15
tests/core.js
generated
@ -1529,6 +1529,21 @@ describe('write features', function() {
|
||||
var str = X.write(wb, {bookType:"html", type:"binary"});
|
||||
assert.ok(str.indexOf("<b>abc</b>") > 0);
|
||||
});
|
||||
it('should remove javascript: URLs when sanitizeLinks is true', function() {
|
||||
var sheet = X.utils.aoa_to_sheet([["Click me"]]);
|
||||
get_cell(sheet, "A1").l = { Target: "javascript:alert('xss')" };
|
||||
|
||||
assert.ok(X.utils.sheet_to_html(sheet).indexOf("javascript:alert") > -1, "javascript: should not be stripped by default");
|
||||
|
||||
assert.ok(X.utils.sheet_to_html(sheet, { sanitizeLinks: true }).indexOf("javascript:alert") === -1, "javascript: should be stripped with sanitizeLinks");
|
||||
});
|
||||
it('should preserve non-javascript URLs with sanitizeLinks', function() {
|
||||
var sheet = X.utils.aoa_to_sheet([["Link"]]);
|
||||
get_cell(sheet, "A1").l = { Target: "https://example.com" };
|
||||
|
||||
var str = X.utils.sheet_to_html(sheet, { sanitizeLinks: true });
|
||||
assert.ok(str.indexOf('href="https://example.com"') > -1);
|
||||
});
|
||||
});
|
||||
describe('sheet range limits', function() { [
|
||||
["biff2", "IV16384"],
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
var assert = function(bool) { if(!bool) { throw new Error("failed assert"); } };
|
||||
assert.ok = function(bool) { if(!bool) { throw new Error("failed assert"); } };
|
||||
var assert = function(bool, msg) { if(!bool) { throw new Error(msg || "failed assert"); } };
|
||||
assert.ok = function(bool, msg) { if(!bool) { throw new Error(msg || "failed assert"); } };
|
||||
assert.deepEqualArray = function(x,y) {
|
||||
if(x.length != y.length) throw new Error("Length mismatch: " + x.length + " != " + y.length);
|
||||
for(var i = 0; i < x.length; ++i) assert.deepEqual(x[i], y[i]);
|
||||
@ -13,8 +13,8 @@ assert.deepEqual = function(x,y) {
|
||||
};
|
||||
assert.notEqual = function(x,y) { if(x == y) throw new Error(x + " == " + y); };
|
||||
assert.equal = function(x,y) { if(x != y) throw new Error(x + " !== " + y); };
|
||||
assert.throws = function(cb) { var pass = true; try { cb(); pass = false; } catch(e) { } if(!pass) throw new Error("Function did not throw"); };
|
||||
assert.doesNotThrow = function(cb) { var pass = true; try { cb(); } catch(e) { pass = false; } if(!pass) throw new Error("Function did throw"); };
|
||||
assert.throws = function(cb, msg) { var pass = true; try { cb(); pass = false; } catch(e) { } if(!pass) throw new Error(msg || "Function did not throw"); };
|
||||
assert.doesNotThrow = function(cb, msg) { var pass = true; try { cb(); } catch(e) { pass = false; } if(!pass) throw new Error(msg || "Function did throw"); };
|
||||
|
||||
function require(s) {
|
||||
switch(s) {
|
||||
|
||||
3
types/index.d.ts
vendored
3
types/index.d.ts
vendored
@ -800,6 +800,9 @@ export interface Sheet2HTMLOpts {
|
||||
|
||||
/** Footer HTML */
|
||||
footer?: string;
|
||||
|
||||
/** If true, remove javascript: URLs from hyperlinks */
|
||||
sanitizeLinks?: boolean;
|
||||
}
|
||||
|
||||
export interface Sheet2JSONOpts extends DateNFOption {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user