Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
version bump 0.6.0: removing prototype pollution
- 08_blob.js does not add to array prototype
- version numbers included in XLS.js (bits/01_version.js, from package.json)
- min node version 0.8 (removed bits/03_shim.js)
- CFB cleaned up (does not rely on separate module)
  • Loading branch information
SheetJSDev committed Jan 21, 2014
1 parent 8876109 commit c52fe38
Show file tree
Hide file tree
Showing 13 changed files with 130 additions and 187 deletions.
3 changes: 3 additions & 0 deletions Makefile
Expand Up @@ -4,6 +4,9 @@ TARGET=xls.js
$(TARGET): $(DEPS)
cat $^ > $@

bits/01_version.js: package.json
echo "XLS.version = '"`grep version package.json | awk '{gsub(/[^0-9\.]/,"",$$2); print $$2}'`"';" > bits/01_version.js

.PHONY: clean
clean:
rm $(TARGET)
Expand Down
12 changes: 9 additions & 3 deletions bin/xls2csv.njs
Expand Up @@ -4,7 +4,7 @@
var XLS = require('../');
var fs = require('fs'), program = require('commander');
program
.version('0.5.1')
.version(XLS.version)
.usage('[options] <file> [sheetname]')
.option('-f, --file <file>', 'use specified workbook')
.option('-s, --sheet <sheet>', 'print specified sheet (default first sheet)')
Expand All @@ -16,8 +16,14 @@ program
.option('-R, --row-sep <sep>', 'CSV row separator', "\n")
.option('--dev', 'development mode')
.option('--read', 'read but do not print out contents')
.option('-q, --quiet', 'quiet mode')
.parse(process.argv);
.option('-q, --quiet', 'quiet mode');

program.on('--help', function() {
console.log(' Support email: dev@sheetjs.com');
console.log(' Web Demo: http://oss.sheetjs.com/js-xls/');
});

program.parse(process.argv);

var filename, sheetname = '';
if(program.args[0]) {
Expand Down
1 change: 1 addition & 0 deletions bits/01_version.js
@@ -0,0 +1 @@
XLS.version = '0.6.0';
File renamed without changes.
30 changes: 0 additions & 30 deletions bits/03_shim.js

This file was deleted.

67 changes: 37 additions & 30 deletions bits/08_blob.js
@@ -1,6 +1,3 @@

var Buffers = Array;

function readIEEE754(buf, idx, isLE, nl, ml) {
if(isLE === undefined) isLE = true;
if(!nl) nl = 8;
Expand Down Expand Up @@ -67,6 +64,7 @@ function s2a(s) {
return w;
}

var __toBuffer;
if(typeof Buffer !== "undefined") {
Buffer.prototype.hexlify= function() { return this.toString('hex'); };
Buffer.prototype.utf16le= function(s,e){return this.toString('utf16le',s,e).replace(/\u0000/,'').replace(/[\u0001-\u0006]/,'!');};
Expand Down Expand Up @@ -94,89 +92,98 @@ if(typeof Buffer !== "undefined") {
}
return o;
};
__toBuffer = function(bufs) { return Buffer.concat(bufs[0]); };
} else {
__toBuffer = function(bufs) {
var x = [];
for(var i = 0; i != bufs[0].length; ++i) { x = x.concat(bufs[0][i]); }
return x;
};
}

Array.prototype.readUInt8 = function(idx) { return this[idx]; };
Array.prototype.readUInt16LE = function(idx) { return this[idx+1]*(1<<8)+this[idx]; };
Array.prototype.readInt16LE = function(idx) { var u = this.readUInt16LE(idx); if(!(u & 0x8000)) return u; return (0xffff - u + 1) * -1; };
Array.prototype.readUInt32LE = function(idx) { return this[idx+3]*(1<<24)+this[idx+2]*(1<<16)+this[idx+1]*(1<<8)+this[idx]; };
Array.prototype.readInt32LE = function(idx) { var u = this.readUInt32LE(idx); if(!(u & 0x80000000)) return u; return (0xffffffff - u + 1) * -1; };
Array.prototype.readDoubleLE = function(idx) { return readIEEE754(this, idx||0);};
var __readUInt8 = function(b, idx) { return b.readUInt8 ? b.readUInt8(idx) : b[idx]; };
var __readUInt16LE = function(b, idx) { return b.readUInt16LE ? b.readUInt16LE(idx) : b[idx+1]*(1<<8)+b[idx]; };
var __readInt16LE = function(b, idx) { var u = __readUInt16LE(b,idx); if(!(u & 0x8000)) return u; return (0xffff - u + 1) * -1; };
var __readUInt32LE = function(b, idx) { return b.readUInt32LE ? b.readUInt32LE(idx) : b[idx+3]*(1<<24)+b[idx+2]*(1<<16)+b[idx+1]*(1<<8)+b[idx]; };
var __readInt32LE = function(b, idx) { if(b.readInt32LE) return b.readInt32LE(idx); var u = __readUInt32LE(b,idx); if(!(u & 0x80000000)) return u; return (0xffffffff - u + 1) * -1; };
var __readDoubleLE = function(b, idx) { return b.readDoubleLE ? b.readDoubleLE(idx) : readIEEE754(b, idx||0);};

Array.prototype.hexlify = function() { return this.map(function(x){return (x<16?"0":"") + x.toString(16);}).join(""); };
var __hexlify = function(b) { return b.map(function(x){return (x<16?"0":"") + x.toString(16);}).join(""); };

Array.prototype.utf16le = function(s,e) { var str = ""; for(var i=s; i<e; i+=2) str += String.fromCharCode(this.readUInt16LE(i)); return str.replace(/\u0000/,'').replace(/[\u0001-\u0006]/,'!'); };
var __utf16le = function(b,s,e) { if(b.utf16le) return b.utf16le(s,e); var str = ""; for(var i=s; i<e; i+=2) str += String.fromCharCode(__readUInt16LE(b,i)); return str.replace(/\u0000/,'').replace(/[\u0001-\u0006]/,'!'); };

Array.prototype.utf8 = function(s,e) { var str = ""; for(var i=s; i<e; i++) str += String.fromCharCode(this.readUInt8(i)); return str; };
var __utf8 = function(b,s,e) { if(b.utf8) return b.utf8(s,e); var str = ""; for(var i=s; i<e; i++) str += String.fromCharCode(__readUInt8(b,i)); return str; };

Array.prototype.lpstr = function(i) { var len = this.readUInt32LE(i); return len > 0 ? this.utf8(i+4,i+4+len-1) : "";};
Array.prototype.lpwstr = function(i) { var len = 2*this.readUInt32LE(i); return this.utf8(i+4,i+4+len-1);};
var __lpstr = function(b,i) { if(b.lpstr) return b.lpstr(i); var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
var __lpwstr = function(b,i) { if(b.lpwstr) return b.lpwstr(i); var len = 2*__readUInt32LE(b,i); return __utf8(b, i+4,i+4+len-1);};

function bconcat(bufs) { return (typeof Buffer !== 'undefined') ? Buffer.concat(bufs) : [].concat.apply([], bufs); }

function ReadShift(size, t) {
var o, w, vv, i, loc; t = t || 'u';
if(size === 'ieee754') { size = 8; t = 'f'; }
switch(size) {
case 1: o = this.readUInt8(this.l); break;
case 2: o=t==='u'?this.readUInt16LE(this.l):this.readInt16LE(this.l);break;
case 4: o = this.readUInt32LE(this.l); break;
case 8: if(t === 'f') { o = this.readDoubleLE(this.l); break; }
case 1: o = __readUInt8(this, this.l); break;
case 2: o=(t==='u' ? __readUInt16LE : __readInt16LE)(this, this.l); break;
case 4: o = __readUInt32LE(this, this.l); break;
case 8: if(t === 'f') { o = __readDoubleLE(this, this.l); break; }
/* falls through */
case 16: o = this.toString('hex', this.l,this.l+size); break;

case 'utf8': size = t; o = this.utf8(this.l, this.l + size); break;
case 'utf16le': size = 2*t; o = this.utf16le(this.l, this.l + size); break;
case 'utf8': size = t; o = __utf8(this, this.l, this.l + size); break;
case 'utf16le': size=2*t; o = __utf16le(this, this.l, this.l + size); break;

/* [MS-OLEDS] 2.1.4 LengthPrefixedAnsiString */
case 'lpstr': o = this.lpstr(this.l); size = 5 + o.length; break;
case 'lpstr': o = __lpstr(this, this.l); size = 5 + o.length; break;

case 'lpwstr': o = this.lpwstr(this.l); size = 5 + o.length; if(o[o.length-1] == '\u0000') size += 2; break;
case 'lpwstr': o = __lpwstr(this, this.l); size = 5 + o.length; if(o[o.length-1] == '\u0000') size += 2; break;

/* sbcs and dbcs support continue records in the SST way TODO codepages */
/* TODO: DBCS http://msdn.microsoft.com/en-us/library/cc194788.aspx */
case 'dbcs': size = 2*t; o = ""; loc = this.l;
for(i = 0; i != t; ++i) {
if(this.lens && this.lens.indexOf(loc) !== -1) {
w = this.readUInt8(loc);
w = __readUInt8(this, loc);
this.l = loc + 1;
vv = ReadShift.call(this, w ? 'dbcs' : 'sbcs', t-i);
return o + vv;
}
o += _getchar(this.readUInt16LE(loc));
o += _getchar(__readUInt16LE(this, loc));
loc+=2;
} break;

case 'sbcs': size = t; o = ""; loc = this.l;
for(i = 0; i != t; ++i) {
if(this.lens && this.lens.indexOf(loc) !== -1) {
w = this.readUInt8(loc);
w = __readUInt8(this, loc);
this.l = loc + 1;
vv = ReadShift.call(this, w ? 'dbcs' : 'sbcs', t-i);
return o + vv;
}
o += _getchar(this.readUInt8(loc));
o += _getchar(__readUInt8(this, loc));
loc+=1;
} break;

case 'cstr': size = 0; o = "";
while((w=this.readUInt8(this.l + size++))!==0) o+= _getchar(w);
while((w=__readUInt8(this, this.l + size++))!==0) o+= _getchar(w);
break;
case 'wstr': size = 0; o = "";
while((w=this.readUInt16LE(this.l +size))!==0){o+= _getchar(w);size+=2;}
while((w=__readUInt16LE(this,this.l +size))!==0){o+= _getchar(w);size+=2;}
size+=2; break;
}
this.l+=size; return o;
}

function CheckField(hexstr, fld) {
var m = this.slice(this.l, this.l+hexstr.length/2).hexlify('hex');
var b = this.slice(this.l, this.l+hexstr.length/2);
var m = b.hexlify ? b.hexlify() : __hexlify(b);
if(m !== hexstr) throw (fld||"") + 'Expected ' + hexstr + ' saw ' + m;
this.l += hexstr.length/2;
}

function WarnField(hexstr, fld) {
var m = this.slice(this.l, this.l+hexstr.length/2).hexlify('hex');
var b = this.slice(this.l, this.l+hexstr.length/2);
var m = b.hexlify ? b.hexlify() : __hexlify(b);
if(m !== hexstr) console.error((fld||"") + 'Expected ' + hexstr +' saw ' + m);
this.l += hexstr.length/2;
}
Expand Down
29 changes: 9 additions & 20 deletions bits/18_cfb.js
@@ -1,6 +1,6 @@
/* [MS-CFB] v20130118 */
if(typeof module !== "undefined" && typeof require !== 'undefined') CFB = require('cfb');
else var CFB = (function(){
/*if(typeof module !== "undefined" && typeof require !== 'undefined') CFB = require('cfb');
else*/ var CFB = (function(){
var exports = {};
function parse(file) {

Expand Down Expand Up @@ -122,10 +122,10 @@ function sleuth_fat(idx, cnt) {
if(idx !== FREESECT) {
var sector = sectors[idx];
for(var i = 0; i != ssz/4-1; ++i) {
if((q = sector.readUInt32LE(i*4)) === ENDOFCHAIN) break;
if((q = __readUInt32LE(sector,i*4)) === ENDOFCHAIN) break;
fat_addrs.push(q);
}
sleuth_fat(sector.readUInt32LE(ssz-4),cnt - 1);
sleuth_fat(__readUInt32LE(sector,ssz-4),cnt - 1);
}
}
sleuth_fat(difat_start, ndfs);
Expand All @@ -139,7 +139,7 @@ function get_buffer(byte_addr, bytes) {
}

function get_buffer_u32(byte_addr) {
return get_buffer(byte_addr,4).readUInt32LE(0);
return __readUInt32LE(get_buffer(byte_addr,4), 0);
}

function get_next_sector(idx) { return get_buffer_u32(idx); }
Expand All @@ -152,7 +152,7 @@ for(i=0; i != sectors.length; ++i) {
if(chkd[k]) continue;
for(j=k; j<=MAXREGSECT; buf.push(j),j=get_next_sector(j)) chkd[j] = true;
sector_list[k] = {nodes: buf};
sector_list[k].data = Buffers(buf.map(get_sector)).toBuffer();
sector_list[k].data = __toBuffer(Array(buf.map(get_sector)));
}
sector_list[dir_start].name = "!Directory";
if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
Expand All @@ -169,7 +169,7 @@ function read_directory(idx) {
read = ReadShift.bind(blob);
var namelen = read(2);
if(namelen === 0) return;
var name = blob.utf16le(0,namelen-(Paths.length?2:0)); // OLE
var name = __utf16le(blob,0,namelen-(Paths.length?2:0)); // OLE
Paths.push(name);
var o = { name: name };
o.type = EntryTypes[read(1)];
Expand Down Expand Up @@ -203,12 +203,12 @@ function read_directory(idx) {
}
if(o.ctime) {
var ct = blob.slice(blob.l-24, blob.l-16);
var c2 = (ct.readUInt32LE(4)/1e7)*Math.pow(2,32)+ct.readUInt32LE(0)/1e7;
var c2 = (__readUInt32LE(ct,4)/1e7)*Math.pow(2,32)+__readUInt32LE(ct,0)/1e7;
o.ct = new Date((c2 - 11644473600)*1000);
}
if(o.mtime) {
var mt = blob.slice(blob.l-16, blob.l-8);
var m2 = (mt.readUInt32LE(4)/1e7)*Math.pow(2,32)+mt.readUInt32LE(0)/1e7;
var m2 = (__readUInt32LE(mt,4)/1e7)*Math.pow(2,32)+__readUInt32LE(mt,0)/1e7;
o.mt = new Date((m2 - 11644473600)*1000);
}
files[name] = o;
Expand Down Expand Up @@ -326,10 +326,6 @@ return exports;
}

if(typeof require !== 'undefined' && typeof exports !== 'undefined') {
Buffers = Array;
Buffers.prototype.toBuffer = function() {
return Buffer.concat(this[0]);
};
var fs = require('fs');
//exports.read = CFB.read;
//exports.parse = CFB.parse;
Expand All @@ -341,11 +337,4 @@ if(typeof require !== 'undefined' && typeof exports !== 'undefined') {
};
if(typeof module !== 'undefined' && require.main === module)
exports.main(process.argv.slice(2));
} else {
Buffers = Array;
Buffers.prototype.toBuffer = function() {
var x = [];
for(var i = 0; i != this[0].length; ++i) { x = x.concat(this[0][i]); }
return x;
};
}
2 changes: 1 addition & 1 deletion bits/20_parsebits.js
Expand Up @@ -67,7 +67,7 @@ function parse_XLUnicodeStringNoCch(blob, cch) {
var read = blob.read_shift.bind(blob);
var fHighByte = read(1);
var retval;
if(fHighByte===0) { retval = blob.utf8(blob.l, blob.l+cch); blob.l += cch; }
if(fHighByte===0) { retval = __utf8(blob,blob.l, blob.l+cch); blob.l += cch; }
else { retval = blob.read_shift('dbcs', cch); }
return retval;
}
Expand Down
2 changes: 1 addition & 1 deletion bits/30_bifffunc.js
Expand Up @@ -38,7 +38,7 @@ function parse_RkNumber(blob) {
var fX100 = b[0] & 1, fInt = b[0] & 2;
blob.l+=4;
b[0] &= ~3;
var RK = fInt === 0 ? [0,0,0,0,b[0],b[1],b[2],b[3]].readDoubleLE(0) : b.readInt32LE(0)>>2;
var RK = fInt === 0 ? __readDoubleLE([0,0,0,0,b[0],b[1],b[2],b[3]],0) : __readInt32LE(b,0)>>2;
return fX100 ? RK/100 : RK;
}

Expand Down
2 changes: 1 addition & 1 deletion bits/68_fparse.js
Expand Up @@ -12,7 +12,7 @@ function parse_Formula(blob, length) {
/* 2.5.133 */
function parse_FormulaValue(blob) {
var b;
if(blob.readUInt16LE(blob.l + 6) !== 0xFFFF) return parse_Xnum(blob);
if(__readUInt16LE(blob,blob.l + 6) !== 0xFFFF) return parse_Xnum(blob);
switch(blob[blob.l]) {
case 0x00: blob.l += 8; return "String";
case 0x01: b = blob[blob.l+2] === 0x1; blob.l += 8; return b;
Expand Down
16 changes: 8 additions & 8 deletions bits/80_xls.js
Expand Up @@ -5,12 +5,12 @@ function parse_compobj(obj) {

/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
var l = 28, m;
m = o.lpstr(l);
l += 4 + o.readUInt32LE(l);
m = __lpstr(o, l);
l += 4 + __readUInt32LE(o,l);
v.UserType = m;

/* [MS-OLEDS] 2.3.1 ClipboardFormatOrAnsiString */
m = o.readUInt32LE(l); l+= 4;
m = __readUInt32LE(o,l); l+= 4;
switch(m) {
case 0x00000000: break;
case 0xffffffff: case 0xfffffffe: l+=4; break;
Expand All @@ -19,9 +19,9 @@ function parse_compobj(obj) {
l += m;
}

m = o.lpstr(l); l += m.length === 0 ? 0 : 5 + m.length; v.Reserved1 = m;
m = __lpstr(o, l); l += m.length === 0 ? 0 : 5 + m.length; v.Reserved1 = m;

if((m = o.readUInt32LE(l)) !== 0x71b2e9f4) return v;
if((m = __readUInt32LE(o,l)) !== 0x71b2e9f4) return v;
throw "Unsupported Unicode Extension";
}

Expand All @@ -41,12 +41,12 @@ function slurp(R, blob, length, opts) {
var l = length;
var bufs = [blob.slice(blob.l,blob.l+l)];
blob.l += length;
var next = (RecordEnum[blob.readUInt16LE(blob.l)]);
var next = (RecordEnum[__readUInt16LE(blob,blob.l)]);
while(next && next.n === 'Continue') {
l = blob.readUInt16LE(blob.l+2);
l = __readUInt16LE(blob,blob.l+2);
bufs.push(blob.slice(blob.l+4,blob.l+4+l));
blob.l += 4+l;
next = (RecordEnum[blob.readUInt16LE(blob.l)]);
next = (RecordEnum[__readUInt16LE(blob, blob.l)]);
}
var b = bconcat(bufs);
prep_blob(b);
Expand Down
4 changes: 2 additions & 2 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "xlsjs",
"version": "0.5.1",
"version": "0.6.0",
"author": "sheetjs",
"description": "(one day) a full-featured XLS parser and writer. For now, primitive parser",
"keywords": [ "xls", "office", "excel", "spreadsheet" ],
Expand Down Expand Up @@ -29,5 +29,5 @@
},
"bugs": { "url": "https://github.com/SheetJS/js-xls/issues" },
"license": "Apache-2.0",
"engines": { "node": ">=0.4" }
"engines": { "node": ">=0.8" }
}

0 comments on commit c52fe38

Please sign in to comment.