version bump 0.12.9: XLSX/XLSB abnormal paths

- support for arbitrary subfile paths in OPC
- updated CFB to 1.0.6
This commit is contained in:
SheetJS 2018-04-13 00:48:21 -04:00
parent 93f7749bec
commit 04d5e49e95
21 changed files with 150 additions and 98 deletions

@ -1 +1 @@
XLSX.version = '0.12.8';
XLSX.version = '0.12.9';

@ -38,7 +38,7 @@ type CFBFiles = {[n:string]:CFBEntry};
/* [MS-CFB] v20171201 */
var CFB = (function _CFB(){
var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/;
exports.version = '1.0.5';
exports.version = '1.0.6';
/* [MS-CFB] 2.6.4 */
function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
var L = l.split("/"), R = r.split("/");
@ -216,8 +216,8 @@ function build_full_paths(FI/*:CFBFileIndex*/, FP/*:Array<string>*/, Paths/*:Arr
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
}
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
}
for(i=1; i < pl; ++i) if(dad[i] === i) {
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
@ -684,8 +684,9 @@ function cfb_new(opts/*:?any*/)/*:CFBContainer*/ {
}
function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, opts/*:?any*/)/*:CFBEntry*/ {
init_cfb(cfb);
var file = CFB.find(cfb, name);
var unsafe = opts && opts.unsafe;
if(!unsafe) init_cfb(cfb);
var file = !unsafe && CFB.find(cfb, name);
if(!file) {
var fpath/*:string*/ = cfb.FullPaths[0];
if(name.slice(0, fpath.length) == fpath) fpath = name;
@ -696,7 +697,7 @@ function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, o
file = ({name: filename(name), type: 2}/*:any*/);
cfb.FileIndex.push(file);
cfb.FullPaths.push(fpath);
CFB.utils.cfb_gc(cfb);
if(!unsafe) CFB.utils.cfb_gc(cfb);
}
/*:: if(!file) throw new Error("unreachable"); */
file.content = (content/*:any*/);

@ -129,15 +129,20 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
}
var wbext = xlsb ? "bin" : "xml";
var wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
var wbrelsi = dir.workbooks[0].lastIndexOf("/");
var wbrelsfile = (dir.workbooks[0].slice(0, wbrelsi+1) + "_rels/" + dir.workbooks[0].slice(wbrelsi+1) + ".rels").replace(/^\//,"");
if(!safegetzipfile(zip, wbrelsfile)) wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
var wbrels = parse_rels(getzipstr(zip, wbrelsfile, true), wbrelsfile);
if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
/* Numbers iOS hack */
var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
for(i = 0; i != props.Worksheets; ++i) {
var stype = "sheet";
if(wbrels && wbrels[i]) {
path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
if(!safegetzipfile(zip, path)) path = wbrels[i][1];
if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/.*$/,"") + wbrels[i][1];
stype = wbrels[i][2];
} else {
path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;

2
dist/shim.min.js generated vendored

File diff suppressed because one or more lines are too long

28
dist/xlsx.core.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.core.min.map generated vendored

File diff suppressed because one or more lines are too long

28
dist/xlsx.extendscript.js generated vendored

@ -54,6 +54,12 @@ if(!Array.prototype.indexOf) Array.prototype.indexOf = function(needle) {
return -1;
};
if(!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(needle) {
var len = (this.length>>>0), i = len - 1;
for(; i>=0; --i) if(this[i] === needle) return i;
return -1;
};
if(!Array.isArray) Array.isArray = function(obj) { return Object.prototype.toString.call(obj) === "[object Array]"; };
if(!Date.prototype.toISOString) Date.prototype.toISOString = (function() {
@ -9141,7 +9147,7 @@ module.exports = ZStream;
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.12.8';
XLSX.version = '0.12.9';
var current_codepage = 1200, current_ansi = 1252;
/*global cptable:true */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -10261,7 +10267,7 @@ var DO_NOT_EXPORT_CFB = true;
/* [MS-CFB] v20171201 */
var CFB = (function _CFB(){
var exports = {};
exports.version = '1.0.5';
exports.version = '1.0.6';
/* [MS-CFB] 2.6.4 */
function namecmp(l, r) {
var L = l.split("/"), R = r.split("/");
@ -10439,8 +10445,8 @@ function build_full_paths(FI, FP, Paths) {
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
}
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
}
for(i=1; i < pl; ++i) if(dad[i] === i) {
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
@ -10901,8 +10907,9 @@ function cfb_new(opts) {
}
function cfb_add(cfb, name, content, opts) {
init_cfb(cfb);
var file = CFB.find(cfb, name);
var unsafe = opts && opts.unsafe;
if(!unsafe) init_cfb(cfb);
var file = !unsafe && CFB.find(cfb, name);
if(!file) {
var fpath = cfb.FullPaths[0];
if(name.slice(0, fpath.length) == fpath) fpath = name;
@ -10913,7 +10920,7 @@ function cfb_add(cfb, name, content, opts) {
file = ({name: filename(name), type: 2});
cfb.FileIndex.push(file);
cfb.FullPaths.push(fpath);
CFB.utils.cfb_gc(cfb);
if(!unsafe) CFB.utils.cfb_gc(cfb);
}
file.content = (content);
file.size = content ? content.length : 0;
@ -28082,15 +28089,20 @@ function parse_zip(zip, opts) {
}
var wbext = xlsb ? "bin" : "xml";
var wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
var wbrelsi = dir.workbooks[0].lastIndexOf("/");
var wbrelsfile = (dir.workbooks[0].slice(0, wbrelsi+1) + "_rels/" + dir.workbooks[0].slice(wbrelsi+1) + ".rels").replace(/^\//,"");
if(!safegetzipfile(zip, wbrelsfile)) wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
var wbrels = parse_rels(getzipstr(zip, wbrelsfile, true), wbrelsfile);
if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
/* Numbers iOS hack */
var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
for(i = 0; i != props.Worksheets; ++i) {
var stype = "sheet";
if(wbrels && wbrels[i]) {
path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
if(!safegetzipfile(zip, path)) path = wbrels[i][1];
if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/.*$/,"") + wbrels[i][1];
stype = wbrels[i][2];
} else {
path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;

32
dist/xlsx.full.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.full.min.map generated vendored

File diff suppressed because one or more lines are too long

22
dist/xlsx.js generated vendored

@ -4,7 +4,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.12.8';
XLSX.version = '0.12.9';
var current_codepage = 1200, current_ansi = 1252;
/*global cptable:true */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -1124,7 +1124,7 @@ var DO_NOT_EXPORT_CFB = true;
/* [MS-CFB] v20171201 */
var CFB = (function _CFB(){
var exports = {};
exports.version = '1.0.5';
exports.version = '1.0.6';
/* [MS-CFB] 2.6.4 */
function namecmp(l, r) {
var L = l.split("/"), R = r.split("/");
@ -1302,8 +1302,8 @@ function build_full_paths(FI, FP, Paths) {
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
}
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
}
for(i=1; i < pl; ++i) if(dad[i] === i) {
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
@ -1764,8 +1764,9 @@ function cfb_new(opts) {
}
function cfb_add(cfb, name, content, opts) {
init_cfb(cfb);
var file = CFB.find(cfb, name);
var unsafe = opts && opts.unsafe;
if(!unsafe) init_cfb(cfb);
var file = !unsafe && CFB.find(cfb, name);
if(!file) {
var fpath = cfb.FullPaths[0];
if(name.slice(0, fpath.length) == fpath) fpath = name;
@ -1776,7 +1777,7 @@ function cfb_add(cfb, name, content, opts) {
file = ({name: filename(name), type: 2});
cfb.FileIndex.push(file);
cfb.FullPaths.push(fpath);
CFB.utils.cfb_gc(cfb);
if(!unsafe) CFB.utils.cfb_gc(cfb);
}
file.content = (content);
file.size = content ? content.length : 0;
@ -18945,15 +18946,20 @@ function parse_zip(zip, opts) {
}
var wbext = xlsb ? "bin" : "xml";
var wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
var wbrelsi = dir.workbooks[0].lastIndexOf("/");
var wbrelsfile = (dir.workbooks[0].slice(0, wbrelsi+1) + "_rels/" + dir.workbooks[0].slice(wbrelsi+1) + ".rels").replace(/^\//,"");
if(!safegetzipfile(zip, wbrelsfile)) wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
var wbrels = parse_rels(getzipstr(zip, wbrelsfile, true), wbrelsfile);
if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
/* Numbers iOS hack */
var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
for(i = 0; i != props.Worksheets; ++i) {
var stype = "sheet";
if(wbrels && wbrels[i]) {
path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
if(!safegetzipfile(zip, path)) path = wbrels[i][1];
if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/.*$/,"") + wbrels[i][1];
stype = wbrels[i][2];
} else {
path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;

26
dist/xlsx.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.min.map generated vendored

File diff suppressed because one or more lines are too long

@ -1,6 +1,6 @@
{
"name": "xlsx",
"version": "0.12.8",
"version": "0.12.9",
"author": "sheetjs",
"description": "SheetJS Spreadsheet data parser and writer",
"keywords": [
@ -31,7 +31,7 @@
},
"dependencies": {
"adler-32": "~1.2.0",
"cfb": "~1.0.5",
"cfb": "~1.0.6",
"codepage": "~1.12.1",
"commander": "~2.14.1",
"crc-32": "~1.2.0",

@ -53,6 +53,12 @@ if(!Array.prototype.indexOf) Array.prototype.indexOf = function(needle) {
return -1;
};
if(!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(needle) {
var len = (this.length>>>0), i = len - 1;
for(; i>=0; --i) if(this[i] === needle) return i;
return -1;
};
if(!Array.isArray) Array.isArray = function(obj) { return Object.prototype.toString.call(obj) === "[object Array]"; };
if(!Date.prototype.toISOString) Date.prototype.toISOString = (function() {

11
test.js

@ -1767,7 +1767,6 @@ describe('json output', function() {
if(n & 2) opts.raw = 1;
if(n & 4) opts.defval = null;
var J = X.utils.sheet_to_json(ws, opts);
// $FlowIgnore
for(var i = 0; i < 3; ++i) {
var k = ((n&1) ? J[i+1][0] : J[i].Field);
assert((n&4) ? (k === null) : (k !== null));
@ -1953,10 +1952,10 @@ describe('CSV', function() {
});
});
if(fs.existsSync('./test_files/dbf/d11.dbf')) describe('dbf', function() {
if(fs.existsSync(dir + 'dbf/d11.dbf')) describe('dbf', function() {
var wbs/*:Array<any>*/ = ([
['d11', './test_files/dbf/d11.dbf'],
['vfp3', './test_files/dbf/vfp3.dbf']
['d11', dir + 'dbf/d11.dbf'],
['vfp3', dir + 'dbf/vfp3.dbf']
]/*:any*/);
var bef = (function() {
wbs = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), {type:TYPE})]; });
@ -2150,6 +2149,10 @@ describe('corner cases', function() {
void X.read(X.write(wb, {bookType:btype, type:type}), {type:type});
});
});
if(fs.existsSync(dir + 'wtf_path.xlsx')) it('OPC oddities', function() {
X.read(fs.readFileSync(dir + 'wtf_path.xlsx'), {WTF:1, type:TYPE});
X.read(fs.readFileSync(dir + 'wtf_path.xlsb'), {WTF:1, type:TYPE});
});
});
describe('encryption', function() {

@ -1 +1 @@
Subproject commit a889cc5c7131bce253d5e861dcdf46ae60a9c4fd
Subproject commit d1cad393ce43824fcaa31287afd633e2287361b7

11
tests/core.js generated

@ -1767,7 +1767,6 @@ describe('json output', function() {
if(n & 2) opts.raw = 1;
if(n & 4) opts.defval = null;
var J = X.utils.sheet_to_json(ws, opts);
// $FlowIgnore
for(var i = 0; i < 3; ++i) {
var k = ((n&1) ? J[i+1][0] : J[i].Field);
assert((n&4) ? (k === null) : (k !== null));
@ -1953,10 +1952,10 @@ describe('CSV', function() {
});
});
if(fs.existsSync('./test_files/dbf/d11.dbf')) describe('dbf', function() {
if(fs.existsSync(dir + 'dbf/d11.dbf')) describe('dbf', function() {
var wbs/*:Array<any>*/ = ([
['d11', './test_files/dbf/d11.dbf'],
['vfp3', './test_files/dbf/vfp3.dbf']
['d11', dir + 'dbf/d11.dbf'],
['vfp3', dir + 'dbf/vfp3.dbf']
]/*:any*/);
var bef = (function() {
wbs = wbs.map(function(x) { return [x[0], X.read(fs.readFileSync(x[1]), {type:TYPE})]; });
@ -2150,6 +2149,10 @@ describe('corner cases', function() {
void X.read(X.write(wb, {bookType:btype, type:type}), {type:type});
});
});
if(fs.existsSync(dir + 'wtf_path.xlsx')) it('OPC oddities', function() {
X.read(fs.readFileSync(dir + 'wtf_path.xlsx'), {WTF:1, type:TYPE});
X.read(fs.readFileSync(dir + 'wtf_path.xlsb'), {WTF:1, type:TYPE});
});
});
describe('encryption', function() {

File diff suppressed because one or more lines are too long

@ -115,3 +115,5 @@
./test_files/password_2002_40_xor.xls
./test_files/dbf/d11.dbf
./test_files/dbf/vfp3.dbf
./test_files/wtf_path.xlsx
./test_files/wtf_path.xlsb

@ -4,7 +4,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.12.8';
XLSX.version = '0.12.9';
var current_codepage = 1200, current_ansi = 1252;
/*:: declare var cptable:any; */
/*global cptable:true */
@ -1188,7 +1188,7 @@ type CFBFiles = {[n:string]:CFBEntry};
/* [MS-CFB] v20171201 */
var CFB = (function _CFB(){
var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/;
exports.version = '1.0.5';
exports.version = '1.0.6';
/* [MS-CFB] 2.6.4 */
function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
var L = l.split("/"), R = r.split("/");
@ -1366,8 +1366,8 @@ function build_full_paths(FI/*:CFBFileIndex*/, FP/*:Array<string>*/, Paths/*:Arr
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
}
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
}
for(i=1; i < pl; ++i) if(dad[i] === i) {
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
@ -1834,8 +1834,9 @@ function cfb_new(opts/*:?any*/)/*:CFBContainer*/ {
}
function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, opts/*:?any*/)/*:CFBEntry*/ {
init_cfb(cfb);
var file = CFB.find(cfb, name);
var unsafe = opts && opts.unsafe;
if(!unsafe) init_cfb(cfb);
var file = !unsafe && CFB.find(cfb, name);
if(!file) {
var fpath/*:string*/ = cfb.FullPaths[0];
if(name.slice(0, fpath.length) == fpath) fpath = name;
@ -1846,7 +1847,7 @@ function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, o
file = ({name: filename(name), type: 2}/*:any*/);
cfb.FileIndex.push(file);
cfb.FullPaths.push(fpath);
CFB.utils.cfb_gc(cfb);
if(!unsafe) CFB.utils.cfb_gc(cfb);
}
/*:: if(!file) throw new Error("unreachable"); */
file.content = (content/*:any*/);
@ -19057,15 +19058,20 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
}
var wbext = xlsb ? "bin" : "xml";
var wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
var wbrelsi = dir.workbooks[0].lastIndexOf("/");
var wbrelsfile = (dir.workbooks[0].slice(0, wbrelsi+1) + "_rels/" + dir.workbooks[0].slice(wbrelsi+1) + ".rels").replace(/^\//,"");
if(!safegetzipfile(zip, wbrelsfile)) wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
var wbrels = parse_rels(getzipstr(zip, wbrelsfile, true), wbrelsfile);
if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
/* Numbers iOS hack */
var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
for(i = 0; i != props.Worksheets; ++i) {
var stype = "sheet";
if(wbrels && wbrels[i]) {
path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
if(!safegetzipfile(zip, path)) path = wbrels[i][1];
if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/.*$/,"") + wbrels[i][1];
stype = wbrels[i][2];
} else {
path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;

22
xlsx.js generated

@ -4,7 +4,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.12.8';
XLSX.version = '0.12.9';
var current_codepage = 1200, current_ansi = 1252;
/*global cptable:true */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -1124,7 +1124,7 @@ var DO_NOT_EXPORT_CFB = true;
/* [MS-CFB] v20171201 */
var CFB = (function _CFB(){
var exports = {};
exports.version = '1.0.5';
exports.version = '1.0.6';
/* [MS-CFB] 2.6.4 */
function namecmp(l, r) {
var L = l.split("/"), R = r.split("/");
@ -1302,8 +1302,8 @@ function build_full_paths(FI, FP, Paths) {
if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
}
if(C !== -1 /*NOSTREAM*/) dad[C] = i;
if(L !== -1) { dad[L] = dad[i]; q.push(L); }
if(R !== -1) { dad[R] = dad[i]; q.push(R); }
if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
}
for(i=1; i < pl; ++i) if(dad[i] === i) {
if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
@ -1764,8 +1764,9 @@ function cfb_new(opts) {
}
function cfb_add(cfb, name, content, opts) {
init_cfb(cfb);
var file = CFB.find(cfb, name);
var unsafe = opts && opts.unsafe;
if(!unsafe) init_cfb(cfb);
var file = !unsafe && CFB.find(cfb, name);
if(!file) {
var fpath = cfb.FullPaths[0];
if(name.slice(0, fpath.length) == fpath) fpath = name;
@ -1776,7 +1777,7 @@ function cfb_add(cfb, name, content, opts) {
file = ({name: filename(name), type: 2});
cfb.FileIndex.push(file);
cfb.FullPaths.push(fpath);
CFB.utils.cfb_gc(cfb);
if(!unsafe) CFB.utils.cfb_gc(cfb);
}
file.content = (content);
file.size = content ? content.length : 0;
@ -18945,15 +18946,20 @@ function parse_zip(zip, opts) {
}
var wbext = xlsb ? "bin" : "xml";
var wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
var wbrelsi = dir.workbooks[0].lastIndexOf("/");
var wbrelsfile = (dir.workbooks[0].slice(0, wbrelsi+1) + "_rels/" + dir.workbooks[0].slice(wbrelsi+1) + ".rels").replace(/^\//,"");
if(!safegetzipfile(zip, wbrelsfile)) wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
var wbrels = parse_rels(getzipstr(zip, wbrelsfile, true), wbrelsfile);
if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
/* Numbers iOS hack */
var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
for(i = 0; i != props.Worksheets; ++i) {
var stype = "sheet";
if(wbrels && wbrels[i]) {
path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
if(!safegetzipfile(zip, path)) path = wbrels[i][1];
if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/.*$/,"") + wbrels[i][1];
stype = wbrels[i][2];
} else {
path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;