Skip to content

Commit 30c03a2

Browse files
committed
Strip quoted delims in file type magic 0x3C
1 parent fcf9182 commit 30c03a2

11 files changed

+67
-10
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ tmp
1515
*.[pP][dD][fF]
1616
*.[sS][lL][kK]
1717
*.socialcalc
18-
*.[xX][lL][sSwWcCaAtTmM]
18+
*.[xX][lL][sSwWcCaAtTmMrR]
1919
*.[xX][lL][sSaAtT][xXmMbB]
2020
*.[oO][dD][sS]
2121
*.[fF][oO][dD][sS]
2222
*.[xX][mM][lL]
2323
*.[uU][oO][sS]
2424
*.[wW][kKqQbB][S1234567890]
2525
*.[qQ][pP][wW]
26+
*.[fF][mM][3tT]
2627
*.[bB][iI][fF][fF][23458]
2728
*.[rR][tT][fF]
2829
*.[eE][tT][hH]

.spelling

+9
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ webpack
5959
weex
6060

6161
# Other terms
62+
1.x
63+
2.x
64+
3.x
65+
4.x
66+
5.x
67+
6.x
68+
7.x
69+
8.x
70+
9.x
6271
ActiveX
6372
APIs
6473
ArrayBuffer

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ DISTHDR=misc/suppress_export.js
7373
.PHONY: dist
7474
dist: dist-deps $(TARGET) bower.json ## Prepare JS files for distribution
7575
mkdir -p dist
76-
<$(TARGET) sed "s/require('stream')/{}/g;s/require('....*')/undefined/g" > dist/$(TARGET)
76+
<$(TARGET) sed "s/require('....*')/undefined/g" > dist/$(TARGET)
7777
cp LICENSE dist/
7878
uglifyjs shim.js $(UGLIFYOPTS) -o dist/shim.min.js --preamble "$$(head -n 1 bits/00_header.js)"
7979
uglifyjs $(DISTHDR) dist/$(TARGET) $(UGLIFYOPTS) -o dist/$(LIB).min.js --source-map dist/$(LIB).min.map --preamble "$$(head -n 1 bits/00_header.js)"

bin/xlsx.njs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
var n = "xlsx";
66
var X = require('../');
77
try { X = require('../xlsx.flow'); } catch(e) {}
8-
require('exit-on-epipe');
8+
try { require('exit-on-epipe'); } catch(e) {}
99
var fs = require('fs'), program;
1010
try { program = require('commander'); } catch(e) {
1111
[

bits/41_lotus.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ var WK_ = /*#__PURE__*/ (function() {
3434
var refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
3535
var sheetRows = o.sheetRows || 0;
3636

37+
if(d[2] == 0x00) {
38+
if(d[3] == 0x08 || d[3] == 0x09) {
39+
if(d.length >= 16 && d[14] == 0x05 && d[15] === 0x6c) throw new Error("Unsupported Works 3 for Mac file");
40+
}
41+
}
42+
3743
if(d[2] == 0x02) {
3844
o.Enum = WK1Enum;
3945
lotushopper(d, function(val, R, RT) { switch(RT) {
@@ -126,7 +132,8 @@ var WK_ = /*#__PURE__*/ (function() {
126132

127133
write_biff_rec(ba, 0x00, write_BOF_WK1(0x0406));
128134
write_biff_rec(ba, 0x06, write_RANGE(range));
129-
for(var R = range.s.r; R <= range.e.r; ++R) {
135+
var max_R = Math.min(range.e.r, 8191);
136+
for(var R = range.s.r; R <= max_R; ++R) {
130137
var rr = encode_row(R);
131138
for(var C = range.s.c; C <= range.e.c; ++C) {
132139
if(R === range.s.r) cols[C] = encode_col(C);
@@ -165,7 +172,8 @@ var WK_ = /*#__PURE__*/ (function() {
165172
var range = safe_decode_range(ws["!ref"]);
166173
var dense = Array.isArray(ws);
167174
var cols = [];
168-
for(var R = range.s.r; R <= range.e.r; ++R) {
175+
var max_R = Math.min(range.e.r, 8191);
176+
for(var R = range.s.r; R <= max_R; ++R) {
169177
var rr = encode_row(R);
170178
for(var C = range.s.c; C <= range.e.c; ++C) {
171179
if(R === range.s.r) cols[C] = encode_col(C);
@@ -211,6 +219,7 @@ var WK_ = /*#__PURE__*/ (function() {
211219
if(rows < range.e.r) rows = range.e.r;
212220
if(cols < range.e.c) cols = range.e.c;
213221
}
222+
if(rows > 8191) rows = 8191;
214223
out.write_shift(2, rows);
215224
out.write_shift(1, wscnt);
216225
out.write_shift(1, cols);

bits/75_xlml.js

+1
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
183183
else str = utf8read(str);
184184
}
185185
var opening = str.slice(0, 1024).toLowerCase(), ishtml = false;
186+
opening = opening.replace(/".*?"/g, "");
186187
if((opening.indexOf(">") & 1023) > Math.min((opening.indexOf(",") & 1023), (opening.indexOf(";")&1023))) { var _o = dup(opts); _o.type = "string"; return PRN.to_workbook(str, _o); }
187188
if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; });
188189
if(ishtml) return HTML_.to_workbook(str, opts);

bits/76_xls.js

+2
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,8 @@ else/*:: if(cfb instanceof CFBContainer) */ {
950950
else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
951951
/* Quattro Pro 9 */
952952
else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
953+
/* Works 4 for Mac */
954+
else if((_data=CFB.find(cfb, 'MN0')) && _data.content) throw new Error("Unsupported Works 4 for Mac file");
953955
else throw new Error("Cannot find Workbook stream");
954956
if(options.bookVBA && cfb.FullPaths && CFB.find(cfb, '/_VBA_PROJECT_CUR/VBA/dir')) WorkbookP.vbaraw = make_vba_xls(cfb);
955957
}

bits/87_read.js

+11-3
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,20 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
9191
case 0x54: if(n[1] === 0x41 && n[2] === 0x42 && n[3] === 0x4C) return DIF.to_workbook(d, o); break;
9292
case 0x50: return (n[1] === 0x4B && n[2] < 0x09 && n[3] < 0x09) ? read_zip(d, o) : read_prn(data, d, o, str);
9393
case 0xEF: return n[3] === 0x3C ? parse_xlml(d, o) : read_prn(data, d, o, str);
94-
case 0xFF: if(n[1] === 0xFE) { return read_utf16(d, o); } break;
95-
case 0x00: if(n[1] === 0x00 && n[2] >= 0x02 && n[3] === 0x00) return WK_.to_workbook(d, o); break;
94+
case 0xFF:
95+
if(n[1] === 0xFE) { return read_utf16(d, o); }
96+
else if(n[1] === 0x00 && n[2] === 0x02 && n[3] === 0x00) return WK_.to_workbook(d, o);
97+
break;
98+
case 0x00:
99+
if(n[1] === 0x00) {
100+
if(n[2] >= 0x02 && n[3] === 0x00) return WK_.to_workbook(d, o);
101+
if(n[2] === 0x00 && (n[3] === 0x08 || n[3] === 0x09)) return WK_.to_workbook(d, o);
102+
}
103+
break;
96104
case 0x03: case 0x83: case 0x8B: case 0x8C: return DBF.to_workbook(d, o);
97105
case 0x7B: if(n[1] === 0x5C && n[2] === 0x72 && n[3] === 0x74) return RTF.to_workbook(d, o); break;
98106
case 0x0A: case 0x0D: case 0x20: return read_plaintext_raw(d, o);
99-
case 0x89: if(n[1] === 0x50 && n[2] === 0x4E && n[3] === 0x47) throw new Error("PNG Image File is not a spreadsheet"); break;
107+
case 0x89: if(n[1] === 0x50 && n[2] === 0x4E && n[3] === 0x47) throw new Error("PNG Image File is not a spreadsheet"); break;
100108
}
101109
if(DBF.versions.indexOf(n[0]) > -1 && n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
102110
return read_prn(data, d, o, str);

bits/99_footer.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ else if(typeof module !== 'undefined' && module.exports) make_xlsx_lib(module.ex
66
else if(typeof define === 'function' && define.amd) define('xlsx', function() { if(!XLSX.version) make_xlsx_lib(XLSX); return XLSX; });
77
else make_xlsx_lib(XLSX);
88
/* NOTE: the following extra line is needed for "Lightning Locker Service" */
9-
if(typeof window !== 'undefined' && !window.XLSX) window.XLSX = XLSX;
9+
if(typeof window !== 'undefined' && !window.XLSX) try { window.XLSX = XLSX; } catch(e) {}
1010
/*exported XLS, ODS */
1111
var XLS = XLSX, ODS = XLSX;

docbits/80_parseopts.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ file but Excel will know how to handle it. This library applies similar logic:
8585

8686
| Byte 0 | Raw File Type | Spreadsheet Types |
8787
|:-------|:--------------|:----------------------------------------------------|
88-
| `0xD0` | CFB Container | BIFF 5/8 or password-protected XLSX/XLSB or WQ3/QPW |
88+
| `0xD0` | CFB Container | BIFF 5/8 or protected XLSX/XLSB or WQ3/QPW or XLR |
8989
| `0x09` | BIFF Stream | BIFF 2/3/4/5 |
9090
| `0x3C` | XML/HTML | SpreadsheetML / Flat ODS / UOS1 / HTML / plain text |
9191
| `0x50` | ZIP Archive | XLSB or XLSX/M or ODS or UOS2 or plain text |
@@ -102,6 +102,8 @@ file but Excel will know how to handle it. This library applies similar logic:
102102
DBF files are detected based on the first byte as well as the third and fourth
103103
bytes (corresponding to month and day of the file date)
104104

105+
Works for Windows files are detected based on the BOF record with type `0xFF`
106+
105107
Plain text format guessing follows the priority order:
106108

107109
| Format | Test |

docbits/85_filetype.md

+25
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
2727
| Lotus 1-2-3 (WK1/WK3) |||
2828
| Lotus 1-2-3 (WKS/WK2/WK4/123) || |
2929
| Quattro Pro Spreadsheet (WQ1/WQ2/WB1/WB2/WB3/QPW) || |
30+
| Works 1.x-3.x DOS / 2.x-5.x Windows Spreadsheet (WKS) || |
31+
| Works 6.x-9.x Spreadsheet (XLR) || |
3032
| **Other Common Spreadsheet Output Formats** |:-----:|:-----:|
3133
| HTML Tables |||
3234
| Rich Text Format tables (RTF) | ||
@@ -44,6 +46,8 @@ range limits will be silently truncated:
4446
| Excel 4.0 (XLS BIFF4) | IV16384 | 256 | 16384 |
4547
| Excel 3.0 (XLS BIFF3) | IV16384 | 256 | 16384 |
4648
| Excel 2.0/2.1 (XLS BIFF2) | IV16384 | 256 | 16384 |
49+
| Lotus 1-2-3 R2-R5 (WK1/WK3/WK4) | IV8192 | 256 | 8192 |
50+
| Lotus 1-2-3 R1 (WKS) | IV2048 | 256 | 2048 |
4751

4852
Excel 2003 SpreadsheetML range limits are governed by the version of Excel and
4953
are not enforced by the writer.
@@ -180,6 +184,27 @@ BIFF8 XLS.
180184

181185
</details>
182186

187+
#### Works for DOS / Windows Spreadsheet (WKS/XLR)
188+
189+
<details>
190+
<summary>(click to show)</summary>
191+
192+
All versions of Works were limited to a single worksheet.
193+
194+
Works for DOS 1.x - 3.x and Works for Windows 2.x extends the Lotus WKS format
195+
with additional record types.
196+
197+
Works for Windows 3.x - 5.x uses the same format and WKS extension. The BOF
198+
record has type `FF`
199+
200+
Works for Windows 6.x - 9.x use the XLR format. XLR is nearly identical to
201+
BIFF8 XLS: it uses the CFB container with a Workbook stream. Works 9 saves the
202+
exact Workbook stream for the XLR and the 97-2003 XLS export. Works 6 XLS
203+
includes two empty worksheets but the main worksheet has an identical encoding.
204+
XLR also includes a `WksSSWorkBook` stream similar to Lotus FM3/FMT files.
205+
206+
</details>
207+
183208
#### OpenDocument Spreadsheet (ODS/FODS)
184209

185210
<details>

0 commit comments

Comments
 (0)