UNPKG

1.01 MBJavaScriptView Raw
1/*! xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
2/*! shim.js (C) 2013-present SheetJS -- http://sheetjs.com */
3/* ES3/5 Compatibility shims and other utilities for older browsers. */
4
5// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
6if(!Object.keys) Object.keys = (function() {
7 var hasOwnProperty = Object.prototype.hasOwnProperty,
8 hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
9 dontEnums = [
10 'toString',
11 'toLocaleString',
12 'valueOf',
13 'hasOwnProperty',
14 'isPrototypeOf',
15 'propertyIsEnumerable',
16 'constructor'
17 ],
18 dontEnumsLength = dontEnums.length;
19
20 return function(obj) {
21 if(typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');
22
23 var result = [];
24
25 for(var prop in obj) if(hasOwnProperty.call(obj, prop)) result.push(prop);
26
27 if(hasDontEnumBug)
28 for(var i=0; i < dontEnumsLength; ++i)
29 if(hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
30 return result;
31 };
32})();
33
34if(!String.prototype.trim) String.prototype.trim = function() {
35 var s = this.replace(/^\s+/, '');
36 for(var i = s.length - 1; i >=0 ; --i) if(!s.charAt(i).match(/^\s/)) return s.slice(0,i+1);
37 return "";
38};
39
40if(!Array.prototype.forEach) Array.prototype.forEach = function(cb) {
41 var len = (this.length>>>0), self = (arguments[1]||void 0);
42 for(var i=0; i<len; ++i) if(i in this) self ? cb.call(self, this[i], i, this) : cb(this[i], i, this);
43};
44
45if(!Array.prototype.map) Array.prototype.map = function(cb) {
46 var len = (this.length>>>0), self = (arguments[1]||void 0), A = new Array(len);
47 for(var i=0; i<len; ++i) if(i in this) A[i] = self ? cb.call(self, this[i], i, this) : cb(this[i], i, this);
48 return A;
49};
50
51if(!Array.prototype.indexOf) Array.prototype.indexOf = function(needle) {
52 var len = (this.length>>>0), i = ((arguments[1]|0)||0);
53 for(i<0 && (i+=len)<0 && (i=0); i<len; ++i) if(this[i] === needle) return i;
54 return -1;
55};
56
57if(!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(needle) {
58 var len = (this.length>>>0), i = len - 1;
59 for(; i>=0; --i) if(this[i] === needle) return i;
60 return -1;
61};
62
63if(!Array.isArray) Array.isArray = function(obj) { return Object.prototype.toString.call(obj) === "[object Array]"; };
64
65if(!Date.prototype.toISOString) Date.prototype.toISOString = (function() {
66 function p(n,i) { return ('0000000' + n).slice(-(i||2)); }
67
68 return function _toISOString() {
69 var y = this.getUTCFullYear(), yr = "";
70 if(y>9999) yr = '+' + p( y, 6);
71 else if(y<0) yr = '-' + p(-y, 6);
72 else yr = p( y, 4);
73
74 return [
75 yr, p(this.getUTCMonth()+1), p(this.getUTCDate())
76 ].join('-') + 'T' + [
77 p(this.getUTCHours()), p(this.getUTCMinutes()), p(this.getUTCSeconds())
78 ].join(':') + '.' + p(this.getUTCMilliseconds(),3) + 'Z';
79 };
80}());
81
82if(typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) ArrayBuffer.prototype.slice = function(start, end) {
83 if(start == null) start = 0;
84 if(start < 0) { start += this.byteLength; if(start < 0) start = 0; }
85 if(start >= this.byteLength) return new Uint8Array(0);
86 if(end == null) end = this.byteLength;
87 if(end < 0) { end += this.byteLength; if(end < 0) end = 0; }
88 if(end > this.byteLength) end = this.byteLength;
89 if(start > end) return new Uint8Array(0);
90 var out = new ArrayBuffer(end - start);
91 var view = new Uint8Array(out);
92 var data = new Uint8Array(this, start, end - start)
93 /* IE10 should have Uint8Array#set */
94 if(view.set) view.set(data); else while(start <= --end) view[end - start] = data[end];
95 return out;
96};
97if(typeof Uint8Array !== 'undefined' && !Uint8Array.prototype.slice) Uint8Array.prototype.slice = function(start, end) {
98 if(start == null) start = 0;
99 if(start < 0) { start += this.length; if(start < 0) start = 0; }
100 if(start >= this.length) return new Uint8Array(0);
101 if(end == null) end = this.length;
102 if(end < 0) { end += this.length; if(end < 0) end = 0; }
103 if(end > this.length) end = this.length;
104 if(start > end) return new Uint8Array(0);
105 var out = new Uint8Array(end - start);
106 while(start <= --end) out[end - start] = this[end];
107 return out;
108};
109
110// VBScript + ActiveX fallback for IE5+
111var IE_SaveFile = (function() { try {
112 if(typeof IE_SaveFile_Impl == "undefined") document.write([
113'<script type="text/vbscript" language="vbscript">',
114'IE_GetProfileAndPath_Key = "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\"',
115'Function IE_GetProfileAndPath(key): Set wshell = CreateObject("WScript.Shell"): IE_GetProfileAndPath = wshell.RegRead(IE_GetProfileAndPath_Key & key): IE_GetProfileAndPath = wshell.ExpandEnvironmentStrings("%USERPROFILE%") & "!" & IE_GetProfileAndPath: End Function',
116'Function IE_SaveFile_Impl(FileName, payload): Dim data, plen, i, bit: data = CStr(payload): plen = Len(data): Set fso = CreateObject("Scripting.FileSystemObject"): fso.CreateTextFile FileName, True: Set f = fso.GetFile(FileName): Set stream = f.OpenAsTextStream(2, 0): For i = 1 To plen Step 3: bit = Mid(data, i, 2): stream.write Chr(CLng("&h" & bit)): Next: stream.Close: IE_SaveFile_Impl = True: End Function',
117'|/script>'.replace("|","<")
118 ].join("\r\n"));
119 if(typeof IE_SaveFile_Impl == "undefined") return void 0;
120 var IE_GetPath = (function() {
121 var DDP1 = "";
122 try { DDP1 = IE_GetProfileAndPath("{374DE290-123F-4565-9164-39C4925E467B}"); } catch(e) { try { DDP1 = IE_GetProfileAndPath("Personal"); } catch(e) { try { DDP1 = IE_GetProfileAndPath("Desktop"); } catch(e) { throw e; }}}
123 var o = DDP1.split("!");
124 DDP = o[1].replace("%USERPROFILE%", o[0]);
125 return function(path) { return DDP + "\\" + path; };
126 })();
127 function fix_data(data) {
128 var out = [];
129 var T = typeof data == "string";
130 for(var i = 0; i < data.length; ++i) out.push(("00"+(T ? data.charCodeAt(i) : data[i]).toString(16)).slice(-2));
131 var o = out.join("|");
132 return o;
133 }
134 return function(data, filename) { return IE_SaveFile_Impl(IE_GetPath(filename), fix_data(data)); };
135} catch(e) { return void 0; }})();
136var IE_LoadFile = (function() { try {
137 if(typeof IE_LoadFile_Impl == "undefined") document.write([
138'<script type="text/vbscript" language="vbscript">',
139'Function IE_LoadFile_Impl(FileName): Dim out(), plen, i, cc: Set fso = CreateObject("Scripting.FileSystemObject"): Set f = fso.GetFile(FileName): Set stream = f.OpenAsTextStream(1, 0): plen = f.Size: ReDim out(plen): For i = 1 To plen Step 1: cc = Hex(Asc(stream.read(1))): If Len(cc) < 2 Then: cc = "0" & cc: End If: out(i) = cc: Next: IE_LoadFile_Impl = Join(out,""): End Function',
140'|/script>'.replace("|","<")
141 ].join("\r\n"));
142 if(typeof IE_LoadFile_Impl == "undefined") return void 0;
143 function fix_data(data) {
144 var out = [];
145 for(var i = 0; i < data.length; i+=2) out.push(String.fromCharCode(parseInt(data.slice(i, i+2), 16)));
146 var o = out.join("");
147 return o;
148 }
149 return function(filename) { return fix_data(IE_LoadFile_Impl(filename)); };
150} catch(e) { return void 0; }})();
151
152// getComputedStyle polyfill from https://gist.github.com/8HNHoFtE/5891086
153if(typeof window !== 'undefined' && typeof window.getComputedStyle !== 'function') {
154 window.getComputedStyle = function(e,t){return this.el=e,this.getPropertyValue=function(t){var n=/(\-([a-z]){1})/g;return t=="float"&&(t="styleFloat"),n.test(t)&&(t=t.replace(n,function(){return arguments[2].toUpperCase()})),e.currentStyle[t]?e.currentStyle[t]:null},this}
155}
156var DO_NOT_EXPORT_CODEPAGE = true;
157var DO_NOT_EXPORT_JSZIP = true;
158/*
159
160JSZip - A Javascript class for generating and reading zip files
161<http://stuartk.com/jszip>
162
163(c) 2009-2014 Stuart Knightley <stuart [at] stuartk.com>
164Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown.
165
166JSZip uses the library pako released under the MIT license :
167https://github.com/nodeca/pako/blob/master/LICENSE
168
169Note: since JSZip 3 removed critical functionality, this version assigns to the
170`JSZipSync` variable. Another JSZip version can be loaded in parallel.
171*/
172(function(e){
173 if("object"==typeof exports&&"undefined"!=typeof module&&"undefined"==typeof DO_NOT_EXPORT_JSZIP)module.exports=e();
174 else if("function"==typeof define&&define.amd&&"undefined"==typeof DO_NOT_EXPORT_JSZIP){JSZipSync=e();define([],e);}
175 else{
176 var f;
177 "undefined"!=typeof window?f=window:
178 "undefined"!=typeof global?f=global:
179 "undefined"!=typeof $ && $.global?f=$.global:
180 "undefined"!=typeof self&&(f=self),f.JSZipSync=e()
181 }
182}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
183'use strict';
184// private property
185var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
186
187
188// public method for encoding
189exports.encode = function(input, utf8) {
190 var output = "";
191 var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
192 var i = 0;
193
194 while (i < input.length) {
195
196 chr1 = input.charCodeAt(i++);
197 chr2 = input.charCodeAt(i++);
198 chr3 = input.charCodeAt(i++);
199
200 enc1 = chr1 >> 2;
201 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
202 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
203 enc4 = chr3 & 63;
204
205 if (isNaN(chr2)) {
206 enc3 = enc4 = 64;
207 }
208 else if (isNaN(chr3)) {
209 enc4 = 64;
210 }
211
212 output = output + _keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
213
214 }
215
216 return output;
217};
218
219// public method for decoding
220exports.decode = function(input, utf8) {
221 var output = "";
222 var chr1, chr2, chr3;
223 var enc1, enc2, enc3, enc4;
224 var i = 0;
225
226 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
227
228 while (i < input.length) {
229
230 enc1 = _keyStr.indexOf(input.charAt(i++));
231 enc2 = _keyStr.indexOf(input.charAt(i++));
232 enc3 = _keyStr.indexOf(input.charAt(i++));
233 enc4 = _keyStr.indexOf(input.charAt(i++));
234
235 chr1 = (enc1 << 2) | (enc2 >> 4);
236 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
237 chr3 = ((enc3 & 3) << 6) | enc4;
238
239 output = output + String.fromCharCode(chr1);
240
241 if (enc3 != 64) {
242 output = output + String.fromCharCode(chr2);
243 }
244 if (enc4 != 64) {
245 output = output + String.fromCharCode(chr3);
246 }
247
248 }
249
250 return output;
251
252};
253
254},{}],2:[function(_dereq_,module,exports){
255'use strict';
256function CompressedObject() {
257 this.compressedSize = 0;
258 this.uncompressedSize = 0;
259 this.crc32 = 0;
260 this.compressionMethod = null;
261 this.compressedContent = null;
262}
263
264CompressedObject.prototype = {
265 /**
266 * Return the decompressed content in an unspecified format.
267 * The format will depend on the decompressor.
268 * @return {Object} the decompressed content.
269 */
270 getContent: function() {
271 return null; // see implementation
272 },
273 /**
274 * Return the compressed content in an unspecified format.
275 * The format will depend on the compressed conten source.
276 * @return {Object} the compressed content.
277 */
278 getCompressedContent: function() {
279 return null; // see implementation
280 }
281};
282module.exports = CompressedObject;
283
284},{}],3:[function(_dereq_,module,exports){
285'use strict';
286exports.STORE = {
287 magic: "\x00\x00",
288 compress: function(content) {
289 return content; // no compression
290 },
291 uncompress: function(content) {
292 return content; // no compression
293 },
294 compressInputType: null,
295 uncompressInputType: null
296};
297exports.DEFLATE = _dereq_('./flate');
298
299},{"./flate":8}],4:[function(_dereq_,module,exports){
300'use strict';
301
302var utils = _dereq_('./utils');
303
304var table = [
305 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
306 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
307 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
308 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
309 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
310 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
311 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
312 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
313 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
314 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
315 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
316 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
317 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
318 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
319 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
320 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
321 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
322 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
323 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
324 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
325 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
326 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
327 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
328 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
329 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
330 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
331 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
332 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
333 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
334 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
335 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
336 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
337 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
338 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
339 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
340 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
341 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
342 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
343 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
344 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
345 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
346 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
347 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
348 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
349 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
350 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
351 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
352 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
353 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
354 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
355 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
356 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
357 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
358 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
359 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
360 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
361 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
362 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
363 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
364 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
365 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
366 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
367 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
368 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
369];
370
371/**
372 *
373 * Javascript crc32
374 * http://www.webtoolkit.info/
375 *
376 */
377module.exports = function crc32(input, crc) {
378 if (typeof input === "undefined" || !input.length) {
379 return 0;
380 }
381
382 var isArray = utils.getTypeOf(input) !== "string";
383
384 if (typeof(crc) == "undefined") {
385 crc = 0;
386 }
387 var x = 0;
388 var y = 0;
389 var b = 0;
390
391 crc = crc ^ (-1);
392 for (var i = 0, iTop = input.length; i < iTop; i++) {
393 b = isArray ? input[i] : input.charCodeAt(i);
394 y = (crc ^ b) & 0xFF;
395 x = table[y];
396 crc = (crc >>> 8) ^ x;
397 }
398
399 return crc ^ (-1);
400};
401// vim: set shiftwidth=4 softtabstop=4:
402
403},{"./utils":21}],5:[function(_dereq_,module,exports){
404'use strict';
405var utils = _dereq_('./utils');
406
407function DataReader(data) {
408 this.data = null; // type : see implementation
409 this.length = 0;
410 this.index = 0;
411}
412DataReader.prototype = {
413 /**
414 * Check that the offset will not go too far.
415 * @param {string} offset the additional offset to check.
416 * @throws {Error} an Error if the offset is out of bounds.
417 */
418 checkOffset: function(offset) {
419 this.checkIndex(this.index + offset);
420 },
421 /**
422 * Check that the specifed index will not be too far.
423 * @param {string} newIndex the index to check.
424 * @throws {Error} an Error if the index is out of bounds.
425 */
426 checkIndex: function(newIndex) {
427 if (this.length < newIndex || newIndex < 0) {
428 throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?");
429 }
430 },
431 /**
432 * Change the index.
433 * @param {number} newIndex The new index.
434 * @throws {Error} if the new index is out of the data.
435 */
436 setIndex: function(newIndex) {
437 this.checkIndex(newIndex);
438 this.index = newIndex;
439 },
440 /**
441 * Skip the next n bytes.
442 * @param {number} n the number of bytes to skip.
443 * @throws {Error} if the new index is out of the data.
444 */
445 skip: function(n) {
446 this.setIndex(this.index + n);
447 },
448 /**
449 * Get the byte at the specified index.
450 * @param {number} i the index to use.
451 * @return {number} a byte.
452 */
453 byteAt: function(i) {
454 // see implementations
455 },
456 /**
457 * Get the next number with a given byte size.
458 * @param {number} size the number of bytes to read.
459 * @return {number} the corresponding number.
460 */
461 readInt: function(size) {
462 var result = 0,
463 i;
464 this.checkOffset(size);
465 for (i = this.index + size - 1; i >= this.index; i--) {
466 result = (result << 8) + this.byteAt(i);
467 }
468 this.index += size;
469 return result;
470 },
471 /**
472 * Get the next string with a given byte size.
473 * @param {number} size the number of bytes to read.
474 * @return {string} the corresponding string.
475 */
476 readString: function(size) {
477 return utils.transformTo("string", this.readData(size));
478 },
479 /**
480 * Get raw data without conversion, <size> bytes.
481 * @param {number} size the number of bytes to read.
482 * @return {Object} the raw data, implementation specific.
483 */
484 readData: function(size) {
485 // see implementations
486 },
487 /**
488 * Find the last occurence of a zip signature (4 bytes).
489 * @param {string} sig the signature to find.
490 * @return {number} the index of the last occurence, -1 if not found.
491 */
492 lastIndexOfSignature: function(sig) {
493 // see implementations
494 },
495 /**
496 * Get the next date.
497 * @return {Date} the date.
498 */
499 readDate: function() {
500 var dostime = this.readInt(4);
501 return new Date(
502 ((dostime >> 25) & 0x7f) + 1980, // year
503 ((dostime >> 21) & 0x0f) - 1, // month
504 (dostime >> 16) & 0x1f, // day
505 (dostime >> 11) & 0x1f, // hour
506 (dostime >> 5) & 0x3f, // minute
507 (dostime & 0x1f) << 1); // second
508 }
509};
510module.exports = DataReader;
511
512},{"./utils":21}],6:[function(_dereq_,module,exports){
513'use strict';
514exports.base64 = false;
515exports.binary = false;
516exports.dir = false;
517exports.createFolders = false;
518exports.date = null;
519exports.compression = null;
520exports.comment = null;
521
522},{}],7:[function(_dereq_,module,exports){
523'use strict';
524var utils = _dereq_('./utils');
525
526/**
527 * @deprecated
528 * This function will be removed in a future version without replacement.
529 */
530exports.string2binary = function(str) {
531 return utils.string2binary(str);
532};
533
534/**
535 * @deprecated
536 * This function will be removed in a future version without replacement.
537 */
538exports.string2Uint8Array = function(str) {
539 return utils.transformTo("uint8array", str);
540};
541
542/**
543 * @deprecated
544 * This function will be removed in a future version without replacement.
545 */
546exports.uint8Array2String = function(array) {
547 return utils.transformTo("string", array);
548};
549
550/**
551 * @deprecated
552 * This function will be removed in a future version without replacement.
553 */
554exports.string2Blob = function(str) {
555 var buffer = utils.transformTo("arraybuffer", str);
556 return utils.arrayBuffer2Blob(buffer);
557};
558
559/**
560 * @deprecated
561 * This function will be removed in a future version without replacement.
562 */
563exports.arrayBuffer2Blob = function(buffer) {
564 return utils.arrayBuffer2Blob(buffer);
565};
566
567/**
568 * @deprecated
569 * This function will be removed in a future version without replacement.
570 */
571exports.transformTo = function(outputType, input) {
572 return utils.transformTo(outputType, input);
573};
574
575/**
576 * @deprecated
577 * This function will be removed in a future version without replacement.
578 */
579exports.getTypeOf = function(input) {
580 return utils.getTypeOf(input);
581};
582
583/**
584 * @deprecated
585 * This function will be removed in a future version without replacement.
586 */
587exports.checkSupport = function(type) {
588 return utils.checkSupport(type);
589};
590
591/**
592 * @deprecated
593 * This value will be removed in a future version without replacement.
594 */
595exports.MAX_VALUE_16BITS = utils.MAX_VALUE_16BITS;
596
597/**
598 * @deprecated
599 * This value will be removed in a future version without replacement.
600 */
601exports.MAX_VALUE_32BITS = utils.MAX_VALUE_32BITS;
602
603
604/**
605 * @deprecated
606 * This function will be removed in a future version without replacement.
607 */
608exports.pretty = function(str) {
609 return utils.pretty(str);
610};
611
612/**
613 * @deprecated
614 * This function will be removed in a future version without replacement.
615 */
616exports.findCompression = function(compressionMethod) {
617 return utils.findCompression(compressionMethod);
618};
619
620/**
621 * @deprecated
622 * This function will be removed in a future version without replacement.
623 */
624exports.isRegExp = function (object) {
625 return utils.isRegExp(object);
626};
627
628
629},{"./utils":21}],8:[function(_dereq_,module,exports){
630'use strict';
631var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined');
632
633var pako = _dereq_("pako");
634exports.uncompressInputType = USE_TYPEDARRAY ? "uint8array" : "array";
635exports.compressInputType = USE_TYPEDARRAY ? "uint8array" : "array";
636
637exports.magic = "\x08\x00";
638exports.compress = function(input) {
639 return pako.deflateRaw(input);
640};
641exports.uncompress = function(input) {
642 return pako.inflateRaw(input);
643};
644
645},{"pako":24}],9:[function(_dereq_,module,exports){
646'use strict';
647
648var base64 = _dereq_('./base64');
649
650/**
651Usage:
652 zip = new JSZip();
653 zip.file("hello.txt", "Hello, World!").file("tempfile", "nothing");
654 zip.folder("images").file("smile.gif", base64Data, {base64: true});
655 zip.file("Xmas.txt", "Ho ho ho !", {date : new Date("December 25, 2007 00:00:01")});
656 zip.remove("tempfile");
657
658 base64zip = zip.generate();
659
660**/
661
662/**
663 * Representation a of zip file in js
664 * @constructor
665 * @param {String=|ArrayBuffer=|Uint8Array=} data the data to load, if any (optional).
666 * @param {Object=} options the options for creating this objects (optional).
667 */
668function JSZipSync(data, options) {
669 // if this constructor is used without `new`, it adds `new` before itself:
670 if(!(this instanceof JSZipSync)) return new JSZipSync(data, options);
671
672 // object containing the files :
673 // {
674 // "folder/" : {...},
675 // "folder/data.txt" : {...}
676 // }
677 this.files = {};
678
679 this.comment = null;
680
681 // Where we are in the hierarchy
682 this.root = "";
683 if (data) {
684 this.load(data, options);
685 }
686 this.clone = function() {
687 var newObj = new JSZipSync();
688 for (var i in this) {
689 if (typeof this[i] !== "function") {
690 newObj[i] = this[i];
691 }
692 }
693 return newObj;
694 };
695}
696JSZipSync.prototype = _dereq_('./object');
697JSZipSync.prototype.load = _dereq_('./load');
698JSZipSync.support = _dereq_('./support');
699JSZipSync.defaults = _dereq_('./defaults');
700
701/**
702 * @deprecated
703 * This namespace will be removed in a future version without replacement.
704 */
705JSZipSync.utils = _dereq_('./deprecatedPublicUtils');
706
707JSZipSync.base64 = {
708 /**
709 * @deprecated
710 * This method will be removed in a future version without replacement.
711 */
712 encode : function(input) {
713 return base64.encode(input);
714 },
715 /**
716 * @deprecated
717 * This method will be removed in a future version without replacement.
718 */
719 decode : function(input) {
720 return base64.decode(input);
721 }
722};
723JSZipSync.compressions = _dereq_('./compressions');
724module.exports = JSZipSync;
725
726},{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(_dereq_,module,exports){
727'use strict';
728var base64 = _dereq_('./base64');
729var ZipEntries = _dereq_('./zipEntries');
730module.exports = function(data, options) {
731 var files, zipEntries, i, input;
732 options = options || {};
733 if (options.base64) {
734 data = base64.decode(data);
735 }
736
737 zipEntries = new ZipEntries(data, options);
738 files = zipEntries.files;
739 for (i = 0; i < files.length; i++) {
740 input = files[i];
741 this.file(input.fileName, input.decompressed, {
742 binary: true,
743 optimizedBinaryString: true,
744 date: input.date,
745 dir: input.dir,
746 comment : input.fileComment.length ? input.fileComment : null,
747 createFolders: options.createFolders
748 });
749 }
750 if (zipEntries.zipComment.length) {
751 this.comment = zipEntries.zipComment;
752 }
753
754 return this;
755};
756
757},{"./base64":1,"./zipEntries":22}],11:[function(_dereq_,module,exports){
758(function (Buffer){
759'use strict';
760var Buffer_from = /*::(*/function(){}/*:: :any)*/;
761if(typeof Buffer !== 'undefined') {
762 var nbfs = !Buffer.from;
763 if(!nbfs) try { Buffer.from("foo", "utf8"); } catch(e) { nbfs = true; }
764 Buffer_from = nbfs ? function(buf, enc) { return (enc) ? new Buffer(buf, enc) : new Buffer(buf); } : Buffer.from.bind(Buffer);
765 // $FlowIgnore
766 if(!Buffer.alloc) Buffer.alloc = function(n) { return new Buffer(n); };
767}
768module.exports = function(data, encoding){
769 return typeof data == 'number' ? Buffer.alloc(data) : Buffer_from(data, encoding);
770};
771module.exports.test = function(b){
772 return Buffer.isBuffer(b);
773};
774}).call(this,(typeof Buffer !== "undefined" ? Buffer : undefined))
775},{}],12:[function(_dereq_,module,exports){
776'use strict';
777var Uint8ArrayReader = _dereq_('./uint8ArrayReader');
778
779function NodeBufferReader(data) {
780 this.data = data;
781 this.length = this.data.length;
782 this.index = 0;
783}
784NodeBufferReader.prototype = new Uint8ArrayReader();
785
786/**
787 * @see DataReader.readData
788 */
789NodeBufferReader.prototype.readData = function(size) {
790 this.checkOffset(size);
791 var result = this.data.slice(this.index, this.index + size);
792 this.index += size;
793 return result;
794};
795module.exports = NodeBufferReader;
796
797},{"./uint8ArrayReader":18}],13:[function(_dereq_,module,exports){
798'use strict';
799var support = _dereq_('./support');
800var utils = _dereq_('./utils');
801var crc32 = _dereq_('./crc32');
802var signature = _dereq_('./signature');
803var defaults = _dereq_('./defaults');
804var base64 = _dereq_('./base64');
805var compressions = _dereq_('./compressions');
806var CompressedObject = _dereq_('./compressedObject');
807var nodeBuffer = _dereq_('./nodeBuffer');
808var utf8 = _dereq_('./utf8');
809var StringWriter = _dereq_('./stringWriter');
810var Uint8ArrayWriter = _dereq_('./uint8ArrayWriter');
811
812/**
813 * Returns the raw data of a ZipObject, decompress the content if necessary.
814 * @param {ZipObject} file the file to use.
815 * @return {String|ArrayBuffer|Uint8Array|Buffer} the data.
816 */
817var getRawData = function(file) {
818 if (file._data instanceof CompressedObject) {
819 file._data = file._data.getContent();
820 file.options.binary = true;
821 file.options.base64 = false;
822
823 if (utils.getTypeOf(file._data) === "uint8array") {
824 var copy = file._data;
825 // when reading an arraybuffer, the CompressedObject mechanism will keep it and subarray() a Uint8Array.
826 // if we request a file in the same format, we might get the same Uint8Array or its ArrayBuffer (the original zip file).
827 file._data = new Uint8Array(copy.length);
828 // with an empty Uint8Array, Opera fails with a "Offset larger than array size"
829 if (copy.length !== 0) {
830 file._data.set(copy, 0);
831 }
832 }
833 }
834 return file._data;
835};
836
837/**
838 * Returns the data of a ZipObject in a binary form. If the content is an unicode string, encode it.
839 * @param {ZipObject} file the file to use.
840 * @return {String|ArrayBuffer|Uint8Array|Buffer} the data.
841 */
842var getBinaryData = function(file) {
843 var result = getRawData(file),
844 type = utils.getTypeOf(result);
845 if (type === "string") {
846 if (!file.options.binary) {
847 // unicode text !
848 // unicode string => binary string is a painful process, check if we can avoid it.
849 if (support.nodebuffer) {
850 return nodeBuffer(result, "utf-8");
851 }
852 }
853 return file.asBinary();
854 }
855 return result;
856};
857
858/**
859 * Transform this._data into a string.
860 * @param {function} filter a function String -> String, applied if not null on the result.
861 * @return {String} the string representing this._data.
862 */
863var dataToString = function(asUTF8) {
864 var result = getRawData(this);
865 if (result === null || typeof result === "undefined") {
866 return "";
867 }
868 // if the data is a base64 string, we decode it before checking the encoding !
869 if (this.options.base64) {
870 result = base64.decode(result);
871 }
872 if (asUTF8 && this.options.binary) {
873 // JSZip.prototype.utf8decode supports arrays as input
874 // skip to array => string step, utf8decode will do it.
875 result = out.utf8decode(result);
876 }
877 else {
878 // no utf8 transformation, do the array => string step.
879 result = utils.transformTo("string", result);
880 }
881
882 if (!asUTF8 && !this.options.binary) {
883 result = utils.transformTo("string", out.utf8encode(result));
884 }
885 return result;
886};
887/**
888 * A simple object representing a file in the zip file.
889 * @constructor
890 * @param {string} name the name of the file
891 * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data
892 * @param {Object} options the options of the file
893 */
894var ZipObject = function(name, data, options) {
895 this.name = name;
896 this.dir = options.dir;
897 this.date = options.date;
898 this.comment = options.comment;
899
900 this._data = data;
901 this.options = options;
902
903 /*
904 * This object contains initial values for dir and date.
905 * With them, we can check if the user changed the deprecated metadata in
906 * `ZipObject#options` or not.
907 */
908 this._initialMetadata = {
909 dir : options.dir,
910 date : options.date
911 };
912};
913
914ZipObject.prototype = {
915 /**
916 * Return the content as UTF8 string.
917 * @return {string} the UTF8 string.
918 */
919 asText: function() {
920 return dataToString.call(this, true);
921 },
922 /**
923 * Returns the binary content.
924 * @return {string} the content as binary.
925 */
926 asBinary: function() {
927 return dataToString.call(this, false);
928 },
929 /**
930 * Returns the content as a nodejs Buffer.
931 * @return {Buffer} the content as a Buffer.
932 */
933 asNodeBuffer: function() {
934 var result = getBinaryData(this);
935 return utils.transformTo("nodebuffer", result);
936 },
937 /**
938 * Returns the content as an Uint8Array.
939 * @return {Uint8Array} the content as an Uint8Array.
940 */
941 asUint8Array: function() {
942 var result = getBinaryData(this);
943 return utils.transformTo("uint8array", result);
944 },
945 /**
946 * Returns the content as an ArrayBuffer.
947 * @return {ArrayBuffer} the content as an ArrayBufer.
948 */
949 asArrayBuffer: function() {
950 return this.asUint8Array().buffer;
951 }
952};
953
954/**
955 * Transform an integer into a string in hexadecimal.
956 * @private
957 * @param {number} dec the number to convert.
958 * @param {number} bytes the number of bytes to generate.
959 * @returns {string} the result.
960 */
961var decToHex = function(dec, bytes) {
962 var hex = "",
963 i;
964 for (i = 0; i < bytes; i++) {
965 hex += String.fromCharCode(dec & 0xff);
966 dec = dec >>> 8;
967 }
968 return hex;
969};
970
971/**
972 * Merge the objects passed as parameters into a new one.
973 * @private
974 * @param {...Object} var_args All objects to merge.
975 * @return {Object} a new object with the data of the others.
976 */
977var extend = function() {
978 var result = {}, i, attr;
979 for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers
980 for (attr in arguments[i]) {
981 if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") {
982 result[attr] = arguments[i][attr];
983 }
984 }
985 }
986 return result;
987};
988
989/**
990 * Transforms the (incomplete) options from the user into the complete
991 * set of options to create a file.
992 * @private
993 * @param {Object} o the options from the user.
994 * @return {Object} the complete set of options.
995 */
996var prepareFileAttrs = function(o) {
997 o = o || {};
998 if (o.base64 === true && (o.binary === null || o.binary === undefined)) {
999 o.binary = true;
1000 }
1001 o = extend(o, defaults);
1002 o.date = o.date || new Date();
1003 if (o.compression !== null) o.compression = o.compression.toUpperCase();
1004
1005 return o;
1006};
1007
1008/**
1009 * Add a file in the current folder.
1010 * @private
1011 * @param {string} name the name of the file
1012 * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file
1013 * @param {Object} o the options of the file
1014 * @return {Object} the new file.
1015 */
1016var fileAdd = function(name, data, o) {
1017 // be sure sub folders exist
1018 var dataType = utils.getTypeOf(data),
1019 parent;
1020
1021 o = prepareFileAttrs(o);
1022
1023 if (o.createFolders && (parent = parentFolder(name))) {
1024 folderAdd.call(this, parent, true);
1025 }
1026
1027 if (o.dir || data === null || typeof data === "undefined") {
1028 o.base64 = false;
1029 o.binary = false;
1030 data = null;
1031 }
1032 else if (dataType === "string") {
1033 if (o.binary && !o.base64) {
1034 // optimizedBinaryString == true means that the file has already been filtered with a 0xFF mask
1035 if (o.optimizedBinaryString !== true) {
1036 // this is a string, not in a base64 format.
1037 // Be sure that this is a correct "binary string"
1038 data = utils.string2binary(data);
1039 }
1040 }
1041 }
1042 else { // arraybuffer, uint8array, ...
1043 o.base64 = false;
1044 o.binary = true;
1045
1046 if (!dataType && !(data instanceof CompressedObject)) {
1047 throw new Error("The data of '" + name + "' is in an unsupported format !");
1048 }
1049
1050 // special case : it's way easier to work with Uint8Array than with ArrayBuffer
1051 if (dataType === "arraybuffer") {
1052 data = utils.transformTo("uint8array", data);
1053 }
1054 }
1055
1056 var object = new ZipObject(name, data, o);
1057 this.files[name] = object;
1058 return object;
1059};
1060
1061/**
1062 * Find the parent folder of the path.
1063 * @private
1064 * @param {string} path the path to use
1065 * @return {string} the parent folder, or ""
1066 */
1067var parentFolder = function (path) {
1068 if (path.slice(-1) == '/') {
1069 path = path.substring(0, path.length - 1);
1070 }
1071 var lastSlash = path.lastIndexOf('/');
1072 return (lastSlash > 0) ? path.substring(0, lastSlash) : "";
1073};
1074
1075/**
1076 * Add a (sub) folder in the current folder.
1077 * @private
1078 * @param {string} name the folder's name
1079 * @param {boolean=} [createFolders] If true, automatically create sub
1080 * folders. Defaults to false.
1081 * @return {Object} the new folder.
1082 */
1083var folderAdd = function(name, createFolders) {
1084 // Check the name ends with a /
1085 if (name.slice(-1) != "/") {
1086 name += "/"; // IE doesn't like substr(-1)
1087 }
1088
1089 createFolders = (typeof createFolders !== 'undefined') ? createFolders : false;
1090
1091 // Does this folder already exist?
1092 if (!this.files[name]) {
1093 fileAdd.call(this, name, null, {
1094 dir: true,
1095 createFolders: createFolders
1096 });
1097 }
1098 return this.files[name];
1099};
1100
1101/**
1102 * Generate a JSZip.CompressedObject for a given zipOject.
1103 * @param {ZipObject} file the object to read.
1104 * @param {JSZip.compression} compression the compression to use.
1105 * @return {JSZip.CompressedObject} the compressed result.
1106 */
1107var generateCompressedObjectFrom = function(file, compression) {
1108 var result = new CompressedObject(),
1109 content;
1110
1111 // the data has not been decompressed, we might reuse things !
1112 if (file._data instanceof CompressedObject) {
1113 result.uncompressedSize = file._data.uncompressedSize;
1114 result.crc32 = file._data.crc32;
1115
1116 if (result.uncompressedSize === 0 || file.dir) {
1117 compression = compressions['STORE'];
1118 result.compressedContent = "";
1119 result.crc32 = 0;
1120 }
1121 else if (file._data.compressionMethod === compression.magic) {
1122 result.compressedContent = file._data.getCompressedContent();
1123 }
1124 else {
1125 content = file._data.getContent();
1126 // need to decompress / recompress
1127 result.compressedContent = compression.compress(utils.transformTo(compression.compressInputType, content));
1128 }
1129 }
1130 else {
1131 // have uncompressed data
1132 content = getBinaryData(file);
1133 if (!content || content.length === 0 || file.dir) {
1134 compression = compressions['STORE'];
1135 content = "";
1136 }
1137 result.uncompressedSize = content.length;
1138 result.crc32 = crc32(content);
1139 result.compressedContent = compression.compress(utils.transformTo(compression.compressInputType, content));
1140 }
1141
1142 result.compressedSize = result.compressedContent.length;
1143 result.compressionMethod = compression.magic;
1144
1145 return result;
1146};
1147
1148/**
1149 * Generate the various parts used in the construction of the final zip file.
1150 * @param {string} name the file name.
1151 * @param {ZipObject} file the file content.
1152 * @param {JSZip.CompressedObject} compressedObject the compressed object.
1153 * @param {number} offset the current offset from the start of the zip file.
1154 * @return {object} the zip parts.
1155 */
1156var generateZipParts = function(name, file, compressedObject, offset) {
1157 var data = compressedObject.compressedContent,
1158 utfEncodedFileName = utils.transformTo("string", utf8.utf8encode(file.name)),
1159 comment = file.comment || "",
1160 utfEncodedComment = utils.transformTo("string", utf8.utf8encode(comment)),
1161 useUTF8ForFileName = utfEncodedFileName.length !== file.name.length,
1162 useUTF8ForComment = utfEncodedComment.length !== comment.length,
1163 o = file.options,
1164 dosTime,
1165 dosDate,
1166 extraFields = "",
1167 unicodePathExtraField = "",
1168 unicodeCommentExtraField = "",
1169 dir, date;
1170
1171
1172 // handle the deprecated options.dir
1173 if (file._initialMetadata.dir !== file.dir) {
1174 dir = file.dir;
1175 } else {
1176 dir = o.dir;
1177 }
1178
1179 // handle the deprecated options.date
1180 if(file._initialMetadata.date !== file.date) {
1181 date = file.date;
1182 } else {
1183 date = o.date;
1184 }
1185
1186
1187 dosTime = date.getHours();
1188 dosTime = dosTime << 6;
1189 dosTime = dosTime | date.getMinutes();
1190 dosTime = dosTime << 5;
1191 dosTime = dosTime | date.getSeconds() / 2;
1192
1193 dosDate = date.getFullYear() - 1980;
1194 dosDate = dosDate << 4;
1195 dosDate = dosDate | (date.getMonth() + 1);
1196 dosDate = dosDate << 5;
1197 dosDate = dosDate | date.getDate();
1198
1199 if (useUTF8ForFileName) {
1200 // set the unicode path extra field. unzip needs at least one extra
1201 // field to correctly handle unicode path, so using the path is as good
1202 // as any other information. This could improve the situation with
1203 // other archive managers too.
1204 // This field is usually used without the utf8 flag, with a non
1205 // unicode path in the header (winrar, winzip). This helps (a bit)
1206 // with the messy Windows' default compressed folders feature but
1207 // breaks on p7zip which doesn't seek the unicode path extra field.
1208 // So for now, UTF-8 everywhere !
1209 unicodePathExtraField =
1210 // Version
1211 decToHex(1, 1) +
1212 // NameCRC32
1213 decToHex(crc32(utfEncodedFileName), 4) +
1214 // UnicodeName
1215 utfEncodedFileName;
1216
1217 extraFields +=
1218 // Info-ZIP Unicode Path Extra Field
1219 "\x75\x70" +
1220 // size
1221 decToHex(unicodePathExtraField.length, 2) +
1222 // content
1223 unicodePathExtraField;
1224 }
1225
1226 if(useUTF8ForComment) {
1227
1228 unicodeCommentExtraField =
1229 // Version
1230 decToHex(1, 1) +
1231 // CommentCRC32
1232 decToHex(this.crc32(utfEncodedComment), 4) +
1233 // UnicodeName
1234 utfEncodedComment;
1235
1236 extraFields +=
1237 // Info-ZIP Unicode Path Extra Field
1238 "\x75\x63" +
1239 // size
1240 decToHex(unicodeCommentExtraField.length, 2) +
1241 // content
1242 unicodeCommentExtraField;
1243 }
1244
1245 var header = "";
1246
1247 // version needed to extract
1248 header += "\x0A\x00";
1249 // general purpose bit flag
1250 // set bit 11 if utf8
1251 header += (useUTF8ForFileName || useUTF8ForComment) ? "\x00\x08" : "\x00\x00";
1252 // compression method
1253 header += compressedObject.compressionMethod;
1254 // last mod file time
1255 header += decToHex(dosTime, 2);
1256 // last mod file date
1257 header += decToHex(dosDate, 2);
1258 // crc-32
1259 header += decToHex(compressedObject.crc32, 4);
1260 // compressed size
1261 header += decToHex(compressedObject.compressedSize, 4);
1262 // uncompressed size
1263 header += decToHex(compressedObject.uncompressedSize, 4);
1264 // file name length
1265 header += decToHex(utfEncodedFileName.length, 2);
1266 // extra field length
1267 header += decToHex(extraFields.length, 2);
1268
1269
1270 var fileRecord = signature.LOCAL_FILE_HEADER + header + utfEncodedFileName + extraFields;
1271
1272 var dirRecord = signature.CENTRAL_FILE_HEADER +
1273 // version made by (00: DOS)
1274 "\x14\x00" +
1275 // file header (common to file and central directory)
1276 header +
1277 // file comment length
1278 decToHex(utfEncodedComment.length, 2) +
1279 // disk number start
1280 "\x00\x00" +
1281 // internal file attributes TODO
1282 "\x00\x00" +
1283 // external file attributes
1284 (dir === true ? "\x10\x00\x00\x00" : "\x00\x00\x00\x00") +
1285 // relative offset of local header
1286 decToHex(offset, 4) +
1287 // file name
1288 utfEncodedFileName +
1289 // extra field
1290 extraFields +
1291 // file comment
1292 utfEncodedComment;
1293
1294 return {
1295 fileRecord: fileRecord,
1296 dirRecord: dirRecord,
1297 compressedObject: compressedObject
1298 };
1299};
1300
1301
1302// return the actual prototype of JSZip
1303var out = {
1304 /**
1305 * Read an existing zip and merge the data in the current JSZip object.
1306 * The implementation is in jszip-load.js, don't forget to include it.
1307 * @param {String|ArrayBuffer|Uint8Array|Buffer} stream The stream to load
1308 * @param {Object} options Options for loading the stream.
1309 * options.base64 : is the stream in base64 ? default : false
1310 * @return {JSZip} the current JSZip object
1311 */
1312 load: function(stream, options) {
1313 throw new Error("Load method is not defined. Is the file jszip-load.js included ?");
1314 },
1315
1316 /**
1317 * Filter nested files/folders with the specified function.
1318 * @param {Function} search the predicate to use :
1319 * function (relativePath, file) {...}
1320 * It takes 2 arguments : the relative path and the file.
1321 * @return {Array} An array of matching elements.
1322 */
1323 filter: function(search) {
1324 var result = [],
1325 filename, relativePath, file, fileClone;
1326 for (filename in this.files) {
1327 if (!this.files.hasOwnProperty(filename)) {
1328 continue;
1329 }
1330 file = this.files[filename];
1331 // return a new object, don't let the user mess with our internal objects :)
1332 fileClone = new ZipObject(file.name, file._data, extend(file.options));
1333 relativePath = filename.slice(this.root.length, filename.length);
1334 if (filename.slice(0, this.root.length) === this.root && // the file is in the current root
1335 search(relativePath, fileClone)) { // and the file matches the function
1336 result.push(fileClone);
1337 }
1338 }
1339 return result;
1340 },
1341
1342 /**
1343 * Add a file to the zip file, or search a file.
1344 * @param {string|RegExp} name The name of the file to add (if data is defined),
1345 * the name of the file to find (if no data) or a regex to match files.
1346 * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded
1347 * @param {Object} o File options
1348 * @return {JSZip|Object|Array} this JSZip object (when adding a file),
1349 * a file (when searching by string) or an array of files (when searching by regex).
1350 */
1351 file: function(name, data, o) {
1352 if (arguments.length === 1) {
1353 if (utils.isRegExp(name)) {
1354 var regexp = name;
1355 return this.filter(function(relativePath, file) {
1356 return !file.dir && regexp.test(relativePath);
1357 });
1358 }
1359 else { // text
1360 return this.filter(function(relativePath, file) {
1361 return !file.dir && relativePath === name;
1362 })[0] || null;
1363 }
1364 }
1365 else { // more than one argument : we have data !
1366 name = this.root + name;
1367 fileAdd.call(this, name, data, o);
1368 }
1369 return this;
1370 },
1371
1372 /**
1373 * Add a directory to the zip file, or search.
1374 * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders.
1375 * @return {JSZip} an object with the new directory as the root, or an array containing matching folders.
1376 */
1377 folder: function(arg) {
1378 if (!arg) {
1379 return this;
1380 }
1381
1382 if (utils.isRegExp(arg)) {
1383 return this.filter(function(relativePath, file) {
1384 return file.dir && arg.test(relativePath);
1385 });
1386 }
1387
1388 // else, name is a new folder
1389 var name = this.root + arg;
1390 var newFolder = folderAdd.call(this, name);
1391
1392 // Allow chaining by returning a new object with this folder as the root
1393 var ret = this.clone();
1394 ret.root = newFolder.name;
1395 return ret;
1396 },
1397
1398 /**
1399 * Delete a file, or a directory and all sub-files, from the zip
1400 * @param {string} name the name of the file to delete
1401 * @return {JSZip} this JSZip object
1402 */
1403 remove: function(name) {
1404 name = this.root + name;
1405 var file = this.files[name];
1406 if (!file) {
1407 // Look for any folders
1408 if (name.slice(-1) != "/") {
1409 name += "/";
1410 }
1411 file = this.files[name];
1412 }
1413
1414 if (file && !file.dir) {
1415 // file
1416 delete this.files[name];
1417 } else {
1418 // maybe a folder, delete recursively
1419 var kids = this.filter(function(relativePath, file) {
1420 return file.name.slice(0, name.length) === name;
1421 });
1422 for (var i = 0; i < kids.length; i++) {
1423 delete this.files[kids[i].name];
1424 }
1425 }
1426
1427 return this;
1428 },
1429
1430 /**
1431 * Generate the complete zip file
1432 * @param {Object} options the options to generate the zip file :
1433 * - base64, (deprecated, use type instead) true to generate base64.
1434 * - compression, "STORE" by default.
1435 * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob.
1436 * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file
1437 */
1438 generate: function(options) {
1439 options = extend(options || {}, {
1440 base64: true,
1441 compression: "STORE",
1442 type: "base64",
1443 comment: null
1444 });
1445
1446 utils.checkSupport(options.type);
1447
1448 var zipData = [],
1449 localDirLength = 0,
1450 centralDirLength = 0,
1451 writer, i,
1452 utfEncodedComment = utils.transformTo("string", this.utf8encode(options.comment || this.comment || ""));
1453
1454 // first, generate all the zip parts.
1455 for (var name in this.files) {
1456 if (!this.files.hasOwnProperty(name)) {
1457 continue;
1458 }
1459 var file = this.files[name];
1460
1461 var compressionName = file.options.compression || options.compression.toUpperCase();
1462 var compression = compressions[compressionName];
1463 if (!compression) {
1464 throw new Error(compressionName + " is not a valid compression method !");
1465 }
1466
1467 var compressedObject = generateCompressedObjectFrom.call(this, file, compression);
1468
1469 var zipPart = generateZipParts.call(this, name, file, compressedObject, localDirLength);
1470 localDirLength += zipPart.fileRecord.length + compressedObject.compressedSize;
1471 centralDirLength += zipPart.dirRecord.length;
1472 zipData.push(zipPart);
1473 }
1474
1475 var dirEnd = "";
1476
1477 // end of central dir signature
1478 dirEnd = signature.CENTRAL_DIRECTORY_END +
1479 // number of this disk
1480 "\x00\x00" +
1481 // number of the disk with the start of the central directory
1482 "\x00\x00" +
1483 // total number of entries in the central directory on this disk
1484 decToHex(zipData.length, 2) +
1485 // total number of entries in the central directory
1486 decToHex(zipData.length, 2) +
1487 // size of the central directory 4 bytes
1488 decToHex(centralDirLength, 4) +
1489 // offset of start of central directory with respect to the starting disk number
1490 decToHex(localDirLength, 4) +
1491 // .ZIP file comment length
1492 decToHex(utfEncodedComment.length, 2) +
1493 // .ZIP file comment
1494 utfEncodedComment;
1495
1496
1497 // we have all the parts (and the total length)
1498 // time to create a writer !
1499 var typeName = options.type.toLowerCase();
1500 if(typeName==="uint8array"||typeName==="arraybuffer"||typeName==="blob"||typeName==="nodebuffer") {
1501 writer = new Uint8ArrayWriter(localDirLength + centralDirLength + dirEnd.length);
1502 }else{
1503 writer = new StringWriter(localDirLength + centralDirLength + dirEnd.length);
1504 }
1505
1506 for (i = 0; i < zipData.length; i++) {
1507 writer.append(zipData[i].fileRecord);
1508 writer.append(zipData[i].compressedObject.compressedContent);
1509 }
1510 for (i = 0; i < zipData.length; i++) {
1511 writer.append(zipData[i].dirRecord);
1512 }
1513
1514 writer.append(dirEnd);
1515
1516 var zip = writer.finalize();
1517
1518
1519
1520 switch(options.type.toLowerCase()) {
1521 // case "zip is an Uint8Array"
1522 case "uint8array" :
1523 case "arraybuffer" :
1524 case "nodebuffer" :
1525 return utils.transformTo(options.type.toLowerCase(), zip);
1526 case "blob" :
1527 return utils.arrayBuffer2Blob(utils.transformTo("arraybuffer", zip));
1528 // case "zip is a string"
1529 case "base64" :
1530 return (options.base64) ? base64.encode(zip) : zip;
1531 default : // case "string" :
1532 return zip;
1533 }
1534
1535 },
1536
1537 /**
1538 * @deprecated
1539 * This method will be removed in a future version without replacement.
1540 */
1541 crc32: function (input, crc) {
1542 return crc32(input, crc);
1543 },
1544
1545 /**
1546 * @deprecated
1547 * This method will be removed in a future version without replacement.
1548 */
1549 utf8encode: function (string) {
1550 return utils.transformTo("string", utf8.utf8encode(string));
1551 },
1552
1553 /**
1554 * @deprecated
1555 * This method will be removed in a future version without replacement.
1556 */
1557 utf8decode: function (input) {
1558 return utf8.utf8decode(input);
1559 }
1560};
1561module.exports = out;
1562
1563},{"./base64":1,"./compressedObject":2,"./compressions":3,"./crc32":4,"./defaults":6,"./nodeBuffer":11,"./signature":14,"./stringWriter":16,"./support":17,"./uint8ArrayWriter":19,"./utf8":20,"./utils":21}],14:[function(_dereq_,module,exports){
1564'use strict';
1565exports.LOCAL_FILE_HEADER = "PK\x03\x04";
1566exports.CENTRAL_FILE_HEADER = "PK\x01\x02";
1567exports.CENTRAL_DIRECTORY_END = "PK\x05\x06";
1568exports.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x06\x07";
1569exports.ZIP64_CENTRAL_DIRECTORY_END = "PK\x06\x06";
1570exports.DATA_DESCRIPTOR = "PK\x07\x08";
1571
1572},{}],15:[function(_dereq_,module,exports){
1573'use strict';
1574var DataReader = _dereq_('./dataReader');
1575var utils = _dereq_('./utils');
1576
1577function StringReader(data, optimizedBinaryString) {
1578 this.data = data;
1579 if (!optimizedBinaryString) {
1580 this.data = utils.string2binary(this.data);
1581 }
1582 this.length = this.data.length;
1583 this.index = 0;
1584}
1585StringReader.prototype = new DataReader();
1586/**
1587 * @see DataReader.byteAt
1588 */
1589StringReader.prototype.byteAt = function(i) {
1590 return this.data.charCodeAt(i);
1591};
1592/**
1593 * @see DataReader.lastIndexOfSignature
1594 */
1595StringReader.prototype.lastIndexOfSignature = function(sig) {
1596 return this.data.lastIndexOf(sig);
1597};
1598/**
1599 * @see DataReader.readData
1600 */
1601StringReader.prototype.readData = function(size) {
1602 this.checkOffset(size);
1603 // this will work because the constructor applied the "& 0xff" mask.
1604 var result = this.data.slice(this.index, this.index + size);
1605 this.index += size;
1606 return result;
1607};
1608module.exports = StringReader;
1609
1610},{"./dataReader":5,"./utils":21}],16:[function(_dereq_,module,exports){
1611'use strict';
1612
1613var utils = _dereq_('./utils');
1614
1615/**
1616 * An object to write any content to a string.
1617 * @constructor
1618 */
1619var StringWriter = function() {
1620 this.data = [];
1621};
1622StringWriter.prototype = {
1623 /**
1624 * Append any content to the current string.
1625 * @param {Object} input the content to add.
1626 */
1627 append: function(input) {
1628 input = utils.transformTo("string", input);
1629 this.data.push(input);
1630 },
1631 /**
1632 * Finalize the construction an return the result.
1633 * @return {string} the generated string.
1634 */
1635 finalize: function() {
1636 return this.data.join("");
1637 }
1638};
1639
1640module.exports = StringWriter;
1641
1642},{"./utils":21}],17:[function(_dereq_,module,exports){
1643(function (Buffer){
1644'use strict';
1645exports.base64 = true;
1646exports.array = true;
1647exports.string = true;
1648exports.arraybuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined";
1649// contains true if JSZip can read/generate nodejs Buffer, false otherwise.
1650// Browserify will provide a Buffer implementation for browsers, which is
1651// an augmented Uint8Array (i.e., can be used as either Buffer or U8).
1652exports.nodebuffer = typeof Buffer !== "undefined";
1653// contains true if JSZip can read/generate Uint8Array, false otherwise.
1654exports.uint8array = typeof Uint8Array !== "undefined";
1655
1656if (typeof ArrayBuffer === "undefined") {
1657 exports.blob = false;
1658}
1659else {
1660 var buffer = new ArrayBuffer(0);
1661 try {
1662 exports.blob = new Blob([buffer], {
1663 type: "application/zip"
1664 }).size === 0;
1665 }
1666 catch (e) {
1667 try {
1668 var Builder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
1669 var builder = new Builder();
1670 builder.append(buffer);
1671 exports.blob = builder.getBlob('application/zip').size === 0;
1672 }
1673 catch (e) {
1674 exports.blob = false;
1675 }
1676 }
1677}
1678
1679}).call(this,(typeof Buffer !== "undefined" ? Buffer : undefined))
1680},{}],18:[function(_dereq_,module,exports){
1681'use strict';
1682var DataReader = _dereq_('./dataReader');
1683
1684function Uint8ArrayReader(data) {
1685 if (data) {
1686 this.data = data;
1687 this.length = this.data.length;
1688 this.index = 0;
1689 }
1690}
1691Uint8ArrayReader.prototype = new DataReader();
1692/**
1693 * @see DataReader.byteAt
1694 */
1695Uint8ArrayReader.prototype.byteAt = function(i) {
1696 return this.data[i];
1697};
1698/**
1699 * @see DataReader.lastIndexOfSignature
1700 */
1701Uint8ArrayReader.prototype.lastIndexOfSignature = function(sig) {
1702 var sig0 = sig.charCodeAt(0),
1703 sig1 = sig.charCodeAt(1),
1704 sig2 = sig.charCodeAt(2),
1705 sig3 = sig.charCodeAt(3);
1706 for (var i = this.length - 4; i >= 0; --i) {
1707 if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) {
1708 return i;
1709 }
1710 }
1711
1712 return -1;
1713};
1714/**
1715 * @see DataReader.readData
1716 */
1717Uint8ArrayReader.prototype.readData = function(size) {
1718 this.checkOffset(size);
1719 if(size === 0) {
1720 // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of [].
1721 return new Uint8Array(0);
1722 }
1723 var result = this.data.subarray(this.index, this.index + size);
1724 this.index += size;
1725 return result;
1726};
1727module.exports = Uint8ArrayReader;
1728
1729},{"./dataReader":5}],19:[function(_dereq_,module,exports){
1730'use strict';
1731
1732var utils = _dereq_('./utils');
1733
1734/**
1735 * An object to write any content to an Uint8Array.
1736 * @constructor
1737 * @param {number} length The length of the array.
1738 */
1739var Uint8ArrayWriter = function(length) {
1740 this.data = new Uint8Array(length);
1741 this.index = 0;
1742};
1743Uint8ArrayWriter.prototype = {
1744 /**
1745 * Append any content to the current array.
1746 * @param {Object} input the content to add.
1747 */
1748 append: function(input) {
1749 if (input.length !== 0) {
1750 // with an empty Uint8Array, Opera fails with a "Offset larger than array size"
1751 input = utils.transformTo("uint8array", input);
1752 this.data.set(input, this.index);
1753 this.index += input.length;
1754 }
1755 },
1756 /**
1757 * Finalize the construction an return the result.
1758 * @return {Uint8Array} the generated array.
1759 */
1760 finalize: function() {
1761 return this.data;
1762 }
1763};
1764
1765module.exports = Uint8ArrayWriter;
1766
1767},{"./utils":21}],20:[function(_dereq_,module,exports){
1768'use strict';
1769
1770var utils = _dereq_('./utils');
1771var support = _dereq_('./support');
1772var nodeBuffer = _dereq_('./nodeBuffer');
1773
1774/**
1775 * The following functions come from pako, from pako/lib/utils/strings
1776 * released under the MIT license, see pako https://github.com/nodeca/pako/
1777 */
1778
1779// Table with utf8 lengths (calculated by first byte of sequence)
1780// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,
1781// because max possible codepoint is 0x10ffff
1782var _utf8len = new Array(256);
1783for (var i=0; i<256; i++) {
1784 _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1);
1785}
1786_utf8len[254]=_utf8len[254]=1; // Invalid sequence start
1787
1788// convert string to array (typed, when possible)
1789var string2buf = function (str) {
1790 var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;
1791
1792 // count binary size
1793 for (m_pos = 0; m_pos < str_len; m_pos++) {
1794 c = str.charCodeAt(m_pos);
1795 if (((c & 0xfc00) === 0xd800) && (m_pos+1 < str_len)) {
1796 c2 = str.charCodeAt(m_pos+1);
1797 if ((c2 & 0xfc00) === 0xdc00) {
1798 c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
1799 m_pos++;
1800 }
1801 }
1802 buf_len += (c < 0x80) ? 1 : ((c < 0x800) ? 2 : ((c < 0x10000) ? 3 : 4));
1803 }
1804
1805 // allocate buffer
1806 if (support.uint8array) {
1807 buf = new Uint8Array(buf_len);
1808 } else {
1809 buf = new Array(buf_len);
1810 }
1811
1812 // convert
1813 for (i=0, m_pos = 0; i < buf_len; m_pos++) {
1814 c = str.charCodeAt(m_pos);
1815 if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) {
1816 c2 = str.charCodeAt(m_pos+1);
1817 if ((c2 & 0xfc00) === 0xdc00) {
1818 c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
1819 m_pos++;
1820 }
1821 }
1822 if (c < 0x80) {
1823 /* one byte */
1824 buf[i++] = c;
1825 } else if (c < 0x800) {
1826 /* two bytes */
1827 buf[i++] = 0xC0 | (c >>> 6);
1828 buf[i++] = 0x80 | (c & 0x3f);
1829 } else if (c < 0x10000) {
1830 /* three bytes */
1831 buf[i++] = 0xE0 | (c >>> 12);
1832 buf[i++] = 0x80 | ((c >>> 6) & 0x3f);
1833 buf[i++] = 0x80 | (c & 0x3f);
1834 } else {
1835 /* four bytes */
1836 buf[i++] = 0xf0 | (c >>> 18);
1837 buf[i++] = 0x80 | ((c >>> 12) & 0x3f);
1838 buf[i++] = 0x80 | ((c >>> 6) & 0x3f);
1839 buf[i++] = 0x80 | (c & 0x3f);
1840 }
1841 }
1842
1843 return buf;
1844};
1845
1846// Calculate max possible position in utf8 buffer,
1847// that will not break sequence. If that's not possible
1848// - (very small limits) return max size as is.
1849//
1850// buf[] - utf8 bytes array
1851// max - length limit (mandatory);
1852var utf8border = function(buf, max) {
1853 var pos;
1854
1855 max = max || buf.length;
1856 if (max > buf.length) { max = buf.length; }
1857
1858 // go back from last position, until start of sequence found
1859 pos = max-1;
1860 while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }
1861
1862 // Fuckup - very small and broken sequence,
1863 // return max, because we should return something anyway.
1864 if (pos < 0) { return max; }
1865
1866 // If we came to start of buffer - that means vuffer is too small,
1867 // return max too.
1868 if (pos === 0) { return max; }
1869
1870 return (pos + _utf8len[buf[pos]] > max) ? pos : max;
1871};
1872
1873// convert array to string
1874var buf2string = function (buf) {
1875 var str, i, out, c, c_len;
1876 var len = buf.length;
1877
1878 // Reserve max possible length (2 words per char)
1879 // NB: by unknown reasons, Array is significantly faster for
1880 // String.fromCharCode.apply than Uint16Array.
1881 var utf16buf = new Array(len*2);
1882
1883 for (out=0, i=0; i<len;) {
1884 c = buf[i++];
1885 // quick process ascii
1886 if (c < 0x80) { utf16buf[out++] = c; continue; }
1887
1888 c_len = _utf8len[c];
1889 // skip 5 & 6 byte codes
1890 if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; }
1891
1892 // apply mask on first byte
1893 c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;
1894 // join the rest
1895 while (c_len > 1 && i < len) {
1896 c = (c << 6) | (buf[i++] & 0x3f);
1897 c_len--;
1898 }
1899
1900 // terminated by end of string?
1901 if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }
1902
1903 if (c < 0x10000) {
1904 utf16buf[out++] = c;
1905 } else {
1906 c -= 0x10000;
1907 utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);
1908 utf16buf[out++] = 0xdc00 | (c & 0x3ff);
1909 }
1910 }
1911
1912 // shrinkBuf(utf16buf, out)
1913 if (utf16buf.length !== out) {
1914 if(utf16buf.subarray) {
1915 utf16buf = utf16buf.subarray(0, out);
1916 } else {
1917 utf16buf.length = out;
1918 }
1919 }
1920
1921 // return String.fromCharCode.apply(null, utf16buf);
1922 return utils.applyFromCharCode(utf16buf);
1923};
1924
1925
1926// That's all for the pako functions.
1927
1928
1929/**
1930 * Transform a javascript string into an array (typed if possible) of bytes,
1931 * UTF-8 encoded.
1932 * @param {String} str the string to encode
1933 * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string.
1934 */
1935exports.utf8encode = function utf8encode(str) {
1936 if (support.nodebuffer) {
1937 return nodeBuffer(str, "utf-8");
1938 }
1939
1940 return string2buf(str);
1941};
1942
1943
1944/**
1945 * Transform a bytes array (or a representation) representing an UTF-8 encoded
1946 * string into a javascript string.
1947 * @param {Array|Uint8Array|Buffer} buf the data de decode
1948 * @return {String} the decoded string.
1949 */
1950exports.utf8decode = function utf8decode(buf) {
1951 if (support.nodebuffer) {
1952 return utils.transformTo("nodebuffer", buf).toString("utf-8");
1953 }
1954
1955 buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf);
1956
1957 // return buf2string(buf);
1958 // Chrome prefers to work with "small" chunks of data
1959 // for the method buf2string.
1960 // Firefox and Chrome has their own shortcut, IE doesn't seem to really care.
1961 var result = [], k = 0, len = buf.length, chunk = 65536;
1962 while (k < len) {
1963 var nextBoundary = utf8border(buf, Math.min(k + chunk, len));
1964 if (support.uint8array) {
1965 result.push(buf2string(buf.subarray(k, nextBoundary)));
1966 } else {
1967 result.push(buf2string(buf.slice(k, nextBoundary)));
1968 }
1969 k = nextBoundary;
1970 }
1971 return result.join("");
1972
1973};
1974// vim: set shiftwidth=4 softtabstop=4:
1975
1976},{"./nodeBuffer":11,"./support":17,"./utils":21}],21:[function(_dereq_,module,exports){
1977'use strict';
1978var support = _dereq_('./support');
1979var compressions = _dereq_('./compressions');
1980var nodeBuffer = _dereq_('./nodeBuffer');
1981/**
1982 * Convert a string to a "binary string" : a string containing only char codes between 0 and 255.
1983 * @param {string} str the string to transform.
1984 * @return {String} the binary string.
1985 */
1986exports.string2binary = function(str) {
1987 var result = "";
1988 for (var i = 0; i < str.length; i++) {
1989 result += String.fromCharCode(str.charCodeAt(i) & 0xff);
1990 }
1991 return result;
1992};
1993exports.arrayBuffer2Blob = function(buffer) {
1994 exports.checkSupport("blob");
1995
1996 try {
1997 // Blob constructor
1998 return new Blob([buffer], {
1999 type: "application/zip"
2000 });
2001 }
2002 catch (e) {
2003
2004 try {
2005 // deprecated, browser only, old way
2006 var Builder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
2007 var builder = new Builder();
2008 builder.append(buffer);
2009 return builder.getBlob('application/zip');
2010 }
2011 catch (e) {
2012
2013 // well, fuck ?!
2014 throw new Error("Bug : can't construct the Blob.");
2015 }
2016 }
2017
2018
2019};
2020/**
2021 * The identity function.
2022 * @param {Object} input the input.
2023 * @return {Object} the same input.
2024 */
2025function identity(input) {
2026 return input;
2027}
2028
2029/**
2030 * Fill in an array with a string.
2031 * @param {String} str the string to use.
2032 * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated).
2033 * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array.
2034 */
2035function stringToArrayLike(str, array) {
2036 for (var i = 0; i < str.length; ++i) {
2037 array[i] = str.charCodeAt(i) & 0xFF;
2038 }
2039 return array;
2040}
2041
2042/**
2043 * Transform an array-like object to a string.
2044 * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform.
2045 * @return {String} the result.
2046 */
2047function arrayLikeToString(array) {
2048 // Performances notes :
2049 // --------------------
2050 // String.fromCharCode.apply(null, array) is the fastest, see
2051 // see http://jsperf.com/converting-a-uint8array-to-a-string/2
2052 // but the stack is limited (and we can get huge arrays !).
2053 //
2054 // result += String.fromCharCode(array[i]); generate too many strings !
2055 //
2056 // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2
2057 var chunk = 65536;
2058 var result = [],
2059 len = array.length,
2060 type = exports.getTypeOf(array),
2061 k = 0,
2062 canUseApply = true;
2063 try {
2064 switch(type) {
2065 case "uint8array":
2066 String.fromCharCode.apply(null, new Uint8Array(0));
2067 break;
2068 case "nodebuffer":
2069 String.fromCharCode.apply(null, nodeBuffer(0));
2070 break;
2071 }
2072 } catch(e) {
2073 canUseApply = false;
2074 }
2075
2076 // no apply : slow and painful algorithm
2077 // default browser on android 4.*
2078 if (!canUseApply) {
2079 var resultStr = "";
2080 for(var i = 0; i < array.length;i++) {
2081 resultStr += String.fromCharCode(array[i]);
2082 }
2083 return resultStr;
2084 }
2085 while (k < len && chunk > 1) {
2086 try {
2087 if (type === "array" || type === "nodebuffer") {
2088 result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len))));
2089 }
2090 else {
2091 result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len))));
2092 }
2093 k += chunk;
2094 }
2095 catch (e) {
2096 chunk = Math.floor(chunk / 2);
2097 }
2098 }
2099 return result.join("");
2100}
2101
2102exports.applyFromCharCode = arrayLikeToString;
2103
2104
2105/**
2106 * Copy the data from an array-like to an other array-like.
2107 * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array.
2108 * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated.
2109 * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array.
2110 */
2111function arrayLikeToArrayLike(arrayFrom, arrayTo) {
2112 for (var i = 0; i < arrayFrom.length; i++) {
2113 arrayTo[i] = arrayFrom[i];
2114 }
2115 return arrayTo;
2116}
2117
2118// a matrix containing functions to transform everything into everything.
2119var transform = {};
2120
2121// string to ?
2122transform["string"] = {
2123 "string": identity,
2124 "array": function(input) {
2125 return stringToArrayLike(input, new Array(input.length));
2126 },
2127 "arraybuffer": function(input) {
2128 return transform["string"]["uint8array"](input).buffer;
2129 },
2130 "uint8array": function(input) {
2131 return stringToArrayLike(input, new Uint8Array(input.length));
2132 },
2133 "nodebuffer": function(input) {
2134 return stringToArrayLike(input, nodeBuffer(input.length));
2135 }
2136};
2137
2138// array to ?
2139transform["array"] = {
2140 "string": arrayLikeToString,
2141 "array": identity,
2142 "arraybuffer": function(input) {
2143 return (new Uint8Array(input)).buffer;
2144 },
2145 "uint8array": function(input) {
2146 return new Uint8Array(input);
2147 },
2148 "nodebuffer": function(input) {
2149 return nodeBuffer(input);
2150 }
2151};
2152
2153// arraybuffer to ?
2154transform["arraybuffer"] = {
2155 "string": function(input) {
2156 return arrayLikeToString(new Uint8Array(input));
2157 },
2158 "array": function(input) {
2159 return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength));
2160 },
2161 "arraybuffer": identity,
2162 "uint8array": function(input) {
2163 return new Uint8Array(input);
2164 },
2165 "nodebuffer": function(input) {
2166 return nodeBuffer(new Uint8Array(input));
2167 }
2168};
2169
2170// uint8array to ?
2171transform["uint8array"] = {
2172 "string": arrayLikeToString,
2173 "array": function(input) {
2174 return arrayLikeToArrayLike(input, new Array(input.length));
2175 },
2176 "arraybuffer": function(input) {
2177 return input.buffer;
2178 },
2179 "uint8array": identity,
2180 "nodebuffer": function(input) {
2181 return nodeBuffer(input);
2182 }
2183};
2184
2185// nodebuffer to ?
2186transform["nodebuffer"] = {
2187 "string": arrayLikeToString,
2188 "array": function(input) {
2189 return arrayLikeToArrayLike(input, new Array(input.length));
2190 },
2191 "arraybuffer": function(input) {
2192 return transform["nodebuffer"]["uint8array"](input).buffer;
2193 },
2194 "uint8array": function(input) {
2195 return arrayLikeToArrayLike(input, new Uint8Array(input.length));
2196 },
2197 "nodebuffer": identity
2198};
2199
2200/**
2201 * Transform an input into any type.
2202 * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer.
2203 * If no output type is specified, the unmodified input will be returned.
2204 * @param {String} outputType the output type.
2205 * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert.
2206 * @throws {Error} an Error if the browser doesn't support the requested output type.
2207 */
2208exports.transformTo = function(outputType, input) {
2209 if (!input) {
2210 // undefined, null, etc
2211 // an empty string won't harm.
2212 input = "";
2213 }
2214 if (!outputType) {
2215 return input;
2216 }
2217 exports.checkSupport(outputType);
2218 var inputType = exports.getTypeOf(input);
2219 var result = transform[inputType][outputType](input);
2220 return result;
2221};
2222
2223/**
2224 * Return the type of the input.
2225 * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer.
2226 * @param {Object} input the input to identify.
2227 * @return {String} the (lowercase) type of the input.
2228 */
2229exports.getTypeOf = function(input) {
2230 if (typeof input === "string") {
2231 return "string";
2232 }
2233 if (Object.prototype.toString.call(input) === "[object Array]") {
2234 return "array";
2235 }
2236 if (support.nodebuffer && nodeBuffer.test(input)) {
2237 return "nodebuffer";
2238 }
2239 if (support.uint8array && input instanceof Uint8Array) {
2240 return "uint8array";
2241 }
2242 if (support.arraybuffer && input instanceof ArrayBuffer) {
2243 return "arraybuffer";
2244 }
2245};
2246
2247/**
2248 * Throw an exception if the type is not supported.
2249 * @param {String} type the type to check.
2250 * @throws {Error} an Error if the browser doesn't support the requested type.
2251 */
2252exports.checkSupport = function(type) {
2253 var supported = support[type.toLowerCase()];
2254 if (!supported) {
2255 throw new Error(type + " is not supported by this browser");
2256 }
2257};
2258exports.MAX_VALUE_16BITS = 65535;
2259exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1
2260
2261/**
2262 * Prettify a string read as binary.
2263 * @param {string} str the string to prettify.
2264 * @return {string} a pretty string.
2265 */
2266exports.pretty = function(str) {
2267 var res = '',
2268 code, i;
2269 for (i = 0; i < (str || "").length; i++) {
2270 code = str.charCodeAt(i);
2271 res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase();
2272 }
2273 return res;
2274};
2275
2276/**
2277 * Find a compression registered in JSZip.
2278 * @param {string} compressionMethod the method magic to find.
2279 * @return {Object|null} the JSZip compression object, null if none found.
2280 */
2281exports.findCompression = function(compressionMethod) {
2282 for (var method in compressions) {
2283 if (!compressions.hasOwnProperty(method)) {
2284 continue;
2285 }
2286 if (compressions[method].magic === compressionMethod) {
2287 return compressions[method];
2288 }
2289 }
2290 return null;
2291};
2292/**
2293* Cross-window, cross-Node-context regular expression detection
2294* @param {Object} object Anything
2295* @return {Boolean} true if the object is a regular expression,
2296* false otherwise
2297*/
2298exports.isRegExp = function (object) {
2299 return Object.prototype.toString.call(object) === "[object RegExp]";
2300};
2301
2302
2303},{"./compressions":3,"./nodeBuffer":11,"./support":17}],22:[function(_dereq_,module,exports){
2304'use strict';
2305var StringReader = _dereq_('./stringReader');
2306var NodeBufferReader = _dereq_('./nodeBufferReader');
2307var Uint8ArrayReader = _dereq_('./uint8ArrayReader');
2308var utils = _dereq_('./utils');
2309var sig = _dereq_('./signature');
2310var ZipEntry = _dereq_('./zipEntry');
2311var support = _dereq_('./support');
2312var jszipProto = _dereq_('./object');
2313// class ZipEntries {{{
2314/**
2315 * All the entries in the zip file.
2316 * @constructor
2317 * @param {String|ArrayBuffer|Uint8Array} data the binary stream to load.
2318 * @param {Object} loadOptions Options for loading the stream.
2319 */
2320function ZipEntries(data, loadOptions) {
2321 this.files = [];
2322 this.loadOptions = loadOptions;
2323 if (data) {
2324 this.load(data);
2325 }
2326}
2327ZipEntries.prototype = {
2328 /**
2329 * Check that the reader is on the speficied signature.
2330 * @param {string} expectedSignature the expected signature.
2331 * @throws {Error} if it is an other signature.
2332 */
2333 checkSignature: function(expectedSignature) {
2334 var signature = this.reader.readString(4);
2335 if (signature !== expectedSignature) {
2336 throw new Error("Corrupted zip or bug : unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")");
2337 }
2338 },
2339 /**
2340 * Read the end of the central directory.
2341 */
2342 readBlockEndOfCentral: function() {
2343 this.diskNumber = this.reader.readInt(2);
2344 this.diskWithCentralDirStart = this.reader.readInt(2);
2345 this.centralDirRecordsOnThisDisk = this.reader.readInt(2);
2346 this.centralDirRecords = this.reader.readInt(2);
2347 this.centralDirSize = this.reader.readInt(4);
2348 this.centralDirOffset = this.reader.readInt(4);
2349
2350 this.zipCommentLength = this.reader.readInt(2);
2351 // warning : the encoding depends of the system locale
2352 // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded.
2353 // On a windows machine, this field is encoded with the localized windows code page.
2354 this.zipComment = this.reader.readString(this.zipCommentLength);
2355 // To get consistent behavior with the generation part, we will assume that
2356 // this is utf8 encoded.
2357 this.zipComment = jszipProto.utf8decode(this.zipComment);
2358 },
2359 /**
2360 * Read the end of the Zip 64 central directory.
2361 * Not merged with the method readEndOfCentral :
2362 * The end of central can coexist with its Zip64 brother,
2363 * I don't want to read the wrong number of bytes !
2364 */
2365 readBlockZip64EndOfCentral: function() {
2366 this.zip64EndOfCentralSize = this.reader.readInt(8);
2367 this.versionMadeBy = this.reader.readString(2);
2368 this.versionNeeded = this.reader.readInt(2);
2369 this.diskNumber = this.reader.readInt(4);
2370 this.diskWithCentralDirStart = this.reader.readInt(4);
2371 this.centralDirRecordsOnThisDisk = this.reader.readInt(8);
2372 this.centralDirRecords = this.reader.readInt(8);
2373 this.centralDirSize = this.reader.readInt(8);
2374 this.centralDirOffset = this.reader.readInt(8);
2375
2376 this.zip64ExtensibleData = {};
2377 var extraDataSize = this.zip64EndOfCentralSize - 44,
2378 index = 0,
2379 extraFieldId,
2380 extraFieldLength,
2381 extraFieldValue;
2382 while (index < extraDataSize) {
2383 extraFieldId = this.reader.readInt(2);
2384 extraFieldLength = this.reader.readInt(4);
2385 extraFieldValue = this.reader.readString(extraFieldLength);
2386 this.zip64ExtensibleData[extraFieldId] = {
2387 id: extraFieldId,
2388 length: extraFieldLength,
2389 value: extraFieldValue
2390 };
2391 }
2392 },
2393 /**
2394 * Read the end of the Zip 64 central directory locator.
2395 */
2396 readBlockZip64EndOfCentralLocator: function() {
2397 this.diskWithZip64CentralDirStart = this.reader.readInt(4);
2398 this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8);
2399 this.disksCount = this.reader.readInt(4);
2400 if (this.disksCount > 1) {
2401 throw new Error("Multi-volumes zip are not supported");
2402 }
2403 },
2404 /**
2405 * Read the local files, based on the offset read in the central part.
2406 */
2407 readLocalFiles: function() {
2408 var i, file;
2409 for (i = 0; i < this.files.length; i++) {
2410 file = this.files[i];
2411 this.reader.setIndex(file.localHeaderOffset);
2412 this.checkSignature(sig.LOCAL_FILE_HEADER);
2413 file.readLocalPart(this.reader);
2414 file.handleUTF8();
2415 }
2416 },
2417 /**
2418 * Read the central directory.
2419 */
2420 readCentralDir: function() {
2421 var file;
2422
2423 this.reader.setIndex(this.centralDirOffset);
2424 while (this.reader.readString(4) === sig.CENTRAL_FILE_HEADER) {
2425 file = new ZipEntry({
2426 zip64: this.zip64
2427 }, this.loadOptions);
2428 file.readCentralPart(this.reader);
2429 this.files.push(file);
2430 }
2431 },
2432 /**
2433 * Read the end of central directory.
2434 */
2435 readEndOfCentral: function() {
2436 var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END);
2437 if (offset === -1) {
2438 throw new Error("Corrupted zip : can't find end of central directory");
2439 }
2440 this.reader.setIndex(offset);
2441 this.checkSignature(sig.CENTRAL_DIRECTORY_END);
2442 this.readBlockEndOfCentral();
2443
2444
2445 /* extract from the zip spec :
2446 4) If one of the fields in the end of central directory
2447 record is too small to hold required data, the field
2448 should be set to -1 (0xFFFF or 0xFFFFFFFF) and the
2449 ZIP64 format record should be created.
2450 5) The end of central directory record and the
2451 Zip64 end of central directory locator record must
2452 reside on the same disk when splitting or spanning
2453 an archive.
2454 */
2455 if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) {
2456 this.zip64 = true;
2457
2458 /*
2459 Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from
2460 the zip file can fit into a 32bits integer. This cannot be solved : Javascript represents
2461 all numbers as 64-bit double precision IEEE 754 floating point numbers.
2462 So, we have 53bits for integers and bitwise operations treat everything as 32bits.
2463 see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators
2464 and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5
2465 */
2466
2467 // should look for a zip64 EOCD locator
2468 offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR);
2469 if (offset === -1) {
2470 throw new Error("Corrupted zip : can't find the ZIP64 end of central directory locator");
2471 }
2472 this.reader.setIndex(offset);
2473 this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR);
2474 this.readBlockZip64EndOfCentralLocator();
2475
2476 // now the zip64 EOCD record
2477 this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir);
2478 this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END);
2479 this.readBlockZip64EndOfCentral();
2480 }
2481 },
2482 prepareReader: function(data) {
2483 var type = utils.getTypeOf(data);
2484 if (type === "string" && !support.uint8array) {
2485 this.reader = new StringReader(data, this.loadOptions.optimizedBinaryString);
2486 }
2487 else if (type === "nodebuffer") {
2488 this.reader = new NodeBufferReader(data);
2489 }
2490 else {
2491 this.reader = new Uint8ArrayReader(utils.transformTo("uint8array", data));
2492 }
2493 },
2494 /**
2495 * Read a zip file and create ZipEntries.
2496 * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file.
2497 */
2498 load: function(data) {
2499 this.prepareReader(data);
2500 this.readEndOfCentral();
2501 this.readCentralDir();
2502 this.readLocalFiles();
2503 }
2504};
2505// }}} end of ZipEntries
2506module.exports = ZipEntries;
2507
2508},{"./nodeBufferReader":12,"./object":13,"./signature":14,"./stringReader":15,"./support":17,"./uint8ArrayReader":18,"./utils":21,"./zipEntry":23}],23:[function(_dereq_,module,exports){
2509'use strict';
2510var StringReader = _dereq_('./stringReader');
2511var utils = _dereq_('./utils');
2512var CompressedObject = _dereq_('./compressedObject');
2513var jszipProto = _dereq_('./object');
2514// class ZipEntry {{{
2515/**
2516 * An entry in the zip file.
2517 * @constructor
2518 * @param {Object} options Options of the current file.
2519 * @param {Object} loadOptions Options for loading the stream.
2520 */
2521function ZipEntry(options, loadOptions) {
2522 this.options = options;
2523 this.loadOptions = loadOptions;
2524}
2525ZipEntry.prototype = {
2526 /**
2527 * say if the file is encrypted.
2528 * @return {boolean} true if the file is encrypted, false otherwise.
2529 */
2530 isEncrypted: function() {
2531 // bit 1 is set
2532 return (this.bitFlag & 0x0001) === 0x0001;
2533 },
2534 /**
2535 * say if the file has utf-8 filename/comment.
2536 * @return {boolean} true if the filename/comment is in utf-8, false otherwise.
2537 */
2538 useUTF8: function() {
2539 // bit 11 is set
2540 return (this.bitFlag & 0x0800) === 0x0800;
2541 },
2542 /**
2543 * Prepare the function used to generate the compressed content from this ZipFile.
2544 * @param {DataReader} reader the reader to use.
2545 * @param {number} from the offset from where we should read the data.
2546 * @param {number} length the length of the data to read.
2547 * @return {Function} the callback to get the compressed content (the type depends of the DataReader class).
2548 */
2549 prepareCompressedContent: function(reader, from, length) {
2550 return function() {
2551 var previousIndex = reader.index;
2552 reader.setIndex(from);
2553 var compressedFileData = reader.readData(length);
2554 reader.setIndex(previousIndex);
2555
2556 return compressedFileData;
2557 };
2558 },
2559 /**
2560 * Prepare the function used to generate the uncompressed content from this ZipFile.
2561 * @param {DataReader} reader the reader to use.
2562 * @param {number} from the offset from where we should read the data.
2563 * @param {number} length the length of the data to read.
2564 * @param {JSZip.compression} compression the compression used on this file.
2565 * @param {number} uncompressedSize the uncompressed size to expect.
2566 * @return {Function} the callback to get the uncompressed content (the type depends of the DataReader class).
2567 */
2568 prepareContent: function(reader, from, length, compression, uncompressedSize) {
2569 return function() {
2570
2571 var compressedFileData = utils.transformTo(compression.uncompressInputType, this.getCompressedContent());
2572 var uncompressedFileData = compression.uncompress(compressedFileData);
2573
2574 if (uncompressedFileData.length !== uncompressedSize) {
2575 throw new Error("Bug : uncompressed data size mismatch");
2576 }
2577
2578 return uncompressedFileData;
2579 };
2580 },
2581 /**
2582 * Read the local part of a zip file and add the info in this object.
2583 * @param {DataReader} reader the reader to use.
2584 */
2585 readLocalPart: function(reader) {
2586 var compression, localExtraFieldsLength;
2587
2588 // we already know everything from the central dir !
2589 // If the central dir data are false, we are doomed.
2590 // On the bright side, the local part is scary : zip64, data descriptors, both, etc.
2591 // The less data we get here, the more reliable this should be.
2592 // Let's skip the whole header and dash to the data !
2593 reader.skip(22);
2594 // in some zip created on windows, the filename stored in the central dir contains \ instead of /.
2595 // Strangely, the filename here is OK.
2596 // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes
2597 // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators...
2598 // Search "unzip mismatching "local" filename continuing with "central" filename version" on
2599 // the internet.
2600 //
2601 // I think I see the logic here : the central directory is used to display
2602 // content and the local directory is used to extract the files. Mixing / and \
2603 // may be used to display \ to windows users and use / when extracting the files.
2604 // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394
2605 this.fileNameLength = reader.readInt(2);
2606 localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir
2607 this.fileName = reader.readString(this.fileNameLength);
2608 reader.skip(localExtraFieldsLength);
2609
2610 if (this.compressedSize == -1 || this.uncompressedSize == -1) {
2611 throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " + "(compressedSize == -1 || uncompressedSize == -1)");
2612 }
2613
2614 compression = utils.findCompression(this.compressionMethod);
2615 if (compression === null) { // no compression found
2616 throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + this.fileName + ")");
2617 }
2618 this.decompressed = new CompressedObject();
2619 this.decompressed.compressedSize = this.compressedSize;
2620 this.decompressed.uncompressedSize = this.uncompressedSize;
2621 this.decompressed.crc32 = this.crc32;
2622 this.decompressed.compressionMethod = this.compressionMethod;
2623 this.decompressed.getCompressedContent = this.prepareCompressedContent(reader, reader.index, this.compressedSize, compression);
2624 this.decompressed.getContent = this.prepareContent(reader, reader.index, this.compressedSize, compression, this.uncompressedSize);
2625
2626 // we need to compute the crc32...
2627 if (this.loadOptions.checkCRC32) {
2628 this.decompressed = utils.transformTo("string", this.decompressed.getContent());
2629 if (jszipProto.crc32(this.decompressed) !== this.crc32) {
2630 throw new Error("Corrupted zip : CRC32 mismatch");
2631 }
2632 }
2633 },
2634
2635 /**
2636 * Read the central part of a zip file and add the info in this object.
2637 * @param {DataReader} reader the reader to use.
2638 */
2639 readCentralPart: function(reader) {
2640 this.versionMadeBy = reader.readString(2);
2641 this.versionNeeded = reader.readInt(2);
2642 this.bitFlag = reader.readInt(2);
2643 this.compressionMethod = reader.readString(2);
2644 this.date = reader.readDate();
2645 this.crc32 = reader.readInt(4);
2646 this.compressedSize = reader.readInt(4);
2647 this.uncompressedSize = reader.readInt(4);
2648 this.fileNameLength = reader.readInt(2);
2649 this.extraFieldsLength = reader.readInt(2);
2650 this.fileCommentLength = reader.readInt(2);
2651 this.diskNumberStart = reader.readInt(2);
2652 this.internalFileAttributes = reader.readInt(2);
2653 this.externalFileAttributes = reader.readInt(4);
2654 this.localHeaderOffset = reader.readInt(4);
2655
2656 if (this.isEncrypted()) {
2657 throw new Error("Encrypted zip are not supported");
2658 }
2659
2660 this.fileName = reader.readString(this.fileNameLength);
2661 this.readExtraFields(reader);
2662 this.parseZIP64ExtraField(reader);
2663 this.fileComment = reader.readString(this.fileCommentLength);
2664
2665 // warning, this is true only for zip with madeBy == DOS (plateform dependent feature)
2666 this.dir = this.externalFileAttributes & 0x00000010 ? true : false;
2667 },
2668 /**
2669 * Parse the ZIP64 extra field and merge the info in the current ZipEntry.
2670 * @param {DataReader} reader the reader to use.
2671 */
2672 parseZIP64ExtraField: function(reader) {
2673
2674 if (!this.extraFields[0x0001]) {
2675 return;
2676 }
2677
2678 // should be something, preparing the extra reader
2679 var extraReader = new StringReader(this.extraFields[0x0001].value);
2680
2681 // I really hope that these 64bits integer can fit in 32 bits integer, because js
2682 // won't let us have more.
2683 if (this.uncompressedSize === utils.MAX_VALUE_32BITS) {
2684 this.uncompressedSize = extraReader.readInt(8);
2685 }
2686 if (this.compressedSize === utils.MAX_VALUE_32BITS) {
2687 this.compressedSize = extraReader.readInt(8);
2688 }
2689 if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) {
2690 this.localHeaderOffset = extraReader.readInt(8);
2691 }
2692 if (this.diskNumberStart === utils.MAX_VALUE_32BITS) {
2693 this.diskNumberStart = extraReader.readInt(4);
2694 }
2695 },
2696 /**
2697 * Read the central part of a zip file and add the info in this object.
2698 * @param {DataReader} reader the reader to use.
2699 */
2700 readExtraFields: function(reader) {
2701 var start = reader.index,
2702 extraFieldId,
2703 extraFieldLength,
2704 extraFieldValue;
2705
2706 this.extraFields = this.extraFields || {};
2707
2708 while (reader.index < start + this.extraFieldsLength) {
2709 extraFieldId = reader.readInt(2);
2710 extraFieldLength = reader.readInt(2);
2711 extraFieldValue = reader.readString(extraFieldLength);
2712
2713 this.extraFields[extraFieldId] = {
2714 id: extraFieldId,
2715 length: extraFieldLength,
2716 value: extraFieldValue
2717 };
2718 }
2719 },
2720 /**
2721 * Apply an UTF8 transformation if needed.
2722 */
2723 handleUTF8: function() {
2724 if (this.useUTF8()) {
2725 this.fileName = jszipProto.utf8decode(this.fileName);
2726 this.fileComment = jszipProto.utf8decode(this.fileComment);
2727 } else {
2728 var upath = this.findExtraFieldUnicodePath();
2729 if (upath !== null) {
2730 this.fileName = upath;
2731 }
2732 var ucomment = this.findExtraFieldUnicodeComment();
2733 if (ucomment !== null) {
2734 this.fileComment = ucomment;
2735 }
2736 }
2737 },
2738
2739 /**
2740 * Find the unicode path declared in the extra field, if any.
2741 * @return {String} the unicode path, null otherwise.
2742 */
2743 findExtraFieldUnicodePath: function() {
2744 var upathField = this.extraFields[0x7075];
2745 if (upathField) {
2746 var extraReader = new StringReader(upathField.value);
2747
2748 // wrong version
2749 if (extraReader.readInt(1) !== 1) {
2750 return null;
2751 }
2752
2753 // the crc of the filename changed, this field is out of date.
2754 if (jszipProto.crc32(this.fileName) !== extraReader.readInt(4)) {
2755 return null;
2756 }
2757
2758 return jszipProto.utf8decode(extraReader.readString(upathField.length - 5));
2759 }
2760 return null;
2761 },
2762
2763 /**
2764 * Find the unicode comment declared in the extra field, if any.
2765 * @return {String} the unicode comment, null otherwise.
2766 */
2767 findExtraFieldUnicodeComment: function() {
2768 var ucommentField = this.extraFields[0x6375];
2769 if (ucommentField) {
2770 var extraReader = new StringReader(ucommentField.value);
2771
2772 // wrong version
2773 if (extraReader.readInt(1) !== 1) {
2774 return null;
2775 }
2776
2777 // the crc of the comment changed, this field is out of date.
2778 if (jszipProto.crc32(this.fileComment) !== extraReader.readInt(4)) {
2779 return null;
2780 }
2781
2782 return jszipProto.utf8decode(extraReader.readString(ucommentField.length - 5));
2783 }
2784 return null;
2785 }
2786};
2787module.exports = ZipEntry;
2788
2789},{"./compressedObject":2,"./object":13,"./stringReader":15,"./utils":21}],24:[function(_dereq_,module,exports){
2790// Top level file is just a mixin of submodules & constants
2791'use strict';
2792
2793var assign = _dereq_('./lib/utils/common').assign;
2794
2795var deflate = _dereq_('./lib/deflate');
2796var inflate = _dereq_('./lib/inflate');
2797var constants = _dereq_('./lib/zlib/constants');
2798
2799var pako = {};
2800
2801assign(pako, deflate, inflate, constants);
2802
2803module.exports = pako;
2804},{"./lib/deflate":25,"./lib/inflate":26,"./lib/utils/common":27,"./lib/zlib/constants":30}],25:[function(_dereq_,module,exports){
2805'use strict';
2806
2807
2808var zlib_deflate = _dereq_('./zlib/deflate.js');
2809var utils = _dereq_('./utils/common');
2810var strings = _dereq_('./utils/strings');
2811var msg = _dereq_('./zlib/messages');
2812var zstream = _dereq_('./zlib/zstream');
2813
2814
2815/* Public constants ==========================================================*/
2816/* ===========================================================================*/
2817
2818var Z_NO_FLUSH = 0;
2819var Z_FINISH = 4;
2820
2821var Z_OK = 0;
2822var Z_STREAM_END = 1;
2823
2824var Z_DEFAULT_COMPRESSION = -1;
2825
2826var Z_DEFAULT_STRATEGY = 0;
2827
2828var Z_DEFLATED = 8;
2829
2830/* ===========================================================================*/
2831
2832
2833/**
2834 * class Deflate
2835 *
2836 * Generic JS-style wrapper for zlib calls. If you don't need
2837 * streaming behaviour - use more simple functions: [[deflate]],
2838 * [[deflateRaw]] and [[gzip]].
2839 **/
2840
2841/* internal
2842 * Deflate.chunks -> Array
2843 *
2844 * Chunks of output data, if [[Deflate#onData]] not overriden.
2845 **/
2846
2847/**
2848 * Deflate.result -> Uint8Array|Array
2849 *
2850 * Compressed result, generated by default [[Deflate#onData]]
2851 * and [[Deflate#onEnd]] handlers. Filled after you push last chunk
2852 * (call [[Deflate#push]] with `Z_FINISH` / `true` param).
2853 **/
2854
2855/**
2856 * Deflate.err -> Number
2857 *
2858 * Error code after deflate finished. 0 (Z_OK) on success.
2859 * You will not need it in real life, because deflate errors
2860 * are possible only on wrong options or bad `onData` / `onEnd`
2861 * custom handlers.
2862 **/
2863
2864/**
2865 * Deflate.msg -> String
2866 *
2867 * Error message, if [[Deflate.err]] != 0
2868 **/
2869
2870
2871/**
2872 * new Deflate(options)
2873 * - options (Object): zlib deflate options.
2874 *
2875 * Creates new deflator instance with specified params. Throws exception
2876 * on bad params. Supported options:
2877 *
2878 * - `level`
2879 * - `windowBits`
2880 * - `memLevel`
2881 * - `strategy`
2882 *
2883 * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
2884 * for more information on these.
2885 *
2886 * Additional options, for internal needs:
2887 *
2888 * - `chunkSize` - size of generated data chunks (16K by default)
2889 * - `raw` (Boolean) - do raw deflate
2890 * - `gzip` (Boolean) - create gzip wrapper
2891 * - `to` (String) - if equal to 'string', then result will be "binary string"
2892 * (each char code [0..255])
2893 * - `header` (Object) - custom header for gzip
2894 * - `text` (Boolean) - true if compressed data believed to be text
2895 * - `time` (Number) - modification time, unix timestamp
2896 * - `os` (Number) - operation system code
2897 * - `extra` (Array) - array of bytes with extra data (max 65536)
2898 * - `name` (String) - file name (binary string)
2899 * - `comment` (String) - comment (binary string)
2900 * - `hcrc` (Boolean) - true if header crc should be added
2901 *
2902 * ##### Example:
2903 *
2904 * ```javascript
2905 * var pako = require('pako')
2906 * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9])
2907 * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]);
2908 *
2909 * var deflate = new pako.Deflate({ level: 3});
2910 *
2911 * deflate.push(chunk1, false);
2912 * deflate.push(chunk2, true); // true -> last chunk
2913 *
2914 * if (deflate.err) { throw new Error(deflate.err); }
2915 *
2916 * console.log(deflate.result);
2917 * ```
2918 **/
2919var Deflate = function(options) {
2920
2921 this.options = utils.assign({
2922 level: Z_DEFAULT_COMPRESSION,
2923 method: Z_DEFLATED,
2924 chunkSize: 16384,
2925 windowBits: 15,
2926 memLevel: 8,
2927 strategy: Z_DEFAULT_STRATEGY,
2928 to: ''
2929 }, options || {});
2930
2931 var opt = this.options;
2932
2933 if (opt.raw && (opt.windowBits > 0)) {
2934 opt.windowBits = -opt.windowBits;
2935 }
2936
2937 else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) {
2938 opt.windowBits += 16;
2939 }
2940
2941 this.err = 0; // error code, if happens (0 = Z_OK)
2942 this.msg = ''; // error message
2943 this.ended = false; // used to avoid multiple onEnd() calls
2944 this.chunks = []; // chunks of compressed data
2945
2946 this.strm = new zstream();
2947 this.strm.avail_out = 0;
2948
2949 var status = zlib_deflate.deflateInit2(
2950 this.strm,
2951 opt.level,
2952 opt.method,
2953 opt.windowBits,
2954 opt.memLevel,
2955 opt.strategy
2956 );
2957
2958 if (status !== Z_OK) {
2959 throw new Error(msg[status]);
2960 }
2961
2962 if (opt.header) {
2963 zlib_deflate.deflateSetHeader(this.strm, opt.header);
2964 }
2965};
2966
2967/**
2968 * Deflate#push(data[, mode]) -> Boolean
2969 * - data (Uint8Array|Array|String): input data. Strings will be converted to
2970 * utf8 byte sequence.
2971 * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.
2972 * See constants. Skipped or `false` means Z_NO_FLUSH, `true` meansh Z_FINISH.
2973 *
2974 * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with
2975 * new compressed chunks. Returns `true` on success. The last data block must have
2976 * mode Z_FINISH (or `true`). That flush internal pending buffers and call
2977 * [[Deflate#onEnd]].
2978 *
2979 * On fail call [[Deflate#onEnd]] with error code and return false.
2980 *
2981 * We strongly recommend to use `Uint8Array` on input for best speed (output
2982 * array format is detected automatically). Also, don't skip last param and always
2983 * use the same type in your code (boolean or number). That will improve JS speed.
2984 *
2985 * For regular `Array`-s make sure all elements are [0..255].
2986 *
2987 * ##### Example
2988 *
2989 * ```javascript
2990 * push(chunk, false); // push one of data chunks
2991 * ...
2992 * push(chunk, true); // push last chunk
2993 * ```
2994 **/
2995Deflate.prototype.push = function(data, mode) {
2996 var strm = this.strm;
2997 var chunkSize = this.options.chunkSize;
2998 var status, _mode;
2999
3000 if (this.ended) { return false; }
3001
3002 _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH);
3003
3004 // Convert data if needed
3005 if (typeof data === 'string') {
3006 // If we need to compress text, change encoding to utf8.
3007 strm.input = strings.string2buf(data);
3008 } else {
3009 strm.input = data;
3010 }
3011
3012 strm.next_in = 0;
3013 strm.avail_in = strm.input.length;
3014
3015 do {
3016 if (strm.avail_out === 0) {
3017 strm.output = new utils.Buf8(chunkSize);
3018 strm.next_out = 0;
3019 strm.avail_out = chunkSize;
3020 }
3021 status = zlib_deflate.deflate(strm, _mode); /* no bad return value */
3022
3023 if (status !== Z_STREAM_END && status !== Z_OK) {
3024 this.onEnd(status);
3025 this.ended = true;
3026 return false;
3027 }
3028 if (strm.avail_out === 0 || (strm.avail_in === 0 && _mode === Z_FINISH)) {
3029 if (this.options.to === 'string') {
3030 this.onData(strings.buf2binstring(utils.shrinkBuf(strm.output, strm.next_out)));
3031 } else {
3032 this.onData(utils.shrinkBuf(strm.output, strm.next_out));
3033 }
3034 }
3035 } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END);
3036
3037 // Finalize on the last chunk.
3038 if (_mode === Z_FINISH) {
3039 status = zlib_deflate.deflateEnd(this.strm);
3040 this.onEnd(status);
3041 this.ended = true;
3042 return status === Z_OK;
3043 }
3044
3045 return true;
3046};
3047
3048
3049/**
3050 * Deflate#onData(chunk) -> Void
3051 * - chunk (Uint8Array|Array|String): ouput data. Type of array depends
3052 * on js engine support. When string output requested, each chunk
3053 * will be string.
3054 *
3055 * By default, stores data blocks in `chunks[]` property and glue
3056 * those in `onEnd`. Override this handler, if you need another behaviour.
3057 **/
3058Deflate.prototype.onData = function(chunk) {
3059 this.chunks.push(chunk);
3060};
3061
3062
3063/**
3064 * Deflate#onEnd(status) -> Void
3065 * - status (Number): deflate status. 0 (Z_OK) on success,
3066 * other if not.
3067 *
3068 * Called once after you tell deflate that input stream complete
3069 * or error happenned. By default - join collected chunks,
3070 * free memory and fill `results` / `err` properties.
3071 **/
3072Deflate.prototype.onEnd = function(status) {
3073 // On success - join
3074 if (status === Z_OK) {
3075 if (this.options.to === 'string') {
3076 this.result = this.chunks.join('');
3077 } else {
3078 this.result = utils.flattenChunks(this.chunks);
3079 }
3080 }
3081 this.chunks = [];
3082 this.err = status;
3083 this.msg = this.strm.msg;
3084};
3085
3086
3087/**
3088 * deflate(data[, options]) -> Uint8Array|Array|String
3089 * - data (Uint8Array|Array|String): input data to compress.
3090 * - options (Object): zlib deflate options.
3091 *
3092 * Compress `data` with deflate alrorythm and `options`.
3093 *
3094 * Supported options are:
3095 *
3096 * - level
3097 * - windowBits
3098 * - memLevel
3099 * - strategy
3100 *
3101 * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
3102 * for more information on these.
3103 *
3104 * Sugar (options):
3105 *
3106 * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify
3107 * negative windowBits implicitly.
3108 * - `to` (String) - if equal to 'string', then result will be "binary string"
3109 * (each char code [0..255])
3110 *
3111 * ##### Example:
3112 *
3113 * ```javascript
3114 * var pako = require('pako')
3115 * , data = Uint8Array([1,2,3,4,5,6,7,8,9]);
3116 *
3117 * console.log(pako.deflate(data));
3118 * ```
3119 **/
3120function deflate(input, options) {
3121 var deflator = new Deflate(options);
3122
3123 deflator.push(input, true);
3124
3125 // That will never happens, if you don't cheat with options :)
3126 if (deflator.err) { throw deflator.msg; }
3127
3128 return deflator.result;
3129}
3130
3131
3132/**
3133 * deflateRaw(data[, options]) -> Uint8Array|Array|String
3134 * - data (Uint8Array|Array|String): input data to compress.
3135 * - options (Object): zlib deflate options.
3136 *
3137 * The same as [[deflate]], but creates raw data, without wrapper
3138 * (header and adler32 crc).
3139 **/
3140function deflateRaw(input, options) {
3141 options = options || {};
3142 options.raw = true;
3143 return deflate(input, options);
3144}
3145
3146
3147/**
3148 * gzip(data[, options]) -> Uint8Array|Array|String
3149 * - data (Uint8Array|Array|String): input data to compress.
3150 * - options (Object): zlib deflate options.
3151 *
3152 * The same as [[deflate]], but create gzip wrapper instead of
3153 * deflate one.
3154 **/
3155function gzip(input, options) {
3156 options = options || {};
3157 options.gzip = true;
3158 return deflate(input, options);
3159}
3160
3161
3162exports.Deflate = Deflate;
3163exports.deflate = deflate;
3164exports.deflateRaw = deflateRaw;
3165exports.gzip = gzip;
3166},{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37,"./zlib/zstream":39}],26:[function(_dereq_,module,exports){
3167'use strict';
3168
3169
3170var zlib_inflate = _dereq_('./zlib/inflate.js');
3171var utils = _dereq_('./utils/common');
3172var strings = _dereq_('./utils/strings');
3173var c = _dereq_('./zlib/constants');
3174var msg = _dereq_('./zlib/messages');
3175var zstream = _dereq_('./zlib/zstream');
3176var gzheader = _dereq_('./zlib/gzheader');
3177
3178
3179/**
3180 * class Inflate
3181 *
3182 * Generic JS-style wrapper for zlib calls. If you don't need
3183 * streaming behaviour - use more simple functions: [[inflate]]
3184 * and [[inflateRaw]].
3185 **/
3186
3187/* internal
3188 * inflate.chunks -> Array
3189 *
3190 * Chunks of output data, if [[Inflate#onData]] not overriden.
3191 **/
3192
3193/**
3194 * Inflate.result -> Uint8Array|Array|String
3195 *
3196 * Uncompressed result, generated by default [[Inflate#onData]]
3197 * and [[Inflate#onEnd]] handlers. Filled after you push last chunk
3198 * (call [[Inflate#push]] with `Z_FINISH` / `true` param).
3199 **/
3200
3201/**
3202 * Inflate.err -> Number
3203 *
3204 * Error code after inflate finished. 0 (Z_OK) on success.
3205 * Should be checked if broken data possible.
3206 **/
3207
3208/**
3209 * Inflate.msg -> String
3210 *
3211 * Error message, if [[Inflate.err]] != 0
3212 **/
3213
3214
3215/**
3216 * new Inflate(options)
3217 * - options (Object): zlib inflate options.
3218 *
3219 * Creates new inflator instance with specified params. Throws exception
3220 * on bad params. Supported options:
3221 *
3222 * - `windowBits`
3223 *
3224 * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
3225 * for more information on these.
3226 *
3227 * Additional options, for internal needs:
3228 *
3229 * - `chunkSize` - size of generated data chunks (16K by default)
3230 * - `raw` (Boolean) - do raw inflate
3231 * - `to` (String) - if equal to 'string', then result will be converted
3232 * from utf8 to utf16 (javascript) string. When string output requested,
3233 * chunk length can differ from `chunkSize`, depending on content.
3234 *
3235 * By default, when no options set, autodetect deflate/gzip data format via
3236 * wrapper header.
3237 *
3238 * ##### Example:
3239 *
3240 * ```javascript
3241 * var pako = require('pako')
3242 * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9])
3243 * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]);
3244 *
3245 * var inflate = new pako.Inflate({ level: 3});
3246 *
3247 * inflate.push(chunk1, false);
3248 * inflate.push(chunk2, true); // true -> last chunk
3249 *
3250 * if (inflate.err) { throw new Error(inflate.err); }
3251 *
3252 * console.log(inflate.result);
3253 * ```
3254 **/
3255var Inflate = function(options) {
3256
3257 this.options = utils.assign({
3258 chunkSize: 16384,
3259 windowBits: 0,
3260 to: ''
3261 }, options || {});
3262
3263 var opt = this.options;
3264
3265 // Force window size for `raw` data, if not set directly,
3266 // because we have no header for autodetect.
3267 if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) {
3268 opt.windowBits = -opt.windowBits;
3269 if (opt.windowBits === 0) { opt.windowBits = -15; }
3270 }
3271
3272 // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate
3273 if ((opt.windowBits >= 0) && (opt.windowBits < 16) &&
3274 !(options && options.windowBits)) {
3275 opt.windowBits += 32;
3276 }
3277
3278 // Gzip header has no info about windows size, we can do autodetect only
3279 // for deflate. So, if window size not set, force it to max when gzip possible
3280 if ((opt.windowBits > 15) && (opt.windowBits < 48)) {
3281 // bit 3 (16) -> gzipped data
3282 // bit 4 (32) -> autodetect gzip/deflate
3283 if ((opt.windowBits & 15) === 0) {
3284 opt.windowBits |= 15;
3285 }
3286 }
3287
3288 this.err = 0; // error code, if happens (0 = Z_OK)
3289 this.msg = ''; // error message
3290 this.ended = false; // used to avoid multiple onEnd() calls
3291 this.chunks = []; // chunks of compressed data
3292
3293 this.strm = new zstream();
3294 this.strm.avail_out = 0;
3295
3296 var status = zlib_inflate.inflateInit2(
3297 this.strm,
3298 opt.windowBits
3299 );
3300
3301 if (status !== c.Z_OK) {
3302 throw new Error(msg[status]);
3303 }
3304
3305 this.header = new gzheader();
3306
3307 zlib_inflate.inflateGetHeader(this.strm, this.header);
3308};
3309
3310/**
3311 * Inflate#push(data[, mode]) -> Boolean
3312 * - data (Uint8Array|Array|String): input data
3313 * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.
3314 * See constants. Skipped or `false` means Z_NO_FLUSH, `true` meansh Z_FINISH.
3315 *
3316 * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with
3317 * new output chunks. Returns `true` on success. The last data block must have
3318 * mode Z_FINISH (or `true`). That flush internal pending buffers and call
3319 * [[Inflate#onEnd]].
3320 *
3321 * On fail call [[Inflate#onEnd]] with error code and return false.
3322 *
3323 * We strongly recommend to use `Uint8Array` on input for best speed (output
3324 * format is detected automatically). Also, don't skip last param and always
3325 * use the same type in your code (boolean or number). That will improve JS speed.
3326 *
3327 * For regular `Array`-s make sure all elements are [0..255].
3328 *
3329 * ##### Example
3330 *
3331 * ```javascript
3332 * push(chunk, false); // push one of data chunks
3333 * ...
3334 * push(chunk, true); // push last chunk
3335 * ```
3336 **/
3337Inflate.prototype.push = function(data, mode) {
3338 var strm = this.strm;
3339 var chunkSize = this.options.chunkSize;
3340 var status, _mode;
3341 var next_out_utf8, tail, utf8str;
3342
3343 if (this.ended) { return false; }
3344 _mode = (mode === ~~mode) ? mode : ((mode === true) ? c.Z_FINISH : c.Z_NO_FLUSH);
3345
3346 // Convert data if needed
3347 if (typeof data === 'string') {
3348 // Only binary strings can be decompressed on practice
3349 strm.input = strings.binstring2buf(data);
3350 } else {
3351 strm.input = data;
3352 }
3353
3354 strm.next_in = 0;
3355 strm.avail_in = strm.input.length;
3356
3357 do {
3358 if (strm.avail_out === 0) {
3359 strm.output = new utils.Buf8(chunkSize);
3360 strm.next_out = 0;
3361 strm.avail_out = chunkSize;
3362 }
3363
3364 status = zlib_inflate.inflate(strm, c.Z_NO_FLUSH); /* no bad return value */
3365
3366 if (status !== c.Z_STREAM_END && status !== c.Z_OK) {
3367 this.onEnd(status);
3368 this.ended = true;
3369 return false;
3370 }
3371
3372 if (strm.next_out) {
3373 if (strm.avail_out === 0 || status === c.Z_STREAM_END || (strm.avail_in === 0 && _mode === c.Z_FINISH)) {
3374
3375 if (this.options.to === 'string') {
3376
3377 next_out_utf8 = strings.utf8border(strm.output, strm.next_out);
3378
3379 tail = strm.next_out - next_out_utf8;
3380 utf8str = strings.buf2string(strm.output, next_out_utf8);
3381
3382 // move tail
3383 strm.next_out = tail;
3384 strm.avail_out = chunkSize - tail;
3385 if (tail) { utils.arraySet(strm.output, strm.output, next_out_utf8, tail, 0); }
3386
3387 this.onData(utf8str);
3388
3389 } else {
3390 this.onData(utils.shrinkBuf(strm.output, strm.next_out));
3391 }
3392 }
3393 }
3394 } while ((strm.avail_in > 0) && status !== c.Z_STREAM_END);
3395
3396 if (status === c.Z_STREAM_END) {
3397 _mode = c.Z_FINISH;
3398 }
3399 // Finalize on the last chunk.
3400 if (_mode === c.Z_FINISH) {
3401 status = zlib_inflate.inflateEnd(this.strm);
3402 this.onEnd(status);
3403 this.ended = true;
3404 return status === c.Z_OK;
3405 }
3406
3407 return true;
3408};
3409
3410
3411/**
3412 * Inflate#onData(chunk) -> Void
3413 * - chunk (Uint8Array|Array|String): ouput data. Type of array depends
3414 * on js engine support. When string output requested, each chunk
3415 * will be string.
3416 *
3417 * By default, stores data blocks in `chunks[]` property and glue
3418 * those in `onEnd`. Override this handler, if you need another behaviour.
3419 **/
3420Inflate.prototype.onData = function(chunk) {
3421 this.chunks.push(chunk);
3422};
3423
3424
3425/**
3426 * Inflate#onEnd(status) -> Void
3427 * - status (Number): inflate status. 0 (Z_OK) on success,
3428 * other if not.
3429 *
3430 * Called once after you tell inflate that input stream complete
3431 * or error happenned. By default - join collected chunks,
3432 * free memory and fill `results` / `err` properties.
3433 **/
3434Inflate.prototype.onEnd = function(status) {
3435 // On success - join
3436 if (status === c.Z_OK) {
3437 if (this.options.to === 'string') {
3438 // Glue & convert here, until we teach pako to send
3439 // utf8 alligned strings to onData
3440 this.result = this.chunks.join('');
3441 } else {
3442 this.result = utils.flattenChunks(this.chunks);
3443 }
3444 }
3445 this.chunks = [];
3446 this.err = status;
3447 this.msg = this.strm.msg;
3448};
3449
3450
3451/**
3452 * inflate(data[, options]) -> Uint8Array|Array|String
3453 * - data (Uint8Array|Array|String): input data to decompress.
3454 * - options (Object): zlib inflate options.
3455 *
3456 * Decompress `data` with inflate/ungzip and `options`. Autodetect
3457 * format via wrapper header by default. That's why we don't provide
3458 * separate `ungzip` method.
3459 *
3460 * Supported options are:
3461 *
3462 * - windowBits
3463 *
3464 * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)
3465 * for more information.
3466 *
3467 * Sugar (options):
3468 *
3469 * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify
3470 * negative windowBits implicitly.
3471 * - `to` (String) - if equal to 'string', then result will be converted
3472 * from utf8 to utf16 (javascript) string. When string output requested,
3473 * chunk length can differ from `chunkSize`, depending on content.
3474 *
3475 *
3476 * ##### Example:
3477 *
3478 * ```javascript
3479 * var pako = require('pako')
3480 * , input = pako.deflate([1,2,3,4,5,6,7,8,9])
3481 * , output;
3482 *
3483 * try {
3484 * output = pako.inflate(input);
3485 * } catch (err)
3486 * console.log(err);
3487 * }
3488 * ```
3489 **/
3490function inflate(input, options) {
3491 var inflator = new Inflate(options);
3492
3493 inflator.push(input, true);
3494
3495 // That will never happens, if you don't cheat with options :)
3496 if (inflator.err) { throw inflator.msg; }
3497
3498 return inflator.result;
3499}
3500
3501
3502/**
3503 * inflateRaw(data[, options]) -> Uint8Array|Array|String
3504 * - data (Uint8Array|Array|String): input data to decompress.
3505 * - options (Object): zlib inflate options.
3506 *
3507 * The same as [[inflate]], but creates raw data, without wrapper
3508 * (header and adler32 crc).
3509 **/
3510function inflateRaw(input, options) {
3511 options = options || {};
3512 options.raw = true;
3513 return inflate(input, options);
3514}
3515
3516
3517/**
3518 * ungzip(data[, options]) -> Uint8Array|Array|String
3519 * - data (Uint8Array|Array|String): input data to decompress.
3520 * - options (Object): zlib inflate options.
3521 *
3522 * Just shortcut to [[inflate]], because it autodetects format
3523 * by header.content. Done for convenience.
3524 **/
3525
3526
3527exports.Inflate = Inflate;
3528exports.inflate = inflate;
3529exports.inflateRaw = inflateRaw;
3530exports.ungzip = inflate;
3531
3532},{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(_dereq_,module,exports){
3533'use strict';
3534
3535
3536var TYPED_OK = (typeof Uint8Array !== 'undefined') &&
3537 (typeof Uint16Array !== 'undefined') &&
3538 (typeof Int32Array !== 'undefined');
3539
3540
3541exports.assign = function (obj /*from1, from2, from3, ...*/) {
3542 var sources = Array.prototype.slice.call(arguments, 1);
3543 while (sources.length) {
3544 var source = sources.shift();
3545 if (!source) { continue; }
3546
3547 if (typeof(source) !== 'object') {
3548 throw new TypeError(source + 'must be non-object');
3549 }
3550
3551 for (var p in source) {
3552 if (source.hasOwnProperty(p)) {
3553 obj[p] = source[p];
3554 }
3555 }
3556 }
3557
3558 return obj;
3559};
3560
3561
3562// reduce buffer size, avoiding mem copy
3563exports.shrinkBuf = function (buf, size) {
3564 if (buf.length === size) { return buf; }
3565 if (buf.subarray) { return buf.subarray(0, size); }
3566 buf.length = size;
3567 return buf;
3568};
3569
3570
3571var fnTyped = {
3572 arraySet: function (dest, src, src_offs, len, dest_offs) {
3573 if (src.subarray && dest.subarray) {
3574 dest.set(src.subarray(src_offs, src_offs+len), dest_offs);
3575 return;
3576 }
3577 // Fallback to ordinary array
3578 for(var i=0; i<len; i++) {
3579 dest[dest_offs + i] = src[src_offs + i];
3580 }
3581 },
3582 // Join array of chunks to single array.
3583 flattenChunks: function(chunks) {
3584 var i, l, len, pos, chunk, result;
3585
3586 // calculate data length
3587 len = 0;
3588 for (i=0, l=chunks.length; i<l; i++) {
3589 len += chunks[i].length;
3590 }
3591
3592 // join chunks
3593 result = new Uint8Array(len);
3594 pos = 0;
3595 for (i=0, l=chunks.length; i<l; i++) {
3596 chunk = chunks[i];
3597 result.set(chunk, pos);
3598 pos += chunk.length;
3599 }
3600
3601 return result;
3602 }
3603};
3604
3605var fnUntyped = {
3606 arraySet: function (dest, src, src_offs, len, dest_offs) {
3607 for(var i=0; i<len; i++) {
3608 dest[dest_offs + i] = src[src_offs + i];
3609 }
3610 },
3611 // Join array of chunks to single array.
3612 flattenChunks: function(chunks) {
3613 return [].concat.apply([], chunks);
3614 }
3615};
3616
3617
3618// Enable/Disable typed arrays use, for testing
3619//
3620exports.setTyped = function (on) {
3621 if (on) {
3622 exports.Buf8 = Uint8Array;
3623 exports.Buf16 = Uint16Array;
3624 exports.Buf32 = Int32Array;
3625 exports.assign(exports, fnTyped);
3626 } else {
3627 exports.Buf8 = Array;
3628 exports.Buf16 = Array;
3629 exports.Buf32 = Array;
3630 exports.assign(exports, fnUntyped);
3631 }
3632};
3633
3634exports.setTyped(TYPED_OK);
3635},{}],28:[function(_dereq_,module,exports){
3636// String encode/decode helpers
3637'use strict';
3638
3639
3640var utils = _dereq_('./common');
3641
3642
3643// Quick check if we can use fast array to bin string conversion
3644//
3645// - apply(Array) can fail on Android 2.2
3646// - apply(Uint8Array) can fail on iOS 5.1 Safary
3647//
3648var STR_APPLY_OK = true;
3649var STR_APPLY_UIA_OK = true;
3650
3651try { String.fromCharCode.apply(null, [0]); } catch(__) { STR_APPLY_OK = false; }
3652try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch(__) { STR_APPLY_UIA_OK = false; }
3653
3654
3655// Table with utf8 lengths (calculated by first byte of sequence)
3656// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,
3657// because max possible codepoint is 0x10ffff
3658var _utf8len = new utils.Buf8(256);
3659for (var i=0; i<256; i++) {
3660 _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1);
3661}
3662_utf8len[254]=_utf8len[254]=1; // Invalid sequence start
3663
3664
3665// convert string to array (typed, when possible)
3666exports.string2buf = function (str) {
3667 var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;
3668
3669 // count binary size
3670 for (m_pos = 0; m_pos < str_len; m_pos++) {
3671 c = str.charCodeAt(m_pos);
3672 if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) {
3673 c2 = str.charCodeAt(m_pos+1);
3674 if ((c2 & 0xfc00) === 0xdc00) {
3675 c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
3676 m_pos++;
3677 }
3678 }
3679 buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;
3680 }
3681
3682 // allocate buffer
3683 buf = new utils.Buf8(buf_len);
3684
3685 // convert
3686 for (i=0, m_pos = 0; i < buf_len; m_pos++) {
3687 c = str.charCodeAt(m_pos);
3688 if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) {
3689 c2 = str.charCodeAt(m_pos+1);
3690 if ((c2 & 0xfc00) === 0xdc00) {
3691 c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
3692 m_pos++;
3693 }
3694 }
3695 if (c < 0x80) {
3696 /* one byte */
3697 buf[i++] = c;
3698 } else if (c < 0x800) {
3699 /* two bytes */
3700 buf[i++] = 0xC0 | (c >>> 6);
3701 buf[i++] = 0x80 | (c & 0x3f);
3702 } else if (c < 0x10000) {
3703 /* three bytes */
3704 buf[i++] = 0xE0 | (c >>> 12);
3705 buf[i++] = 0x80 | (c >>> 6 & 0x3f);
3706 buf[i++] = 0x80 | (c & 0x3f);
3707 } else {
3708 /* four bytes */
3709 buf[i++] = 0xf0 | (c >>> 18);
3710 buf[i++] = 0x80 | (c >>> 12 & 0x3f);
3711 buf[i++] = 0x80 | (c >>> 6 & 0x3f);
3712 buf[i++] = 0x80 | (c & 0x3f);
3713 }
3714 }
3715
3716 return buf;
3717};
3718
3719// Helper (used in 2 places)
3720function buf2binstring(buf, len) {
3721 // use fallback for big arrays to avoid stack overflow
3722 if (len < 65537) {
3723 if ((buf.subarray && STR_APPLY_UIA_OK) || (!buf.subarray && STR_APPLY_OK)) {
3724 return String.fromCharCode.apply(null, utils.shrinkBuf(buf, len));
3725 }
3726 }
3727
3728 var result = '';
3729 for(var i=0; i < len; i++) {
3730 result += String.fromCharCode(buf[i]);
3731 }
3732 return result;
3733}
3734
3735
3736// Convert byte array to binary string
3737exports.buf2binstring = function(buf) {
3738 return buf2binstring(buf, buf.length);
3739};
3740
3741
3742// Convert binary string (typed, when possible)
3743exports.binstring2buf = function(str) {
3744 var buf = new utils.Buf8(str.length);
3745 for(var i=0, len=buf.length; i < len; i++) {
3746 buf[i] = str.charCodeAt(i);
3747 }
3748 return buf;
3749};
3750
3751
3752// convert array to string
3753exports.buf2string = function (buf, max) {
3754 var i, out, c, c_len;
3755 var len = max || buf.length;
3756
3757 // Reserve max possible length (2 words per char)
3758 // NB: by unknown reasons, Array is significantly faster for
3759 // String.fromCharCode.apply than Uint16Array.
3760 var utf16buf = new Array(len*2);
3761
3762 for (out=0, i=0; i<len;) {
3763 c = buf[i++];
3764 // quick process ascii
3765 if (c < 0x80) { utf16buf[out++] = c; continue; }
3766
3767 c_len = _utf8len[c];
3768 // skip 5 & 6 byte codes
3769 if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; }
3770
3771 // apply mask on first byte
3772 c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;
3773 // join the rest
3774 while (c_len > 1 && i < len) {
3775 c = (c << 6) | (buf[i++] & 0x3f);
3776 c_len--;
3777 }
3778
3779 // terminated by end of string?
3780 if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }
3781
3782 if (c < 0x10000) {
3783 utf16buf[out++] = c;
3784 } else {
3785 c -= 0x10000;
3786 utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);
3787 utf16buf[out++] = 0xdc00 | (c & 0x3ff);
3788 }
3789 }
3790
3791 return buf2binstring(utf16buf, out);
3792};
3793
3794
3795// Calculate max possible position in utf8 buffer,
3796// that will not break sequence. If that's not possible
3797// - (very small limits) return max size as is.
3798//
3799// buf[] - utf8 bytes array
3800// max - length limit (mandatory);
3801exports.utf8border = function(buf, max) {
3802 var pos;
3803
3804 max = max || buf.length;
3805 if (max > buf.length) { max = buf.length; }
3806
3807 // go back from last position, until start of sequence found
3808 pos = max-1;
3809 while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }
3810
3811 // Fuckup - very small and broken sequence,
3812 // return max, because we should return something anyway.
3813 if (pos < 0) { return max; }
3814
3815 // If we came to start of buffer - that means vuffer is too small,
3816 // return max too.
3817 if (pos === 0) { return max; }
3818
3819 return (pos + _utf8len[buf[pos]] > max) ? pos : max;
3820};
3821
3822},{"./common":27}],29:[function(_dereq_,module,exports){
3823'use strict';
3824
3825// Note: adler32 takes 12% for level 0 and 2% for level 6.
3826// It doesn't worth to make additional optimizationa as in original.
3827// Small size is preferable.
3828
3829function adler32(adler, buf, len, pos) {
3830 var s1 = (adler & 0xffff) |0
3831 , s2 = ((adler >>> 16) & 0xffff) |0
3832 , n = 0;
3833
3834 while (len !== 0) {
3835 // Set limit ~ twice less than 5552, to keep
3836 // s2 in 31-bits, because we force signed ints.
3837 // in other case %= will fail.
3838 n = len > 2000 ? 2000 : len;
3839 len -= n;
3840
3841 do {
3842 s1 = (s1 + buf[pos++]) |0;
3843 s2 = (s2 + s1) |0;
3844 } while (--n);
3845
3846 s1 %= 65521;
3847 s2 %= 65521;
3848 }
3849
3850 return (s1 | (s2 << 16)) |0;
3851}
3852
3853
3854module.exports = adler32;
3855},{}],30:[function(_dereq_,module,exports){
3856module.exports = {
3857
3858 /* Allowed flush values; see deflate() and inflate() below for details */
3859 Z_NO_FLUSH: 0,
3860 Z_PARTIAL_FLUSH: 1,
3861 Z_SYNC_FLUSH: 2,
3862 Z_FULL_FLUSH: 3,
3863 Z_FINISH: 4,
3864 Z_BLOCK: 5,
3865 Z_TREES: 6,
3866
3867 /* Return codes for the compression/decompression functions. Negative values
3868 * are errors, positive values are used for special but normal events.
3869 */
3870 Z_OK: 0,
3871 Z_STREAM_END: 1,
3872 Z_NEED_DICT: 2,
3873 Z_ERRNO: -1,
3874 Z_STREAM_ERROR: -2,
3875 Z_DATA_ERROR: -3,
3876 //Z_MEM_ERROR: -4,
3877 Z_BUF_ERROR: -5,
3878 //Z_VERSION_ERROR: -6,
3879
3880 /* compression levels */
3881 Z_NO_COMPRESSION: 0,
3882 Z_BEST_SPEED: 1,
3883 Z_BEST_COMPRESSION: 9,
3884 Z_DEFAULT_COMPRESSION: -1,
3885
3886
3887 Z_FILTERED: 1,
3888 Z_HUFFMAN_ONLY: 2,
3889 Z_RLE: 3,
3890 Z_FIXED: 4,
3891 Z_DEFAULT_STRATEGY: 0,
3892
3893 /* Possible values of the data_type field (though see inflate()) */
3894 Z_BINARY: 0,
3895 Z_TEXT: 1,
3896 //Z_ASCII: 1, // = Z_TEXT (deprecated)
3897 Z_UNKNOWN: 2,
3898
3899 /* The deflate compression method */
3900 Z_DEFLATED: 8
3901 //Z_NULL: null // Use -1 or null inline, depending on var type
3902};
3903},{}],31:[function(_dereq_,module,exports){
3904'use strict';
3905
3906// Note: we can't get significant speed boost here.
3907// So write code to minimize size - no pregenerated tables
3908// and array tools dependencies.
3909
3910
3911// Use ordinary array, since untyped makes no boost here
3912function makeTable() {
3913 var c, table = [];
3914
3915 for(var n =0; n < 256; n++){
3916 c = n;
3917 for(var k =0; k < 8; k++){
3918 c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
3919 }
3920 table[n] = c;
3921 }
3922
3923 return table;
3924}
3925
3926// Create table on load. Just 255 signed longs. Not a problem.
3927var crcTable = makeTable();
3928
3929
3930function crc32(crc, buf, len, pos) {
3931 var t = crcTable
3932 , end = pos + len;
3933
3934 crc = crc ^ (-1);
3935
3936 for (var i = pos; i < end; i++ ) {
3937 crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];
3938 }
3939
3940 return (crc ^ (-1)); // >>> 0;
3941}
3942
3943
3944module.exports = crc32;
3945},{}],32:[function(_dereq_,module,exports){
3946'use strict';
3947
3948var utils = _dereq_('../utils/common');
3949var trees = _dereq_('./trees');
3950var adler32 = _dereq_('./adler32');
3951var crc32 = _dereq_('./crc32');
3952var msg = _dereq_('./messages');
3953
3954/* Public constants ==========================================================*/
3955/* ===========================================================================*/
3956
3957
3958/* Allowed flush values; see deflate() and inflate() below for details */
3959var Z_NO_FLUSH = 0;
3960var Z_PARTIAL_FLUSH = 1;
3961//var Z_SYNC_FLUSH = 2;
3962var Z_FULL_FLUSH = 3;
3963var Z_FINISH = 4;
3964var Z_BLOCK = 5;
3965//var Z_TREES = 6;
3966
3967
3968/* Return codes for the compression/decompression functions. Negative values
3969 * are errors, positive values are used for special but normal events.
3970 */
3971var Z_OK = 0;
3972var Z_STREAM_END = 1;
3973//var Z_NEED_DICT = 2;
3974//var Z_ERRNO = -1;
3975var Z_STREAM_ERROR = -2;
3976var Z_DATA_ERROR = -3;
3977//var Z_MEM_ERROR = -4;
3978var Z_BUF_ERROR = -5;
3979//var Z_VERSION_ERROR = -6;
3980
3981
3982/* compression levels */
3983//var Z_NO_COMPRESSION = 0;
3984//var Z_BEST_SPEED = 1;
3985//var Z_BEST_COMPRESSION = 9;
3986var Z_DEFAULT_COMPRESSION = -1;
3987
3988
3989var Z_FILTERED = 1;
3990var Z_HUFFMAN_ONLY = 2;
3991var Z_RLE = 3;
3992var Z_FIXED = 4;
3993var Z_DEFAULT_STRATEGY = 0;
3994
3995/* Possible values of the data_type field (though see inflate()) */
3996//var Z_BINARY = 0;
3997//var Z_TEXT = 1;
3998//var Z_ASCII = 1; // = Z_TEXT
3999var Z_UNKNOWN = 2;
4000
4001
4002/* The deflate compression method */
4003var Z_DEFLATED = 8;
4004
4005/*============================================================================*/
4006
4007
4008var MAX_MEM_LEVEL = 9;
4009/* Maximum value for memLevel in deflateInit2 */
4010var MAX_WBITS = 15;
4011/* 32K LZ77 window */
4012var DEF_MEM_LEVEL = 8;
4013
4014
4015var LENGTH_CODES = 29;
4016/* number of length codes, not counting the special END_BLOCK code */
4017var LITERALS = 256;
4018/* number of literal bytes 0..255 */
4019var L_CODES = LITERALS + 1 + LENGTH_CODES;
4020/* number of Literal or Length codes, including the END_BLOCK code */
4021var D_CODES = 30;
4022/* number of distance codes */
4023var BL_CODES = 19;
4024/* number of codes used to transfer the bit lengths */
4025var HEAP_SIZE = 2*L_CODES + 1;
4026/* maximum heap size */
4027var MAX_BITS = 15;
4028/* All codes must not exceed MAX_BITS bits */
4029
4030var MIN_MATCH = 3;
4031var MAX_MATCH = 258;
4032var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
4033
4034var PRESET_DICT = 0x20;
4035
4036var INIT_STATE = 42;
4037var EXTRA_STATE = 69;
4038var NAME_STATE = 73;
4039var COMMENT_STATE = 91;
4040var HCRC_STATE = 103;
4041var BUSY_STATE = 113;
4042var FINISH_STATE = 666;
4043
4044var BS_NEED_MORE = 1; /* block not completed, need more input or more output */
4045var BS_BLOCK_DONE = 2; /* block flush performed */
4046var BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */
4047var BS_FINISH_DONE = 4; /* finish done, accept no more input or output */
4048
4049var OS_CODE = 0x03; // Unix :) . Don't detect, use this default.
4050
4051function err(strm, errorCode) {
4052 strm.msg = msg[errorCode];
4053 return errorCode;
4054}
4055
4056function rank(f) {
4057 return ((f) << 1) - ((f) > 4 ? 9 : 0);
4058}
4059
4060function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } }
4061
4062
4063/* =========================================================================
4064 * Flush as much pending output as possible. All deflate() output goes
4065 * through this function so some applications may wish to modify it
4066 * to avoid allocating a large strm->output buffer and copying into it.
4067 * (See also read_buf()).
4068 */
4069function flush_pending(strm) {
4070 var s = strm.state;
4071
4072 //_tr_flush_bits(s);
4073 var len = s.pending;
4074 if (len > strm.avail_out) {
4075 len = strm.avail_out;
4076 }
4077 if (len === 0) { return; }
4078
4079 utils.arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out);
4080 strm.next_out += len;
4081 s.pending_out += len;
4082 strm.total_out += len;
4083 strm.avail_out -= len;
4084 s.pending -= len;
4085 if (s.pending === 0) {
4086 s.pending_out = 0;
4087 }
4088}
4089
4090
4091function flush_block_only (s, last) {
4092 trees._tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last);
4093 s.block_start = s.strstart;
4094 flush_pending(s.strm);
4095}
4096
4097
4098function put_byte(s, b) {
4099 s.pending_buf[s.pending++] = b;
4100}
4101
4102
4103/* =========================================================================
4104 * Put a short in the pending buffer. The 16-bit value is put in MSB order.
4105 * IN assertion: the stream state is correct and there is enough room in
4106 * pending_buf.
4107 */
4108function putShortMSB(s, b) {
4109// put_byte(s, (Byte)(b >> 8));
4110// put_byte(s, (Byte)(b & 0xff));
4111 s.pending_buf[s.pending++] = (b >>> 8) & 0xff;
4112 s.pending_buf[s.pending++] = b & 0xff;
4113}
4114
4115
4116/* ===========================================================================
4117 * Read a new buffer from the current input stream, update the adler32
4118 * and total number of bytes read. All deflate() input goes through
4119 * this function so some applications may wish to modify it to avoid
4120 * allocating a large strm->input buffer and copying from it.
4121 * (See also flush_pending()).
4122 */
4123function read_buf(strm, buf, start, size) {
4124 var len = strm.avail_in;
4125
4126 if (len > size) { len = size; }
4127 if (len === 0) { return 0; }
4128
4129 strm.avail_in -= len;
4130
4131 utils.arraySet(buf, strm.input, strm.next_in, len, start);
4132 if (strm.state.wrap === 1) {
4133 strm.adler = adler32(strm.adler, buf, len, start);
4134 }
4135
4136 else if (strm.state.wrap === 2) {
4137 strm.adler = crc32(strm.adler, buf, len, start);
4138 }
4139
4140 strm.next_in += len;
4141 strm.total_in += len;
4142
4143 return len;
4144}
4145
4146
4147/* ===========================================================================
4148 * Set match_start to the longest match starting at the given string and
4149 * return its length. Matches shorter or equal to prev_length are discarded,
4150 * in which case the result is equal to prev_length and match_start is
4151 * garbage.
4152 * IN assertions: cur_match is the head of the hash chain for the current
4153 * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
4154 * OUT assertion: the match length is not greater than s->lookahead.
4155 */
4156function longest_match(s, cur_match) {
4157 var chain_length = s.max_chain_length; /* max hash chain length */
4158 var scan = s.strstart; /* current string */
4159 var match; /* matched string */
4160 var len; /* length of current match */
4161 var best_len = s.prev_length; /* best match length so far */
4162 var nice_match = s.nice_match; /* stop if match long enough */
4163 var limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ?
4164 s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/;
4165
4166 var _win = s.window; // shortcut
4167
4168 var wmask = s.w_mask;
4169 var prev = s.prev;
4170
4171 /* Stop when cur_match becomes <= limit. To simplify the code,
4172 * we prevent matches with the string of window index 0.
4173 */
4174
4175 var strend = s.strstart + MAX_MATCH;
4176 var scan_end1 = _win[scan + best_len - 1];
4177 var scan_end = _win[scan + best_len];
4178
4179 /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
4180 * It is easy to get rid of this optimization if necessary.
4181 */
4182 // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
4183
4184 /* Do not waste too much time if we already have a good match: */
4185 if (s.prev_length >= s.good_match) {
4186 chain_length >>= 2;
4187 }
4188 /* Do not look for matches beyond the end of the input. This is necessary
4189 * to make deflate deterministic.
4190 */
4191 if (nice_match > s.lookahead) { nice_match = s.lookahead; }
4192
4193 // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
4194
4195 do {
4196 // Assert(cur_match < s->strstart, "no future");
4197 match = cur_match;
4198
4199 /* Skip to next match if the match length cannot increase
4200 * or if the match length is less than 2. Note that the checks below
4201 * for insufficient lookahead only occur occasionally for performance
4202 * reasons. Therefore uninitialized memory will be accessed, and
4203 * conditional jumps will be made that depend on those values.
4204 * However the length of the match is limited to the lookahead, so
4205 * the output of deflate is not affected by the uninitialized values.
4206 */
4207
4208 if (_win[match + best_len] !== scan_end ||
4209 _win[match + best_len - 1] !== scan_end1 ||
4210 _win[match] !== _win[scan] ||
4211 _win[++match] !== _win[scan + 1]) {
4212 continue;
4213 }
4214
4215 /* The check at best_len-1 can be removed because it will be made
4216 * again later. (This heuristic is not always a win.)
4217 * It is not necessary to compare scan[2] and match[2] since they
4218 * are always equal when the other bytes match, given that
4219 * the hash keys are equal and that HASH_BITS >= 8.
4220 */
4221 scan += 2;
4222 match++;
4223 // Assert(*scan == *match, "match[2]?");
4224
4225 /* We check for insufficient lookahead only every 8th comparison;
4226 * the 256th check will be made at strstart+258.
4227 */
4228 do {
4229 /*jshint noempty:false*/
4230 } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
4231 _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
4232 _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
4233 _win[++scan] === _win[++match] && _win[++scan] === _win[++match] &&
4234 scan < strend);
4235
4236 // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
4237
4238 len = MAX_MATCH - (strend - scan);
4239 scan = strend - MAX_MATCH;
4240
4241 if (len > best_len) {
4242 s.match_start = cur_match;
4243 best_len = len;
4244 if (len >= nice_match) {
4245 break;
4246 }
4247 scan_end1 = _win[scan + best_len - 1];
4248 scan_end = _win[scan + best_len];
4249 }
4250 } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0);
4251
4252 if (best_len <= s.lookahead) {
4253 return best_len;
4254 }
4255 return s.lookahead;
4256}
4257
4258
4259/* ===========================================================================
4260 * Fill the window when the lookahead becomes insufficient.
4261 * Updates strstart and lookahead.
4262 *
4263 * IN assertion: lookahead < MIN_LOOKAHEAD
4264 * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
4265 * At least one byte has been read, or avail_in == 0; reads are
4266 * performed for at least two bytes (required for the zip translate_eol
4267 * option -- not supported here).
4268 */
4269function fill_window(s) {
4270 var _w_size = s.w_size;
4271 var p, n, m, more, str;
4272
4273 //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
4274
4275 do {
4276 more = s.window_size - s.lookahead - s.strstart;
4277
4278 // JS ints have 32 bit, block below not needed
4279 /* Deal with !@#$% 64K limit: */
4280 //if (sizeof(int) <= 2) {
4281 // if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
4282 // more = wsize;
4283 //
4284 // } else if (more == (unsigned)(-1)) {
4285 // /* Very unlikely, but possible on 16 bit machine if
4286 // * strstart == 0 && lookahead == 1 (input done a byte at time)
4287 // */
4288 // more--;
4289 // }
4290 //}
4291
4292
4293 /* If the window is almost full and there is insufficient lookahead,
4294 * move the upper half to the lower one to make room in the upper half.
4295 */
4296 if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) {
4297
4298 utils.arraySet(s.window, s.window, _w_size, _w_size, 0);
4299 s.match_start -= _w_size;
4300 s.strstart -= _w_size;
4301 /* we now have strstart >= MAX_DIST */
4302 s.block_start -= _w_size;
4303
4304 /* Slide the hash table (could be avoided with 32 bit values
4305 at the expense of memory usage). We slide even when level == 0
4306 to keep the hash table consistent if we switch back to level > 0
4307 later. (Using level 0 permanently is not an optimal usage of
4308 zlib, so we don't care about this pathological case.)
4309 */
4310
4311 n = s.hash_size;
4312 p = n;
4313 do {
4314 m = s.head[--p];
4315 s.head[p] = (m >= _w_size ? m - _w_size : 0);
4316 } while (--n);
4317
4318 n = _w_size;
4319 p = n;
4320 do {
4321 m = s.prev[--p];
4322 s.prev[p] = (m >= _w_size ? m - _w_size : 0);
4323 /* If n is not on any hash chain, prev[n] is garbage but
4324 * its value will never be used.
4325 */
4326 } while (--n);
4327
4328 more += _w_size;
4329 }
4330 if (s.strm.avail_in === 0) {
4331 break;
4332 }
4333
4334 /* If there was no sliding:
4335 * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
4336 * more == window_size - lookahead - strstart
4337 * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
4338 * => more >= window_size - 2*WSIZE + 2
4339 * In the BIG_MEM or MMAP case (not yet supported),
4340 * window_size == input_size + MIN_LOOKAHEAD &&
4341 * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
4342 * Otherwise, window_size == 2*WSIZE so more >= 2.
4343 * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
4344 */
4345 //Assert(more >= 2, "more < 2");
4346 n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more);
4347 s.lookahead += n;
4348
4349 /* Initialize the hash value now that we have some input: */
4350 if (s.lookahead + s.insert >= MIN_MATCH) {
4351 str = s.strstart - s.insert;
4352 s.ins_h = s.window[str];
4353
4354 /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */
4355 s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask;
4356//#if MIN_MATCH != 3
4357// Call update_hash() MIN_MATCH-3 more times
4358//#endif
4359 while (s.insert) {
4360 /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */
4361 s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH-1]) & s.hash_mask;
4362
4363 s.prev[str & s.w_mask] = s.head[s.ins_h];
4364 s.head[s.ins_h] = str;
4365 str++;
4366 s.insert--;
4367 if (s.lookahead + s.insert < MIN_MATCH) {
4368 break;
4369 }
4370 }
4371 }
4372 /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
4373 * but this is not important since only literal bytes will be emitted.
4374 */
4375
4376 } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0);
4377
4378 /* If the WIN_INIT bytes after the end of the current data have never been
4379 * written, then zero those bytes in order to avoid memory check reports of
4380 * the use of uninitialized (or uninitialised as Julian writes) bytes by
4381 * the longest match routines. Update the high water mark for the next
4382 * time through here. WIN_INIT is set to MAX_MATCH since the longest match
4383 * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
4384 */
4385// if (s.high_water < s.window_size) {
4386// var curr = s.strstart + s.lookahead;
4387// var init = 0;
4388//
4389// if (s.high_water < curr) {
4390// /* Previous high water mark below current data -- zero WIN_INIT
4391// * bytes or up to end of window, whichever is less.
4392// */
4393// init = s.window_size - curr;
4394// if (init > WIN_INIT)
4395// init = WIN_INIT;
4396// zmemzero(s->window + curr, (unsigned)init);
4397// s->high_water = curr + init;
4398// }
4399// else if (s->high_water < (ulg)curr + WIN_INIT) {
4400// /* High water mark at or above current data, but below current data
4401// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
4402// * to end of window, whichever is less.
4403// */
4404// init = (ulg)curr + WIN_INIT - s->high_water;
4405// if (init > s->window_size - s->high_water)
4406// init = s->window_size - s->high_water;
4407// zmemzero(s->window + s->high_water, (unsigned)init);
4408// s->high_water += init;
4409// }
4410// }
4411//
4412// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
4413// "not enough room for search");
4414}
4415
4416/* ===========================================================================
4417 * Copy without compression as much as possible from the input stream, return
4418 * the current block state.
4419 * This function does not insert new strings in the dictionary since
4420 * uncompressible data is probably not useful. This function is used
4421 * only for the level=0 compression option.
4422 * NOTE: this function should be optimized to avoid extra copying from
4423 * window to pending_buf.
4424 */
4425function deflate_stored(s, flush) {
4426 /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
4427 * to pending_buf_size, and each stored block has a 5 byte header:
4428 */
4429 var max_block_size = 0xffff;
4430
4431 if (max_block_size > s.pending_buf_size - 5) {
4432 max_block_size = s.pending_buf_size - 5;
4433 }
4434
4435 /* Copy as much as possible from input to output: */
4436 for (;;) {
4437 /* Fill the window as much as possible: */
4438 if (s.lookahead <= 1) {
4439
4440 //Assert(s->strstart < s->w_size+MAX_DIST(s) ||
4441 // s->block_start >= (long)s->w_size, "slide too late");
4442// if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) ||
4443// s.block_start >= s.w_size)) {
4444// throw new Error("slide too late");
4445// }
4446
4447 fill_window(s);
4448 if (s.lookahead === 0 && flush === Z_NO_FLUSH) {
4449 return BS_NEED_MORE;
4450 }
4451
4452 if (s.lookahead === 0) {
4453 break;
4454 }
4455 /* flush the current block */
4456 }
4457 //Assert(s->block_start >= 0L, "block gone");
4458// if (s.block_start < 0) throw new Error("block gone");
4459
4460 s.strstart += s.lookahead;
4461 s.lookahead = 0;
4462
4463 /* Emit a stored block if pending_buf will be full: */
4464 var max_start = s.block_start + max_block_size;
4465
4466 if (s.strstart === 0 || s.strstart >= max_start) {
4467 /* strstart == 0 is possible when wraparound on 16-bit machine */
4468 s.lookahead = s.strstart - max_start;
4469 s.strstart = max_start;
4470 /*** FLUSH_BLOCK(s, 0); ***/
4471 flush_block_only(s, false);
4472 if (s.strm.avail_out === 0) {
4473 return BS_NEED_MORE;
4474 }
4475 /***/
4476
4477
4478 }
4479 /* Flush if we may have to slide, otherwise block_start may become
4480 * negative and the data will be gone:
4481 */
4482 if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) {
4483 /*** FLUSH_BLOCK(s, 0); ***/
4484 flush_block_only(s, false);
4485 if (s.strm.avail_out === 0) {
4486 return BS_NEED_MORE;
4487 }
4488 /***/
4489 }
4490 }
4491
4492 s.insert = 0;
4493
4494 if (flush === Z_FINISH) {
4495 /*** FLUSH_BLOCK(s, 1); ***/
4496 flush_block_only(s, true);
4497 if (s.strm.avail_out === 0) {
4498 return BS_FINISH_STARTED;
4499 }
4500 /***/
4501 return BS_FINISH_DONE;
4502 }
4503
4504 if (s.strstart > s.block_start) {
4505 /*** FLUSH_BLOCK(s, 0); ***/
4506 flush_block_only(s, false);
4507 if (s.strm.avail_out === 0) {
4508 return BS_NEED_MORE;
4509 }
4510 /***/
4511 }
4512
4513 return BS_NEED_MORE;
4514}
4515
4516/* ===========================================================================
4517 * Compress as much as possible from the input stream, return the current
4518 * block state.
4519 * This function does not perform lazy evaluation of matches and inserts
4520 * new strings in the dictionary only for unmatched strings or for short
4521 * matches. It is used only for the fast compression options.
4522 */
4523function deflate_fast(s, flush) {
4524 var hash_head; /* head of the hash chain */
4525 var bflush; /* set if current block must be flushed */
4526
4527 for (;;) {
4528 /* Make sure that we always have enough lookahead, except
4529 * at the end of the input file. We need MAX_MATCH bytes
4530 * for the next match, plus MIN_MATCH bytes to insert the
4531 * string following the next match.
4532 */
4533 if (s.lookahead < MIN_LOOKAHEAD) {
4534 fill_window(s);
4535 if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {
4536 return BS_NEED_MORE;
4537 }
4538 if (s.lookahead === 0) {
4539 break; /* flush the current block */
4540 }
4541 }
4542
4543 /* Insert the string window[strstart .. strstart+2] in the
4544 * dictionary, and set hash_head to the head of the hash chain:
4545 */
4546 hash_head = 0/*NIL*/;
4547 if (s.lookahead >= MIN_MATCH) {
4548 /*** INSERT_STRING(s, s.strstart, hash_head); ***/
4549 s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
4550 hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
4551 s.head[s.ins_h] = s.strstart;
4552 /***/
4553 }
4554
4555 /* Find the longest match, discarding those <= prev_length.
4556 * At this point we have always match_length < MIN_MATCH
4557 */
4558 if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) {
4559 /* To simplify the code, we prevent matches with the string
4560 * of window index 0 (in particular we have to avoid a match
4561 * of the string with itself at the start of the input file).
4562 */
4563 s.match_length = longest_match(s, hash_head);
4564 /* longest_match() sets match_start */
4565 }
4566 if (s.match_length >= MIN_MATCH) {
4567 // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only
4568
4569 /*** _tr_tally_dist(s, s.strstart - s.match_start,
4570 s.match_length - MIN_MATCH, bflush); ***/
4571 bflush = trees._tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH);
4572
4573 s.lookahead -= s.match_length;
4574
4575 /* Insert new strings in the hash table only if the match length
4576 * is not too large. This saves time but degrades compression.
4577 */
4578 if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) {
4579 s.match_length--; /* string at strstart already in table */
4580 do {
4581 s.strstart++;
4582 /*** INSERT_STRING(s, s.strstart, hash_head); ***/
4583 s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
4584 hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
4585 s.head[s.ins_h] = s.strstart;
4586 /***/
4587 /* strstart never exceeds WSIZE-MAX_MATCH, so there are
4588 * always MIN_MATCH bytes ahead.
4589 */
4590 } while (--s.match_length !== 0);
4591 s.strstart++;
4592 } else
4593 {
4594 s.strstart += s.match_length;
4595 s.match_length = 0;
4596 s.ins_h = s.window[s.strstart];
4597 /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */
4598 s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask;
4599
4600//#if MIN_MATCH != 3
4601// Call UPDATE_HASH() MIN_MATCH-3 more times
4602//#endif
4603 /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
4604 * matter since it will be recomputed at next deflate call.
4605 */
4606 }
4607 } else {
4608 /* No match, output a literal byte */
4609 //Tracevv((stderr,"%c", s.window[s.strstart]));
4610 /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
4611 bflush = trees._tr_tally(s, 0, s.window[s.strstart]);
4612
4613 s.lookahead--;
4614 s.strstart++;
4615 }
4616 if (bflush) {
4617 /*** FLUSH_BLOCK(s, 0); ***/
4618 flush_block_only(s, false);
4619 if (s.strm.avail_out === 0) {
4620 return BS_NEED_MORE;
4621 }
4622 /***/
4623 }
4624 }
4625 s.insert = ((s.strstart < (MIN_MATCH-1)) ? s.strstart : MIN_MATCH-1);
4626 if (flush === Z_FINISH) {
4627 /*** FLUSH_BLOCK(s, 1); ***/
4628 flush_block_only(s, true);
4629 if (s.strm.avail_out === 0) {
4630 return BS_FINISH_STARTED;
4631 }
4632 /***/
4633 return BS_FINISH_DONE;
4634 }
4635 if (s.last_lit) {
4636 /*** FLUSH_BLOCK(s, 0); ***/
4637 flush_block_only(s, false);
4638 if (s.strm.avail_out === 0) {
4639 return BS_NEED_MORE;
4640 }
4641 /***/
4642 }
4643 return BS_BLOCK_DONE;
4644}
4645
4646/* ===========================================================================
4647 * Same as above, but achieves better compression. We use a lazy
4648 * evaluation for matches: a match is finally adopted only if there is
4649 * no better match at the next window position.
4650 */
4651function deflate_slow(s, flush) {
4652 var hash_head; /* head of hash chain */
4653 var bflush; /* set if current block must be flushed */
4654
4655 var max_insert;
4656
4657 /* Process the input block. */
4658 for (;;) {
4659 /* Make sure that we always have enough lookahead, except
4660 * at the end of the input file. We need MAX_MATCH bytes
4661 * for the next match, plus MIN_MATCH bytes to insert the
4662 * string following the next match.
4663 */
4664 if (s.lookahead < MIN_LOOKAHEAD) {
4665 fill_window(s);
4666 if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) {
4667 return BS_NEED_MORE;
4668 }
4669 if (s.lookahead === 0) { break; } /* flush the current block */
4670 }
4671
4672 /* Insert the string window[strstart .. strstart+2] in the
4673 * dictionary, and set hash_head to the head of the hash chain:
4674 */
4675 hash_head = 0/*NIL*/;
4676 if (s.lookahead >= MIN_MATCH) {
4677 /*** INSERT_STRING(s, s.strstart, hash_head); ***/
4678 s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
4679 hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
4680 s.head[s.ins_h] = s.strstart;
4681 /***/
4682 }
4683
4684 /* Find the longest match, discarding those <= prev_length.
4685 */
4686 s.prev_length = s.match_length;
4687 s.prev_match = s.match_start;
4688 s.match_length = MIN_MATCH-1;
4689
4690 if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match &&
4691 s.strstart - hash_head <= (s.w_size-MIN_LOOKAHEAD)/*MAX_DIST(s)*/) {
4692 /* To simplify the code, we prevent matches with the string
4693 * of window index 0 (in particular we have to avoid a match
4694 * of the string with itself at the start of the input file).
4695 */
4696 s.match_length = longest_match(s, hash_head);
4697 /* longest_match() sets match_start */
4698
4699 if (s.match_length <= 5 &&
4700 (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) {
4701
4702 /* If prev_match is also MIN_MATCH, match_start is garbage
4703 * but we will ignore the current match anyway.
4704 */
4705 s.match_length = MIN_MATCH-1;
4706 }
4707 }
4708 /* If there was a match at the previous step and the current
4709 * match is not better, output the previous match:
4710 */
4711 if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) {
4712 max_insert = s.strstart + s.lookahead - MIN_MATCH;
4713 /* Do not insert strings in hash table beyond this. */
4714
4715 //check_match(s, s.strstart-1, s.prev_match, s.prev_length);
4716
4717 /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match,
4718 s.prev_length - MIN_MATCH, bflush);***/
4719 bflush = trees._tr_tally(s, s.strstart - 1- s.prev_match, s.prev_length - MIN_MATCH);
4720 /* Insert in hash table all strings up to the end of the match.
4721 * strstart-1 and strstart are already inserted. If there is not
4722 * enough lookahead, the last two strings are not inserted in
4723 * the hash table.
4724 */
4725 s.lookahead -= s.prev_length-1;
4726 s.prev_length -= 2;
4727 do {
4728 if (++s.strstart <= max_insert) {
4729 /*** INSERT_STRING(s, s.strstart, hash_head); ***/
4730 s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask;
4731 hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h];
4732 s.head[s.ins_h] = s.strstart;
4733 /***/
4734 }
4735 } while (--s.prev_length !== 0);
4736 s.match_available = 0;
4737 s.match_length = MIN_MATCH-1;
4738 s.strstart++;
4739
4740 if (bflush) {
4741 /*** FLUSH_BLOCK(s, 0); ***/
4742 flush_block_only(s, false);
4743 if (s.strm.avail_out === 0) {
4744 return BS_NEED_MORE;
4745 }
4746 /***/
4747 }
4748
4749 } else if (s.match_available) {
4750 /* If there was no match at the previous position, output a
4751 * single literal. If there was a match but the current match
4752 * is longer, truncate the previous match to a single literal.
4753 */
4754 //Tracevv((stderr,"%c", s->window[s->strstart-1]));
4755 /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
4756 bflush = trees._tr_tally(s, 0, s.window[s.strstart-1]);
4757
4758 if (bflush) {
4759 /*** FLUSH_BLOCK_ONLY(s, 0) ***/
4760 flush_block_only(s, false);
4761 /***/
4762 }
4763 s.strstart++;
4764 s.lookahead--;
4765 if (s.strm.avail_out === 0) {
4766 return BS_NEED_MORE;
4767 }
4768 } else {
4769 /* There is no previous match to compare with, wait for
4770 * the next step to decide.
4771 */
4772 s.match_available = 1;
4773 s.strstart++;
4774 s.lookahead--;
4775 }
4776 }
4777 //Assert (flush != Z_NO_FLUSH, "no flush?");
4778 if (s.match_available) {
4779 //Tracevv((stderr,"%c", s->window[s->strstart-1]));
4780 /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/
4781 bflush = trees._tr_tally(s, 0, s.window[s.strstart-1]);
4782
4783 s.match_available = 0;
4784 }
4785 s.insert = s.strstart < MIN_MATCH-1 ? s.strstart : MIN_MATCH-1;
4786 if (flush === Z_FINISH) {
4787 /*** FLUSH_BLOCK(s, 1); ***/
4788 flush_block_only(s, true);
4789 if (s.strm.avail_out === 0) {
4790 return BS_FINISH_STARTED;
4791 }
4792 /***/
4793 return BS_FINISH_DONE;
4794 }
4795 if (s.last_lit) {
4796 /*** FLUSH_BLOCK(s, 0); ***/
4797 flush_block_only(s, false);
4798 if (s.strm.avail_out === 0) {
4799 return BS_NEED_MORE;
4800 }
4801 /***/
4802 }
4803
4804 return BS_BLOCK_DONE;
4805}
4806
4807
4808/* ===========================================================================
4809 * For Z_RLE, simply look for runs of bytes, generate matches only of distance
4810 * one. Do not maintain a hash table. (It will be regenerated if this run of
4811 * deflate switches away from Z_RLE.)
4812 */
4813function deflate_rle(s, flush) {
4814 var bflush; /* set if current block must be flushed */
4815 var prev; /* byte at distance one to match */
4816 var scan, strend; /* scan goes up to strend for length of run */
4817
4818 var _win = s.window;
4819
4820 for (;;) {
4821 /* Make sure that we always have enough lookahead, except
4822 * at the end of the input file. We need MAX_MATCH bytes
4823 * for the longest run, plus one for the unrolled loop.
4824 */
4825 if (s.lookahead <= MAX_MATCH) {
4826 fill_window(s);
4827 if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH) {
4828 return BS_NEED_MORE;
4829 }
4830 if (s.lookahead === 0) { break; } /* flush the current block */
4831 }
4832
4833 /* See how many times the previous byte repeats */
4834 s.match_length = 0;
4835 if (s.lookahead >= MIN_MATCH && s.strstart > 0) {
4836 scan = s.strstart - 1;
4837 prev = _win[scan];
4838 if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) {
4839 strend = s.strstart + MAX_MATCH;
4840 do {
4841 /*jshint noempty:false*/
4842 } while (prev === _win[++scan] && prev === _win[++scan] &&
4843 prev === _win[++scan] && prev === _win[++scan] &&
4844 prev === _win[++scan] && prev === _win[++scan] &&
4845 prev === _win[++scan] && prev === _win[++scan] &&
4846 scan < strend);
4847 s.match_length = MAX_MATCH - (strend - scan);
4848 if (s.match_length > s.lookahead) {
4849 s.match_length = s.lookahead;
4850 }
4851 }
4852 //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
4853 }
4854
4855 /* Emit match if have run of MIN_MATCH or longer, else emit literal */
4856 if (s.match_length >= MIN_MATCH) {
4857 //check_match(s, s.strstart, s.strstart - 1, s.match_length);
4858
4859 /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/
4860 bflush = trees._tr_tally(s, 1, s.match_length - MIN_MATCH);
4861
4862 s.lookahead -= s.match_length;
4863 s.strstart += s.match_length;
4864 s.match_length = 0;
4865 } else {
4866 /* No match, output a literal byte */
4867 //Tracevv((stderr,"%c", s->window[s->strstart]));
4868 /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
4869 bflush = trees._tr_tally(s, 0, s.window[s.strstart]);
4870
4871 s.lookahead--;
4872 s.strstart++;
4873 }
4874 if (bflush) {
4875 /*** FLUSH_BLOCK(s, 0); ***/
4876 flush_block_only(s, false);
4877 if (s.strm.avail_out === 0) {
4878 return BS_NEED_MORE;
4879 }
4880 /***/
4881 }
4882 }
4883 s.insert = 0;
4884 if (flush === Z_FINISH) {
4885 /*** FLUSH_BLOCK(s, 1); ***/
4886 flush_block_only(s, true);
4887 if (s.strm.avail_out === 0) {
4888 return BS_FINISH_STARTED;
4889 }
4890 /***/
4891 return BS_FINISH_DONE;
4892 }
4893 if (s.last_lit) {
4894 /*** FLUSH_BLOCK(s, 0); ***/
4895 flush_block_only(s, false);
4896 if (s.strm.avail_out === 0) {
4897 return BS_NEED_MORE;
4898 }
4899 /***/
4900 }
4901 return BS_BLOCK_DONE;
4902}
4903
4904/* ===========================================================================
4905 * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table.
4906 * (It will be regenerated if this run of deflate switches away from Huffman.)
4907 */
4908function deflate_huff(s, flush) {
4909 var bflush; /* set if current block must be flushed */
4910
4911 for (;;) {
4912 /* Make sure that we have a literal to write. */
4913 if (s.lookahead === 0) {
4914 fill_window(s);
4915 if (s.lookahead === 0) {
4916 if (flush === Z_NO_FLUSH) {
4917 return BS_NEED_MORE;
4918 }
4919 break; /* flush the current block */
4920 }
4921 }
4922
4923 /* Output a literal byte */
4924 s.match_length = 0;
4925 //Tracevv((stderr,"%c", s->window[s->strstart]));
4926 /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/
4927 bflush = trees._tr_tally(s, 0, s.window[s.strstart]);
4928 s.lookahead--;
4929 s.strstart++;
4930 if (bflush) {
4931 /*** FLUSH_BLOCK(s, 0); ***/
4932 flush_block_only(s, false);
4933 if (s.strm.avail_out === 0) {
4934 return BS_NEED_MORE;
4935 }
4936 /***/
4937 }
4938 }
4939 s.insert = 0;
4940 if (flush === Z_FINISH) {
4941 /*** FLUSH_BLOCK(s, 1); ***/
4942 flush_block_only(s, true);
4943 if (s.strm.avail_out === 0) {
4944 return BS_FINISH_STARTED;
4945 }
4946 /***/
4947 return BS_FINISH_DONE;
4948 }
4949 if (s.last_lit) {
4950 /*** FLUSH_BLOCK(s, 0); ***/
4951 flush_block_only(s, false);
4952 if (s.strm.avail_out === 0) {
4953 return BS_NEED_MORE;
4954 }
4955 /***/
4956 }
4957 return BS_BLOCK_DONE;
4958}
4959
4960/* Values for max_lazy_match, good_match and max_chain_length, depending on
4961 * the desired pack level (0..9). The values given below have been tuned to
4962 * exclude worst case performance for pathological files. Better values may be
4963 * found for specific files.
4964 */
4965var Config = function (good_length, max_lazy, nice_length, max_chain, func) {
4966 this.good_length = good_length;
4967 this.max_lazy = max_lazy;
4968 this.nice_length = nice_length;
4969 this.max_chain = max_chain;
4970 this.func = func;
4971};
4972
4973var configuration_table;
4974
4975configuration_table = [
4976 /* good lazy nice chain */
4977 new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */
4978 new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */
4979 new Config(4, 5, 16, 8, deflate_fast), /* 2 */
4980 new Config(4, 6, 32, 32, deflate_fast), /* 3 */
4981
4982 new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */
4983 new Config(8, 16, 32, 32, deflate_slow), /* 5 */
4984 new Config(8, 16, 128, 128, deflate_slow), /* 6 */
4985 new Config(8, 32, 128, 256, deflate_slow), /* 7 */
4986 new Config(32, 128, 258, 1024, deflate_slow), /* 8 */
4987 new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */
4988];
4989
4990
4991/* ===========================================================================
4992 * Initialize the "longest match" routines for a new zlib stream
4993 */
4994function lm_init(s) {
4995 s.window_size = 2 * s.w_size;
4996
4997 /*** CLEAR_HASH(s); ***/
4998 zero(s.head); // Fill with NIL (= 0);
4999
5000 /* Set the default configuration parameters:
5001 */
5002 s.max_lazy_match = configuration_table[s.level].max_lazy;
5003 s.good_match = configuration_table[s.level].good_length;
5004 s.nice_match = configuration_table[s.level].nice_length;
5005 s.max_chain_length = configuration_table[s.level].max_chain;
5006
5007 s.strstart = 0;
5008 s.block_start = 0;
5009 s.lookahead = 0;
5010 s.insert = 0;
5011 s.match_length = s.prev_length = MIN_MATCH - 1;
5012 s.match_available = 0;
5013 s.ins_h = 0;
5014}
5015
5016
5017function DeflateState() {
5018 this.strm = null; /* pointer back to this zlib stream */
5019 this.status = 0; /* as the name implies */
5020 this.pending_buf = null; /* output still pending */
5021 this.pending_buf_size = 0; /* size of pending_buf */
5022 this.pending_out = 0; /* next pending byte to output to the stream */
5023 this.pending = 0; /* nb of bytes in the pending buffer */
5024 this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */
5025 this.gzhead = null; /* gzip header information to write */
5026 this.gzindex = 0; /* where in extra, name, or comment */
5027 this.method = Z_DEFLATED; /* can only be DEFLATED */
5028 this.last_flush = -1; /* value of flush param for previous deflate call */
5029
5030 this.w_size = 0; /* LZ77 window size (32K by default) */
5031 this.w_bits = 0; /* log2(w_size) (8..16) */
5032 this.w_mask = 0; /* w_size - 1 */
5033
5034 this.window = null;
5035 /* Sliding window. Input bytes are read into the second half of the window,
5036 * and move to the first half later to keep a dictionary of at least wSize
5037 * bytes. With this organization, matches are limited to a distance of
5038 * wSize-MAX_MATCH bytes, but this ensures that IO is always
5039 * performed with a length multiple of the block size.
5040 */
5041
5042 this.window_size = 0;
5043 /* Actual size of window: 2*wSize, except when the user input buffer
5044 * is directly used as sliding window.
5045 */
5046
5047 this.prev = null;
5048 /* Link to older string with same hash index. To limit the size of this
5049 * array to 64K, this link is maintained only for the last 32K strings.
5050 * An index in this array is thus a window index modulo 32K.
5051 */
5052
5053 this.head = null; /* Heads of the hash chains or NIL. */
5054
5055 this.ins_h = 0; /* hash index of string to be inserted */
5056 this.hash_size = 0; /* number of elements in hash table */
5057 this.hash_bits = 0; /* log2(hash_size) */
5058 this.hash_mask = 0; /* hash_size-1 */
5059
5060 this.hash_shift = 0;
5061 /* Number of bits by which ins_h must be shifted at each input
5062 * step. It must be such that after MIN_MATCH steps, the oldest
5063 * byte no longer takes part in the hash key, that is:
5064 * hash_shift * MIN_MATCH >= hash_bits
5065 */
5066
5067 this.block_start = 0;
5068 /* Window position at the beginning of the current output block. Gets
5069 * negative when the window is moved backwards.
5070 */
5071
5072 this.match_length = 0; /* length of best match */
5073 this.prev_match = 0; /* previous match */
5074 this.match_available = 0; /* set if previous match exists */
5075 this.strstart = 0; /* start of string to insert */
5076 this.match_start = 0; /* start of matching string */
5077 this.lookahead = 0; /* number of valid bytes ahead in window */
5078
5079 this.prev_length = 0;
5080 /* Length of the best match at previous step. Matches not greater than this
5081 * are discarded. This is used in the lazy match evaluation.
5082 */
5083
5084 this.max_chain_length = 0;
5085 /* To speed up deflation, hash chains are never searched beyond this
5086 * length. A higher limit improves compression ratio but degrades the
5087 * speed.
5088 */
5089
5090 this.max_lazy_match = 0;
5091 /* Attempt to find a better match only when the current match is strictly
5092 * smaller than this value. This mechanism is used only for compression
5093 * levels >= 4.
5094 */
5095 // That's alias to max_lazy_match, don't use directly
5096 //this.max_insert_length = 0;
5097 /* Insert new strings in the hash table only if the match length is not
5098 * greater than this length. This saves time but degrades compression.
5099 * max_insert_length is used only for compression levels <= 3.
5100 */
5101
5102 this.level = 0; /* compression level (1..9) */
5103 this.strategy = 0; /* favor or force Huffman coding*/
5104
5105 this.good_match = 0;
5106 /* Use a faster search when the previous match is longer than this */
5107
5108 this.nice_match = 0; /* Stop searching when current match exceeds this */
5109
5110 /* used by trees.c: */
5111
5112 /* Didn't use ct_data typedef below to suppress compiler warning */
5113
5114 // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
5115 // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
5116 // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
5117
5118 // Use flat array of DOUBLE size, with interleaved fata,
5119 // because JS does not support effective
5120 this.dyn_ltree = new utils.Buf16(HEAP_SIZE * 2);
5121 this.dyn_dtree = new utils.Buf16((2*D_CODES+1) * 2);
5122 this.bl_tree = new utils.Buf16((2*BL_CODES+1) * 2);
5123 zero(this.dyn_ltree);
5124 zero(this.dyn_dtree);
5125 zero(this.bl_tree);
5126
5127 this.l_desc = null; /* desc. for literal tree */
5128 this.d_desc = null; /* desc. for distance tree */
5129 this.bl_desc = null; /* desc. for bit length tree */
5130
5131 //ush bl_count[MAX_BITS+1];
5132 this.bl_count = new utils.Buf16(MAX_BITS+1);
5133 /* number of codes at each bit length for an optimal tree */
5134
5135 //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
5136 this.heap = new utils.Buf16(2*L_CODES+1); /* heap used to build the Huffman trees */
5137 zero(this.heap);
5138
5139 this.heap_len = 0; /* number of elements in the heap */
5140 this.heap_max = 0; /* element of largest frequency */
5141 /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
5142 * The same heap array is used to build all trees.
5143 */
5144
5145 this.depth = new utils.Buf16(2*L_CODES+1); //uch depth[2*L_CODES+1];
5146 zero(this.depth);
5147 /* Depth of each subtree used as tie breaker for trees of equal frequency
5148 */
5149
5150 this.l_buf = 0; /* buffer index for literals or lengths */
5151
5152 this.lit_bufsize = 0;
5153 /* Size of match buffer for literals/lengths. There are 4 reasons for
5154 * limiting lit_bufsize to 64K:
5155 * - frequencies can be kept in 16 bit counters
5156 * - if compression is not successful for the first block, all input
5157 * data is still in the window so we can still emit a stored block even
5158 * when input comes from standard input. (This can also be done for
5159 * all blocks if lit_bufsize is not greater than 32K.)
5160 * - if compression is not successful for a file smaller than 64K, we can
5161 * even emit a stored file instead of a stored block (saving 5 bytes).
5162 * This is applicable only for zip (not gzip or zlib).
5163 * - creating new Huffman trees less frequently may not provide fast
5164 * adaptation to changes in the input data statistics. (Take for
5165 * example a binary file with poorly compressible code followed by
5166 * a highly compressible string table.) Smaller buffer sizes give
5167 * fast adaptation but have of course the overhead of transmitting
5168 * trees more frequently.
5169 * - I can't count above 4
5170 */
5171
5172 this.last_lit = 0; /* running index in l_buf */
5173
5174 this.d_buf = 0;
5175 /* Buffer index for distances. To simplify the code, d_buf and l_buf have
5176 * the same number of elements. To use different lengths, an extra flag
5177 * array would be necessary.
5178 */
5179
5180 this.opt_len = 0; /* bit length of current block with optimal trees */
5181 this.static_len = 0; /* bit length of current block with static trees */
5182 this.matches = 0; /* number of string matches in current block */
5183 this.insert = 0; /* bytes at end of window left to insert */
5184
5185
5186 this.bi_buf = 0;
5187 /* Output buffer. bits are inserted starting at the bottom (least
5188 * significant bits).
5189 */
5190 this.bi_valid = 0;
5191 /* Number of valid bits in bi_buf. All bits above the last valid bit
5192 * are always zero.
5193 */
5194
5195 // Used for window memory init. We safely ignore it for JS. That makes
5196 // sense only for pointers and memory check tools.
5197 //this.high_water = 0;
5198 /* High water mark offset in window for initialized bytes -- bytes above
5199 * this are set to zero in order to avoid memory check warnings when
5200 * longest match routines access bytes past the input. This is then
5201 * updated to the new high water mark.
5202 */
5203}
5204
5205
5206function deflateResetKeep(strm) {
5207 var s;
5208
5209 if (!strm || !strm.state) {
5210 return err(strm, Z_STREAM_ERROR);
5211 }
5212
5213 strm.total_in = strm.total_out = 0;
5214 strm.data_type = Z_UNKNOWN;
5215
5216 s = strm.state;
5217 s.pending = 0;
5218 s.pending_out = 0;
5219
5220 if (s.wrap < 0) {
5221 s.wrap = -s.wrap;
5222 /* was made negative by deflate(..., Z_FINISH); */
5223 }
5224 s.status = (s.wrap ? INIT_STATE : BUSY_STATE);
5225 strm.adler = (s.wrap === 2) ?
5226 0 // crc32(0, Z_NULL, 0)
5227 :
5228 1; // adler32(0, Z_NULL, 0)
5229 s.last_flush = Z_NO_FLUSH;
5230 trees._tr_init(s);
5231 return Z_OK;
5232}
5233
5234
5235function deflateReset(strm) {
5236 var ret = deflateResetKeep(strm);
5237 if (ret === Z_OK) {
5238 lm_init(strm.state);
5239 }
5240 return ret;
5241}
5242
5243
5244function deflateSetHeader(strm, head) {
5245 if (!strm || !strm.state) { return Z_STREAM_ERROR; }
5246 if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; }
5247 strm.state.gzhead = head;
5248 return Z_OK;
5249}
5250
5251
5252function deflateInit2(strm, level, method, windowBits, memLevel, strategy) {
5253 if (!strm) { // === Z_NULL
5254 return Z_STREAM_ERROR;
5255 }
5256 var wrap = 1;
5257
5258 if (level === Z_DEFAULT_COMPRESSION) {
5259 level = 6;
5260 }
5261
5262 if (windowBits < 0) { /* suppress zlib wrapper */
5263 wrap = 0;
5264 windowBits = -windowBits;
5265 }
5266
5267 else if (windowBits > 15) {
5268 wrap = 2; /* write gzip wrapper instead */
5269 windowBits -= 16;
5270 }
5271
5272
5273 if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED ||
5274 windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
5275 strategy < 0 || strategy > Z_FIXED) {
5276 return err(strm, Z_STREAM_ERROR);
5277 }
5278
5279
5280 if (windowBits === 8) {
5281 windowBits = 9;
5282 }
5283 /* until 256-byte window bug fixed */
5284
5285 var s = new DeflateState();
5286
5287 strm.state = s;
5288 s.strm = strm;
5289
5290 s.wrap = wrap;
5291 s.gzhead = null;
5292 s.w_bits = windowBits;
5293 s.w_size = 1 << s.w_bits;
5294 s.w_mask = s.w_size - 1;
5295
5296 s.hash_bits = memLevel + 7;
5297 s.hash_size = 1 << s.hash_bits;
5298 s.hash_mask = s.hash_size - 1;
5299 s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH);
5300
5301 s.window = new utils.Buf8(s.w_size * 2);
5302 s.head = new utils.Buf16(s.hash_size);
5303 s.prev = new utils.Buf16(s.w_size);
5304
5305 // Don't need mem init magic for JS.
5306 //s.high_water = 0; /* nothing written to s->window yet */
5307
5308 s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
5309
5310 s.pending_buf_size = s.lit_bufsize * 4;
5311 s.pending_buf = new utils.Buf8(s.pending_buf_size);
5312
5313 s.d_buf = s.lit_bufsize >> 1;
5314 s.l_buf = (1 + 2) * s.lit_bufsize;
5315
5316 s.level = level;
5317 s.strategy = strategy;
5318 s.method = method;
5319
5320 return deflateReset(strm);
5321}
5322
5323function deflateInit(strm, level) {
5324 return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
5325}
5326
5327
5328function deflate(strm, flush) {
5329 var old_flush, s;
5330 var beg, val; // for gzip header write only
5331
5332 if (!strm || !strm.state ||
5333 flush > Z_BLOCK || flush < 0) {
5334 return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR;
5335 }
5336
5337 s = strm.state;
5338
5339 if (!strm.output ||
5340 (!strm.input && strm.avail_in !== 0) ||
5341 (s.status === FINISH_STATE && flush !== Z_FINISH)) {
5342 return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR);
5343 }
5344
5345 s.strm = strm; /* just in case */
5346 old_flush = s.last_flush;
5347 s.last_flush = flush;
5348
5349 /* Write the header */
5350 if (s.status === INIT_STATE) {
5351
5352 if (s.wrap === 2) { // GZIP header
5353 strm.adler = 0; //crc32(0L, Z_NULL, 0);
5354 put_byte(s, 31);
5355 put_byte(s, 139);
5356 put_byte(s, 8);
5357 if (!s.gzhead) { // s->gzhead == Z_NULL
5358 put_byte(s, 0);
5359 put_byte(s, 0);
5360 put_byte(s, 0);
5361 put_byte(s, 0);
5362 put_byte(s, 0);
5363 put_byte(s, s.level === 9 ? 2 :
5364 (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
5365 4 : 0));
5366 put_byte(s, OS_CODE);
5367 s.status = BUSY_STATE;
5368 }
5369 else {
5370 put_byte(s, (s.gzhead.text ? 1 : 0) +
5371 (s.gzhead.hcrc ? 2 : 0) +
5372 (!s.gzhead.extra ? 0 : 4) +
5373 (!s.gzhead.name ? 0 : 8) +
5374 (!s.gzhead.comment ? 0 : 16)
5375 );
5376 put_byte(s, s.gzhead.time & 0xff);
5377 put_byte(s, (s.gzhead.time >> 8) & 0xff);
5378 put_byte(s, (s.gzhead.time >> 16) & 0xff);
5379 put_byte(s, (s.gzhead.time >> 24) & 0xff);
5380 put_byte(s, s.level === 9 ? 2 :
5381 (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ?
5382 4 : 0));
5383 put_byte(s, s.gzhead.os & 0xff);
5384 if (s.gzhead.extra && s.gzhead.extra.length) {
5385 put_byte(s, s.gzhead.extra.length & 0xff);
5386 put_byte(s, (s.gzhead.extra.length >> 8) & 0xff);
5387 }
5388 if (s.gzhead.hcrc) {
5389 strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0);
5390 }
5391 s.gzindex = 0;
5392 s.status = EXTRA_STATE;
5393 }
5394 }
5395 else // DEFLATE header
5396 {
5397 var header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8;
5398 var level_flags = -1;
5399
5400 if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) {
5401 level_flags = 0;
5402 } else if (s.level < 6) {
5403 level_flags = 1;
5404 } else if (s.level === 6) {
5405 level_flags = 2;
5406 } else {
5407 level_flags = 3;
5408 }
5409 header |= (level_flags << 6);
5410 if (s.strstart !== 0) { header |= PRESET_DICT; }
5411 header += 31 - (header % 31);
5412
5413 s.status = BUSY_STATE;
5414 putShortMSB(s, header);
5415
5416 /* Save the adler32 of the preset dictionary: */
5417 if (s.strstart !== 0) {
5418 putShortMSB(s, strm.adler >>> 16);
5419 putShortMSB(s, strm.adler & 0xffff);
5420 }
5421 strm.adler = 1; // adler32(0L, Z_NULL, 0);
5422 }
5423 }
5424
5425//#ifdef GZIP
5426 if (s.status === EXTRA_STATE) {
5427 if (s.gzhead.extra/* != Z_NULL*/) {
5428 beg = s.pending; /* start of bytes to update crc */
5429
5430 while (s.gzindex < (s.gzhead.extra.length & 0xffff)) {
5431 if (s.pending === s.pending_buf_size) {
5432 if (s.gzhead.hcrc && s.pending > beg) {
5433 strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
5434 }
5435 flush_pending(strm);
5436 beg = s.pending;
5437 if (s.pending === s.pending_buf_size) {
5438 break;
5439 }
5440 }
5441 put_byte(s, s.gzhead.extra[s.gzindex] & 0xff);
5442 s.gzindex++;
5443 }
5444 if (s.gzhead.hcrc && s.pending > beg) {
5445 strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
5446 }
5447 if (s.gzindex === s.gzhead.extra.length) {
5448 s.gzindex = 0;
5449 s.status = NAME_STATE;
5450 }
5451 }
5452 else {
5453 s.status = NAME_STATE;
5454 }
5455 }
5456 if (s.status === NAME_STATE) {
5457 if (s.gzhead.name/* != Z_NULL*/) {
5458 beg = s.pending; /* start of bytes to update crc */
5459 //int val;
5460
5461 do {
5462 if (s.pending === s.pending_buf_size) {
5463 if (s.gzhead.hcrc && s.pending > beg) {
5464 strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
5465 }
5466 flush_pending(strm);
5467 beg = s.pending;
5468 if (s.pending === s.pending_buf_size) {
5469 val = 1;
5470 break;
5471 }
5472 }
5473 // JS specific: little magic to add zero terminator to end of string
5474 if (s.gzindex < s.gzhead.name.length) {
5475 val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff;
5476 } else {
5477 val = 0;
5478 }
5479 put_byte(s, val);
5480 } while (val !== 0);
5481
5482 if (s.gzhead.hcrc && s.pending > beg){
5483 strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
5484 }
5485 if (val === 0) {
5486 s.gzindex = 0;
5487 s.status = COMMENT_STATE;
5488 }
5489 }
5490 else {
5491 s.status = COMMENT_STATE;
5492 }
5493 }
5494 if (s.status === COMMENT_STATE) {
5495 if (s.gzhead.comment/* != Z_NULL*/) {
5496 beg = s.pending; /* start of bytes to update crc */
5497 //int val;
5498
5499 do {
5500 if (s.pending === s.pending_buf_size) {
5501 if (s.gzhead.hcrc && s.pending > beg) {
5502 strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
5503 }
5504 flush_pending(strm);
5505 beg = s.pending;
5506 if (s.pending === s.pending_buf_size) {
5507 val = 1;
5508 break;
5509 }
5510 }
5511 // JS specific: little magic to add zero terminator to end of string
5512 if (s.gzindex < s.gzhead.comment.length) {
5513 val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff;
5514 } else {
5515 val = 0;
5516 }
5517 put_byte(s, val);
5518 } while (val !== 0);
5519
5520 if (s.gzhead.hcrc && s.pending > beg) {
5521 strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg);
5522 }
5523 if (val === 0) {
5524 s.status = HCRC_STATE;
5525 }
5526 }
5527 else {
5528 s.status = HCRC_STATE;
5529 }
5530 }
5531 if (s.status === HCRC_STATE) {
5532 if (s.gzhead.hcrc) {
5533 if (s.pending + 2 > s.pending_buf_size) {
5534 flush_pending(strm);
5535 }
5536 if (s.pending + 2 <= s.pending_buf_size) {
5537 put_byte(s, strm.adler & 0xff);
5538 put_byte(s, (strm.adler >> 8) & 0xff);
5539 strm.adler = 0; //crc32(0L, Z_NULL, 0);
5540 s.status = BUSY_STATE;
5541 }
5542 }
5543 else {
5544 s.status = BUSY_STATE;
5545 }
5546 }
5547//#endif
5548
5549 /* Flush as much pending output as possible */
5550 if (s.pending !== 0) {
5551 flush_pending(strm);
5552 if (strm.avail_out === 0) {
5553 /* Since avail_out is 0, deflate will be called again with
5554 * more output space, but possibly with both pending and
5555 * avail_in equal to zero. There won't be anything to do,
5556 * but this is not an error situation so make sure we
5557 * return OK instead of BUF_ERROR at next call of deflate:
5558 */
5559 s.last_flush = -1;
5560 return Z_OK;
5561 }
5562
5563 /* Make sure there is something to do and avoid duplicate consecutive
5564 * flushes. For repeated and useless calls with Z_FINISH, we keep
5565 * returning Z_STREAM_END instead of Z_BUF_ERROR.
5566 */
5567 } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) &&
5568 flush !== Z_FINISH) {
5569 return err(strm, Z_BUF_ERROR);
5570 }
5571
5572 /* User must not provide more input after the first FINISH: */
5573 if (s.status === FINISH_STATE && strm.avail_in !== 0) {
5574 return err(strm, Z_BUF_ERROR);
5575 }
5576
5577 /* Start a new block or continue the current one.
5578 */
5579 if (strm.avail_in !== 0 || s.lookahead !== 0 ||
5580 (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) {
5581 var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) :
5582 (s.strategy === Z_RLE ? deflate_rle(s, flush) :
5583 configuration_table[s.level].func(s, flush));
5584
5585 if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) {
5586 s.status = FINISH_STATE;
5587 }
5588 if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) {
5589 if (strm.avail_out === 0) {
5590 s.last_flush = -1;
5591 /* avoid BUF_ERROR next call, see above */
5592 }
5593 return Z_OK;
5594 /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
5595 * of deflate should use the same flush parameter to make sure
5596 * that the flush is complete. So we don't have to output an
5597 * empty block here, this will be done at next call. This also
5598 * ensures that for a very small output buffer, we emit at most
5599 * one empty block.
5600 */
5601 }
5602 if (bstate === BS_BLOCK_DONE) {
5603 if (flush === Z_PARTIAL_FLUSH) {
5604 trees._tr_align(s);
5605 }
5606 else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
5607
5608 trees._tr_stored_block(s, 0, 0, false);
5609 /* For a full flush, this empty block will be recognized
5610 * as a special marker by inflate_sync().
5611 */
5612 if (flush === Z_FULL_FLUSH) {
5613 /*** CLEAR_HASH(s); ***/ /* forget history */
5614 zero(s.head); // Fill with NIL (= 0);
5615
5616 if (s.lookahead === 0) {
5617 s.strstart = 0;
5618 s.block_start = 0;
5619 s.insert = 0;
5620 }
5621 }
5622 }
5623 flush_pending(strm);
5624 if (strm.avail_out === 0) {
5625 s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */
5626 return Z_OK;
5627 }
5628 }
5629 }
5630 //Assert(strm->avail_out > 0, "bug2");
5631 //if (strm.avail_out <= 0) { throw new Error("bug2");}
5632
5633 if (flush !== Z_FINISH) { return Z_OK; }
5634 if (s.wrap <= 0) { return Z_STREAM_END; }
5635
5636 /* Write the trailer */
5637 if (s.wrap === 2) {
5638 put_byte(s, strm.adler & 0xff);
5639 put_byte(s, (strm.adler >> 8) & 0xff);
5640 put_byte(s, (strm.adler >> 16) & 0xff);
5641 put_byte(s, (strm.adler >> 24) & 0xff);
5642 put_byte(s, strm.total_in & 0xff);
5643 put_byte(s, (strm.total_in >> 8) & 0xff);
5644 put_byte(s, (strm.total_in >> 16) & 0xff);
5645 put_byte(s, (strm.total_in >> 24) & 0xff);
5646 }
5647 else
5648 {
5649 putShortMSB(s, strm.adler >>> 16);
5650 putShortMSB(s, strm.adler & 0xffff);
5651 }
5652
5653 flush_pending(strm);
5654 /* If avail_out is zero, the application will call deflate again
5655 * to flush the rest.
5656 */
5657 if (s.wrap > 0) { s.wrap = -s.wrap; }
5658 /* write the trailer only once! */
5659 return s.pending !== 0 ? Z_OK : Z_STREAM_END;
5660}
5661
5662function deflateEnd(strm) {
5663 var status;
5664
5665 if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) {
5666 return Z_STREAM_ERROR;
5667 }
5668
5669 status = strm.state.status;
5670 if (status !== INIT_STATE &&
5671 status !== EXTRA_STATE &&
5672 status !== NAME_STATE &&
5673 status !== COMMENT_STATE &&
5674 status !== HCRC_STATE &&
5675 status !== BUSY_STATE &&
5676 status !== FINISH_STATE
5677 ) {
5678 return err(strm, Z_STREAM_ERROR);
5679 }
5680
5681 strm.state = null;
5682
5683 return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK;
5684}
5685
5686/* =========================================================================
5687 * Copy the source state to the destination state
5688 */
5689//function deflateCopy(dest, source) {
5690//
5691//}
5692
5693exports.deflateInit = deflateInit;
5694exports.deflateInit2 = deflateInit2;
5695exports.deflateReset = deflateReset;
5696exports.deflateResetKeep = deflateResetKeep;
5697exports.deflateSetHeader = deflateSetHeader;
5698exports.deflate = deflate;
5699exports.deflateEnd = deflateEnd;
5700exports.deflateInfo = 'pako deflate (from Nodeca project)';
5701
5702/* Not implemented
5703exports.deflateBound = deflateBound;
5704exports.deflateCopy = deflateCopy;
5705exports.deflateSetDictionary = deflateSetDictionary;
5706exports.deflateParams = deflateParams;
5707exports.deflatePending = deflatePending;
5708exports.deflatePrime = deflatePrime;
5709exports.deflateTune = deflateTune;
5710*/
5711},{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(_dereq_,module,exports){
5712'use strict';
5713
5714
5715function GZheader() {
5716 /* true if compressed data believed to be text */
5717 this.text = 0;
5718 /* modification time */
5719 this.time = 0;
5720 /* extra flags (not used when writing a gzip file) */
5721 this.xflags = 0;
5722 /* operating system */
5723 this.os = 0;
5724 /* pointer to extra field or Z_NULL if none */
5725 this.extra = null;
5726 /* extra field length (valid if extra != Z_NULL) */
5727 this.extra_len = 0; // Actually, we don't need it in JS,
5728 // but leave for few code modifications
5729
5730 //
5731 // Setup limits is not necessary because in js we should not preallocate memory
5732 // for inflate use constant limit in 65536 bytes
5733 //
5734
5735 /* space at extra (only when reading header) */
5736 // this.extra_max = 0;
5737 /* pointer to zero-terminated file name or Z_NULL */
5738 this.name = '';
5739 /* space at name (only when reading header) */
5740 // this.name_max = 0;
5741 /* pointer to zero-terminated comment or Z_NULL */
5742 this.comment = '';
5743 /* space at comment (only when reading header) */
5744 // this.comm_max = 0;
5745 /* true if there was or will be a header crc */
5746 this.hcrc = 0;
5747 /* true when done reading gzip header (not used when writing a gzip file) */
5748 this.done = false;
5749}
5750
5751module.exports = GZheader;
5752},{}],34:[function(_dereq_,module,exports){
5753'use strict';
5754
5755// See state defs from inflate.js
5756var BAD = 30; /* got a data error -- remain here until reset */
5757var TYPE = 12; /* i: waiting for type bits, including last-flag bit */
5758
5759/*
5760 Decode literal, length, and distance codes and write out the resulting
5761 literal and match bytes until either not enough input or output is
5762 available, an end-of-block is encountered, or a data error is encountered.
5763 When large enough input and output buffers are supplied to inflate(), for
5764 example, a 16K input buffer and a 64K output buffer, more than 95% of the
5765 inflate execution time is spent in this routine.
5766
5767 Entry assumptions:
5768
5769 state.mode === LEN
5770 strm.avail_in >= 6
5771 strm.avail_out >= 258
5772 start >= strm.avail_out
5773 state.bits < 8
5774
5775 On return, state.mode is one of:
5776
5777 LEN -- ran out of enough output space or enough available input
5778 TYPE -- reached end of block code, inflate() to interpret next block
5779 BAD -- error in block data
5780
5781 Notes:
5782
5783 - The maximum input bits used by a length/distance pair is 15 bits for the
5784 length code, 5 bits for the length extra, 15 bits for the distance code,
5785 and 13 bits for the distance extra. This totals 48 bits, or six bytes.
5786 Therefore if strm.avail_in >= 6, then there is enough input to avoid
5787 checking for available input while decoding.
5788
5789 - The maximum bytes that a single length/distance pair can output is 258
5790 bytes, which is the maximum length that can be coded. inflate_fast()
5791 requires strm.avail_out >= 258 for each loop to avoid checking for
5792 output space.
5793 */
5794module.exports = function inflate_fast(strm, start) {
5795 var state;
5796 var _in; /* local strm.input */
5797 var last; /* have enough input while in < last */
5798 var _out; /* local strm.output */
5799 var beg; /* inflate()'s initial strm.output */
5800 var end; /* while out < end, enough space available */
5801//#ifdef INFLATE_STRICT
5802 var dmax; /* maximum distance from zlib header */
5803//#endif
5804 var wsize; /* window size or zero if not using window */
5805 var whave; /* valid bytes in the window */
5806 var wnext; /* window write index */
5807 var window; /* allocated sliding window, if wsize != 0 */
5808 var hold; /* local strm.hold */
5809 var bits; /* local strm.bits */
5810 var lcode; /* local strm.lencode */
5811 var dcode; /* local strm.distcode */
5812 var lmask; /* mask for first level of length codes */
5813 var dmask; /* mask for first level of distance codes */
5814 var here; /* retrieved table entry */
5815 var op; /* code bits, operation, extra bits, or */
5816 /* window position, window bytes to copy */
5817 var len; /* match length, unused bytes */
5818 var dist; /* match distance */
5819 var from; /* where to copy match from */
5820 var from_source;
5821
5822
5823 var input, output; // JS specific, because we have no pointers
5824
5825 /* copy state to local variables */
5826 state = strm.state;
5827 //here = state.here;
5828 _in = strm.next_in;
5829 input = strm.input;
5830 last = _in + (strm.avail_in - 5);
5831 _out = strm.next_out;
5832 output = strm.output;
5833 beg = _out - (start - strm.avail_out);
5834 end = _out + (strm.avail_out - 257);
5835//#ifdef INFLATE_STRICT
5836 dmax = state.dmax;
5837//#endif
5838 wsize = state.wsize;
5839 whave = state.whave;
5840 wnext = state.wnext;
5841 window = state.window;
5842 hold = state.hold;
5843 bits = state.bits;
5844 lcode = state.lencode;
5845 dcode = state.distcode;
5846 lmask = (1 << state.lenbits) - 1;
5847 dmask = (1 << state.distbits) - 1;
5848
5849
5850 /* decode literals and length/distances until end-of-block or not enough
5851 input data or output space */
5852
5853 top:
5854 do {
5855 if (bits < 15) {
5856 hold += input[_in++] << bits;
5857 bits += 8;
5858 hold += input[_in++] << bits;
5859 bits += 8;
5860 }
5861
5862 here = lcode[hold & lmask];
5863
5864 dolen:
5865 for (;;) { // Goto emulation
5866 op = here >>> 24/*here.bits*/;
5867 hold >>>= op;
5868 bits -= op;
5869 op = (here >>> 16) & 0xff/*here.op*/;
5870 if (op === 0) { /* literal */
5871 //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
5872 // "inflate: literal '%c'\n" :
5873 // "inflate: literal 0x%02x\n", here.val));
5874 output[_out++] = here & 0xffff/*here.val*/;
5875 }
5876 else if (op & 16) { /* length base */
5877 len = here & 0xffff/*here.val*/;
5878 op &= 15; /* number of extra bits */
5879 if (op) {
5880 if (bits < op) {
5881 hold += input[_in++] << bits;
5882 bits += 8;
5883 }
5884 len += hold & ((1 << op) - 1);
5885 hold >>>= op;
5886 bits -= op;
5887 }
5888 //Tracevv((stderr, "inflate: length %u\n", len));
5889 if (bits < 15) {
5890 hold += input[_in++] << bits;
5891 bits += 8;
5892 hold += input[_in++] << bits;
5893 bits += 8;
5894 }
5895 here = dcode[hold & dmask];
5896
5897 dodist:
5898 for (;;) { // goto emulation
5899 op = here >>> 24/*here.bits*/;
5900 hold >>>= op;
5901 bits -= op;
5902 op = (here >>> 16) & 0xff/*here.op*/;
5903
5904 if (op & 16) { /* distance base */
5905 dist = here & 0xffff/*here.val*/;
5906 op &= 15; /* number of extra bits */
5907 if (bits < op) {
5908 hold += input[_in++] << bits;
5909 bits += 8;
5910 if (bits < op) {
5911 hold += input[_in++] << bits;
5912 bits += 8;
5913 }
5914 }
5915 dist += hold & ((1 << op) - 1);
5916//#ifdef INFLATE_STRICT
5917 if (dist > dmax) {
5918 strm.msg = 'invalid distance too far back';
5919 state.mode = BAD;
5920 break top;
5921 }
5922//#endif
5923 hold >>>= op;
5924 bits -= op;
5925 //Tracevv((stderr, "inflate: distance %u\n", dist));
5926 op = _out - beg; /* max distance in output */
5927 if (dist > op) { /* see if copy from window */
5928 op = dist - op; /* distance back in window */
5929 if (op > whave) {
5930 if (state.sane) {
5931 strm.msg = 'invalid distance too far back';
5932 state.mode = BAD;
5933 break top;
5934 }
5935
5936// (!) This block is disabled in zlib defailts,
5937// don't enable it for binary compatibility
5938//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
5939// if (len <= op - whave) {
5940// do {
5941// output[_out++] = 0;
5942// } while (--len);
5943// continue top;
5944// }
5945// len -= op - whave;
5946// do {
5947// output[_out++] = 0;
5948// } while (--op > whave);
5949// if (op === 0) {
5950// from = _out - dist;
5951// do {
5952// output[_out++] = output[from++];
5953// } while (--len);
5954// continue top;
5955// }
5956//#endif
5957 }
5958 from = 0; // window index
5959 from_source = window;
5960 if (wnext === 0) { /* very common case */
5961 from += wsize - op;
5962 if (op < len) { /* some from window */
5963 len -= op;
5964 do {
5965 output[_out++] = window[from++];
5966 } while (--op);
5967 from = _out - dist; /* rest from output */
5968 from_source = output;
5969 }
5970 }
5971 else if (wnext < op) { /* wrap around window */
5972 from += wsize + wnext - op;
5973 op -= wnext;
5974 if (op < len) { /* some from end of window */
5975 len -= op;
5976 do {
5977 output[_out++] = window[from++];
5978 } while (--op);
5979 from = 0;
5980 if (wnext < len) { /* some from start of window */
5981 op = wnext;
5982 len -= op;
5983 do {
5984 output[_out++] = window[from++];
5985 } while (--op);
5986 from = _out - dist; /* rest from output */
5987 from_source = output;
5988 }
5989 }
5990 }
5991 else { /* contiguous in window */
5992 from += wnext - op;
5993 if (op < len) { /* some from window */
5994 len -= op;
5995 do {
5996 output[_out++] = window[from++];
5997 } while (--op);
5998 from = _out - dist; /* rest from output */
5999 from_source = output;
6000 }
6001 }
6002 while (len > 2) {
6003 output[_out++] = from_source[from++];
6004 output[_out++] = from_source[from++];
6005 output[_out++] = from_source[from++];
6006 len -= 3;
6007 }
6008 if (len) {
6009 output[_out++] = from_source[from++];
6010 if (len > 1) {
6011 output[_out++] = from_source[from++];
6012 }
6013 }
6014 }
6015 else {
6016 from = _out - dist; /* copy direct from output */
6017 do { /* minimum length is three */
6018 output[_out++] = output[from++];
6019 output[_out++] = output[from++];
6020 output[_out++] = output[from++];
6021 len -= 3;
6022 } while (len > 2);
6023 if (len) {
6024 output[_out++] = output[from++];
6025 if (len > 1) {
6026 output[_out++] = output[from++];
6027 }
6028 }
6029 }
6030 }
6031 else if ((op & 64) === 0) { /* 2nd level distance code */
6032 here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
6033 continue dodist;
6034 }
6035 else {
6036 strm.msg = 'invalid distance code';
6037 state.mode = BAD;
6038 break top;
6039 }
6040
6041 break; // need to emulate goto via "continue"
6042 }
6043 }
6044 else if ((op & 64) === 0) { /* 2nd level length code */
6045 here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
6046 continue dolen;
6047 }
6048 else if (op & 32) { /* end-of-block */
6049 //Tracevv((stderr, "inflate: end of block\n"));
6050 state.mode = TYPE;
6051 break top;
6052 }
6053 else {
6054 strm.msg = 'invalid literal/length code';
6055 state.mode = BAD;
6056 break top;
6057 }
6058
6059 break; // need to emulate goto via "continue"
6060 }
6061 } while (_in < last && _out < end);
6062
6063 /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
6064 len = bits >> 3;
6065 _in -= len;
6066 bits -= len << 3;
6067 hold &= (1 << bits) - 1;
6068
6069 /* update state and return */
6070 strm.next_in = _in;
6071 strm.next_out = _out;
6072 strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last));
6073 strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end));
6074 state.hold = hold;
6075 state.bits = bits;
6076 return;
6077};
6078
6079},{}],35:[function(_dereq_,module,exports){
6080'use strict';
6081
6082
6083var utils = _dereq_('../utils/common');
6084var adler32 = _dereq_('./adler32');
6085var crc32 = _dereq_('./crc32');
6086var inflate_fast = _dereq_('./inffast');
6087var inflate_table = _dereq_('./inftrees');
6088
6089var CODES = 0;
6090var LENS = 1;
6091var DISTS = 2;
6092
6093/* Public constants ==========================================================*/
6094/* ===========================================================================*/
6095
6096
6097/* Allowed flush values; see deflate() and inflate() below for details */
6098//var Z_NO_FLUSH = 0;
6099//var Z_PARTIAL_FLUSH = 1;
6100//var Z_SYNC_FLUSH = 2;
6101//var Z_FULL_FLUSH = 3;
6102var Z_FINISH = 4;
6103var Z_BLOCK = 5;
6104var Z_TREES = 6;
6105
6106
6107/* Return codes for the compression/decompression functions. Negative values
6108 * are errors, positive values are used for special but normal events.
6109 */
6110var Z_OK = 0;
6111var Z_STREAM_END = 1;
6112var Z_NEED_DICT = 2;
6113//var Z_ERRNO = -1;
6114var Z_STREAM_ERROR = -2;
6115var Z_DATA_ERROR = -3;
6116var Z_MEM_ERROR = -4;
6117var Z_BUF_ERROR = -5;
6118//var Z_VERSION_ERROR = -6;
6119
6120/* The deflate compression method */
6121var Z_DEFLATED = 8;
6122
6123
6124/* STATES ====================================================================*/
6125/* ===========================================================================*/
6126
6127
6128var HEAD = 1; /* i: waiting for magic header */
6129var FLAGS = 2; /* i: waiting for method and flags (gzip) */
6130var TIME = 3; /* i: waiting for modification time (gzip) */
6131var OS = 4; /* i: waiting for extra flags and operating system (gzip) */
6132var EXLEN = 5; /* i: waiting for extra length (gzip) */
6133var EXTRA = 6; /* i: waiting for extra bytes (gzip) */
6134var NAME = 7; /* i: waiting for end of file name (gzip) */
6135var COMMENT = 8; /* i: waiting for end of comment (gzip) */
6136var HCRC = 9; /* i: waiting for header crc (gzip) */
6137var DICTID = 10; /* i: waiting for dictionary check value */
6138var DICT = 11; /* waiting for inflateSetDictionary() call */
6139var TYPE = 12; /* i: waiting for type bits, including last-flag bit */
6140var TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */
6141var STORED = 14; /* i: waiting for stored size (length and complement) */
6142var COPY_ = 15; /* i/o: same as COPY below, but only first time in */
6143var COPY = 16; /* i/o: waiting for input or output to copy stored block */
6144var TABLE = 17; /* i: waiting for dynamic block table lengths */
6145var LENLENS = 18; /* i: waiting for code length code lengths */
6146var CODELENS = 19; /* i: waiting for length/lit and distance code lengths */
6147var LEN_ = 20; /* i: same as LEN below, but only first time in */
6148var LEN = 21; /* i: waiting for length/lit/eob code */
6149var LENEXT = 22; /* i: waiting for length extra bits */
6150var DIST = 23; /* i: waiting for distance code */
6151var DISTEXT = 24; /* i: waiting for distance extra bits */
6152var MATCH = 25; /* o: waiting for output space to copy string */
6153var LIT = 26; /* o: waiting for output space to write literal */
6154var CHECK = 27; /* i: waiting for 32-bit check value */
6155var LENGTH = 28; /* i: waiting for 32-bit length (gzip) */
6156var DONE = 29; /* finished check, done -- remain here until reset */
6157var BAD = 30; /* got a data error -- remain here until reset */
6158var MEM = 31; /* got an inflate() memory error -- remain here until reset */
6159var SYNC = 32; /* looking for synchronization bytes to restart inflate() */
6160
6161/* ===========================================================================*/
6162
6163
6164
6165var ENOUGH_LENS = 852;
6166var ENOUGH_DISTS = 592;
6167//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);
6168
6169var MAX_WBITS = 15;
6170/* 32K LZ77 window */
6171var DEF_WBITS = MAX_WBITS;
6172
6173
6174function ZSWAP32(q) {
6175 return (((q >>> 24) & 0xff) +
6176 ((q >>> 8) & 0xff00) +
6177 ((q & 0xff00) << 8) +
6178 ((q & 0xff) << 24));
6179}
6180
6181
6182function InflateState() {
6183 this.mode = 0; /* current inflate mode */
6184 this.last = false; /* true if processing last block */
6185 this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */
6186 this.havedict = false; /* true if dictionary provided */
6187 this.flags = 0; /* gzip header method and flags (0 if zlib) */
6188 this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */
6189 this.check = 0; /* protected copy of check value */
6190 this.total = 0; /* protected copy of output count */
6191 // TODO: may be {}
6192 this.head = null; /* where to save gzip header information */
6193
6194 /* sliding window */
6195 this.wbits = 0; /* log base 2 of requested window size */
6196 this.wsize = 0; /* window size or zero if not using window */
6197 this.whave = 0; /* valid bytes in the window */
6198 this.wnext = 0; /* window write index */
6199 this.window = null; /* allocated sliding window, if needed */
6200
6201 /* bit accumulator */
6202 this.hold = 0; /* input bit accumulator */
6203 this.bits = 0; /* number of bits in "in" */
6204
6205 /* for string and stored block copying */
6206 this.length = 0; /* literal or length of data to copy */
6207 this.offset = 0; /* distance back to copy string from */
6208
6209 /* for table and code decoding */
6210 this.extra = 0; /* extra bits needed */
6211
6212 /* fixed and dynamic code tables */
6213 this.lencode = null; /* starting table for length/literal codes */
6214 this.distcode = null; /* starting table for distance codes */
6215 this.lenbits = 0; /* index bits for lencode */
6216 this.distbits = 0; /* index bits for distcode */
6217
6218 /* dynamic table building */
6219 this.ncode = 0; /* number of code length code lengths */
6220 this.nlen = 0; /* number of length code lengths */
6221 this.ndist = 0; /* number of distance code lengths */
6222 this.have = 0; /* number of code lengths in lens[] */
6223 this.next = null; /* next available space in codes[] */
6224
6225 this.lens = new utils.Buf16(320); /* temporary storage for code lengths */
6226 this.work = new utils.Buf16(288); /* work area for code table building */
6227
6228 /*
6229 because we don't have pointers in js, we use lencode and distcode directly
6230 as buffers so we don't need codes
6231 */
6232 //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */
6233 this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */
6234 this.distdyn = null; /* dynamic table for distance codes (JS specific) */
6235 this.sane = 0; /* if false, allow invalid distance too far */
6236 this.back = 0; /* bits back of last unprocessed length/lit */
6237 this.was = 0; /* initial length of match */
6238}
6239
6240function inflateResetKeep(strm) {
6241 var state;
6242
6243 if (!strm || !strm.state) { return Z_STREAM_ERROR; }
6244 state = strm.state;
6245 strm.total_in = strm.total_out = state.total = 0;
6246 strm.msg = ''; /*Z_NULL*/
6247 if (state.wrap) { /* to support ill-conceived Java test suite */
6248 strm.adler = state.wrap & 1;
6249 }
6250 state.mode = HEAD;
6251 state.last = 0;
6252 state.havedict = 0;
6253 state.dmax = 32768;
6254 state.head = null/*Z_NULL*/;
6255 state.hold = 0;
6256 state.bits = 0;
6257 //state.lencode = state.distcode = state.next = state.codes;
6258 state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS);
6259 state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS);
6260
6261 state.sane = 1;
6262 state.back = -1;
6263 //Tracev((stderr, "inflate: reset\n"));
6264 return Z_OK;
6265}
6266
6267function inflateReset(strm) {
6268 var state;
6269
6270 if (!strm || !strm.state) { return Z_STREAM_ERROR; }
6271 state = strm.state;
6272 state.wsize = 0;
6273 state.whave = 0;
6274 state.wnext = 0;
6275 return inflateResetKeep(strm);
6276
6277}
6278
6279function inflateReset2(strm, windowBits) {
6280 var wrap;
6281 var state;
6282
6283 /* get the state */
6284 if (!strm || !strm.state) { return Z_STREAM_ERROR; }
6285 state = strm.state;
6286
6287 /* extract wrap request from windowBits parameter */
6288 if (windowBits < 0) {
6289 wrap = 0;
6290 windowBits = -windowBits;
6291 }
6292 else {
6293 wrap = (windowBits >> 4) + 1;
6294 if (windowBits < 48) {
6295 windowBits &= 15;
6296 }
6297 }
6298
6299 /* set number of window bits, free window if different */
6300 if (windowBits && (windowBits < 8 || windowBits > 15)) {
6301 return Z_STREAM_ERROR;
6302 }
6303 if (state.window !== null && state.wbits !== windowBits) {
6304 state.window = null;
6305 }
6306
6307 /* update state and reset the rest of it */
6308 state.wrap = wrap;
6309 state.wbits = windowBits;
6310 return inflateReset(strm);
6311}
6312
6313function inflateInit2(strm, windowBits) {
6314 var ret;
6315 var state;
6316
6317 if (!strm) { return Z_STREAM_ERROR; }
6318 //strm.msg = Z_NULL; /* in case we return an error */
6319
6320 state = new InflateState();
6321
6322 //if (state === Z_NULL) return Z_MEM_ERROR;
6323 //Tracev((stderr, "inflate: allocated\n"));
6324 strm.state = state;
6325 state.window = null/*Z_NULL*/;
6326 ret = inflateReset2(strm, windowBits);
6327 if (ret !== Z_OK) {
6328 strm.state = null/*Z_NULL*/;
6329 }
6330 return ret;
6331}
6332
6333function inflateInit(strm) {
6334 return inflateInit2(strm, DEF_WBITS);
6335}
6336
6337
6338/*
6339 Return state with length and distance decoding tables and index sizes set to
6340 fixed code decoding. Normally this returns fixed tables from inffixed.h.
6341 If BUILDFIXED is defined, then instead this routine builds the tables the
6342 first time it's called, and returns those tables the first time and
6343 thereafter. This reduces the size of the code by about 2K bytes, in
6344 exchange for a little execution time. However, BUILDFIXED should not be
6345 used for threaded applications, since the rewriting of the tables and virgin
6346 may not be thread-safe.
6347 */
6348var virgin = true;
6349
6350var lenfix, distfix; // We have no pointers in JS, so keep tables separate
6351
6352function fixedtables(state) {
6353 /* build fixed huffman tables if first call (may not be thread safe) */
6354 if (virgin) {
6355 var sym;
6356
6357 lenfix = new utils.Buf32(512);
6358 distfix = new utils.Buf32(32);
6359
6360 /* literal/length table */
6361 sym = 0;
6362 while (sym < 144) { state.lens[sym++] = 8; }
6363 while (sym < 256) { state.lens[sym++] = 9; }
6364 while (sym < 280) { state.lens[sym++] = 7; }
6365 while (sym < 288) { state.lens[sym++] = 8; }
6366
6367 inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, {bits: 9});
6368
6369 /* distance table */
6370 sym = 0;
6371 while (sym < 32) { state.lens[sym++] = 5; }
6372
6373 inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, {bits: 5});
6374
6375 /* do this just once */
6376 virgin = false;
6377 }
6378
6379 state.lencode = lenfix;
6380 state.lenbits = 9;
6381 state.distcode = distfix;
6382 state.distbits = 5;
6383}
6384
6385
6386/*
6387 Update the window with the last wsize (normally 32K) bytes written before
6388 returning. If window does not exist yet, create it. This is only called
6389 when a window is already in use, or when output has been written during this
6390 inflate call, but the end of the deflate stream has not been reached yet.
6391 It is also called to create a window for dictionary data when a dictionary
6392 is loaded.
6393
6394 Providing output buffers larger than 32K to inflate() should provide a speed
6395 advantage, since only the last 32K of output is copied to the sliding window
6396 upon return from inflate(), and since all distances after the first 32K of
6397 output will fall in the output data, making match copies simpler and faster.
6398 The advantage may be dependent on the size of the processor's data caches.
6399 */
6400function updatewindow(strm, src, end, copy) {
6401 var dist;
6402 var state = strm.state;
6403
6404 /* if it hasn't been done already, allocate space for the window */
6405 if (state.window === null) {
6406 state.wsize = 1 << state.wbits;
6407 state.wnext = 0;
6408 state.whave = 0;
6409
6410 state.window = new utils.Buf8(state.wsize);
6411 }
6412
6413 /* copy state->wsize or less output bytes into the circular window */
6414 if (copy >= state.wsize) {
6415 utils.arraySet(state.window,src, end - state.wsize, state.wsize, 0);
6416 state.wnext = 0;
6417 state.whave = state.wsize;
6418 }
6419 else {
6420 dist = state.wsize - state.wnext;
6421 if (dist > copy) {
6422 dist = copy;
6423 }
6424 //zmemcpy(state->window + state->wnext, end - copy, dist);
6425 utils.arraySet(state.window,src, end - copy, dist, state.wnext);
6426 copy -= dist;
6427 if (copy) {
6428 //zmemcpy(state->window, end - copy, copy);
6429 utils.arraySet(state.window,src, end - copy, copy, 0);
6430 state.wnext = copy;
6431 state.whave = state.wsize;
6432 }
6433 else {
6434 state.wnext += dist;
6435 if (state.wnext === state.wsize) { state.wnext = 0; }
6436 if (state.whave < state.wsize) { state.whave += dist; }
6437 }
6438 }
6439 return 0;
6440}
6441
6442function inflate(strm, flush) {
6443 var state;
6444 var input, output; // input/output buffers
6445 var next; /* next input INDEX */
6446 var put; /* next output INDEX */
6447 var have, left; /* available input and output */
6448 var hold; /* bit buffer */
6449 var bits; /* bits in bit buffer */
6450 var _in, _out; /* save starting available input and output */
6451 var copy; /* number of stored or match bytes to copy */
6452 var from; /* where to copy match bytes from */
6453 var from_source;
6454 var here = 0; /* current decoding table entry */
6455 var here_bits, here_op, here_val; // paked "here" denormalized (JS specific)
6456 //var last; /* parent table entry */
6457 var last_bits, last_op, last_val; // paked "last" denormalized (JS specific)
6458 var len; /* length to copy for repeats, bits to drop */
6459 var ret; /* return code */
6460 var hbuf = new utils.Buf8(4); /* buffer for gzip header crc calculation */
6461 var opts;
6462
6463 var n; // temporary var for NEED_BITS
6464
6465 var order = /* permutation of code lengths */
6466 [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
6467
6468
6469 if (!strm || !strm.state || !strm.output ||
6470 (!strm.input && strm.avail_in !== 0)) {
6471 return Z_STREAM_ERROR;
6472 }
6473
6474 state = strm.state;
6475 if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */
6476
6477
6478 //--- LOAD() ---
6479 put = strm.next_out;
6480 output = strm.output;
6481 left = strm.avail_out;
6482 next = strm.next_in;
6483 input = strm.input;
6484 have = strm.avail_in;
6485 hold = state.hold;
6486 bits = state.bits;
6487 //---
6488
6489 _in = have;
6490 _out = left;
6491 ret = Z_OK;
6492
6493 inf_leave: // goto emulation
6494 for (;;) {
6495 switch (state.mode) {
6496 case HEAD:
6497 if (state.wrap === 0) {
6498 state.mode = TYPEDO;
6499 break;
6500 }
6501 //=== NEEDBITS(16);
6502 while (bits < 16) {
6503 if (have === 0) { break inf_leave; }
6504 have--;
6505 hold += input[next++] << bits;
6506 bits += 8;
6507 }
6508 //===//
6509 if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */
6510 state.check = 0/*crc32(0L, Z_NULL, 0)*/;
6511 //=== CRC2(state.check, hold);
6512 hbuf[0] = hold & 0xff;
6513 hbuf[1] = (hold >>> 8) & 0xff;
6514 state.check = crc32(state.check, hbuf, 2, 0);
6515 //===//
6516
6517 //=== INITBITS();
6518 hold = 0;
6519 bits = 0;
6520 //===//
6521 state.mode = FLAGS;
6522 break;
6523 }
6524 state.flags = 0; /* expect zlib header */
6525 if (state.head) {
6526 state.head.done = false;
6527 }
6528 if (!(state.wrap & 1) || /* check if zlib header allowed */
6529 (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {
6530 strm.msg = 'incorrect header check';
6531 state.mode = BAD;
6532 break;
6533 }
6534 if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) {
6535 strm.msg = 'unknown compression method';
6536 state.mode = BAD;
6537 break;
6538 }
6539 //--- DROPBITS(4) ---//
6540 hold >>>= 4;
6541 bits -= 4;
6542 //---//
6543 len = (hold & 0x0f)/*BITS(4)*/ + 8;
6544 if (state.wbits === 0) {
6545 state.wbits = len;
6546 }
6547 else if (len > state.wbits) {
6548 strm.msg = 'invalid window size';
6549 state.mode = BAD;
6550 break;
6551 }
6552 state.dmax = 1 << len;
6553 //Tracev((stderr, "inflate: zlib header ok\n"));
6554 strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
6555 state.mode = hold & 0x200 ? DICTID : TYPE;
6556 //=== INITBITS();
6557 hold = 0;
6558 bits = 0;
6559 //===//
6560 break;
6561 case FLAGS:
6562 //=== NEEDBITS(16); */
6563 while (bits < 16) {
6564 if (have === 0) { break inf_leave; }
6565 have--;
6566 hold += input[next++] << bits;
6567 bits += 8;
6568 }
6569 //===//
6570 state.flags = hold;
6571 if ((state.flags & 0xff) !== Z_DEFLATED) {
6572 strm.msg = 'unknown compression method';
6573 state.mode = BAD;
6574 break;
6575 }
6576 if (state.flags & 0xe000) {
6577 strm.msg = 'unknown header flags set';
6578 state.mode = BAD;
6579 break;
6580 }
6581 if (state.head) {
6582 state.head.text = ((hold >> 8) & 1);
6583 }
6584 if (state.flags & 0x0200) {
6585 //=== CRC2(state.check, hold);
6586 hbuf[0] = hold & 0xff;
6587 hbuf[1] = (hold >>> 8) & 0xff;
6588 state.check = crc32(state.check, hbuf, 2, 0);
6589 //===//
6590 }
6591 //=== INITBITS();
6592 hold = 0;
6593 bits = 0;
6594 //===//
6595 state.mode = TIME;
6596 /* falls through */
6597 case TIME:
6598 //=== NEEDBITS(32); */
6599 while (bits < 32) {
6600 if (have === 0) { break inf_leave; }
6601 have--;
6602 hold += input[next++] << bits;
6603 bits += 8;
6604 }
6605 //===//
6606 if (state.head) {
6607 state.head.time = hold;
6608 }
6609 if (state.flags & 0x0200) {
6610 //=== CRC4(state.check, hold)
6611 hbuf[0] = hold & 0xff;
6612 hbuf[1] = (hold >>> 8) & 0xff;
6613 hbuf[2] = (hold >>> 16) & 0xff;
6614 hbuf[3] = (hold >>> 24) & 0xff;
6615 state.check = crc32(state.check, hbuf, 4, 0);
6616 //===
6617 }
6618 //=== INITBITS();
6619 hold = 0;
6620 bits = 0;
6621 //===//
6622 state.mode = OS;
6623 /* falls through */
6624 case OS:
6625 //=== NEEDBITS(16); */
6626 while (bits < 16) {
6627 if (have === 0) { break inf_leave; }
6628 have--;
6629 hold += input[next++] << bits;
6630 bits += 8;
6631 }
6632 //===//
6633 if (state.head) {
6634 state.head.xflags = (hold & 0xff);
6635 state.head.os = (hold >> 8);
6636 }
6637 if (state.flags & 0x0200) {
6638 //=== CRC2(state.check, hold);
6639 hbuf[0] = hold & 0xff;
6640 hbuf[1] = (hold >>> 8) & 0xff;
6641 state.check = crc32(state.check, hbuf, 2, 0);
6642 //===//
6643 }
6644 //=== INITBITS();
6645 hold = 0;
6646 bits = 0;
6647 //===//
6648 state.mode = EXLEN;
6649 /* falls through */
6650 case EXLEN:
6651 if (state.flags & 0x0400) {
6652 //=== NEEDBITS(16); */
6653 while (bits < 16) {
6654 if (have === 0) { break inf_leave; }
6655 have--;
6656 hold += input[next++] << bits;
6657 bits += 8;
6658 }
6659 //===//
6660 state.length = hold;
6661 if (state.head) {
6662 state.head.extra_len = hold;
6663 }
6664 if (state.flags & 0x0200) {
6665 //=== CRC2(state.check, hold);
6666 hbuf[0] = hold & 0xff;
6667 hbuf[1] = (hold >>> 8) & 0xff;
6668 state.check = crc32(state.check, hbuf, 2, 0);
6669 //===//
6670 }
6671 //=== INITBITS();
6672 hold = 0;
6673 bits = 0;
6674 //===//
6675 }
6676 else if (state.head) {
6677 state.head.extra = null/*Z_NULL*/;
6678 }
6679 state.mode = EXTRA;
6680 /* falls through */
6681 case EXTRA:
6682 if (state.flags & 0x0400) {
6683 copy = state.length;
6684 if (copy > have) { copy = have; }
6685 if (copy) {
6686 if (state.head) {
6687 len = state.head.extra_len - state.length;
6688 if (!state.head.extra) {
6689 // Use untyped array for more conveniend processing later
6690 state.head.extra = new Array(state.head.extra_len);
6691 }
6692 utils.arraySet(
6693 state.head.extra,
6694 input,
6695 next,
6696 // extra field is limited to 65536 bytes
6697 // - no need for additional size check
6698 copy,
6699 /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/
6700 len
6701 );
6702 //zmemcpy(state.head.extra + len, next,
6703 // len + copy > state.head.extra_max ?
6704 // state.head.extra_max - len : copy);
6705 }
6706 if (state.flags & 0x0200) {
6707 state.check = crc32(state.check, input, copy, next);
6708 }
6709 have -= copy;
6710 next += copy;
6711 state.length -= copy;
6712 }
6713 if (state.length) { break inf_leave; }
6714 }
6715 state.length = 0;
6716 state.mode = NAME;
6717 /* falls through */
6718 case NAME:
6719 if (state.flags & 0x0800) {
6720 if (have === 0) { break inf_leave; }
6721 copy = 0;
6722 do {
6723 // TODO: 2 or 1 bytes?
6724 len = input[next + copy++];
6725 /* use constant limit because in js we should not preallocate memory */
6726 if (state.head && len &&
6727 (state.length < 65536 /*state.head.name_max*/)) {
6728 state.head.name += String.fromCharCode(len);
6729 }
6730 } while (len && copy < have);
6731
6732 if (state.flags & 0x0200) {
6733 state.check = crc32(state.check, input, copy, next);
6734 }
6735 have -= copy;
6736 next += copy;
6737 if (len) { break inf_leave; }
6738 }
6739 else if (state.head) {
6740 state.head.name = null;
6741 }
6742 state.length = 0;
6743 state.mode = COMMENT;
6744 /* falls through */
6745 case COMMENT:
6746 if (state.flags & 0x1000) {
6747 if (have === 0) { break inf_leave; }
6748 copy = 0;
6749 do {
6750 len = input[next + copy++];
6751 /* use constant limit because in js we should not preallocate memory */
6752 if (state.head && len &&
6753 (state.length < 65536 /*state.head.comm_max*/)) {
6754 state.head.comment += String.fromCharCode(len);
6755 }
6756 } while (len && copy < have);
6757 if (state.flags & 0x0200) {
6758 state.check = crc32(state.check, input, copy, next);
6759 }
6760 have -= copy;
6761 next += copy;
6762 if (len) { break inf_leave; }
6763 }
6764 else if (state.head) {
6765 state.head.comment = null;
6766 }
6767 state.mode = HCRC;
6768 /* falls through */
6769 case HCRC:
6770 if (state.flags & 0x0200) {
6771 //=== NEEDBITS(16); */
6772 while (bits < 16) {
6773 if (have === 0) { break inf_leave; }
6774 have--;
6775 hold += input[next++] << bits;
6776 bits += 8;
6777 }
6778 //===//
6779 if (hold !== (state.check & 0xffff)) {
6780 strm.msg = 'header crc mismatch';
6781 state.mode = BAD;
6782 break;
6783 }
6784 //=== INITBITS();
6785 hold = 0;
6786 bits = 0;
6787 //===//
6788 }
6789 if (state.head) {
6790 state.head.hcrc = ((state.flags >> 9) & 1);
6791 state.head.done = true;
6792 }
6793 strm.adler = state.check = 0 /*crc32(0L, Z_NULL, 0)*/;
6794 state.mode = TYPE;
6795 break;
6796 case DICTID:
6797 //=== NEEDBITS(32); */
6798 while (bits < 32) {
6799 if (have === 0) { break inf_leave; }
6800 have--;
6801 hold += input[next++] << bits;
6802 bits += 8;
6803 }
6804 //===//
6805 strm.adler = state.check = ZSWAP32(hold);
6806 //=== INITBITS();
6807 hold = 0;
6808 bits = 0;
6809 //===//
6810 state.mode = DICT;
6811 /* falls through */
6812 case DICT:
6813 if (state.havedict === 0) {
6814 //--- RESTORE() ---
6815 strm.next_out = put;
6816 strm.avail_out = left;
6817 strm.next_in = next;
6818 strm.avail_in = have;
6819 state.hold = hold;
6820 state.bits = bits;
6821 //---
6822 return Z_NEED_DICT;
6823 }
6824 strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;
6825 state.mode = TYPE;
6826 /* falls through */
6827 case TYPE:
6828 if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; }
6829 /* falls through */
6830 case TYPEDO:
6831 if (state.last) {
6832 //--- BYTEBITS() ---//
6833 hold >>>= bits & 7;
6834 bits -= bits & 7;
6835 //---//
6836 state.mode = CHECK;
6837 break;
6838 }
6839 //=== NEEDBITS(3); */
6840 while (bits < 3) {
6841 if (have === 0) { break inf_leave; }
6842 have--;
6843 hold += input[next++] << bits;
6844 bits += 8;
6845 }
6846 //===//
6847 state.last = (hold & 0x01)/*BITS(1)*/;
6848 //--- DROPBITS(1) ---//
6849 hold >>>= 1;
6850 bits -= 1;
6851 //---//
6852
6853 switch ((hold & 0x03)/*BITS(2)*/) {
6854 case 0: /* stored block */
6855 //Tracev((stderr, "inflate: stored block%s\n",
6856 // state.last ? " (last)" : ""));
6857 state.mode = STORED;
6858 break;
6859 case 1: /* fixed block */
6860 fixedtables(state);
6861 //Tracev((stderr, "inflate: fixed codes block%s\n",
6862 // state.last ? " (last)" : ""));
6863 state.mode = LEN_; /* decode codes */
6864 if (flush === Z_TREES) {
6865 //--- DROPBITS(2) ---//
6866 hold >>>= 2;
6867 bits -= 2;
6868 //---//
6869 break inf_leave;
6870 }
6871 break;
6872 case 2: /* dynamic block */
6873 //Tracev((stderr, "inflate: dynamic codes block%s\n",
6874 // state.last ? " (last)" : ""));
6875 state.mode = TABLE;
6876 break;
6877 case 3:
6878 strm.msg = 'invalid block type';
6879 state.mode = BAD;
6880 }
6881 //--- DROPBITS(2) ---//
6882 hold >>>= 2;
6883 bits -= 2;
6884 //---//
6885 break;
6886 case STORED:
6887 //--- BYTEBITS() ---// /* go to byte boundary */
6888 hold >>>= bits & 7;
6889 bits -= bits & 7;
6890 //---//
6891 //=== NEEDBITS(32); */
6892 while (bits < 32) {
6893 if (have === 0) { break inf_leave; }
6894 have--;
6895 hold += input[next++] << bits;
6896 bits += 8;
6897 }
6898 //===//
6899 if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) {
6900 strm.msg = 'invalid stored block lengths';
6901 state.mode = BAD;
6902 break;
6903 }
6904 state.length = hold & 0xffff;
6905 //Tracev((stderr, "inflate: stored length %u\n",
6906 // state.length));
6907 //=== INITBITS();
6908 hold = 0;
6909 bits = 0;
6910 //===//
6911 state.mode = COPY_;
6912 if (flush === Z_TREES) { break inf_leave; }
6913 /* falls through */
6914 case COPY_:
6915 state.mode = COPY;
6916 /* falls through */
6917 case COPY:
6918 copy = state.length;
6919 if (copy) {
6920 if (copy > have) { copy = have; }
6921 if (copy > left) { copy = left; }
6922 if (copy === 0) { break inf_leave; }
6923 //--- zmemcpy(put, next, copy); ---
6924 utils.arraySet(output, input, next, copy, put);
6925 //---//
6926 have -= copy;
6927 next += copy;
6928 left -= copy;
6929 put += copy;
6930 state.length -= copy;
6931 break;
6932 }
6933 //Tracev((stderr, "inflate: stored end\n"));
6934 state.mode = TYPE;
6935 break;
6936 case TABLE:
6937 //=== NEEDBITS(14); */
6938 while (bits < 14) {
6939 if (have === 0) { break inf_leave; }
6940 have--;
6941 hold += input[next++] << bits;
6942 bits += 8;
6943 }
6944 //===//
6945 state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257;
6946 //--- DROPBITS(5) ---//
6947 hold >>>= 5;
6948 bits -= 5;
6949 //---//
6950 state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1;
6951 //--- DROPBITS(5) ---//
6952 hold >>>= 5;
6953 bits -= 5;
6954 //---//
6955 state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4;
6956 //--- DROPBITS(4) ---//
6957 hold >>>= 4;
6958 bits -= 4;
6959 //---//
6960//#ifndef PKZIP_BUG_WORKAROUND
6961 if (state.nlen > 286 || state.ndist > 30) {
6962 strm.msg = 'too many length or distance symbols';
6963 state.mode = BAD;
6964 break;
6965 }
6966//#endif
6967 //Tracev((stderr, "inflate: table sizes ok\n"));
6968 state.have = 0;
6969 state.mode = LENLENS;
6970 /* falls through */
6971 case LENLENS:
6972 while (state.have < state.ncode) {
6973 //=== NEEDBITS(3);
6974 while (bits < 3) {
6975 if (have === 0) { break inf_leave; }
6976 have--;
6977 hold += input[next++] << bits;
6978 bits += 8;
6979 }
6980 //===//
6981 state.lens[order[state.have++]] = (hold & 0x07);//BITS(3);
6982 //--- DROPBITS(3) ---//
6983 hold >>>= 3;
6984 bits -= 3;
6985 //---//
6986 }
6987 while (state.have < 19) {
6988 state.lens[order[state.have++]] = 0;
6989 }
6990 // We have separate tables & no pointers. 2 commented lines below not needed.
6991 //state.next = state.codes;
6992 //state.lencode = state.next;
6993 // Switch to use dynamic table
6994 state.lencode = state.lendyn;
6995 state.lenbits = 7;
6996
6997 opts = {bits: state.lenbits};
6998 ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts);
6999 state.lenbits = opts.bits;
7000
7001 if (ret) {
7002 strm.msg = 'invalid code lengths set';
7003 state.mode = BAD;
7004 break;
7005 }
7006 //Tracev((stderr, "inflate: code lengths ok\n"));
7007 state.have = 0;
7008 state.mode = CODELENS;
7009 /* falls through */
7010 case CODELENS:
7011 while (state.have < state.nlen + state.ndist) {
7012 for (;;) {
7013 here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/
7014 here_bits = here >>> 24;
7015 here_op = (here >>> 16) & 0xff;
7016 here_val = here & 0xffff;
7017
7018 if ((here_bits) <= bits) { break; }
7019 //--- PULLBYTE() ---//
7020 if (have === 0) { break inf_leave; }
7021 have--;
7022 hold += input[next++] << bits;
7023 bits += 8;
7024 //---//
7025 }
7026 if (here_val < 16) {
7027 //--- DROPBITS(here.bits) ---//
7028 hold >>>= here_bits;
7029 bits -= here_bits;
7030 //---//
7031 state.lens[state.have++] = here_val;
7032 }
7033 else {
7034 if (here_val === 16) {
7035 //=== NEEDBITS(here.bits + 2);
7036 n = here_bits + 2;
7037 while (bits < n) {
7038 if (have === 0) { break inf_leave; }
7039 have--;
7040 hold += input[next++] << bits;
7041 bits += 8;
7042 }
7043 //===//
7044 //--- DROPBITS(here.bits) ---//
7045 hold >>>= here_bits;
7046 bits -= here_bits;
7047 //---//
7048 if (state.have === 0) {
7049 strm.msg = 'invalid bit length repeat';
7050 state.mode = BAD;
7051 break;
7052 }
7053 len = state.lens[state.have - 1];
7054 copy = 3 + (hold & 0x03);//BITS(2);
7055 //--- DROPBITS(2) ---//
7056 hold >>>= 2;
7057 bits -= 2;
7058 //---//
7059 }
7060 else if (here_val === 17) {
7061 //=== NEEDBITS(here.bits + 3);
7062 n = here_bits + 3;
7063 while (bits < n) {
7064 if (have === 0) { break inf_leave; }
7065 have--;
7066 hold += input[next++] << bits;
7067 bits += 8;
7068 }
7069 //===//
7070 //--- DROPBITS(here.bits) ---//
7071 hold >>>= here_bits;
7072 bits -= here_bits;
7073 //---//
7074 len = 0;
7075 copy = 3 + (hold & 0x07);//BITS(3);
7076 //--- DROPBITS(3) ---//
7077 hold >>>= 3;
7078 bits -= 3;
7079 //---//
7080 }
7081 else {
7082 //=== NEEDBITS(here.bits + 7);
7083 n = here_bits + 7;
7084 while (bits < n) {
7085 if (have === 0) { break inf_leave; }
7086 have--;
7087 hold += input[next++] << bits;
7088 bits += 8;
7089 }
7090 //===//
7091 //--- DROPBITS(here.bits) ---//
7092 hold >>>= here_bits;
7093 bits -= here_bits;
7094 //---//
7095 len = 0;
7096 copy = 11 + (hold & 0x7f);//BITS(7);
7097 //--- DROPBITS(7) ---//
7098 hold >>>= 7;
7099 bits -= 7;
7100 //---//
7101 }
7102 if (state.have + copy > state.nlen + state.ndist) {
7103 strm.msg = 'invalid bit length repeat';
7104 state.mode = BAD;
7105 break;
7106 }
7107 while (copy--) {
7108 state.lens[state.have++] = len;
7109 }
7110 }
7111 }
7112
7113 /* handle error breaks in while */
7114 if (state.mode === BAD) { break; }
7115
7116 /* check for end-of-block code (better have one) */
7117 if (state.lens[256] === 0) {
7118 strm.msg = 'invalid code -- missing end-of-block';
7119 state.mode = BAD;
7120 break;
7121 }
7122
7123 /* build code tables -- note: do not change the lenbits or distbits
7124 values here (9 and 6) without reading the comments in inftrees.h
7125 concerning the ENOUGH constants, which depend on those values */
7126 state.lenbits = 9;
7127
7128 opts = {bits: state.lenbits};
7129 ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);
7130 // We have separate tables & no pointers. 2 commented lines below not needed.
7131 // state.next_index = opts.table_index;
7132 state.lenbits = opts.bits;
7133 // state.lencode = state.next;
7134
7135 if (ret) {
7136 strm.msg = 'invalid literal/lengths set';
7137 state.mode = BAD;
7138 break;
7139 }
7140
7141 state.distbits = 6;
7142 //state.distcode.copy(state.codes);
7143 // Switch to use dynamic table
7144 state.distcode = state.distdyn;
7145 opts = {bits: state.distbits};
7146 ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);
7147 // We have separate tables & no pointers. 2 commented lines below not needed.
7148 // state.next_index = opts.table_index;
7149 state.distbits = opts.bits;
7150 // state.distcode = state.next;
7151
7152 if (ret) {
7153 strm.msg = 'invalid distances set';
7154 state.mode = BAD;
7155 break;
7156 }
7157 //Tracev((stderr, 'inflate: codes ok\n'));
7158 state.mode = LEN_;
7159 if (flush === Z_TREES) { break inf_leave; }
7160 /* falls through */
7161 case LEN_:
7162 state.mode = LEN;
7163 /* falls through */
7164 case LEN:
7165 if (have >= 6 && left >= 258) {
7166 //--- RESTORE() ---
7167 strm.next_out = put;
7168 strm.avail_out = left;
7169 strm.next_in = next;
7170 strm.avail_in = have;
7171 state.hold = hold;
7172 state.bits = bits;
7173 //---
7174 inflate_fast(strm, _out);
7175 //--- LOAD() ---
7176 put = strm.next_out;
7177 output = strm.output;
7178 left = strm.avail_out;
7179 next = strm.next_in;
7180 input = strm.input;
7181 have = strm.avail_in;
7182 hold = state.hold;
7183 bits = state.bits;
7184 //---
7185
7186 if (state.mode === TYPE) {
7187 state.back = -1;
7188 }
7189 break;
7190 }
7191 state.back = 0;
7192 for (;;) {
7193 here = state.lencode[hold & ((1 << state.lenbits) -1)]; /*BITS(state.lenbits)*/
7194 here_bits = here >>> 24;
7195 here_op = (here >>> 16) & 0xff;
7196 here_val = here & 0xffff;
7197
7198 if (here_bits <= bits) { break; }
7199 //--- PULLBYTE() ---//
7200 if (have === 0) { break inf_leave; }
7201 have--;
7202 hold += input[next++] << bits;
7203 bits += 8;
7204 //---//
7205 }
7206 if (here_op && (here_op & 0xf0) === 0) {
7207 last_bits = here_bits;
7208 last_op = here_op;
7209 last_val = here_val;
7210 for (;;) {
7211 here = state.lencode[last_val +
7212 ((hold & ((1 << (last_bits + last_op)) -1))/*BITS(last.bits + last.op)*/ >> last_bits)];
7213 here_bits = here >>> 24;
7214 here_op = (here >>> 16) & 0xff;
7215 here_val = here & 0xffff;
7216
7217 if ((last_bits + here_bits) <= bits) { break; }
7218 //--- PULLBYTE() ---//
7219 if (have === 0) { break inf_leave; }
7220 have--;
7221 hold += input[next++] << bits;
7222 bits += 8;
7223 //---//
7224 }
7225 //--- DROPBITS(last.bits) ---//
7226 hold >>>= last_bits;
7227 bits -= last_bits;
7228 //---//
7229 state.back += last_bits;
7230 }
7231 //--- DROPBITS(here.bits) ---//
7232 hold >>>= here_bits;
7233 bits -= here_bits;
7234 //---//
7235 state.back += here_bits;
7236 state.length = here_val;
7237 if (here_op === 0) {
7238 //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
7239 // "inflate: literal '%c'\n" :
7240 // "inflate: literal 0x%02x\n", here.val));
7241 state.mode = LIT;
7242 break;
7243 }
7244 if (here_op & 32) {
7245 //Tracevv((stderr, "inflate: end of block\n"));
7246 state.back = -1;
7247 state.mode = TYPE;
7248 break;
7249 }
7250 if (here_op & 64) {
7251 strm.msg = 'invalid literal/length code';
7252 state.mode = BAD;
7253 break;
7254 }
7255 state.extra = here_op & 15;
7256 state.mode = LENEXT;
7257 /* falls through */
7258 case LENEXT:
7259 if (state.extra) {
7260 //=== NEEDBITS(state.extra);
7261 n = state.extra;
7262 while (bits < n) {
7263 if (have === 0) { break inf_leave; }
7264 have--;
7265 hold += input[next++] << bits;
7266 bits += 8;
7267 }
7268 //===//
7269 state.length += hold & ((1 << state.extra) -1)/*BITS(state.extra)*/;
7270 //--- DROPBITS(state.extra) ---//
7271 hold >>>= state.extra;
7272 bits -= state.extra;
7273 //---//
7274 state.back += state.extra;
7275 }
7276 //Tracevv((stderr, "inflate: length %u\n", state.length));
7277 state.was = state.length;
7278 state.mode = DIST;
7279 /* falls through */
7280 case DIST:
7281 for (;;) {
7282 here = state.distcode[hold & ((1 << state.distbits) -1)];/*BITS(state.distbits)*/
7283 here_bits = here >>> 24;
7284 here_op = (here >>> 16) & 0xff;
7285 here_val = here & 0xffff;
7286
7287 if ((here_bits) <= bits) { break; }
7288 //--- PULLBYTE() ---//
7289 if (have === 0) { break inf_leave; }
7290 have--;
7291 hold += input[next++] << bits;
7292 bits += 8;
7293 //---//
7294 }
7295 if ((here_op & 0xf0) === 0) {
7296 last_bits = here_bits;
7297 last_op = here_op;
7298 last_val = here_val;
7299 for (;;) {
7300 here = state.distcode[last_val +
7301 ((hold & ((1 << (last_bits + last_op)) -1))/*BITS(last.bits + last.op)*/ >> last_bits)];
7302 here_bits = here >>> 24;
7303 here_op = (here >>> 16) & 0xff;
7304 here_val = here & 0xffff;
7305
7306 if ((last_bits + here_bits) <= bits) { break; }
7307 //--- PULLBYTE() ---//
7308 if (have === 0) { break inf_leave; }
7309 have--;
7310 hold += input[next++] << bits;
7311 bits += 8;
7312 //---//
7313 }
7314 //--- DROPBITS(last.bits) ---//
7315 hold >>>= last_bits;
7316 bits -= last_bits;
7317 //---//
7318 state.back += last_bits;
7319 }
7320 //--- DROPBITS(here.bits) ---//
7321 hold >>>= here_bits;
7322 bits -= here_bits;
7323 //---//
7324 state.back += here_bits;
7325 if (here_op & 64) {
7326 strm.msg = 'invalid distance code';
7327 state.mode = BAD;
7328 break;
7329 }
7330 state.offset = here_val;
7331 state.extra = (here_op) & 15;
7332 state.mode = DISTEXT;
7333 /* falls through */
7334 case DISTEXT:
7335 if (state.extra) {
7336 //=== NEEDBITS(state.extra);
7337 n = state.extra;
7338 while (bits < n) {
7339 if (have === 0) { break inf_leave; }
7340 have--;
7341 hold += input[next++] << bits;
7342 bits += 8;
7343 }
7344 //===//
7345 state.offset += hold & ((1 << state.extra) -1)/*BITS(state.extra)*/;
7346 //--- DROPBITS(state.extra) ---//
7347 hold >>>= state.extra;
7348 bits -= state.extra;
7349 //---//
7350 state.back += state.extra;
7351 }
7352//#ifdef INFLATE_STRICT
7353 if (state.offset > state.dmax) {
7354 strm.msg = 'invalid distance too far back';
7355 state.mode = BAD;
7356 break;
7357 }
7358//#endif
7359 //Tracevv((stderr, "inflate: distance %u\n", state.offset));
7360 state.mode = MATCH;
7361 /* falls through */
7362 case MATCH:
7363 if (left === 0) { break inf_leave; }
7364 copy = _out - left;
7365 if (state.offset > copy) { /* copy from window */
7366 copy = state.offset - copy;
7367 if (copy > state.whave) {
7368 if (state.sane) {
7369 strm.msg = 'invalid distance too far back';
7370 state.mode = BAD;
7371 break;
7372 }
7373// (!) This block is disabled in zlib defailts,
7374// don't enable it for binary compatibility
7375//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
7376// Trace((stderr, "inflate.c too far\n"));
7377// copy -= state.whave;
7378// if (copy > state.length) { copy = state.length; }
7379// if (copy > left) { copy = left; }
7380// left -= copy;
7381// state.length -= copy;
7382// do {
7383// output[put++] = 0;
7384// } while (--copy);
7385// if (state.length === 0) { state.mode = LEN; }
7386// break;
7387//#endif
7388 }
7389 if (copy > state.wnext) {
7390 copy -= state.wnext;
7391 from = state.wsize - copy;
7392 }
7393 else {
7394 from = state.wnext - copy;
7395 }
7396 if (copy > state.length) { copy = state.length; }
7397 from_source = state.window;
7398 }
7399 else { /* copy from output */
7400 from_source = output;
7401 from = put - state.offset;
7402 copy = state.length;
7403 }
7404 if (copy > left) { copy = left; }
7405 left -= copy;
7406 state.length -= copy;
7407 do {
7408 output[put++] = from_source[from++];
7409 } while (--copy);
7410 if (state.length === 0) { state.mode = LEN; }
7411 break;
7412 case LIT:
7413 if (left === 0) { break inf_leave; }
7414 output[put++] = state.length;
7415 left--;
7416 state.mode = LEN;
7417 break;
7418 case CHECK:
7419 if (state.wrap) {
7420 //=== NEEDBITS(32);
7421 while (bits < 32) {
7422 if (have === 0) { break inf_leave; }
7423 have--;
7424 // Use '|' insdead of '+' to make sure that result is signed
7425 hold |= input[next++] << bits;
7426 bits += 8;
7427 }
7428 //===//
7429 _out -= left;
7430 strm.total_out += _out;
7431 state.total += _out;
7432 if (_out) {
7433 strm.adler = state.check =
7434 /*UPDATE(state.check, put - _out, _out);*/
7435 (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out));
7436
7437 }
7438 _out = left;
7439 // NB: crc32 stored as signed 32-bit int, ZSWAP32 returns signed too
7440 if ((state.flags ? hold : ZSWAP32(hold)) !== state.check) {
7441 strm.msg = 'incorrect data check';
7442 state.mode = BAD;
7443 break;
7444 }
7445 //=== INITBITS();
7446 hold = 0;
7447 bits = 0;
7448 //===//
7449 //Tracev((stderr, "inflate: check matches trailer\n"));
7450 }
7451 state.mode = LENGTH;
7452 /* falls through */
7453 case LENGTH:
7454 if (state.wrap && state.flags) {
7455 //=== NEEDBITS(32);
7456 while (bits < 32) {
7457 if (have === 0) { break inf_leave; }
7458 have--;
7459 hold += input[next++] << bits;
7460 bits += 8;
7461 }
7462 //===//
7463 if (hold !== (state.total & 0xffffffff)) {
7464 strm.msg = 'incorrect length check';
7465 state.mode = BAD;
7466 break;
7467 }
7468 //=== INITBITS();
7469 hold = 0;
7470 bits = 0;
7471 //===//
7472 //Tracev((stderr, "inflate: length matches trailer\n"));
7473 }
7474 state.mode = DONE;
7475 /* falls through */
7476 case DONE:
7477 ret = Z_STREAM_END;
7478 break inf_leave;
7479 case BAD:
7480 ret = Z_DATA_ERROR;
7481 break inf_leave;
7482 case MEM:
7483 return Z_MEM_ERROR;
7484 case SYNC:
7485 /* falls through */
7486 default:
7487 return Z_STREAM_ERROR;
7488 }
7489 }
7490
7491 // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave"
7492
7493 /*
7494 Return from inflate(), updating the total counts and the check value.
7495 If there was no progress during the inflate() call, return a buffer
7496 error. Call updatewindow() to create and/or update the window state.
7497 Note: a memory error from inflate() is non-recoverable.
7498 */
7499
7500 //--- RESTORE() ---
7501 strm.next_out = put;
7502 strm.avail_out = left;
7503 strm.next_in = next;
7504 strm.avail_in = have;
7505 state.hold = hold;
7506 state.bits = bits;
7507 //---
7508
7509 if (state.wsize || (_out !== strm.avail_out && state.mode < BAD &&
7510 (state.mode < CHECK || flush !== Z_FINISH))) {
7511 if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) {
7512 state.mode = MEM;
7513 return Z_MEM_ERROR;
7514 }
7515 }
7516 _in -= strm.avail_in;
7517 _out -= strm.avail_out;
7518 strm.total_in += _in;
7519 strm.total_out += _out;
7520 state.total += _out;
7521 if (state.wrap && _out) {
7522 strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/
7523 (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out));
7524 }
7525 strm.data_type = state.bits + (state.last ? 64 : 0) +
7526 (state.mode === TYPE ? 128 : 0) +
7527 (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0);
7528 if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) {
7529 ret = Z_BUF_ERROR;
7530 }
7531 return ret;
7532}
7533
7534function inflateEnd(strm) {
7535
7536 if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) {
7537 return Z_STREAM_ERROR;
7538 }
7539
7540 var state = strm.state;
7541 if (state.window) {
7542 state.window = null;
7543 }
7544 strm.state = null;
7545 return Z_OK;
7546}
7547
7548function inflateGetHeader(strm, head) {
7549 var state;
7550
7551 /* check state */
7552 if (!strm || !strm.state) { return Z_STREAM_ERROR; }
7553 state = strm.state;
7554 if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; }
7555
7556 /* save header structure */
7557 state.head = head;
7558 head.done = false;
7559 return Z_OK;
7560}
7561
7562
7563exports.inflateReset = inflateReset;
7564exports.inflateReset2 = inflateReset2;
7565exports.inflateResetKeep = inflateResetKeep;
7566exports.inflateInit = inflateInit;
7567exports.inflateInit2 = inflateInit2;
7568exports.inflate = inflate;
7569exports.inflateEnd = inflateEnd;
7570exports.inflateGetHeader = inflateGetHeader;
7571exports.inflateInfo = 'pako inflate (from Nodeca project)';
7572
7573/* Not implemented
7574exports.inflateCopy = inflateCopy;
7575exports.inflateGetDictionary = inflateGetDictionary;
7576exports.inflateMark = inflateMark;
7577exports.inflatePrime = inflatePrime;
7578exports.inflateSetDictionary = inflateSetDictionary;
7579exports.inflateSync = inflateSync;
7580exports.inflateSyncPoint = inflateSyncPoint;
7581exports.inflateUndermine = inflateUndermine;
7582*/
7583},{"../utils/common":27,"./adler32":29,"./crc32":31,"./inffast":34,"./inftrees":36}],36:[function(_dereq_,module,exports){
7584'use strict';
7585
7586
7587var utils = _dereq_('../utils/common');
7588
7589var MAXBITS = 15;
7590var ENOUGH_LENS = 852;
7591var ENOUGH_DISTS = 592;
7592//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);
7593
7594var CODES = 0;
7595var LENS = 1;
7596var DISTS = 2;
7597
7598var lbase = [ /* Length codes 257..285 base */
7599 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
7600 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
7601];
7602
7603var lext = [ /* Length codes 257..285 extra */
7604 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
7605 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78
7606];
7607
7608var dbase = [ /* Distance codes 0..29 base */
7609 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
7610 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
7611 8193, 12289, 16385, 24577, 0, 0
7612];
7613
7614var dext = [ /* Distance codes 0..29 extra */
7615 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
7616 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
7617 28, 28, 29, 29, 64, 64
7618];
7619
7620module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts)
7621{
7622 var bits = opts.bits;
7623 //here = opts.here; /* table entry for duplication */
7624
7625 var len = 0; /* a code's length in bits */
7626 var sym = 0; /* index of code symbols */
7627 var min = 0, max = 0; /* minimum and maximum code lengths */
7628 var root = 0; /* number of index bits for root table */
7629 var curr = 0; /* number of index bits for current table */
7630 var drop = 0; /* code bits to drop for sub-table */
7631 var left = 0; /* number of prefix codes available */
7632 var used = 0; /* code entries in table used */
7633 var huff = 0; /* Huffman code */
7634 var incr; /* for incrementing code, index */
7635 var fill; /* index for replicating entries */
7636 var low; /* low bits for current root entry */
7637 var mask; /* mask for low root bits */
7638 var next; /* next available space in table */
7639 var base = null; /* base value table to use */
7640 var base_index = 0;
7641// var shoextra; /* extra bits table to use */
7642 var end; /* use base and extra for symbol > end */
7643 var count = new utils.Buf16(MAXBITS+1); //[MAXBITS+1]; /* number of codes of each length */
7644 var offs = new utils.Buf16(MAXBITS+1); //[MAXBITS+1]; /* offsets in table for each length */
7645 var extra = null;
7646 var extra_index = 0;
7647
7648 var here_bits, here_op, here_val;
7649
7650 /*
7651 Process a set of code lengths to create a canonical Huffman code. The
7652 code lengths are lens[0..codes-1]. Each length corresponds to the
7653 symbols 0..codes-1. The Huffman code is generated by first sorting the
7654 symbols by length from short to long, and retaining the symbol order
7655 for codes with equal lengths. Then the code starts with all zero bits
7656 for the first code of the shortest length, and the codes are integer
7657 increments for the same length, and zeros are appended as the length
7658 increases. For the deflate format, these bits are stored backwards
7659 from their more natural integer increment ordering, and so when the
7660 decoding tables are built in the large loop below, the integer codes
7661 are incremented backwards.
7662
7663 This routine assumes, but does not check, that all of the entries in
7664 lens[] are in the range 0..MAXBITS. The caller must assure this.
7665 1..MAXBITS is interpreted as that code length. zero means that that
7666 symbol does not occur in this code.
7667
7668 The codes are sorted by computing a count of codes for each length,
7669 creating from that a table of starting indices for each length in the
7670 sorted table, and then entering the symbols in order in the sorted
7671 table. The sorted table is work[], with that space being provided by
7672 the caller.
7673
7674 The length counts are used for other purposes as well, i.e. finding
7675 the minimum and maximum length codes, determining if there are any
7676 codes at all, checking for a valid set of lengths, and looking ahead
7677 at length counts to determine sub-table sizes when building the
7678 decoding tables.
7679 */
7680
7681 /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
7682 for (len = 0; len <= MAXBITS; len++) {
7683 count[len] = 0;
7684 }
7685 for (sym = 0; sym < codes; sym++) {
7686 count[lens[lens_index + sym]]++;
7687 }
7688
7689 /* bound code lengths, force root to be within code lengths */
7690 root = bits;
7691 for (max = MAXBITS; max >= 1; max--) {
7692 if (count[max] !== 0) { break; }
7693 }
7694 if (root > max) {
7695 root = max;
7696 }
7697 if (max === 0) { /* no symbols to code at all */
7698 //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */
7699 //table.bits[opts.table_index] = 1; //here.bits = (var char)1;
7700 //table.val[opts.table_index++] = 0; //here.val = (var short)0;
7701 table[table_index++] = (1 << 24) | (64 << 16) | 0;
7702
7703
7704 //table.op[opts.table_index] = 64;
7705 //table.bits[opts.table_index] = 1;
7706 //table.val[opts.table_index++] = 0;
7707 table[table_index++] = (1 << 24) | (64 << 16) | 0;
7708
7709 opts.bits = 1;
7710 return 0; /* no symbols, but wait for decoding to report error */
7711 }
7712 for (min = 1; min < max; min++) {
7713 if (count[min] !== 0) { break; }
7714 }
7715 if (root < min) {
7716 root = min;
7717 }
7718
7719 /* check for an over-subscribed or incomplete set of lengths */
7720 left = 1;
7721 for (len = 1; len <= MAXBITS; len++) {
7722 left <<= 1;
7723 left -= count[len];
7724 if (left < 0) {
7725 return -1;
7726 } /* over-subscribed */
7727 }
7728 if (left > 0 && (type === CODES || max !== 1)) {
7729 return -1; /* incomplete set */
7730 }
7731
7732 /* generate offsets into symbol table for each length for sorting */
7733 offs[1] = 0;
7734 for (len = 1; len < MAXBITS; len++) {
7735 offs[len + 1] = offs[len] + count[len];
7736 }
7737
7738 /* sort symbols by length, by symbol order within each length */
7739 for (sym = 0; sym < codes; sym++) {
7740 if (lens[lens_index + sym] !== 0) {
7741 work[offs[lens[lens_index + sym]]++] = sym;
7742 }
7743 }
7744
7745 /*
7746 Create and fill in decoding tables. In this loop, the table being
7747 filled is at next and has curr index bits. The code being used is huff
7748 with length len. That code is converted to an index by dropping drop
7749 bits off of the bottom. For codes where len is less than drop + curr,
7750 those top drop + curr - len bits are incremented through all values to
7751 fill the table with replicated entries.
7752
7753 root is the number of index bits for the root table. When len exceeds
7754 root, sub-tables are created pointed to by the root entry with an index
7755 of the low root bits of huff. This is saved in low to check for when a
7756 new sub-table should be started. drop is zero when the root table is
7757 being filled, and drop is root when sub-tables are being filled.
7758
7759 When a new sub-table is needed, it is necessary to look ahead in the
7760 code lengths to determine what size sub-table is needed. The length
7761 counts are used for this, and so count[] is decremented as codes are
7762 entered in the tables.
7763
7764 used keeps track of how many table entries have been allocated from the
7765 provided *table space. It is checked for LENS and DIST tables against
7766 the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
7767 the initial root table size constants. See the comments in inftrees.h
7768 for more information.
7769
7770 sym increments through all symbols, and the loop terminates when
7771 all codes of length max, i.e. all codes, have been processed. This
7772 routine permits incomplete codes, so another loop after this one fills
7773 in the rest of the decoding tables with invalid code markers.
7774 */
7775
7776 /* set up for code type */
7777 // poor man optimization - use if-else instead of switch,
7778 // to avoid deopts in old v8
7779 if (type === CODES) {
7780 base = extra = work; /* dummy value--not used */
7781 end = 19;
7782 } else if (type === LENS) {
7783 base = lbase;
7784 base_index -= 257;
7785 extra = lext;
7786 extra_index -= 257;
7787 end = 256;
7788 } else { /* DISTS */
7789 base = dbase;
7790 extra = dext;
7791 end = -1;
7792 }
7793
7794 /* initialize opts for loop */
7795 huff = 0; /* starting code */
7796 sym = 0; /* starting code symbol */
7797 len = min; /* starting code length */
7798 next = table_index; /* current table to fill in */
7799 curr = root; /* current table index bits */
7800 drop = 0; /* current bits to drop from code for index */
7801 low = -1; /* trigger new sub-table when len > root */
7802 used = 1 << root; /* use root table entries */
7803 mask = used - 1; /* mask for comparing low */
7804
7805 /* check available table space */
7806 if ((type === LENS && used > ENOUGH_LENS) ||
7807 (type === DISTS && used > ENOUGH_DISTS)) {
7808 return 1;
7809 }
7810
7811 var i=0;
7812 /* process all codes and make table entries */
7813 for (;;) {
7814 i++;
7815 /* create table entry */
7816 here_bits = len - drop;
7817 if (work[sym] < end) {
7818 here_op = 0;
7819 here_val = work[sym];
7820 }
7821 else if (work[sym] > end) {
7822 here_op = extra[extra_index + work[sym]];
7823 here_val = base[base_index + work[sym]];
7824 }
7825 else {
7826 here_op = 32 + 64; /* end of block */
7827 here_val = 0;
7828 }
7829
7830 /* replicate for those indices with low len bits equal to huff */
7831 incr = 1 << (len - drop);
7832 fill = 1 << curr;
7833 min = fill; /* save offset to next table */
7834 do {
7835 fill -= incr;
7836 table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0;
7837 } while (fill !== 0);
7838
7839 /* backwards increment the len-bit code huff */
7840 incr = 1 << (len - 1);
7841 while (huff & incr) {
7842 incr >>= 1;
7843 }
7844 if (incr !== 0) {
7845 huff &= incr - 1;
7846 huff += incr;
7847 } else {
7848 huff = 0;
7849 }
7850
7851 /* go to next symbol, update count, len */
7852 sym++;
7853 if (--count[len] === 0) {
7854 if (len === max) { break; }
7855 len = lens[lens_index + work[sym]];
7856 }
7857
7858 /* create new sub-table if needed */
7859 if (len > root && (huff & mask) !== low) {
7860 /* if first time, transition to sub-tables */
7861 if (drop === 0) {
7862 drop = root;
7863 }
7864
7865 /* increment past last table */
7866 next += min; /* here min is 1 << curr */
7867
7868 /* determine length of next table */
7869 curr = len - drop;
7870 left = 1 << curr;
7871 while (curr + drop < max) {
7872 left -= count[curr + drop];
7873 if (left <= 0) { break; }
7874 curr++;
7875 left <<= 1;
7876 }
7877
7878 /* check for enough space */
7879 used += 1 << curr;
7880 if ((type === LENS && used > ENOUGH_LENS) ||
7881 (type === DISTS && used > ENOUGH_DISTS)) {
7882 return 1;
7883 }
7884
7885 /* point entry in root table to sub-table */
7886 low = huff & mask;
7887 /*table.op[low] = curr;
7888 table.bits[low] = root;
7889 table.val[low] = next - opts.table_index;*/
7890 table[low] = (root << 24) | (curr << 16) | (next - table_index) |0;
7891 }
7892 }
7893
7894 /* fill in remaining table entry if code is incomplete (guaranteed to have
7895 at most one remaining entry, since if the code is incomplete, the
7896 maximum code length that was allowed to get this far is one bit) */
7897 if (huff !== 0) {
7898 //table.op[next + huff] = 64; /* invalid code marker */
7899 //table.bits[next + huff] = len - drop;
7900 //table.val[next + huff] = 0;
7901 table[next + huff] = ((len - drop) << 24) | (64 << 16) |0;
7902 }
7903
7904 /* set return parameters */
7905 //opts.table_index += used;
7906 opts.bits = root;
7907 return 0;
7908};
7909
7910},{"../utils/common":27}],37:[function(_dereq_,module,exports){
7911'use strict';
7912
7913module.exports = {
7914 '2': 'need dictionary', /* Z_NEED_DICT 2 */
7915 '1': 'stream end', /* Z_STREAM_END 1 */
7916 '0': '', /* Z_OK 0 */
7917 '-1': 'file error', /* Z_ERRNO (-1) */
7918 '-2': 'stream error', /* Z_STREAM_ERROR (-2) */
7919 '-3': 'data error', /* Z_DATA_ERROR (-3) */
7920 '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */
7921 '-5': 'buffer error', /* Z_BUF_ERROR (-5) */
7922 '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */
7923};
7924},{}],38:[function(_dereq_,module,exports){
7925'use strict';
7926
7927
7928var utils = _dereq_('../utils/common');
7929
7930/* Public constants ==========================================================*/
7931/* ===========================================================================*/
7932
7933
7934//var Z_FILTERED = 1;
7935//var Z_HUFFMAN_ONLY = 2;
7936//var Z_RLE = 3;
7937var Z_FIXED = 4;
7938//var Z_DEFAULT_STRATEGY = 0;
7939
7940/* Possible values of the data_type field (though see inflate()) */
7941var Z_BINARY = 0;
7942var Z_TEXT = 1;
7943//var Z_ASCII = 1; // = Z_TEXT
7944var Z_UNKNOWN = 2;
7945
7946/*============================================================================*/
7947
7948
7949function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } }
7950
7951// From zutil.h
7952
7953var STORED_BLOCK = 0;
7954var STATIC_TREES = 1;
7955var DYN_TREES = 2;
7956/* The three kinds of block type */
7957
7958var MIN_MATCH = 3;
7959var MAX_MATCH = 258;
7960/* The minimum and maximum match lengths */
7961
7962// From deflate.h
7963/* ===========================================================================
7964 * Internal compression state.
7965 */
7966
7967var LENGTH_CODES = 29;
7968/* number of length codes, not counting the special END_BLOCK code */
7969
7970var LITERALS = 256;
7971/* number of literal bytes 0..255 */
7972
7973var L_CODES = LITERALS + 1 + LENGTH_CODES;
7974/* number of Literal or Length codes, including the END_BLOCK code */
7975
7976var D_CODES = 30;
7977/* number of distance codes */
7978
7979var BL_CODES = 19;
7980/* number of codes used to transfer the bit lengths */
7981
7982var HEAP_SIZE = 2*L_CODES + 1;
7983/* maximum heap size */
7984
7985var MAX_BITS = 15;
7986/* All codes must not exceed MAX_BITS bits */
7987
7988var Buf_size = 16;
7989/* size of bit buffer in bi_buf */
7990
7991
7992/* ===========================================================================
7993 * Constants
7994 */
7995
7996var MAX_BL_BITS = 7;
7997/* Bit length codes must not exceed MAX_BL_BITS bits */
7998
7999var END_BLOCK = 256;
8000/* end of block literal code */
8001
8002var REP_3_6 = 16;
8003/* repeat previous bit length 3-6 times (2 bits of repeat count) */
8004
8005var REPZ_3_10 = 17;
8006/* repeat a zero length 3-10 times (3 bits of repeat count) */
8007
8008var REPZ_11_138 = 18;
8009/* repeat a zero length 11-138 times (7 bits of repeat count) */
8010
8011var extra_lbits = /* extra bits for each length code */
8012 [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0];
8013
8014var extra_dbits = /* extra bits for each distance code */
8015 [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13];
8016
8017var extra_blbits = /* extra bits for each bit length code */
8018 [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7];
8019
8020var bl_order =
8021 [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];
8022/* The lengths of the bit length codes are sent in order of decreasing
8023 * probability, to avoid transmitting the lengths for unused bit length codes.
8024 */
8025
8026/* ===========================================================================
8027 * Local data. These are initialized only once.
8028 */
8029
8030// We pre-fill arrays with 0 to avoid uninitialized gaps
8031
8032var DIST_CODE_LEN = 512; /* see definition of array dist_code below */
8033
8034// !!!! Use flat array insdead of structure, Freq = i*2, Len = i*2+1
8035var static_ltree = new Array((L_CODES+2) * 2);
8036zero(static_ltree);
8037/* The static literal tree. Since the bit lengths are imposed, there is no
8038 * need for the L_CODES extra codes used during heap construction. However
8039 * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
8040 * below).
8041 */
8042
8043var static_dtree = new Array(D_CODES * 2);
8044zero(static_dtree);
8045/* The static distance tree. (Actually a trivial tree since all codes use
8046 * 5 bits.)
8047 */
8048
8049var _dist_code = new Array(DIST_CODE_LEN);
8050zero(_dist_code);
8051/* Distance codes. The first 256 values correspond to the distances
8052 * 3 .. 258, the last 256 values correspond to the top 8 bits of
8053 * the 15 bit distances.
8054 */
8055
8056var _length_code = new Array(MAX_MATCH-MIN_MATCH+1);
8057zero(_length_code);
8058/* length code for each normalized match length (0 == MIN_MATCH) */
8059
8060var base_length = new Array(LENGTH_CODES);
8061zero(base_length);
8062/* First normalized length for each code (0 = MIN_MATCH) */
8063
8064var base_dist = new Array(D_CODES);
8065zero(base_dist);
8066/* First normalized distance for each code (0 = distance of 1) */
8067
8068
8069var StaticTreeDesc = function (static_tree, extra_bits, extra_base, elems, max_length) {
8070
8071 this.static_tree = static_tree; /* static tree or NULL */
8072 this.extra_bits = extra_bits; /* extra bits for each code or NULL */
8073 this.extra_base = extra_base; /* base index for extra_bits */
8074 this.elems = elems; /* max number of elements in the tree */
8075 this.max_length = max_length; /* max bit length for the codes */
8076
8077 // show if `static_tree` has data or dummy - needed for monomorphic objects
8078 this.has_stree = static_tree && static_tree.length;
8079};
8080
8081
8082var static_l_desc;
8083var static_d_desc;
8084var static_bl_desc;
8085
8086
8087var TreeDesc = function(dyn_tree, stat_desc) {
8088 this.dyn_tree = dyn_tree; /* the dynamic tree */
8089 this.max_code = 0; /* largest code with non zero frequency */
8090 this.stat_desc = stat_desc; /* the corresponding static tree */
8091};
8092
8093
8094
8095function d_code(dist) {
8096 return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)];
8097}
8098
8099
8100/* ===========================================================================
8101 * Output a short LSB first on the stream.
8102 * IN assertion: there is enough room in pendingBuf.
8103 */
8104function put_short (s, w) {
8105// put_byte(s, (uch)((w) & 0xff));
8106// put_byte(s, (uch)((ush)(w) >> 8));
8107 s.pending_buf[s.pending++] = (w) & 0xff;
8108 s.pending_buf[s.pending++] = (w >>> 8) & 0xff;
8109}
8110
8111
8112/* ===========================================================================
8113 * Send a value on a given number of bits.
8114 * IN assertion: length <= 16 and value fits in length bits.
8115 */
8116function send_bits(s, value, length) {
8117 if (s.bi_valid > (Buf_size - length)) {
8118 s.bi_buf |= (value << s.bi_valid) & 0xffff;
8119 put_short(s, s.bi_buf);
8120 s.bi_buf = value >> (Buf_size - s.bi_valid);
8121 s.bi_valid += length - Buf_size;
8122 } else {
8123 s.bi_buf |= (value << s.bi_valid) & 0xffff;
8124 s.bi_valid += length;
8125 }
8126}
8127
8128
8129function send_code(s, c, tree) {
8130 send_bits(s, tree[c*2]/*.Code*/, tree[c*2 + 1]/*.Len*/);
8131}
8132
8133
8134/* ===========================================================================
8135 * Reverse the first len bits of a code, using straightforward code (a faster
8136 * method would use a table)
8137 * IN assertion: 1 <= len <= 15
8138 */
8139function bi_reverse(code, len) {
8140 var res = 0;
8141 do {
8142 res |= code & 1;
8143 code >>>= 1;
8144 res <<= 1;
8145 } while (--len > 0);
8146 return res >>> 1;
8147}
8148
8149
8150/* ===========================================================================
8151 * Flush the bit buffer, keeping at most 7 bits in it.
8152 */
8153function bi_flush(s) {
8154 if (s.bi_valid === 16) {
8155 put_short(s, s.bi_buf);
8156 s.bi_buf = 0;
8157 s.bi_valid = 0;
8158
8159 } else if (s.bi_valid >= 8) {
8160 s.pending_buf[s.pending++] = s.bi_buf & 0xff;
8161 s.bi_buf >>= 8;
8162 s.bi_valid -= 8;
8163 }
8164}
8165
8166
8167/* ===========================================================================
8168 * Compute the optimal bit lengths for a tree and update the total bit length
8169 * for the current block.
8170 * IN assertion: the fields freq and dad are set, heap[heap_max] and
8171 * above are the tree nodes sorted by increasing frequency.
8172 * OUT assertions: the field len is set to the optimal bit length, the
8173 * array bl_count contains the frequencies for each bit length.
8174 * The length opt_len is updated; static_len is also updated if stree is
8175 * not null.
8176 */
8177function gen_bitlen(s, desc)
8178// deflate_state *s;
8179// tree_desc *desc; /* the tree descriptor */
8180{
8181 var tree = desc.dyn_tree;
8182 var max_code = desc.max_code;
8183 var stree = desc.stat_desc.static_tree;
8184 var has_stree = desc.stat_desc.has_stree;
8185 var extra = desc.stat_desc.extra_bits;
8186 var base = desc.stat_desc.extra_base;
8187 var max_length = desc.stat_desc.max_length;
8188 var h; /* heap index */
8189 var n, m; /* iterate over the tree elements */
8190 var bits; /* bit length */
8191 var xbits; /* extra bits */
8192 var f; /* frequency */
8193 var overflow = 0; /* number of elements with bit length too large */
8194
8195 for (bits = 0; bits <= MAX_BITS; bits++) {
8196 s.bl_count[bits] = 0;
8197 }
8198
8199 /* In a first pass, compute the optimal bit lengths (which may
8200 * overflow in the case of the bit length tree).
8201 */
8202 tree[s.heap[s.heap_max]*2 + 1]/*.Len*/ = 0; /* root of the heap */
8203
8204 for (h = s.heap_max+1; h < HEAP_SIZE; h++) {
8205 n = s.heap[h];
8206 bits = tree[tree[n*2 +1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1;
8207 if (bits > max_length) {
8208 bits = max_length;
8209 overflow++;
8210 }
8211 tree[n*2 + 1]/*.Len*/ = bits;
8212 /* We overwrite tree[n].Dad which is no longer needed */
8213
8214 if (n > max_code) { continue; } /* not a leaf node */
8215
8216 s.bl_count[bits]++;
8217 xbits = 0;
8218 if (n >= base) {
8219 xbits = extra[n-base];
8220 }
8221 f = tree[n * 2]/*.Freq*/;
8222 s.opt_len += f * (bits + xbits);
8223 if (has_stree) {
8224 s.static_len += f * (stree[n*2 + 1]/*.Len*/ + xbits);
8225 }
8226 }
8227 if (overflow === 0) { return; }
8228
8229 // Trace((stderr,"\nbit length overflow\n"));
8230 /* This happens for example on obj2 and pic of the Calgary corpus */
8231
8232 /* Find the first bit length which could increase: */
8233 do {
8234 bits = max_length-1;
8235 while (s.bl_count[bits] === 0) { bits--; }
8236 s.bl_count[bits]--; /* move one leaf down the tree */
8237 s.bl_count[bits+1] += 2; /* move one overflow item as its brother */
8238 s.bl_count[max_length]--;
8239 /* The brother of the overflow item also moves one step up,
8240 * but this does not affect bl_count[max_length]
8241 */
8242 overflow -= 2;
8243 } while (overflow > 0);
8244
8245 /* Now recompute all bit lengths, scanning in increasing frequency.
8246 * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
8247 * lengths instead of fixing only the wrong ones. This idea is taken
8248 * from 'ar' written by Haruhiko Okumura.)
8249 */
8250 for (bits = max_length; bits !== 0; bits--) {
8251 n = s.bl_count[bits];
8252 while (n !== 0) {
8253 m = s.heap[--h];
8254 if (m > max_code) { continue; }
8255 if (tree[m*2 + 1]/*.Len*/ !== bits) {
8256 // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
8257 s.opt_len += (bits - tree[m*2 + 1]/*.Len*/)*tree[m*2]/*.Freq*/;
8258 tree[m*2 + 1]/*.Len*/ = bits;
8259 }
8260 n--;
8261 }
8262 }
8263}
8264
8265
8266/* ===========================================================================
8267 * Generate the codes for a given tree and bit counts (which need not be
8268 * optimal).
8269 * IN assertion: the array bl_count contains the bit length statistics for
8270 * the given tree and the field len is set for all tree elements.
8271 * OUT assertion: the field code is set for all tree elements of non
8272 * zero code length.
8273 */
8274function gen_codes(tree, max_code, bl_count)
8275// ct_data *tree; /* the tree to decorate */
8276// int max_code; /* largest code with non zero frequency */
8277// ushf *bl_count; /* number of codes at each bit length */
8278{
8279 var next_code = new Array(MAX_BITS+1); /* next code value for each bit length */
8280 var code = 0; /* running code value */
8281 var bits; /* bit index */
8282 var n; /* code index */
8283
8284 /* The distribution counts are first used to generate the code values
8285 * without bit reversal.
8286 */
8287 for (bits = 1; bits <= MAX_BITS; bits++) {
8288 next_code[bits] = code = (code + bl_count[bits-1]) << 1;
8289 }
8290 /* Check that the bit counts in bl_count are consistent. The last code
8291 * must be all ones.
8292 */
8293 //Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
8294 // "inconsistent bit counts");
8295 //Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
8296
8297 for (n = 0; n <= max_code; n++) {
8298 var len = tree[n*2 + 1]/*.Len*/;
8299 if (len === 0) { continue; }
8300 /* Now reverse the bits */
8301 tree[n*2]/*.Code*/ = bi_reverse(next_code[len]++, len);
8302
8303 //Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
8304 // n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
8305 }
8306}
8307
8308
8309/* ===========================================================================
8310 * Initialize the various 'constant' tables.
8311 */
8312function tr_static_init() {
8313 var n; /* iterates over tree elements */
8314 var bits; /* bit counter */
8315 var length; /* length value */
8316 var code; /* code value */
8317 var dist; /* distance index */
8318 var bl_count = new Array(MAX_BITS+1);
8319 /* number of codes at each bit length for an optimal tree */
8320
8321 // do check in _tr_init()
8322 //if (static_init_done) return;
8323
8324 /* For some embedded targets, global variables are not initialized: */
8325/*#ifdef NO_INIT_GLOBAL_POINTERS
8326 static_l_desc.static_tree = static_ltree;
8327 static_l_desc.extra_bits = extra_lbits;
8328 static_d_desc.static_tree = static_dtree;
8329 static_d_desc.extra_bits = extra_dbits;
8330 static_bl_desc.extra_bits = extra_blbits;
8331#endif*/
8332
8333 /* Initialize the mapping length (0..255) -> length code (0..28) */
8334 length = 0;
8335 for (code = 0; code < LENGTH_CODES-1; code++) {
8336 base_length[code] = length;
8337 for (n = 0; n < (1<<extra_lbits[code]); n++) {
8338 _length_code[length++] = code;
8339 }
8340 }
8341 //Assert (length == 256, "tr_static_init: length != 256");
8342 /* Note that the length 255 (match length 258) can be represented
8343 * in two different ways: code 284 + 5 bits or code 285, so we
8344 * overwrite length_code[255] to use the best encoding:
8345 */
8346 _length_code[length-1] = code;
8347
8348 /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
8349 dist = 0;
8350 for (code = 0 ; code < 16; code++) {
8351 base_dist[code] = dist;
8352 for (n = 0; n < (1<<extra_dbits[code]); n++) {
8353 _dist_code[dist++] = code;
8354 }
8355 }
8356 //Assert (dist == 256, "tr_static_init: dist != 256");
8357 dist >>= 7; /* from now on, all distances are divided by 128 */
8358 for ( ; code < D_CODES; code++) {
8359 base_dist[code] = dist << 7;
8360 for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
8361 _dist_code[256 + dist++] = code;
8362 }
8363 }
8364 //Assert (dist == 256, "tr_static_init: 256+dist != 512");
8365
8366 /* Construct the codes of the static literal tree */
8367 for (bits = 0; bits <= MAX_BITS; bits++) {
8368 bl_count[bits] = 0;
8369 }
8370
8371 n = 0;
8372 while (n <= 143) {
8373 static_ltree[n*2 + 1]/*.Len*/ = 8;
8374 n++;
8375 bl_count[8]++;
8376 }
8377 while (n <= 255) {
8378 static_ltree[n*2 + 1]/*.Len*/ = 9;
8379 n++;
8380 bl_count[9]++;
8381 }
8382 while (n <= 279) {
8383 static_ltree[n*2 + 1]/*.Len*/ = 7;
8384 n++;
8385 bl_count[7]++;
8386 }
8387 while (n <= 287) {
8388 static_ltree[n*2 + 1]/*.Len*/ = 8;
8389 n++;
8390 bl_count[8]++;
8391 }
8392 /* Codes 286 and 287 do not exist, but we must include them in the
8393 * tree construction to get a canonical Huffman tree (longest code
8394 * all ones)
8395 */
8396 gen_codes(static_ltree, L_CODES+1, bl_count);
8397
8398 /* The static distance tree is trivial: */
8399 for (n = 0; n < D_CODES; n++) {
8400 static_dtree[n*2 + 1]/*.Len*/ = 5;
8401 static_dtree[n*2]/*.Code*/ = bi_reverse(n, 5);
8402 }
8403
8404 // Now data ready and we can init static trees
8405 static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS);
8406 static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS);
8407 static_bl_desc =new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS);
8408
8409 //static_init_done = true;
8410}
8411
8412
8413/* ===========================================================================
8414 * Initialize a new block.
8415 */
8416function init_block(s) {
8417 var n; /* iterates over tree elements */
8418
8419 /* Initialize the trees. */
8420 for (n = 0; n < L_CODES; n++) { s.dyn_ltree[n*2]/*.Freq*/ = 0; }
8421 for (n = 0; n < D_CODES; n++) { s.dyn_dtree[n*2]/*.Freq*/ = 0; }
8422 for (n = 0; n < BL_CODES; n++) { s.bl_tree[n*2]/*.Freq*/ = 0; }
8423
8424 s.dyn_ltree[END_BLOCK*2]/*.Freq*/ = 1;
8425 s.opt_len = s.static_len = 0;
8426 s.last_lit = s.matches = 0;
8427}
8428
8429
8430/* ===========================================================================
8431 * Flush the bit buffer and align the output on a byte boundary
8432 */
8433function bi_windup(s)
8434{
8435 if (s.bi_valid > 8) {
8436 put_short(s, s.bi_buf);
8437 } else if (s.bi_valid > 0) {
8438 //put_byte(s, (Byte)s->bi_buf);
8439 s.pending_buf[s.pending++] = s.bi_buf;
8440 }
8441 s.bi_buf = 0;
8442 s.bi_valid = 0;
8443}
8444
8445/* ===========================================================================
8446 * Copy a stored block, storing first the length and its
8447 * one's complement if requested.
8448 */
8449function copy_block(s, buf, len, header)
8450//DeflateState *s;
8451//charf *buf; /* the input data */
8452//unsigned len; /* its length */
8453//int header; /* true if block header must be written */
8454{
8455 bi_windup(s); /* align on byte boundary */
8456
8457 if (header) {
8458 put_short(s, len);
8459 put_short(s, ~len);
8460 }
8461// while (len--) {
8462// put_byte(s, *buf++);
8463// }
8464 utils.arraySet(s.pending_buf, s.window, buf, len, s.pending);
8465 s.pending += len;
8466}
8467
8468/* ===========================================================================
8469 * Compares to subtrees, using the tree depth as tie breaker when
8470 * the subtrees have equal frequency. This minimizes the worst case length.
8471 */
8472function smaller(tree, n, m, depth) {
8473 var _n2 = n*2;
8474 var _m2 = m*2;
8475 return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ ||
8476 (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m]));
8477}
8478
8479/* ===========================================================================
8480 * Restore the heap property by moving down the tree starting at node k,
8481 * exchanging a node with the smallest of its two sons if necessary, stopping
8482 * when the heap property is re-established (each father smaller than its
8483 * two sons).
8484 */
8485function pqdownheap(s, tree, k)
8486// deflate_state *s;
8487// ct_data *tree; /* the tree to restore */
8488// int k; /* node to move down */
8489{
8490 var v = s.heap[k];
8491 var j = k << 1; /* left son of k */
8492 while (j <= s.heap_len) {
8493 /* Set j to the smallest of the two sons: */
8494 if (j < s.heap_len &&
8495 smaller(tree, s.heap[j+1], s.heap[j], s.depth)) {
8496 j++;
8497 }
8498 /* Exit if v is smaller than both sons */
8499 if (smaller(tree, v, s.heap[j], s.depth)) { break; }
8500
8501 /* Exchange v with the smallest son */
8502 s.heap[k] = s.heap[j];
8503 k = j;
8504
8505 /* And continue down the tree, setting j to the left son of k */
8506 j <<= 1;
8507 }
8508 s.heap[k] = v;
8509}
8510
8511
8512// inlined manually
8513// var SMALLEST = 1;
8514
8515/* ===========================================================================
8516 * Send the block data compressed using the given Huffman trees
8517 */
8518function compress_block(s, ltree, dtree)
8519// deflate_state *s;
8520// const ct_data *ltree; /* literal tree */
8521// const ct_data *dtree; /* distance tree */
8522{
8523 var dist; /* distance of matched string */
8524 var lc; /* match length or unmatched char (if dist == 0) */
8525 var lx = 0; /* running index in l_buf */
8526 var code; /* the code to send */
8527 var extra; /* number of extra bits to send */
8528
8529 if (s.last_lit !== 0) {
8530 do {
8531 dist = (s.pending_buf[s.d_buf + lx*2] << 8) | (s.pending_buf[s.d_buf + lx*2 + 1]);
8532 lc = s.pending_buf[s.l_buf + lx];
8533 lx++;
8534
8535 if (dist === 0) {
8536 send_code(s, lc, ltree); /* send a literal byte */
8537 //Tracecv(isgraph(lc), (stderr," '%c' ", lc));
8538 } else {
8539 /* Here, lc is the match length - MIN_MATCH */
8540 code = _length_code[lc];
8541 send_code(s, code+LITERALS+1, ltree); /* send the length code */
8542 extra = extra_lbits[code];
8543 if (extra !== 0) {
8544 lc -= base_length[code];
8545 send_bits(s, lc, extra); /* send the extra length bits */
8546 }
8547 dist--; /* dist is now the match distance - 1 */
8548 code = d_code(dist);
8549 //Assert (code < D_CODES, "bad d_code");
8550
8551 send_code(s, code, dtree); /* send the distance code */
8552 extra = extra_dbits[code];
8553 if (extra !== 0) {
8554 dist -= base_dist[code];
8555 send_bits(s, dist, extra); /* send the extra distance bits */
8556 }
8557 } /* literal or match pair ? */
8558
8559 /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
8560 //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
8561 // "pendingBuf overflow");
8562
8563 } while (lx < s.last_lit);
8564 }
8565
8566 send_code(s, END_BLOCK, ltree);
8567}
8568
8569
8570/* ===========================================================================
8571 * Construct one Huffman tree and assigns the code bit strings and lengths.
8572 * Update the total bit length for the current block.
8573 * IN assertion: the field freq is set for all tree elements.
8574 * OUT assertions: the fields len and code are set to the optimal bit length
8575 * and corresponding code. The length opt_len is updated; static_len is
8576 * also updated if stree is not null. The field max_code is set.
8577 */
8578function build_tree(s, desc)
8579// deflate_state *s;
8580// tree_desc *desc; /* the tree descriptor */
8581{
8582 var tree = desc.dyn_tree;
8583 var stree = desc.stat_desc.static_tree;
8584 var has_stree = desc.stat_desc.has_stree;
8585 var elems = desc.stat_desc.elems;
8586 var n, m; /* iterate over heap elements */
8587 var max_code = -1; /* largest code with non zero frequency */
8588 var node; /* new node being created */
8589
8590 /* Construct the initial heap, with least frequent element in
8591 * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
8592 * heap[0] is not used.
8593 */
8594 s.heap_len = 0;
8595 s.heap_max = HEAP_SIZE;
8596
8597 for (n = 0; n < elems; n++) {
8598 if (tree[n * 2]/*.Freq*/ !== 0) {
8599 s.heap[++s.heap_len] = max_code = n;
8600 s.depth[n] = 0;
8601
8602 } else {
8603 tree[n*2 + 1]/*.Len*/ = 0;
8604 }
8605 }
8606
8607 /* The pkzip format requires that at least one distance code exists,
8608 * and that at least one bit should be sent even if there is only one
8609 * possible code. So to avoid special checks later on we force at least
8610 * two codes of non zero frequency.
8611 */
8612 while (s.heap_len < 2) {
8613 node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
8614 tree[node * 2]/*.Freq*/ = 1;
8615 s.depth[node] = 0;
8616 s.opt_len--;
8617
8618 if (has_stree) {
8619 s.static_len -= stree[node*2 + 1]/*.Len*/;
8620 }
8621 /* node is 0 or 1 so it does not have extra bits */
8622 }
8623 desc.max_code = max_code;
8624
8625 /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
8626 * establish sub-heaps of increasing lengths:
8627 */
8628 for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); }
8629
8630 /* Construct the Huffman tree by repeatedly combining the least two
8631 * frequent nodes.
8632 */
8633 node = elems; /* next internal node of the tree */
8634 do {
8635 //pqremove(s, tree, n); /* n = node of least frequency */
8636 /*** pqremove ***/
8637 n = s.heap[1/*SMALLEST*/];
8638 s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--];
8639 pqdownheap(s, tree, 1/*SMALLEST*/);
8640 /***/
8641
8642 m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */
8643
8644 s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */
8645 s.heap[--s.heap_max] = m;
8646
8647 /* Create a new node father of n and m */
8648 tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/;
8649 s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1;
8650 tree[n*2 + 1]/*.Dad*/ = tree[m*2 + 1]/*.Dad*/ = node;
8651
8652 /* and insert the new node in the heap */
8653 s.heap[1/*SMALLEST*/] = node++;
8654 pqdownheap(s, tree, 1/*SMALLEST*/);
8655
8656 } while (s.heap_len >= 2);
8657
8658 s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/];
8659
8660 /* At this point, the fields freq and dad are set. We can now
8661 * generate the bit lengths.
8662 */
8663 gen_bitlen(s, desc);
8664
8665 /* The field len is now set, we can generate the bit codes */
8666 gen_codes(tree, max_code, s.bl_count);
8667}
8668
8669
8670/* ===========================================================================
8671 * Scan a literal or distance tree to determine the frequencies of the codes
8672 * in the bit length tree.
8673 */
8674function scan_tree(s, tree, max_code)
8675// deflate_state *s;
8676// ct_data *tree; /* the tree to be scanned */
8677// int max_code; /* and its largest code of non zero frequency */
8678{
8679 var n; /* iterates over all tree elements */
8680 var prevlen = -1; /* last emitted length */
8681 var curlen; /* length of current code */
8682
8683 var nextlen = tree[0*2 + 1]/*.Len*/; /* length of next code */
8684
8685 var count = 0; /* repeat count of the current code */
8686 var max_count = 7; /* max repeat count */
8687 var min_count = 4; /* min repeat count */
8688
8689 if (nextlen === 0) {
8690 max_count = 138;
8691 min_count = 3;
8692 }
8693 tree[(max_code+1)*2 + 1]/*.Len*/ = 0xffff; /* guard */
8694
8695 for (n = 0; n <= max_code; n++) {
8696 curlen = nextlen;
8697 nextlen = tree[(n+1)*2 + 1]/*.Len*/;
8698
8699 if (++count < max_count && curlen === nextlen) {
8700 continue;
8701
8702 } else if (count < min_count) {
8703 s.bl_tree[curlen * 2]/*.Freq*/ += count;
8704
8705 } else if (curlen !== 0) {
8706
8707 if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; }
8708 s.bl_tree[REP_3_6*2]/*.Freq*/++;
8709
8710 } else if (count <= 10) {
8711 s.bl_tree[REPZ_3_10*2]/*.Freq*/++;
8712
8713 } else {
8714 s.bl_tree[REPZ_11_138*2]/*.Freq*/++;
8715 }
8716
8717 count = 0;
8718 prevlen = curlen;
8719
8720 if (nextlen === 0) {
8721 max_count = 138;
8722 min_count = 3;
8723
8724 } else if (curlen === nextlen) {
8725 max_count = 6;
8726 min_count = 3;
8727
8728 } else {
8729 max_count = 7;
8730 min_count = 4;
8731 }
8732 }
8733}
8734
8735
8736/* ===========================================================================
8737 * Send a literal or distance tree in compressed form, using the codes in
8738 * bl_tree.
8739 */
8740function send_tree(s, tree, max_code)
8741// deflate_state *s;
8742// ct_data *tree; /* the tree to be scanned */
8743// int max_code; /* and its largest code of non zero frequency */
8744{
8745 var n; /* iterates over all tree elements */
8746 var prevlen = -1; /* last emitted length */
8747 var curlen; /* length of current code */
8748
8749 var nextlen = tree[0*2 + 1]/*.Len*/; /* length of next code */
8750
8751 var count = 0; /* repeat count of the current code */
8752 var max_count = 7; /* max repeat count */
8753 var min_count = 4; /* min repeat count */
8754
8755 /* tree[max_code+1].Len = -1; */ /* guard already set */
8756 if (nextlen === 0) {
8757 max_count = 138;
8758 min_count = 3;
8759 }
8760
8761 for (n = 0; n <= max_code; n++) {
8762 curlen = nextlen;
8763 nextlen = tree[(n+1)*2 + 1]/*.Len*/;
8764
8765 if (++count < max_count && curlen === nextlen) {
8766 continue;
8767
8768 } else if (count < min_count) {
8769 do { send_code(s, curlen, s.bl_tree); } while (--count !== 0);
8770
8771 } else if (curlen !== 0) {
8772 if (curlen !== prevlen) {
8773 send_code(s, curlen, s.bl_tree);
8774 count--;
8775 }
8776 //Assert(count >= 3 && count <= 6, " 3_6?");
8777 send_code(s, REP_3_6, s.bl_tree);
8778 send_bits(s, count-3, 2);
8779
8780 } else if (count <= 10) {
8781 send_code(s, REPZ_3_10, s.bl_tree);
8782 send_bits(s, count-3, 3);
8783
8784 } else {
8785 send_code(s, REPZ_11_138, s.bl_tree);
8786 send_bits(s, count-11, 7);
8787 }
8788
8789 count = 0;
8790 prevlen = curlen;
8791 if (nextlen === 0) {
8792 max_count = 138;
8793 min_count = 3;
8794
8795 } else if (curlen === nextlen) {
8796 max_count = 6;
8797 min_count = 3;
8798
8799 } else {
8800 max_count = 7;
8801 min_count = 4;
8802 }
8803 }
8804}
8805
8806
8807/* ===========================================================================
8808 * Construct the Huffman tree for the bit lengths and return the index in
8809 * bl_order of the last bit length code to send.
8810 */
8811function build_bl_tree(s) {
8812 var max_blindex; /* index of last bit length code of non zero freq */
8813
8814 /* Determine the bit length frequencies for literal and distance trees */
8815 scan_tree(s, s.dyn_ltree, s.l_desc.max_code);
8816 scan_tree(s, s.dyn_dtree, s.d_desc.max_code);
8817
8818 /* Build the bit length tree: */
8819 build_tree(s, s.bl_desc);
8820 /* opt_len now includes the length of the tree representations, except
8821 * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
8822 */
8823
8824 /* Determine the number of bit length codes to send. The pkzip format
8825 * requires that at least 4 bit length codes be sent. (appnote.txt says
8826 * 3 but the actual value used is 4.)
8827 */
8828 for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
8829 if (s.bl_tree[bl_order[max_blindex]*2 + 1]/*.Len*/ !== 0) {
8830 break;
8831 }
8832 }
8833 /* Update opt_len to include the bit length tree and counts */
8834 s.opt_len += 3*(max_blindex+1) + 5+5+4;
8835 //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
8836 // s->opt_len, s->static_len));
8837
8838 return max_blindex;
8839}
8840
8841
8842/* ===========================================================================
8843 * Send the header for a block using dynamic Huffman trees: the counts, the
8844 * lengths of the bit length codes, the literal tree and the distance tree.
8845 * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
8846 */
8847function send_all_trees(s, lcodes, dcodes, blcodes)
8848// deflate_state *s;
8849// int lcodes, dcodes, blcodes; /* number of codes for each tree */
8850{
8851 var rank; /* index in bl_order */
8852
8853 //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
8854 //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
8855 // "too many codes");
8856 //Tracev((stderr, "\nbl counts: "));
8857 send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
8858 send_bits(s, dcodes-1, 5);
8859 send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */
8860 for (rank = 0; rank < blcodes; rank++) {
8861 //Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
8862 send_bits(s, s.bl_tree[bl_order[rank]*2 + 1]/*.Len*/, 3);
8863 }
8864 //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
8865
8866 send_tree(s, s.dyn_ltree, lcodes-1); /* literal tree */
8867 //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
8868
8869 send_tree(s, s.dyn_dtree, dcodes-1); /* distance tree */
8870 //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
8871}
8872
8873
8874/* ===========================================================================
8875 * Check if the data type is TEXT or BINARY, using the following algorithm:
8876 * - TEXT if the two conditions below are satisfied:
8877 * a) There are no non-portable control characters belonging to the
8878 * "black list" (0..6, 14..25, 28..31).
8879 * b) There is at least one printable character belonging to the
8880 * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
8881 * - BINARY otherwise.
8882 * - The following partially-portable control characters form a
8883 * "gray list" that is ignored in this detection algorithm:
8884 * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
8885 * IN assertion: the fields Freq of dyn_ltree are set.
8886 */
8887function detect_data_type(s) {
8888 /* black_mask is the bit mask of black-listed bytes
8889 * set bits 0..6, 14..25, and 28..31
8890 * 0xf3ffc07f = binary 11110011111111111100000001111111
8891 */
8892 var black_mask = 0xf3ffc07f;
8893 var n;
8894
8895 /* Check for non-textual ("black-listed") bytes. */
8896 for (n = 0; n <= 31; n++, black_mask >>>= 1) {
8897 if ((black_mask & 1) && (s.dyn_ltree[n*2]/*.Freq*/ !== 0)) {
8898 return Z_BINARY;
8899 }
8900 }
8901
8902 /* Check for textual ("white-listed") bytes. */
8903 if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 ||
8904 s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) {
8905 return Z_TEXT;
8906 }
8907 for (n = 32; n < LITERALS; n++) {
8908 if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) {
8909 return Z_TEXT;
8910 }
8911 }
8912
8913 /* There are no "black-listed" or "white-listed" bytes:
8914 * this stream either is empty or has tolerated ("gray-listed") bytes only.
8915 */
8916 return Z_BINARY;
8917}
8918
8919
8920var static_init_done = false;
8921
8922/* ===========================================================================
8923 * Initialize the tree data structures for a new zlib stream.
8924 */
8925function _tr_init(s)
8926{
8927
8928 if (!static_init_done) {
8929 tr_static_init();
8930 static_init_done = true;
8931 }
8932
8933 s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc);
8934 s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc);
8935 s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc);
8936
8937 s.bi_buf = 0;
8938 s.bi_valid = 0;
8939
8940 /* Initialize the first block of the first file: */
8941 init_block(s);
8942}
8943
8944
8945/* ===========================================================================
8946 * Send a stored block
8947 */
8948function _tr_stored_block(s, buf, stored_len, last)
8949//DeflateState *s;
8950//charf *buf; /* input block */
8951//ulg stored_len; /* length of input block */
8952//int last; /* one if this is the last block for a file */
8953{
8954 send_bits(s, (STORED_BLOCK<<1)+(last ? 1 : 0), 3); /* send block type */
8955 copy_block(s, buf, stored_len, true); /* with header */
8956}
8957
8958
8959/* ===========================================================================
8960 * Send one empty static block to give enough lookahead for inflate.
8961 * This takes 10 bits, of which 7 may remain in the bit buffer.
8962 */
8963function _tr_align(s) {
8964 send_bits(s, STATIC_TREES<<1, 3);
8965 send_code(s, END_BLOCK, static_ltree);
8966 bi_flush(s);
8967}
8968
8969
8970/* ===========================================================================
8971 * Determine the best encoding for the current block: dynamic trees, static
8972 * trees or store, and output the encoded block to the zip file.
8973 */
8974function _tr_flush_block(s, buf, stored_len, last)
8975//DeflateState *s;
8976//charf *buf; /* input block, or NULL if too old */
8977//ulg stored_len; /* length of input block */
8978//int last; /* one if this is the last block for a file */
8979{
8980 var opt_lenb, static_lenb; /* opt_len and static_len in bytes */
8981 var max_blindex = 0; /* index of last bit length code of non zero freq */
8982
8983 /* Build the Huffman trees unless a stored block is forced */
8984 if (s.level > 0) {
8985
8986 /* Check if the file is binary or text */
8987 if (s.strm.data_type === Z_UNKNOWN) {
8988 s.strm.data_type = detect_data_type(s);
8989 }
8990
8991 /* Construct the literal and distance trees */
8992 build_tree(s, s.l_desc);
8993 // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
8994 // s->static_len));
8995
8996 build_tree(s, s.d_desc);
8997 // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
8998 // s->static_len));
8999 /* At this point, opt_len and static_len are the total bit lengths of
9000 * the compressed block data, excluding the tree representations.
9001 */
9002
9003 /* Build the bit length tree for the above two trees, and get the index
9004 * in bl_order of the last bit length code to send.
9005 */
9006 max_blindex = build_bl_tree(s);
9007
9008 /* Determine the best encoding. Compute the block lengths in bytes. */
9009 opt_lenb = (s.opt_len+3+7) >>> 3;
9010 static_lenb = (s.static_len+3+7) >>> 3;
9011
9012 // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
9013 // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
9014 // s->last_lit));
9015
9016 if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; }
9017
9018 } else {
9019 // Assert(buf != (char*)0, "lost buf");
9020 opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
9021 }
9022
9023 if ((stored_len+4 <= opt_lenb) && (buf !== -1)) {
9024 /* 4: two words for the lengths */
9025
9026 /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
9027 * Otherwise we can't have processed more than WSIZE input bytes since
9028 * the last block flush, because compression would have been
9029 * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
9030 * transform a block into a stored block.
9031 */
9032 _tr_stored_block(s, buf, stored_len, last);
9033
9034 } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) {
9035
9036 send_bits(s, (STATIC_TREES<<1) + (last ? 1 : 0), 3);
9037 compress_block(s, static_ltree, static_dtree);
9038
9039 } else {
9040 send_bits(s, (DYN_TREES<<1) + (last ? 1 : 0), 3);
9041 send_all_trees(s, s.l_desc.max_code+1, s.d_desc.max_code+1, max_blindex+1);
9042 compress_block(s, s.dyn_ltree, s.dyn_dtree);
9043 }
9044 // Assert (s->compressed_len == s->bits_sent, "bad compressed size");
9045 /* The above check is made mod 2^32, for files larger than 512 MB
9046 * and uLong implemented on 32 bits.
9047 */
9048 init_block(s);
9049
9050 if (last) {
9051 bi_windup(s);
9052 }
9053 // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
9054 // s->compressed_len-7*last));
9055}
9056
9057/* ===========================================================================
9058 * Save the match info and tally the frequency counts. Return true if
9059 * the current block must be flushed.
9060 */
9061function _tr_tally(s, dist, lc)
9062// deflate_state *s;
9063// unsigned dist; /* distance of matched string */
9064// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
9065{
9066 //var out_length, in_length, dcode;
9067
9068 s.pending_buf[s.d_buf + s.last_lit * 2] = (dist >>> 8) & 0xff;
9069 s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff;
9070
9071 s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff;
9072 s.last_lit++;
9073
9074 if (dist === 0) {
9075 /* lc is the unmatched char */
9076 s.dyn_ltree[lc*2]/*.Freq*/++;
9077 } else {
9078 s.matches++;
9079 /* Here, lc is the match length - MIN_MATCH */
9080 dist--; /* dist = match distance - 1 */
9081 //Assert((ush)dist < (ush)MAX_DIST(s) &&
9082 // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
9083 // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
9084
9085 s.dyn_ltree[(_length_code[lc]+LITERALS+1) * 2]/*.Freq*/++;
9086 s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++;
9087 }
9088
9089// (!) This block is disabled in zlib defailts,
9090// don't enable it for binary compatibility
9091
9092//#ifdef TRUNCATE_BLOCK
9093// /* Try to guess if it is profitable to stop the current block here */
9094// if ((s.last_lit & 0x1fff) === 0 && s.level > 2) {
9095// /* Compute an upper bound for the compressed length */
9096// out_length = s.last_lit*8;
9097// in_length = s.strstart - s.block_start;
9098//
9099// for (dcode = 0; dcode < D_CODES; dcode++) {
9100// out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]);
9101// }
9102// out_length >>>= 3;
9103// //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
9104// // s->last_lit, in_length, out_length,
9105// // 100L - out_length*100L/in_length));
9106// if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) {
9107// return true;
9108// }
9109// }
9110//#endif
9111
9112 return (s.last_lit === s.lit_bufsize-1);
9113 /* We avoid equality with lit_bufsize because of wraparound at 64K
9114 * on 16 bit machines and because stored blocks are restricted to
9115 * 64K-1 bytes.
9116 */
9117}
9118
9119exports._tr_init = _tr_init;
9120exports._tr_stored_block = _tr_stored_block;
9121exports._tr_flush_block = _tr_flush_block;
9122exports._tr_tally = _tr_tally;
9123exports._tr_align = _tr_align;
9124},{"../utils/common":27}],39:[function(_dereq_,module,exports){
9125'use strict';
9126
9127
9128function ZStream() {
9129 /* next input byte */
9130 this.input = null; // JS specific, because we have no pointers
9131 this.next_in = 0;
9132 /* number of bytes available at input */
9133 this.avail_in = 0;
9134 /* total number of input bytes read so far */
9135 this.total_in = 0;
9136 /* next output byte should be put there */
9137 this.output = null; // JS specific, because we have no pointers
9138 this.next_out = 0;
9139 /* remaining free space at output */
9140 this.avail_out = 0;
9141 /* total number of bytes output so far */
9142 this.total_out = 0;
9143 /* last error message, NULL if no error */
9144 this.msg = ''/*Z_NULL*/;
9145 /* not visible by applications */
9146 this.state = null;
9147 /* best guess about the data type: binary or text */
9148 this.data_type = 2/*Z_UNKNOWN*/;
9149 /* adler32 value of the uncompressed data */
9150 this.adler = 0;
9151}
9152
9153module.exports = ZStream;
9154},{}]},{},[9])
9155(9)
9156}));
9157/*! xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
9158/* vim: set ts=2: */
9159/*exported XLSX */
9160/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
9161var XLSX = {};
9162function make_xlsx_lib(XLSX){
9163XLSX.version = '0.15.2';
9164var current_codepage = 1200, current_ansi = 1252;
9165/*global cptable:true, window */
9166if(typeof module !== "undefined" && typeof require !== 'undefined') {
9167 if(typeof cptable === 'undefined') {
9168 if(typeof global !== 'undefined') global.cptable = undefined;
9169 else if(typeof window !== 'undefined') window.cptable = undefined;
9170 }
9171}
9172
9173var VALID_ANSI = [ 874, 932, 936, 949, 950 ];
9174for(var i = 0; i <= 8; ++i) VALID_ANSI.push(1250 + i);
9175/* ECMA-376 Part I 18.4.1 charset to codepage mapping */
9176var CS2CP = ({
91770: 1252, /* ANSI */
91781: 65001, /* DEFAULT */
91792: 65001, /* SYMBOL */
918077: 10000, /* MAC */
9181128: 932, /* SHIFTJIS */
9182129: 949, /* HANGUL */
9183130: 1361, /* JOHAB */
9184134: 936, /* GB2312 */
9185136: 950, /* CHINESEBIG5 */
9186161: 1253, /* GREEK */
9187162: 1254, /* TURKISH */
9188163: 1258, /* VIETNAMESE */
9189177: 1255, /* HEBREW */
9190178: 1256, /* ARABIC */
9191186: 1257, /* BALTIC */
9192204: 1251, /* RUSSIAN */
9193222: 874, /* THAI */
9194238: 1250, /* EASTEUROPE */
9195255: 1252, /* OEM */
919669: 6969 /* MISC */
9197});
9198
9199var set_ansi = function(cp) { if(VALID_ANSI.indexOf(cp) == -1) return; current_ansi = CS2CP[0] = cp; };
9200function reset_ansi() { set_ansi(1252); }
9201
9202var set_cp = function(cp) { current_codepage = cp; set_ansi(cp); };
9203function reset_cp() { set_cp(1200); reset_ansi(); }
9204
9205function char_codes(data) { var o = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; }
9206
9207function utf16leread(data) {
9208 var o = [];
9209 for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i) + (data.charCodeAt(2*i+1)<<8));
9210 return o.join("");
9211}
9212function utf16beread(data) {
9213 var o = [];
9214 for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i+1) + (data.charCodeAt(2*i)<<8));
9215 return o.join("");
9216}
9217
9218var debom = function(data) {
9219 var c1 = data.charCodeAt(0), c2 = data.charCodeAt(1);
9220 if(c1 == 0xFF && c2 == 0xFE) return utf16leread(data.slice(2));
9221 if(c1 == 0xFE && c2 == 0xFF) return utf16beread(data.slice(2));
9222 if(c1 == 0xFEFF) return data.slice(1);
9223 return data;
9224};
9225
9226var _getchar = function _gc1(x) { return String.fromCharCode(x); };
9227var _getansi = function _ga1(x) { return String.fromCharCode(x); };
9228if(typeof cptable !== 'undefined') {
9229 set_cp = function(cp) { current_codepage = cp; set_ansi(cp); };
9230 debom = function(data) {
9231 if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.slice(2))); }
9232 return data;
9233 };
9234 _getchar = function _gc2(x) {
9235 if(current_codepage === 1200) return String.fromCharCode(x);
9236 return cptable.utils.decode(current_codepage, [x&255,x>>8])[0];
9237 };
9238 _getansi = function _ga2(x) {
9239 return cptable.utils.decode(current_ansi, [x])[0];
9240 };
9241}
9242var DENSE = null;
9243var DIF_XL = true;
9244var Base64 = (function make_b64(){
9245 var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
9246 return {
9247 encode: function(input) {
9248 var o = "";
9249 var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0;
9250 for(var i = 0; i < input.length; ) {
9251 c1 = input.charCodeAt(i++);
9252 e1 = (c1 >> 2);
9253
9254 c2 = input.charCodeAt(i++);
9255 e2 = ((c1 & 3) << 4) | (c2 >> 4);
9256
9257 c3 = input.charCodeAt(i++);
9258 e3 = ((c2 & 15) << 2) | (c3 >> 6);
9259 e4 = (c3 & 63);
9260 if (isNaN(c2)) { e3 = e4 = 64; }
9261 else if (isNaN(c3)) { e4 = 64; }
9262 o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4);
9263 }
9264 return o;
9265 },
9266 decode: function b64_decode(input) {
9267 var o = "";
9268 var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0;
9269 input = input.replace(/[^\w\+\/\=]/g, "");
9270 for(var i = 0; i < input.length;) {
9271 e1 = map.indexOf(input.charAt(i++));
9272 e2 = map.indexOf(input.charAt(i++));
9273 c1 = (e1 << 2) | (e2 >> 4);
9274 o += String.fromCharCode(c1);
9275
9276 e3 = map.indexOf(input.charAt(i++));
9277 c2 = ((e2 & 15) << 4) | (e3 >> 2);
9278 if (e3 !== 64) { o += String.fromCharCode(c2); }
9279
9280 e4 = map.indexOf(input.charAt(i++));
9281 c3 = ((e3 & 3) << 6) | e4;
9282 if (e4 !== 64) { o += String.fromCharCode(c3); }
9283 }
9284 return o;
9285 }
9286 };
9287})();
9288var has_buf = (typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process.versions !== 'undefined' && !!process.versions.node);
9289
9290var Buffer_from = function(){};
9291
9292if(typeof Buffer !== 'undefined') {
9293 var nbfs = !Buffer.from;
9294 if(!nbfs) try { Buffer.from("foo", "utf8"); } catch(e) { nbfs = true; }
9295 Buffer_from = nbfs ? function(buf, enc) { return (enc) ? new Buffer(buf, enc) : new Buffer(buf); } : Buffer.from.bind(Buffer);
9296 // $FlowIgnore
9297 if(!Buffer.alloc) Buffer.alloc = function(n) { return new Buffer(n); };
9298 // $FlowIgnore
9299 if(!Buffer.allocUnsafe) Buffer.allocUnsafe = function(n) { return new Buffer(n); };
9300}
9301
9302function new_raw_buf(len) {
9303 /* jshint -W056 */
9304 return has_buf ? Buffer.alloc(len) : new Array(len);
9305 /* jshint +W056 */
9306}
9307
9308function new_unsafe_buf(len) {
9309 /* jshint -W056 */
9310 return has_buf ? Buffer.allocUnsafe(len) : new Array(len);
9311 /* jshint +W056 */
9312}
9313
9314var s2a = function s2a(s) {
9315 if(has_buf) return Buffer_from(s, "binary");
9316 return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; });
9317};
9318
9319function s2ab(s) {
9320 if(typeof ArrayBuffer === 'undefined') return s2a(s);
9321 var buf = new ArrayBuffer(s.length), view = new Uint8Array(buf);
9322 for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
9323 return buf;
9324}
9325
9326function a2s(data) {
9327 if(Array.isArray(data)) return data.map(function(c) { return String.fromCharCode(c); }).join("");
9328 var o = []; for(var i = 0; i < data.length; ++i) o[i] = String.fromCharCode(data[i]); return o.join("");
9329}
9330
9331function a2u(data) {
9332 if(typeof Uint8Array === 'undefined') throw new Error("Unsupported");
9333 return new Uint8Array(data);
9334}
9335
9336function ab2a(data) {
9337 if(typeof ArrayBuffer == 'undefined') throw new Error("Unsupported");
9338 if(data instanceof ArrayBuffer) return ab2a(new Uint8Array(data));
9339var o = new Array(data.length);
9340 for(var i = 0; i < data.length; ++i) o[i] = data[i];
9341 return o;
9342}
9343
9344var bconcat = function(bufs) { return [].concat.apply([], bufs); };
9345
9346var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/g;
9347/* ssf.js (C) 2013-present SheetJS -- http://sheetjs.com */
9348/*jshint -W041 */
9349var SSF = ({});
9350var make_ssf = function make_ssf(SSF){
9351SSF.version = '0.10.2';
9352function _strrev(x) { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; }
9353function fill(c,l) { var o = ""; while(o.length < l) o+=c; return o; }
9354function pad0(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
9355function pad_(v,d){var t=""+v;return t.length>=d?t:fill(' ',d-t.length)+t;}
9356function rpad_(v,d){var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);}
9357function pad0r1(v,d){var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;}
9358function pad0r2(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;}
9359var p2_32 = Math.pow(2,32);
9360function pad0r(v,d){if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); }
9361function isgeneral(s, i) { i = i || 0; return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; }
9362var days = [
9363 ['Sun', 'Sunday'],
9364 ['Mon', 'Monday'],
9365 ['Tue', 'Tuesday'],
9366 ['Wed', 'Wednesday'],
9367 ['Thu', 'Thursday'],
9368 ['Fri', 'Friday'],
9369 ['Sat', 'Saturday']
9370];
9371var months = [
9372 ['J', 'Jan', 'January'],
9373 ['F', 'Feb', 'February'],
9374 ['M', 'Mar', 'March'],
9375 ['A', 'Apr', 'April'],
9376 ['M', 'May', 'May'],
9377 ['J', 'Jun', 'June'],
9378 ['J', 'Jul', 'July'],
9379 ['A', 'Aug', 'August'],
9380 ['S', 'Sep', 'September'],
9381 ['O', 'Oct', 'October'],
9382 ['N', 'Nov', 'November'],
9383 ['D', 'Dec', 'December']
9384];
9385function init_table(t) {
9386 t[0]= 'General';
9387 t[1]= '0';
9388 t[2]= '0.00';
9389 t[3]= '#,##0';
9390 t[4]= '#,##0.00';
9391 t[9]= '0%';
9392 t[10]= '0.00%';
9393 t[11]= '0.00E+00';
9394 t[12]= '# ?/?';
9395 t[13]= '# ??/??';
9396 t[14]= 'm/d/yy';
9397 t[15]= 'd-mmm-yy';
9398 t[16]= 'd-mmm';
9399 t[17]= 'mmm-yy';
9400 t[18]= 'h:mm AM/PM';
9401 t[19]= 'h:mm:ss AM/PM';
9402 t[20]= 'h:mm';
9403 t[21]= 'h:mm:ss';
9404 t[22]= 'm/d/yy h:mm';
9405 t[37]= '#,##0 ;(#,##0)';
9406 t[38]= '#,##0 ;[Red](#,##0)';
9407 t[39]= '#,##0.00;(#,##0.00)';
9408 t[40]= '#,##0.00;[Red](#,##0.00)';
9409 t[45]= 'mm:ss';
9410 t[46]= '[h]:mm:ss';
9411 t[47]= 'mmss.0';
9412 t[48]= '##0.0E+0';
9413 t[49]= '@';
9414 t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "';
9415 t[65535]= 'General';
9416}
9417
9418var table_fmt = {};
9419init_table(table_fmt);
9420function frac(x, D, mixed) {
9421 var sgn = x < 0 ? -1 : 1;
9422 var B = x * sgn;
9423 var P_2 = 0, P_1 = 1, P = 0;
9424 var Q_2 = 1, Q_1 = 0, Q = 0;
9425 var A = Math.floor(B);
9426 while(Q_1 < D) {
9427 A = Math.floor(B);
9428 P = A * P_1 + P_2;
9429 Q = A * Q_1 + Q_2;
9430 if((B - A) < 0.00000005) break;
9431 B = 1 / (B - A);
9432 P_2 = P_1; P_1 = P;
9433 Q_2 = Q_1; Q_1 = Q;
9434 }
9435 if(Q > D) { if(Q_1 > D) { Q = Q_2; P = P_2; } else { Q = Q_1; P = P_1; } }
9436 if(!mixed) return [0, sgn * P, Q];
9437 var q = Math.floor(sgn * P/Q);
9438 return [q, sgn*P - q*Q, Q];
9439}
9440function parse_date_code(v,opts,b2) {
9441 if(v > 2958465 || v < 0) return null;
9442 var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0;
9443 var dout=[];
9444 var out={D:date, T:time, u:86400*(v-date)-time,y:0,m:0,d:0,H:0,M:0,S:0,q:0};
9445 if(Math.abs(out.u) < 1e-6) out.u = 0;
9446 if(opts && opts.date1904) date += 1462;
9447 if(out.u > 0.9999) {
9448 out.u = 0;
9449 if(++time == 86400) { out.T = time = 0; ++date; ++out.D; }
9450 }
9451 if(date === 60) {dout = b2 ? [1317,10,29] : [1900,2,29]; dow=3;}
9452 else if(date === 0) {dout = b2 ? [1317,8,29] : [1900,1,0]; dow=6;}
9453 else {
9454 if(date > 60) --date;
9455 /* 1 = Jan 1 1900 in Gregorian */
9456 var d = new Date(1900, 0, 1);
9457 d.setDate(d.getDate() + date - 1);
9458 dout = [d.getFullYear(), d.getMonth()+1,d.getDate()];
9459 dow = d.getDay();
9460 if(date < 60) dow = (dow + 6) % 7;
9461 if(b2) dow = fix_hijri(d, dout);
9462 }
9463 out.y = dout[0]; out.m = dout[1]; out.d = dout[2];
9464 out.S = time % 60; time = Math.floor(time / 60);
9465 out.M = time % 60; time = Math.floor(time / 60);
9466 out.H = time;
9467 out.q = dow;
9468 return out;
9469}
9470SSF.parse_date_code = parse_date_code;
9471var basedate = new Date(1899, 11, 31, 0, 0, 0);
9472var dnthresh = basedate.getTime();
9473var base1904 = new Date(1900, 2, 1, 0, 0, 0);
9474function datenum_local(v, date1904) {
9475 var epoch = v.getTime();
9476 if(date1904) epoch -= 1461*24*60*60*1000;
9477 else if(v >= base1904) epoch += 24*60*60*1000;
9478 return (epoch - (dnthresh + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
9479}
9480function general_fmt_int(v) { return v.toString(10); }
9481SSF._general_int = general_fmt_int;
9482var general_fmt_num = (function make_general_fmt_num() {
9483var gnr1 = /\.(\d*[1-9])0+$/, gnr2 = /\.0*$/, gnr4 = /\.(\d*[1-9])0+/, gnr5 = /\.0*[Ee]/, gnr6 = /(E[+-])(\d)$/;
9484function gfn2(v) {
9485 var w = (v<0?12:11);
9486 var o = gfn5(v.toFixed(12)); if(o.length <= w) return o;
9487 o = v.toPrecision(10); if(o.length <= w) return o;
9488 return v.toExponential(5);
9489}
9490function gfn3(v) {
9491 var o = v.toFixed(11).replace(gnr1,".$1");
9492 if(o.length > (v<0?12:11)) o = v.toPrecision(6);
9493 return o;
9494}
9495function gfn4(o) {
9496 for(var i = 0; i != o.length; ++i) if((o.charCodeAt(i) | 0x20) === 101) return o.replace(gnr4,".$1").replace(gnr5,"E").replace("e","E").replace(gnr6,"$10$2");
9497 return o;
9498}
9499function gfn5(o) {
9500 return o.indexOf(".") > -1 ? o.replace(gnr2,"").replace(gnr1,".$1") : o;
9501}
9502return function general_fmt_num(v) {
9503 var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o;
9504 if(V >= -4 && V <= -1) o = v.toPrecision(10+V);
9505 else if(Math.abs(V) <= 9) o = gfn2(v);
9506 else if(V === 10) o = v.toFixed(10).substr(0,12);
9507 else o = gfn3(v);
9508 return gfn5(gfn4(o));
9509};})();
9510SSF._general_num = general_fmt_num;
9511function general_fmt(v, opts) {
9512 switch(typeof v) {
9513 case 'string': return v;
9514 case 'boolean': return v ? "TRUE" : "FALSE";
9515 case 'number': return (v|0) === v ? general_fmt_int(v) : general_fmt_num(v);
9516 case 'undefined': return "";
9517 case 'object':
9518 if(v == null) return "";
9519 if(v instanceof Date) return format(14, datenum_local(v, opts && opts.date1904), opts);
9520 }
9521 throw new Error("unsupported value in General format: " + v);
9522}
9523SSF._general = general_fmt;
9524function fix_hijri() { return 0; }
9525/*jshint -W086 */
9526function write_date(type, fmt, val, ss0) {
9527 var o="", ss=0, tt=0, y = val.y, out, outl = 0;
9528 switch(type) {
9529 case 98: /* 'b' buddhist year */
9530 y = val.y + 543;
9531 /* falls through */
9532 case 121: /* 'y' year */
9533 switch(fmt.length) {
9534 case 1: case 2: out = y % 100; outl = 2; break;
9535 default: out = y % 10000; outl = 4; break;
9536 } break;
9537 case 109: /* 'm' month */
9538 switch(fmt.length) {
9539 case 1: case 2: out = val.m; outl = fmt.length; break;
9540 case 3: return months[val.m-1][1];
9541 case 5: return months[val.m-1][0];
9542 default: return months[val.m-1][2];
9543 } break;
9544 case 100: /* 'd' day */
9545 switch(fmt.length) {
9546 case 1: case 2: out = val.d; outl = fmt.length; break;
9547 case 3: return days[val.q][0];
9548 default: return days[val.q][1];
9549 } break;
9550 case 104: /* 'h' 12-hour */
9551 switch(fmt.length) {
9552 case 1: case 2: out = 1+(val.H+11)%12; outl = fmt.length; break;
9553 default: throw 'bad hour format: ' + fmt;
9554 } break;
9555 case 72: /* 'H' 24-hour */
9556 switch(fmt.length) {
9557 case 1: case 2: out = val.H; outl = fmt.length; break;
9558 default: throw 'bad hour format: ' + fmt;
9559 } break;
9560 case 77: /* 'M' minutes */
9561 switch(fmt.length) {
9562 case 1: case 2: out = val.M; outl = fmt.length; break;
9563 default: throw 'bad minute format: ' + fmt;
9564 } break;
9565 case 115: /* 's' seconds */
9566 if(fmt != 's' && fmt != 'ss' && fmt != '.0' && fmt != '.00' && fmt != '.000') throw 'bad second format: ' + fmt;
9567 if(val.u === 0 && (fmt == "s" || fmt == "ss")) return pad0(val.S, fmt.length);
9568if(ss0 >= 2) tt = ss0 === 3 ? 1000 : 100;
9569 else tt = ss0 === 1 ? 10 : 1;
9570 ss = Math.round((tt)*(val.S + val.u));
9571 if(ss >= 60*tt) ss = 0;
9572 if(fmt === 's') return ss === 0 ? "0" : ""+ss/tt;
9573 o = pad0(ss,2 + ss0);
9574 if(fmt === 'ss') return o.substr(0,2);
9575 return "." + o.substr(2,fmt.length-1);
9576 case 90: /* 'Z' absolute time */
9577 switch(fmt) {
9578 case '[h]': case '[hh]': out = val.D*24+val.H; break;
9579 case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break;
9580 case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break;
9581 default: throw 'bad abstime format: ' + fmt;
9582 } outl = fmt.length === 3 ? 1 : 2; break;
9583 case 101: /* 'e' era */
9584 out = y; outl = 1;
9585 }
9586 if(outl > 0) return pad0(out, outl); else return "";
9587}
9588/*jshint +W086 */
9589function commaify(s) {
9590 var w = 3;
9591 if(s.length <= w) return s;
9592 var j = (s.length % w), o = s.substr(0,j);
9593 for(; j!=s.length; j+=w) o+=(o.length > 0 ? "," : "") + s.substr(j,w);
9594 return o;
9595}
9596var write_num = (function make_write_num(){
9597var pct1 = /%/g;
9598function write_num_pct(type, fmt, val){
9599 var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
9600 return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
9601}
9602function write_num_cm(type, fmt, val){
9603 var idx = fmt.length - 1;
9604 while(fmt.charCodeAt(idx-1) === 44) --idx;
9605 return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
9606}
9607function write_num_exp(fmt, val){
9608 var o;
9609 var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
9610 if(fmt.match(/^#+0.0E\+0$/)) {
9611 if(val == 0) return "0.0E+0";
9612 else if(val < 0) return "-" + write_num_exp(fmt, -val);
9613 var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
9614 var ee = Math.floor(Math.log(val)*Math.LOG10E)%period;
9615 if(ee < 0) ee += period;
9616 o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
9617 if(o.indexOf("e") === -1) {
9618 var fakee = Math.floor(Math.log(val)*Math.LOG10E);
9619 if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
9620 else o += "E+" + (fakee - ee);
9621 while(o.substr(0,2) === "0.") {
9622 o = o.charAt(0) + o.substr(2,period) + "." + o.substr(2+period);
9623 o = o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0.");
9624 }
9625 o = o.replace(/\+-/,"-");
9626 }
9627 o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
9628 } else o = val.toExponential(idx);
9629 if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
9630 if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
9631 return o.replace("e","E");
9632}
9633var frac1 = /# (\?+)( ?)\/( ?)(\d+)/;
9634function write_num_f1(r, aval, sign) {
9635 var den = parseInt(r[4],10), rr = Math.round(aval * den), base = Math.floor(rr/den);
9636 var myn = (rr - base*den), myd = den;
9637 return sign + (base === 0 ? "" : ""+base) + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[4].length) : pad_(myn,r[1].length) + r[2] + "/" + r[3] + pad0(myd,r[4].length));
9638}
9639function write_num_f2(r, aval, sign) {
9640 return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length);
9641}
9642var dec1 = /^#*0*\.([0#]+)/;
9643var closeparen = /\).*[0#]/;
9644var phone = /\(###\) ###\\?-####/;
9645function hashq(str) {
9646 var o = "", cc;
9647 for(var i = 0; i != str.length; ++i) switch((cc=str.charCodeAt(i))) {
9648 case 35: break;
9649 case 63: o+= " "; break;
9650 case 48: o+= "0"; break;
9651 default: o+= String.fromCharCode(cc);
9652 }
9653 return o;
9654}
9655function rnd(val, d) { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); }
9656function dec(val, d) {
9657 if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
9658 return 0;
9659 }
9660 return Math.round((val-Math.floor(val))*Math.pow(10,d));
9661}
9662function carry(val, d) {
9663 if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) {
9664 return 1;
9665 }
9666 return 0;
9667}
9668function flr(val) { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); }
9669function write_num_flt(type, fmt, val) {
9670 if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
9671 var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
9672 if(val >= 0) return write_num_flt('n', ffmt, val);
9673 return '(' + write_num_flt('n', ffmt, -val) + ')';
9674 }
9675 if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm(type, fmt, val);
9676 if(fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val);
9677 if(fmt.indexOf('E') !== -1) return write_num_exp(fmt, val);
9678 if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt.charAt(1)==' '?2:1),val);
9679 var o;
9680 var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
9681 if(fmt.match(/^00+$/)) return sign + pad0r(aval,fmt.length);
9682 if(fmt.match(/^[#?]+$/)) {
9683 o = pad0r(val,0); if(o === "0") o = "";
9684 return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
9685 }
9686 if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign);
9687 if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0"));
9688 if((r = fmt.match(dec1))) {
9689 o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+hashq(r[1])).replace(/\.$/,"."+hashq(r[1])).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", hashq(r[1]).length-$1.length); });
9690 return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
9691 }
9692 fmt = fmt.replace(/^#+([0.])/, "$1");
9693 if((r = fmt.match(/^(0*)\.(#*)$/))) {
9694 return sign + rnd(aval, r[2].length).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
9695 }
9696 if((r = fmt.match(/^#{1,3},##0(\.?)$/))) return sign + commaify(pad0r(aval,0));
9697 if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
9698 return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length);
9699 }
9700 if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val);
9701 if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
9702 o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g,""), val));
9703 ri = 0;
9704 return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";}));
9705 }
9706 if(fmt.match(phone)) {
9707 o = write_num_flt(type, "##########", val);
9708 return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
9709 }
9710 var oa = "";
9711 if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
9712 ri = Math.min(r[4].length,7);
9713 ff = frac(aval, Math.pow(10,ri)-1, false);
9714 o = "" + sign;
9715 oa = write_num("n", r[1], ff[1]);
9716 if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
9717 o += oa + r[2] + "/" + r[3];
9718 oa = rpad_(ff[2],ri);
9719 if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
9720 o += oa;
9721 return o;
9722 }
9723 if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
9724 ri = Math.min(Math.max(r[1].length, r[4].length),7);
9725 ff = frac(aval, Math.pow(10,ri)-1, true);
9726 return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
9727 }
9728 if((r = fmt.match(/^[#0?]+$/))) {
9729 o = pad0r(val, 0);
9730 if(fmt.length <= o.length) return o;
9731 return hashq(fmt.substr(0,fmt.length-o.length)) + o;
9732 }
9733 if((r = fmt.match(/^([#0?]+)\.([#0]+)$/))) {
9734 o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
9735 ri = o.indexOf(".");
9736 var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
9737 return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
9738 }
9739 if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
9740 ri = dec(val, r[1].length);
9741 return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(flr(val)).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(ri,r[1].length);
9742 }
9743 switch(fmt) {
9744 case "###,##0.00": return write_num_flt(type, "#,##0.00", val);
9745 case "###,###":
9746 case "##,###":
9747 case "#,###": var x = commaify(pad0r(aval,0)); return x !== "0" ? sign + x : "";
9748 case "###,###.00": return write_num_flt(type, "###,##0.00",val).replace(/^0\./,".");
9749 case "#,###.00": return write_num_flt(type, "#,##0.00",val).replace(/^0\./,".");
9750 default:
9751 }
9752 throw new Error("unsupported format |" + fmt + "|");
9753}
9754function write_num_cm2(type, fmt, val){
9755 var idx = fmt.length - 1;
9756 while(fmt.charCodeAt(idx-1) === 44) --idx;
9757 return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx)));
9758}
9759function write_num_pct2(type, fmt, val){
9760 var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length;
9761 return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul);
9762}
9763function write_num_exp2(fmt, val){
9764 var o;
9765 var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1;
9766 if(fmt.match(/^#+0.0E\+0$/)) {
9767 if(val == 0) return "0.0E+0";
9768 else if(val < 0) return "-" + write_num_exp2(fmt, -val);
9769 var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E');
9770 var ee = Math.floor(Math.log(val)*Math.LOG10E)%period;
9771 if(ee < 0) ee += period;
9772 o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period);
9773 if(!o.match(/[Ee]/)) {
9774 var fakee = Math.floor(Math.log(val)*Math.LOG10E);
9775 if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee);
9776 else o += "E+" + (fakee - ee);
9777 o = o.replace(/\+-/,"-");
9778 }
9779 o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; });
9780 } else o = val.toExponential(idx);
9781 if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1);
9782 if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e");
9783 return o.replace("e","E");
9784}
9785function write_num_int(type, fmt, val) {
9786 if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) {
9787 var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,"");
9788 if(val >= 0) return write_num_int('n', ffmt, val);
9789 return '(' + write_num_int('n', ffmt, -val) + ')';
9790 }
9791 if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm2(type, fmt, val);
9792 if(fmt.indexOf('%') !== -1) return write_num_pct2(type, fmt, val);
9793 if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val);
9794 if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt.charAt(1)==' '?2:1),val);
9795 var o;
9796 var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : "";
9797 if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length);
9798 if(fmt.match(/^[#?]+$/)) {
9799 o = (""+val); if(val === 0) o = "";
9800 return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o;
9801 }
9802 if((r = fmt.match(frac1))) return write_num_f2(r, aval, sign);
9803 if(fmt.match(/^#+0+$/)) return sign + pad0(aval,fmt.length - fmt.indexOf("0"));
9804 if((r = fmt.match(dec1))) {
9805o = (""+val).replace(/^([^\.]+)$/,"$1."+hashq(r[1])).replace(/\.$/,"."+hashq(r[1]));
9806 o = o.replace(/\.(\d*)$/,function($$, $1) {
9807return "." + $1 + fill("0", hashq(r[1]).length-$1.length); });
9808 return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,".");
9809 }
9810 fmt = fmt.replace(/^#+([0.])/, "$1");
9811 if((r = fmt.match(/^(0*)\.(#*)$/))) {
9812 return sign + (""+aval).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":".");
9813 }
9814 if((r = fmt.match(/^#{1,3},##0(\.?)$/))) return sign + commaify((""+aval));
9815 if((r = fmt.match(/^#,##0\.([#0]*0)$/))) {
9816 return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify((""+val)) + "." + fill('0',r[1].length);
9817 }
9818 if((r = fmt.match(/^#,#*,#0/))) return write_num_int(type,fmt.replace(/^#,#*,/,""),val);
9819 if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) {
9820 o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g,""), val));
9821 ri = 0;
9822 return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri<o.length?o.charAt(ri++):x==='0'?'0':"";}));
9823 }
9824 if(fmt.match(phone)) {
9825 o = write_num_int(type, "##########", val);
9826 return "(" + o.substr(0,3) + ") " + o.substr(3, 3) + "-" + o.substr(6);
9827 }
9828 var oa = "";
9829 if((r = fmt.match(/^([#0?]+)( ?)\/( ?)([#0?]+)/))) {
9830 ri = Math.min(r[4].length,7);
9831 ff = frac(aval, Math.pow(10,ri)-1, false);
9832 o = "" + sign;
9833 oa = write_num("n", r[1], ff[1]);
9834 if(oa.charAt(oa.length-1) == " ") oa = oa.substr(0,oa.length-1) + "0";
9835 o += oa + r[2] + "/" + r[3];
9836 oa = rpad_(ff[2],ri);
9837 if(oa.length < r[4].length) oa = hashq(r[4].substr(r[4].length-oa.length)) + oa;
9838 o += oa;
9839 return o;
9840 }
9841 if((r = fmt.match(/^# ([#0?]+)( ?)\/( ?)([#0?]+)/))) {
9842 ri = Math.min(Math.max(r[1].length, r[4].length),7);
9843 ff = frac(aval, Math.pow(10,ri)-1, true);
9844 return sign + (ff[0]||(ff[1] ? "" : "0")) + " " + (ff[1] ? pad_(ff[1],ri) + r[2] + "/" + r[3] + rpad_(ff[2],ri): fill(" ", 2*ri+1 + r[2].length + r[3].length));
9845 }
9846 if((r = fmt.match(/^[#0?]+$/))) {
9847 o = "" + val;
9848 if(fmt.length <= o.length) return o;
9849 return hashq(fmt.substr(0,fmt.length-o.length)) + o;
9850 }
9851 if((r = fmt.match(/^([#0]+)\.([#0]+)$/))) {
9852 o = "" + val.toFixed(Math.min(r[2].length,10)).replace(/([^0])0+$/,"$1");
9853 ri = o.indexOf(".");
9854 var lres = fmt.indexOf(".") - ri, rres = fmt.length - o.length - lres;
9855 return hashq(fmt.substr(0,lres) + o + fmt.substr(fmt.length-rres));
9856 }
9857 if((r = fmt.match(/^00,000\.([#0]*0)$/))) {
9858 return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify(""+val).replace(/^\d,\d{3}$/,"0$&").replace(/^\d*$/,function($$) { return "00," + ($$.length < 3 ? pad0(0,3-$$.length) : "") + $$; }) + "." + pad0(0,r[1].length);
9859 }
9860 switch(fmt) {
9861 case "###,###":
9862 case "##,###":
9863 case "#,###": var x = commaify(""+aval); return x !== "0" ? sign + x : "";
9864 default:
9865 if(fmt.match(/\.[0#?]*$/)) return write_num_int(type, fmt.slice(0,fmt.lastIndexOf(".")), val) + hashq(fmt.slice(fmt.lastIndexOf(".")));
9866 }
9867 throw new Error("unsupported format |" + fmt + "|");
9868}
9869return function write_num(type, fmt, val) {
9870 return (val|0) === val ? write_num_int(type, fmt, val) : write_num_flt(type, fmt, val);
9871};})();
9872function split_fmt(fmt) {
9873 var out = [];
9874 var in_str = false/*, cc*/;
9875 for(var i = 0, j = 0; i < fmt.length; ++i) switch((/*cc=*/fmt.charCodeAt(i))) {
9876 case 34: /* '"' */
9877 in_str = !in_str; break;
9878 case 95: case 42: case 92: /* '_' '*' '\\' */
9879 ++i; break;
9880 case 59: /* ';' */
9881 out[out.length] = fmt.substr(j,i-j);
9882 j = i+1;
9883 }
9884 out[out.length] = fmt.substr(j);
9885 if(in_str === true) throw new Error("Format |" + fmt + "| unterminated string ");
9886 return out;
9887}
9888SSF._split = split_fmt;
9889var abstime = /\[[HhMmSs]*\]/;
9890function fmt_is_date(fmt) {
9891 var i = 0, /*cc = 0,*/ c = "", o = "";
9892 while(i < fmt.length) {
9893 switch((c = fmt.charAt(i))) {
9894 case 'G': if(isgeneral(fmt, i)) i+= 6; i++; break;
9895 case '"': for(;(/*cc=*/fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) ++i; ++i; break;
9896 case '\\': i+=2; break;
9897 case '_': i+=2; break;
9898 case '@': ++i; break;
9899 case 'B': case 'b':
9900 if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") return true;
9901 /* falls through */
9902 case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
9903 /* falls through */
9904 case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g': return true;
9905 case 'A': case 'a':
9906 if(fmt.substr(i, 3).toUpperCase() === "A/P") return true;
9907 if(fmt.substr(i, 5).toUpperCase() === "AM/PM") return true;
9908 ++i; break;
9909 case '[':
9910 o = c;
9911 while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
9912 if(o.match(abstime)) return true;
9913 break;
9914 case '.':
9915 /* falls through */
9916 case '0': case '#':
9917 while(i < fmt.length && ("0#?.,E+-%".indexOf(c=fmt.charAt(++i)) > -1 || (c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1))){/* empty */}
9918 break;
9919 case '?': while(fmt.charAt(++i) === c){/* empty */} break;
9920 case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break;
9921 case '(': case ')': ++i; break;
9922 case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
9923 while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1){/* empty */} break;
9924 case ' ': ++i; break;
9925 default: ++i; break;
9926 }
9927 }
9928 return false;
9929}
9930SSF.is_date = fmt_is_date;
9931function eval_fmt(fmt, v, opts, flen) {
9932 var out = [], o = "", i = 0, c = "", lst='t', dt, j, cc;
9933 var hr='H';
9934 /* Tokenize */
9935 while(i < fmt.length) {
9936 switch((c = fmt.charAt(i))) {
9937 case 'G': /* General */
9938 if(!isgeneral(fmt, i)) throw new Error('unrecognized character ' + c + ' in ' +fmt);
9939 out[out.length] = {t:'G', v:'General'}; i+=7; break;
9940 case '"': /* Literal text */
9941 for(o="";(cc=fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) o += String.fromCharCode(cc);
9942 out[out.length] = {t:'t', v:o}; ++i; break;
9943 case '\\': var w = fmt.charAt(++i), t = (w === "(" || w === ")") ? w : 't';
9944 out[out.length] = {t:t, v:w}; ++i; break;
9945 case '_': out[out.length] = {t:'t', v:" "}; i+=2; break;
9946 case '@': /* Text Placeholder */
9947 out[out.length] = {t:'T', v:v}; ++i; break;
9948 case 'B': case 'b':
9949 if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") {
9950 if(dt==null) { dt=parse_date_code(v, opts, fmt.charAt(i+1) === "2"); if(dt==null) return ""; }
9951 out[out.length] = {t:'X', v:fmt.substr(i,2)}; lst = c; i+=2; break;
9952 }
9953 /* falls through */
9954 case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E':
9955 c = c.toLowerCase();
9956 /* falls through */
9957 case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g':
9958 if(v < 0) return "";
9959 if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
9960 o = c; while(++i < fmt.length && fmt.charAt(i).toLowerCase() === c) o+=c;
9961 if(c === 'm' && lst.toLowerCase() === 'h') c = 'M';
9962 if(c === 'h') c = hr;
9963 out[out.length] = {t:c, v:o}; lst = c; break;
9964 case 'A': case 'a':
9965 var q={t:c, v:c};
9966 if(dt==null) dt=parse_date_code(v, opts);
9967 if(fmt.substr(i, 3).toUpperCase() === "A/P") { if(dt!=null) q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;}
9968 else if(fmt.substr(i,5).toUpperCase() === "AM/PM") { if(dt!=null) q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; }
9969 else { q.t = "t"; ++i; }
9970 if(dt==null && q.t === 'T') return "";
9971 out[out.length] = q; lst = c; break;
9972 case '[':
9973 o = c;
9974 while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i);
9975 if(o.slice(-1) !== ']') throw 'unterminated "[" block: |' + o + '|';
9976 if(o.match(abstime)) {
9977 if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; }
9978 out[out.length] = {t:'Z', v:o.toLowerCase()};
9979 lst = o.charAt(1);
9980 } else if(o.indexOf("$") > -1) {
9981 o = (o.match(/\$([^-\[\]]*)/)||[])[1]||"$";
9982 if(!fmt_is_date(fmt)) out[out.length] = {t:'t',v:o};
9983 }
9984 break;
9985 /* Numbers */
9986 case '.':
9987 if(dt != null) {
9988 o = c; while(++i < fmt.length && (c=fmt.charAt(i)) === "0") o += c;
9989 out[out.length] = {t:'s', v:o}; break;
9990 }
9991 /* falls through */
9992 case '0': case '#':
9993 o = c; while((++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1) || (c=='\\' && fmt.charAt(i+1) == "-" && i < fmt.length - 2 && "0#".indexOf(fmt.charAt(i+2))>-1)) o += c;
9994 out[out.length] = {t:'n', v:o}; break;
9995 case '?':
9996 o = c; while(fmt.charAt(++i) === c) o+=c;
9997 out[out.length] = {t:c, v:o}; lst = c; break;
9998 case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break; // **
9999 case '(': case ')': out[out.length] = {t:(flen===1?'t':c), v:c}; ++i; break;
10000 case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
10001 o = c; while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1) o+=fmt.charAt(i);
10002 out[out.length] = {t:'D', v:o}; break;
10003 case ' ': out[out.length] = {t:c, v:c}; ++i; break;
10004 default:
10005 if(",$-+/():!^&'~{}<>=€acfijklopqrtuvwxzP".indexOf(c) === -1) throw new Error('unrecognized character ' + c + ' in ' + fmt);
10006 out[out.length] = {t:'t', v:c}; ++i; break;
10007 }
10008 }
10009 var bt = 0, ss0 = 0, ssm;
10010 for(i=out.length-1, lst='t'; i >= 0; --i) {
10011 switch(out[i].t) {
10012 case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break;
10013 case 's':
10014 if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1);
10015 if(bt < 3) bt = 3;
10016 /* falls through */
10017 case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break;
10018 case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break;
10019 case 'X': /*if(out[i].v === "B2");*/
10020 break;
10021 case 'Z':
10022 if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1;
10023 if(bt < 2 && out[i].v.match(/[Mm]/)) bt = 2;
10024 if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3;
10025 }
10026 }
10027 switch(bt) {
10028 case 0: break;
10029 case 1:
10030if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
10031 if(dt.S >= 60) { dt.S = 0; ++dt.M; }
10032 if(dt.M >= 60) { dt.M = 0; ++dt.H; }
10033 break;
10034 case 2:
10035if(dt.u >= 0.5) { dt.u = 0; ++dt.S; }
10036 if(dt.S >= 60) { dt.S = 0; ++dt.M; }
10037 break;
10038 }
10039 /* replace fields */
10040 var nstr = "", jj;
10041 for(i=0; i < out.length; ++i) {
10042 switch(out[i].t) {
10043 case 't': case 'T': case ' ': case 'D': break;
10044 case 'X': out[i].v = ""; out[i].t = ";"; break;
10045 case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'b': case 'Z':
10046out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0);
10047 out[i].t = 't'; break;
10048 case 'n': case '(': case '?':
10049 jj = i+1;
10050 while(out[jj] != null && (
10051 (c=out[jj].t) === "?" || c === "D" ||
10052 ((c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/')) ||
10053 (out[i].t === '(' && (c === ' ' || c === 'n' || c === ')')) ||
10054 (c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?'))
10055 )) {
10056 out[i].v += out[jj].v;
10057 out[jj] = {v:"", t:";"}; ++jj;
10058 }
10059 nstr += out[i].v;
10060 i = jj-1; break;
10061 case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break;
10062 }
10063 }
10064 var vv = "", myv, ostr;
10065 if(nstr.length > 0) {
10066 if(nstr.charCodeAt(0) == 40) /* '(' */ {
10067 myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v);
10068 ostr = write_num('(', nstr, myv);
10069 } else {
10070 myv = (v<0 && flen > 1 ? -v : v);
10071 ostr = write_num('n', nstr, myv);
10072 if(myv < 0 && out[0] && out[0].t == 't') {
10073 ostr = ostr.substr(1);
10074 out[0].v = "-" + out[0].v;
10075 }
10076 }
10077 jj=ostr.length-1;
10078 var decpt = out.length;
10079 for(i=0; i < out.length; ++i) if(out[i] != null && out[i].t != 't' && out[i].v.indexOf(".") > -1) { decpt = i; break; }
10080 var lasti=out.length;
10081 if(decpt === out.length && ostr.indexOf("E") === -1) {
10082 for(i=out.length-1; i>= 0;--i) {
10083 if(out[i] == null || 'n?('.indexOf(out[i].t) === -1) continue;
10084 if(jj>=out[i].v.length-1) { jj -= out[i].v.length; out[i].v = ostr.substr(jj+1, out[i].v.length); }
10085 else if(jj < 0) out[i].v = "";
10086 else { out[i].v = ostr.substr(0, jj+1); jj = -1; }
10087 out[i].t = 't';
10088 lasti = i;
10089 }
10090 if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
10091 }
10092 else if(decpt !== out.length && ostr.indexOf("E") === -1) {
10093 jj = ostr.indexOf(".")-1;
10094 for(i=decpt; i>= 0; --i) {
10095 if(out[i] == null || 'n?('.indexOf(out[i].t) === -1) continue;
10096 j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1;
10097 vv = out[i].v.substr(j+1);
10098 for(; j>=0; --j) {
10099 if(jj>=0 && (out[i].v.charAt(j) === "0" || out[i].v.charAt(j) === "#")) vv = ostr.charAt(jj--) + vv;
10100 }
10101 out[i].v = vv;
10102 out[i].t = 't';
10103 lasti = i;
10104 }
10105 if(jj>=0 && lasti<out.length) out[lasti].v = ostr.substr(0,jj+1) + out[lasti].v;
10106 jj = ostr.indexOf(".")+1;
10107 for(i=decpt; i<out.length; ++i) {
10108 if(out[i] == null || ('n?('.indexOf(out[i].t) === -1 && i !== decpt)) continue;
10109 j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")+1:0;
10110 vv = out[i].v.substr(0,j);
10111 for(; j<out[i].v.length; ++j) {
10112 if(jj<ostr.length) vv += ostr.charAt(jj++);
10113 }
10114 out[i].v = vv;
10115 out[i].t = 't';
10116 lasti = i;
10117 }
10118 }
10119 }
10120 for(i=0; i<out.length; ++i) if(out[i] != null && 'n(?'.indexOf(out[i].t)>-1) {
10121 myv = (flen >1 && v < 0 && i>0 && out[i-1].v === "-" ? -v:v);
10122 out[i].v = write_num(out[i].t, out[i].v, myv);
10123 out[i].t = 't';
10124 }
10125 var retval = "";
10126 for(i=0; i !== out.length; ++i) if(out[i] != null) retval += out[i].v;
10127 return retval;
10128}
10129SSF._eval = eval_fmt;
10130var cfregex = /\[[=<>]/;
10131var cfregex2 = /\[(=|>[=]?|<[>=]?)(-?\d+(?:\.\d*)?)\]/;
10132function chkcond(v, rr) {
10133 if(rr == null) return false;
10134 var thresh = parseFloat(rr[2]);
10135 switch(rr[1]) {
10136 case "=": if(v == thresh) return true; break;
10137 case ">": if(v > thresh) return true; break;
10138 case "<": if(v < thresh) return true; break;
10139 case "<>": if(v != thresh) return true; break;
10140 case ">=": if(v >= thresh) return true; break;
10141 case "<=": if(v <= thresh) return true; break;
10142 }
10143 return false;
10144}
10145function choose_fmt(f, v) {
10146 var fmt = split_fmt(f);
10147 var l = fmt.length, lat = fmt[l-1].indexOf("@");
10148 if(l<4 && lat>-1) --l;
10149 if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|");
10150 if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"];
10151 switch(fmt.length) {
10152 case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break;
10153 case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break;
10154 case 3: fmt = lat>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break;
10155 case 4: break;
10156 }
10157 var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2];
10158 if(fmt[0].indexOf("[") === -1 && fmt[1].indexOf("[") === -1) return [l, ff];
10159 if(fmt[0].match(cfregex) != null || fmt[1].match(cfregex) != null) {
10160 var m1 = fmt[0].match(cfregex2);
10161 var m2 = fmt[1].match(cfregex2);
10162 return chkcond(v, m1) ? [l, fmt[0]] : chkcond(v, m2) ? [l, fmt[1]] : [l, fmt[m1 != null && m2 != null ? 2 : 1]];
10163 }
10164 return [l, ff];
10165}
10166function format(fmt,v,o) {
10167 if(o == null) o = {};
10168 var sfmt = "";
10169 switch(typeof fmt) {
10170 case "string":
10171 if(fmt == "m/d/yy" && o.dateNF) sfmt = o.dateNF;
10172 else sfmt = fmt;
10173 break;
10174 case "number":
10175 if(fmt == 14 && o.dateNF) sfmt = o.dateNF;
10176 else sfmt = (o.table != null ? (o.table) : table_fmt)[fmt];
10177 break;
10178 }
10179 if(isgeneral(sfmt,0)) return general_fmt(v, o);
10180 if(v instanceof Date) v = datenum_local(v, o.date1904);
10181 var f = choose_fmt(sfmt, v);
10182 if(isgeneral(f[1])) return general_fmt(v, o);
10183 if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
10184 else if(v === "" || v == null) return "";
10185 return eval_fmt(f[1], v, o, f[0]);
10186}
10187function load_entry(fmt, idx) {
10188 if(typeof idx != 'number') {
10189 idx = +idx || -1;
10190for(var i = 0; i < 0x0188; ++i) {
10191if(table_fmt[i] == undefined) { if(idx < 0) idx = i; continue; }
10192 if(table_fmt[i] == fmt) { idx = i; break; }
10193 }
10194if(idx < 0) idx = 0x187;
10195 }
10196table_fmt[idx] = fmt;
10197 return idx;
10198}
10199SSF.load = load_entry;
10200SSF._table = table_fmt;
10201SSF.get_table = function get_table() { return table_fmt; };
10202SSF.load_table = function load_table(tbl) {
10203 for(var i=0; i!=0x0188; ++i)
10204 if(tbl[i] !== undefined) load_entry(tbl[i], i);
10205};
10206SSF.init_table = init_table;
10207SSF.format = format;
10208};
10209make_ssf(SSF);
10210/* map from xlml named formats to SSF TODO: localize */
10211var XLMLFormatMap/*{[string]:string}*/ = ({
10212 "General Number": "General",
10213 "General Date": SSF._table[22],
10214 "Long Date": "dddd, mmmm dd, yyyy",
10215 "Medium Date": SSF._table[15],
10216 "Short Date": SSF._table[14],
10217 "Long Time": SSF._table[19],
10218 "Medium Time": SSF._table[18],
10219 "Short Time": SSF._table[20],
10220 "Currency": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
10221 "Fixed": SSF._table[2],
10222 "Standard": SSF._table[4],
10223 "Percent": SSF._table[10],
10224 "Scientific": SSF._table[11],
10225 "Yes/No": '"Yes";"Yes";"No";@',
10226 "True/False": '"True";"True";"False";@',
10227 "On/Off": '"Yes";"Yes";"No";@'
10228});
10229
10230var SSFImplicit/*{[number]:string}*/ = ({
10231 "5": '"$"#,##0_);\\("$"#,##0\\)',
10232 "6": '"$"#,##0_);[Red]\\("$"#,##0\\)',
10233 "7": '"$"#,##0.00_);\\("$"#,##0.00\\)',
10234 "8": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
10235 "23": 'General', "24": 'General', "25": 'General', "26": 'General',
10236 "27": 'm/d/yy', "28": 'm/d/yy', "29": 'm/d/yy', "30": 'm/d/yy', "31": 'm/d/yy',
10237 "32": 'h:mm:ss', "33": 'h:mm:ss', "34": 'h:mm:ss', "35": 'h:mm:ss',
10238 "36": 'm/d/yy',
10239 "41": '_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)',
10240 "42": '_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)',
10241 "43": '_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)',
10242 "44": '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)',
10243 "50": 'm/d/yy', "51": 'm/d/yy', "52": 'm/d/yy', "53": 'm/d/yy', "54": 'm/d/yy',
10244 "55": 'm/d/yy', "56": 'm/d/yy', "57": 'm/d/yy', "58": 'm/d/yy',
10245 "59": '0',
10246 "60": '0.00',
10247 "61": '#,##0',
10248 "62": '#,##0.00',
10249 "63": '"$"#,##0_);\\("$"#,##0\\)',
10250 "64": '"$"#,##0_);[Red]\\("$"#,##0\\)',
10251 "65": '"$"#,##0.00_);\\("$"#,##0.00\\)',
10252 "66": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)',
10253 "67": '0%',
10254 "68": '0.00%',
10255 "69": '# ?/?',
10256 "70": '# ??/??',
10257 "71": 'm/d/yy',
10258 "72": 'm/d/yy',
10259 "73": 'd-mmm-yy',
10260 "74": 'd-mmm',
10261 "75": 'mmm-yy',
10262 "76": 'h:mm',
10263 "77": 'h:mm:ss',
10264 "78": 'm/d/yy h:mm',
10265 "79": 'mm:ss',
10266 "80": '[h]:mm:ss',
10267 "81": 'mmss.0'
10268});
10269
10270/* dateNF parse TODO: move to SSF */
10271var dateNFregex = /[dD]+|[mM]+|[yYeE]+|[Hh]+|[Ss]+/g;
10272function dateNF_regex(dateNF) {
10273 var fmt = typeof dateNF == "number" ? SSF._table[dateNF] : dateNF;
10274 fmt = fmt.replace(dateNFregex, "(\\d+)");
10275 return new RegExp("^" + fmt + "$");
10276}
10277function dateNF_fix(str, dateNF, match) {
10278 var Y = -1, m = -1, d = -1, H = -1, M = -1, S = -1;
10279 (dateNF.match(dateNFregex)||[]).forEach(function(n, i) {
10280 var v = parseInt(match[i+1], 10);
10281 switch(n.toLowerCase().charAt(0)) {
10282 case 'y': Y = v; break; case 'd': d = v; break;
10283 case 'h': H = v; break; case 's': S = v; break;
10284 case 'm': if(H >= 0) M = v; else m = v; break;
10285 }
10286 });
10287 if(S >= 0 && M == -1 && m >= 0) { M = m; m = -1; }
10288 var datestr = (("" + (Y>=0?Y: new Date().getFullYear())).slice(-4) + "-" + ("00" + (m>=1?m:1)).slice(-2) + "-" + ("00" + (d>=1?d:1)).slice(-2));
10289 if(datestr.length == 7) datestr = "0" + datestr;
10290 if(datestr.length == 8) datestr = "20" + datestr;
10291 var timestr = (("00" + (H>=0?H:0)).slice(-2) + ":" + ("00" + (M>=0?M:0)).slice(-2) + ":" + ("00" + (S>=0?S:0)).slice(-2));
10292 if(H == -1 && M == -1 && S == -1) return datestr;
10293 if(Y == -1 && m == -1 && d == -1) return timestr;
10294 return datestr + "T" + timestr;
10295}
10296
10297var DO_NOT_EXPORT_CFB = true;
10298/* cfb.js (C) 2013-present SheetJS -- http://sheetjs.com */
10299/* vim: set ts=2: */
10300/*jshint eqnull:true */
10301/*exported CFB */
10302/*global module, require:false, process:false, Buffer:false, Uint8Array:false, Uint16Array:false */
10303
10304/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
10305/* vim: set ts=2: */
10306/*exported CRC32 */
10307var CRC32;
10308(function (factory) {
10309 /*jshint ignore:start */
10310 /*eslint-disable */
10311 factory(CRC32 = {});
10312 /*eslint-enable */
10313 /*jshint ignore:end */
10314}(function(CRC32) {
10315CRC32.version = '1.2.0';
10316/* see perf/crc32table.js */
10317/*global Int32Array */
10318function signed_crc_table() {
10319 var c = 0, table = new Array(256);
10320
10321 for(var n =0; n != 256; ++n){
10322 c = n;
10323 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
10324 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
10325 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
10326 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
10327 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
10328 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
10329 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
10330 c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
10331 table[n] = c;
10332 }
10333
10334 return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table;
10335}
10336
10337var T = signed_crc_table();
10338function crc32_bstr(bstr, seed) {
10339 var C = seed ^ -1, L = bstr.length - 1;
10340 for(var i = 0; i < L;) {
10341 C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
10342 C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF];
10343 }
10344 if(i === L) C = (C>>>8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF];
10345 return C ^ -1;
10346}
10347
10348function crc32_buf(buf, seed) {
10349 if(buf.length > 10000) return crc32_buf_8(buf, seed);
10350 var C = seed ^ -1, L = buf.length - 3;
10351 for(var i = 0; i < L;) {
10352 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
10353 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
10354 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
10355 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
10356 }
10357 while(i < L+3) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
10358 return C ^ -1;
10359}
10360
10361function crc32_buf_8(buf, seed) {
10362 var C = seed ^ -1, L = buf.length - 7;
10363 for(var i = 0; i < L;) {
10364 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
10365 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
10366 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
10367 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
10368 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
10369 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
10370 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
10371 C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
10372 }
10373 while(i < L+7) C = (C>>>8) ^ T[(C^buf[i++])&0xFF];
10374 return C ^ -1;
10375}
10376
10377function crc32_str(str, seed) {
10378 var C = seed ^ -1;
10379 for(var i = 0, L=str.length, c, d; i < L;) {
10380 c = str.charCodeAt(i++);
10381 if(c < 0x80) {
10382 C = (C>>>8) ^ T[(C ^ c)&0xFF];
10383 } else if(c < 0x800) {
10384 C = (C>>>8) ^ T[(C ^ (192|((c>>6)&31)))&0xFF];
10385 C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF];
10386 } else if(c >= 0xD800 && c < 0xE000) {
10387 c = (c&1023)+64; d = str.charCodeAt(i++)&1023;
10388 C = (C>>>8) ^ T[(C ^ (240|((c>>8)&7)))&0xFF];
10389 C = (C>>>8) ^ T[(C ^ (128|((c>>2)&63)))&0xFF];
10390 C = (C>>>8) ^ T[(C ^ (128|((d>>6)&15)|((c&3)<<4)))&0xFF];
10391 C = (C>>>8) ^ T[(C ^ (128|(d&63)))&0xFF];
10392 } else {
10393 C = (C>>>8) ^ T[(C ^ (224|((c>>12)&15)))&0xFF];
10394 C = (C>>>8) ^ T[(C ^ (128|((c>>6)&63)))&0xFF];
10395 C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF];
10396 }
10397 }
10398 return C ^ -1;
10399}
10400CRC32.table = T;
10401CRC32.bstr = crc32_bstr;
10402CRC32.buf = crc32_buf;
10403CRC32.str = crc32_str;
10404}));
10405/* [MS-CFB] v20171201 */
10406var CFB = (function _CFB(){
10407var exports = {};
10408exports.version = '1.1.3';
10409/* [MS-CFB] 2.6.4 */
10410function namecmp(l, r) {
10411 var L = l.split("/"), R = r.split("/");
10412 for(var i = 0, c = 0, Z = Math.min(L.length, R.length); i < Z; ++i) {
10413 if((c = L[i].length - R[i].length)) return c;
10414 if(L[i] != R[i]) return L[i] < R[i] ? -1 : 1;
10415 }
10416 return L.length - R.length;
10417}
10418function dirname(p) {
10419 if(p.charAt(p.length - 1) == "/") return (p.slice(0,-1).indexOf("/") === -1) ? p : dirname(p.slice(0, -1));
10420 var c = p.lastIndexOf("/");
10421 return (c === -1) ? p : p.slice(0, c+1);
10422}
10423
10424function filename(p) {
10425 if(p.charAt(p.length - 1) == "/") return filename(p.slice(0, -1));
10426 var c = p.lastIndexOf("/");
10427 return (c === -1) ? p : p.slice(c+1);
10428}
10429/* -------------------------------------------------------------------------- */
10430/* DOS Date format:
10431 high|YYYYYYYm.mmmddddd.HHHHHMMM.MMMSSSSS|low
10432 add 1980 to stored year
10433 stored second should be doubled
10434*/
10435
10436/* write JS date to buf as a DOS date */
10437function write_dos_date(buf, date) {
10438 if(typeof date === "string") date = new Date(date);
10439 var hms = date.getHours();
10440 hms = hms << 6 | date.getMinutes();
10441 hms = hms << 5 | (date.getSeconds()>>>1);
10442 buf.write_shift(2, hms);
10443 var ymd = (date.getFullYear() - 1980);
10444 ymd = ymd << 4 | (date.getMonth()+1);
10445 ymd = ymd << 5 | date.getDate();
10446 buf.write_shift(2, ymd);
10447}
10448
10449/* read four bytes from buf and interpret as a DOS date */
10450function parse_dos_date(buf) {
10451 var hms = buf.read_shift(2) & 0xFFFF;
10452 var ymd = buf.read_shift(2) & 0xFFFF;
10453 var val = new Date();
10454 var d = ymd & 0x1F; ymd >>>= 5;
10455 var m = ymd & 0x0F; ymd >>>= 4;
10456 val.setMilliseconds(0);
10457 val.setFullYear(ymd + 1980);
10458 val.setMonth(m-1);
10459 val.setDate(d);
10460 var S = hms & 0x1F; hms >>>= 5;
10461 var M = hms & 0x3F; hms >>>= 6;
10462 val.setHours(hms);
10463 val.setMinutes(M);
10464 val.setSeconds(S<<1);
10465 return val;
10466}
10467function parse_extra_field(blob) {
10468 prep_blob(blob, 0);
10469 var o = {};
10470 var flags = 0;
10471 while(blob.l <= blob.length - 4) {
10472 var type = blob.read_shift(2);
10473 var sz = blob.read_shift(2), tgt = blob.l + sz;
10474 var p = {};
10475 switch(type) {
10476 /* UNIX-style Timestamps */
10477 case 0x5455: {
10478 flags = blob.read_shift(1);
10479 if(flags & 1) p.mtime = blob.read_shift(4);
10480 /* for some reason, CD flag corresponds to LFH */
10481 if(sz > 5) {
10482 if(flags & 2) p.atime = blob.read_shift(4);
10483 if(flags & 4) p.ctime = blob.read_shift(4);
10484 }
10485 if(p.mtime) p.mt = new Date(p.mtime*1000);
10486 }
10487 break;
10488 }
10489 blob.l = tgt;
10490 o[type] = p;
10491 }
10492 return o;
10493}
10494var fs;
10495function get_fs() { return fs || (fs = require('fs')); }
10496function parse(file, options) {
10497if(file[0] == 0x50 && file[1] == 0x4b) return parse_zip(file, options);
10498if(file.length < 512) throw new Error("CFB file size " + file.length + " < 512");
10499var mver = 3;
10500var ssz = 512;
10501var nmfs = 0; // number of mini FAT sectors
10502var difat_sec_cnt = 0;
10503var dir_start = 0;
10504var minifat_start = 0;
10505var difat_start = 0;
10506
10507var fat_addrs = []; // locations of FAT sectors
10508
10509/* [MS-CFB] 2.2 Compound File Header */
10510var blob = file.slice(0,512);
10511prep_blob(blob, 0);
10512
10513/* major version */
10514var mv = check_get_mver(blob);
10515mver = mv[0];
10516switch(mver) {
10517 case 3: ssz = 512; break; case 4: ssz = 4096; break;
10518 case 0: if(mv[1] == 0) return parse_zip(file, options);
10519 /* falls through */
10520 default: throw new Error("Major Version: Expected 3 or 4 saw " + mver);
10521}
10522
10523/* reprocess header */
10524if(ssz !== 512) { blob = file.slice(0,ssz); prep_blob(blob, 28 /* blob.l */); }
10525/* Save header for final object */
10526var header = file.slice(0,ssz);
10527
10528check_shifts(blob, mver);
10529
10530// Number of Directory Sectors
10531var dir_cnt = blob.read_shift(4, 'i');
10532if(mver === 3 && dir_cnt !== 0) throw new Error('# Directory Sectors: Expected 0 saw ' + dir_cnt);
10533
10534// Number of FAT Sectors
10535blob.l += 4;
10536
10537// First Directory Sector Location
10538dir_start = blob.read_shift(4, 'i');
10539
10540// Transaction Signature
10541blob.l += 4;
10542
10543// Mini Stream Cutoff Size
10544blob.chk('00100000', 'Mini Stream Cutoff Size: ');
10545
10546// First Mini FAT Sector Location
10547minifat_start = blob.read_shift(4, 'i');
10548
10549// Number of Mini FAT Sectors
10550nmfs = blob.read_shift(4, 'i');
10551
10552// First DIFAT sector location
10553difat_start = blob.read_shift(4, 'i');
10554
10555// Number of DIFAT Sectors
10556difat_sec_cnt = blob.read_shift(4, 'i');
10557
10558// Grab FAT Sector Locations
10559for(var q = -1, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */
10560 q = blob.read_shift(4, 'i');
10561 if(q<0) break;
10562 fat_addrs[j] = q;
10563}
10564
10565/** Break the file up into sectors */
10566var sectors = sectorify(file, ssz);
10567
10568sleuth_fat(difat_start, difat_sec_cnt, sectors, ssz, fat_addrs);
10569
10570/** Chains */
10571var sector_list = make_sector_list(sectors, dir_start, fat_addrs, ssz);
10572
10573sector_list[dir_start].name = "!Directory";
10574if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT";
10575sector_list[fat_addrs[0]].name = "!FAT";
10576sector_list.fat_addrs = fat_addrs;
10577sector_list.ssz = ssz;
10578
10579/* [MS-CFB] 2.6.1 Compound File Directory Entry */
10580var files = {}, Paths = [], FileIndex = [], FullPaths = [];
10581read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex, minifat_start);
10582
10583build_full_paths(FileIndex, FullPaths, Paths);
10584Paths.shift();
10585
10586var o = {
10587 FileIndex: FileIndex,
10588 FullPaths: FullPaths
10589};
10590
10591// $FlowIgnore
10592if(options && options.raw) o.raw = {header: header, sectors: sectors};
10593return o;
10594} // parse
10595
10596/* [MS-CFB] 2.2 Compound File Header -- read up to major version */
10597function check_get_mver(blob) {
10598 if(blob[blob.l] == 0x50 && blob[blob.l + 1] == 0x4b) return [0, 0];
10599 // header signature 8
10600 blob.chk(HEADER_SIGNATURE, 'Header Signature: ');
10601
10602 // clsid 16
10603 //blob.chk(HEADER_CLSID, 'CLSID: ');
10604 blob.l += 16;
10605
10606 // minor version 2
10607 var mver = blob.read_shift(2, 'u');
10608
10609 return [blob.read_shift(2,'u'), mver];
10610}
10611function check_shifts(blob, mver) {
10612 var shift = 0x09;
10613
10614 // Byte Order
10615 //blob.chk('feff', 'Byte Order: '); // note: some writers put 0xffff
10616 blob.l += 2;
10617
10618 // Sector Shift
10619 switch((shift = blob.read_shift(2))) {
10620 case 0x09: if(mver != 3) throw new Error('Sector Shift: Expected 9 saw ' + shift); break;
10621 case 0x0c: if(mver != 4) throw new Error('Sector Shift: Expected 12 saw ' + shift); break;
10622 default: throw new Error('Sector Shift: Expected 9 or 12 saw ' + shift);
10623 }
10624
10625 // Mini Sector Shift
10626 blob.chk('0600', 'Mini Sector Shift: ');
10627
10628 // Reserved
10629 blob.chk('000000000000', 'Reserved: ');
10630}
10631
10632/** Break the file up into sectors */
10633function sectorify(file, ssz) {
10634 var nsectors = Math.ceil(file.length/ssz)-1;
10635 var sectors = [];
10636 for(var i=1; i < nsectors; ++i) sectors[i-1] = file.slice(i*ssz,(i+1)*ssz);
10637 sectors[nsectors-1] = file.slice(nsectors*ssz);
10638 return sectors;
10639}
10640
10641/* [MS-CFB] 2.6.4 Red-Black Tree */
10642function build_full_paths(FI, FP, Paths) {
10643 var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length;
10644 var dad = [], q = [];
10645
10646 for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; }
10647
10648 for(; j < q.length; ++j) {
10649 i = q[j];
10650 L = FI[i].L; R = FI[i].R; C = FI[i].C;
10651 if(dad[i] === i) {
10652 if(L !== -1 /*NOSTREAM*/ && dad[L] !== L) dad[i] = dad[L];
10653 if(R !== -1 && dad[R] !== R) dad[i] = dad[R];
10654 }
10655 if(C !== -1 /*NOSTREAM*/) dad[C] = i;
10656 if(L !== -1 && i != dad[i]) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); }
10657 if(R !== -1 && i != dad[i]) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); }
10658 }
10659 for(i=1; i < pl; ++i) if(dad[i] === i) {
10660 if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R];
10661 else if(L !== -1 && dad[L] !== L) dad[i] = dad[L];
10662 }
10663
10664 for(i=1; i < pl; ++i) {
10665 if(FI[i].type === 0 /* unknown */) continue;
10666 j = i;
10667 if(j != dad[j]) do {
10668 j = dad[j];
10669 FP[i] = FP[j] + "/" + FP[i];
10670 } while (j !== 0 && -1 !== dad[j] && j != dad[j]);
10671 dad[i] = -1;
10672 }
10673
10674 FP[0] += "/";
10675 for(i=1; i < pl; ++i) {
10676 if(FI[i].type !== 2 /* stream */) FP[i] += "/";
10677 }
10678}
10679
10680function get_mfat_entry(entry, payload, mini) {
10681 var start = entry.start, size = entry.size;
10682 //return (payload.slice(start*MSSZ, start*MSSZ + size));
10683 var o = [];
10684 var idx = start;
10685 while(mini && size > 0 && idx >= 0) {
10686 o.push(payload.slice(idx * MSSZ, idx * MSSZ + MSSZ));
10687 size -= MSSZ;
10688 idx = __readInt32LE(mini, idx * 4);
10689 }
10690 if(o.length === 0) return (new_buf(0));
10691 return (bconcat(o).slice(0, entry.size));
10692}
10693
10694/** Chase down the rest of the DIFAT chain to build a comprehensive list
10695 DIFAT chains by storing the next sector number as the last 32 bits */
10696function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) {
10697 var q = ENDOFCHAIN;
10698 if(idx === ENDOFCHAIN) {
10699 if(cnt !== 0) throw new Error("DIFAT chain shorter than expected");
10700 } else if(idx !== -1 /*FREESECT*/) {
10701 var sector = sectors[idx], m = (ssz>>>2)-1;
10702 if(!sector) return;
10703 for(var i = 0; i < m; ++i) {
10704 if((q = __readInt32LE(sector,i*4)) === ENDOFCHAIN) break;
10705 fat_addrs.push(q);
10706 }
10707 sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs);
10708 }
10709}
10710
10711/** Follow the linked list of sectors for a given starting point */
10712function get_sector_list(sectors, start, fat_addrs, ssz, chkd) {
10713 var buf = [], buf_chain = [];
10714 if(!chkd) chkd = [];
10715 var modulus = ssz - 1, j = 0, jj = 0;
10716 for(j=start; j>=0;) {
10717 chkd[j] = true;
10718 buf[buf.length] = j;
10719 buf_chain.push(sectors[j]);
10720 var addr = fat_addrs[Math.floor(j*4/ssz)];
10721 jj = ((j*4) & modulus);
10722 if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz);
10723 if(!sectors[addr]) break;
10724 j = __readInt32LE(sectors[addr], jj);
10725 }
10726 return {nodes: buf, data:__toBuffer([buf_chain])};
10727}
10728
10729/** Chase down the sector linked lists */
10730function make_sector_list(sectors, dir_start, fat_addrs, ssz) {
10731 var sl = sectors.length, sector_list = ([]);
10732 var chkd = [], buf = [], buf_chain = [];
10733 var modulus = ssz - 1, i=0, j=0, k=0, jj=0;
10734 for(i=0; i < sl; ++i) {
10735 buf = ([]);
10736 k = (i + dir_start); if(k >= sl) k-=sl;
10737 if(chkd[k]) continue;
10738 buf_chain = [];
10739 for(j=k; j>=0;) {
10740 chkd[j] = true;
10741 buf[buf.length] = j;
10742 buf_chain.push(sectors[j]);
10743 var addr = fat_addrs[Math.floor(j*4/ssz)];
10744 jj = ((j*4) & modulus);
10745 if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz);
10746 if(!sectors[addr]) break;
10747 j = __readInt32LE(sectors[addr], jj);
10748 }
10749 sector_list[k] = ({nodes: buf, data:__toBuffer([buf_chain])});
10750 }
10751 return sector_list;
10752}
10753
10754/* [MS-CFB] 2.6.1 Compound File Directory Entry */
10755function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex, mini) {
10756 var minifat_store = 0, pl = (Paths.length?2:0);
10757 var sector = sector_list[dir_start].data;
10758 var i = 0, namelen = 0, name;
10759 for(; i < sector.length; i+= 128) {
10760 var blob = sector.slice(i, i+128);
10761 prep_blob(blob, 64);
10762 namelen = blob.read_shift(2);
10763 name = __utf16le(blob,0,namelen-pl);
10764 Paths.push(name);
10765 var o = ({
10766 name: name,
10767 type: blob.read_shift(1),
10768 color: blob.read_shift(1),
10769 L: blob.read_shift(4, 'i'),
10770 R: blob.read_shift(4, 'i'),
10771 C: blob.read_shift(4, 'i'),
10772 clsid: blob.read_shift(16),
10773 state: blob.read_shift(4, 'i'),
10774 start: 0,
10775 size: 0
10776 });
10777 var ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2);
10778 if(ctime !== 0) o.ct = read_date(blob, blob.l-8);
10779 var mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2);
10780 if(mtime !== 0) o.mt = read_date(blob, blob.l-8);
10781 o.start = blob.read_shift(4, 'i');
10782 o.size = blob.read_shift(4, 'i');
10783 if(o.size < 0 && o.start < 0) { o.size = o.type = 0; o.start = ENDOFCHAIN; o.name = ""; }
10784 if(o.type === 5) { /* root */
10785 minifat_store = o.start;
10786 if(nmfs > 0 && minifat_store !== ENDOFCHAIN) sector_list[minifat_store].name = "!StreamData";
10787 /*minifat_size = o.size;*/
10788 } else if(o.size >= 4096 /* MSCSZ */) {
10789 o.storage = 'fat';
10790 if(sector_list[o.start] === undefined) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz);
10791 sector_list[o.start].name = o.name;
10792 o.content = (sector_list[o.start].data.slice(0,o.size));
10793 } else {
10794 o.storage = 'minifat';
10795 if(o.size < 0) o.size = 0;
10796 else if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) {
10797 o.content = get_mfat_entry(o, sector_list[minifat_store].data, (sector_list[mini]||{}).data);
10798 }
10799 }
10800 if(o.content) prep_blob(o.content, 0);
10801 files[name] = o;
10802 FileIndex.push(o);
10803 }
10804}
10805
10806function read_date(blob, offset) {
10807 return new Date(( ( (__readUInt32LE(blob,offset+4)/1e7)*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7 ) - 11644473600)*1000);
10808}
10809
10810function read_file(filename, options) {
10811 get_fs();
10812 return parse(fs.readFileSync(filename), options);
10813}
10814
10815function read(blob, options) {
10816 switch(options && options.type || "base64") {
10817 case "file": return read_file(blob, options);
10818 case "base64": return parse(s2a(Base64.decode(blob)), options);
10819 case "binary": return parse(s2a(blob), options);
10820 }
10821 return parse(blob, options);
10822}
10823
10824function init_cfb(cfb, opts) {
10825 var o = opts || {}, root = o.root || "Root Entry";
10826 if(!cfb.FullPaths) cfb.FullPaths = [];
10827 if(!cfb.FileIndex) cfb.FileIndex = [];
10828 if(cfb.FullPaths.length !== cfb.FileIndex.length) throw new Error("inconsistent CFB structure");
10829 if(cfb.FullPaths.length === 0) {
10830 cfb.FullPaths[0] = root + "/";
10831 cfb.FileIndex[0] = ({ name: root, type: 5 });
10832 }
10833 if(o.CLSID) cfb.FileIndex[0].clsid = o.CLSID;
10834 seed_cfb(cfb);
10835}
10836function seed_cfb(cfb) {
10837 var nm = "\u0001Sh33tJ5";
10838 if(CFB.find(cfb, "/" + nm)) return;
10839 var p = new_buf(4); p[0] = 55; p[1] = p[3] = 50; p[2] = 54;
10840 cfb.FileIndex.push(({ name: nm, type: 2, content:p, size:4, L:69, R:69, C:69 }));
10841 cfb.FullPaths.push(cfb.FullPaths[0] + nm);
10842 rebuild_cfb(cfb);
10843}
10844function rebuild_cfb(cfb, f) {
10845 init_cfb(cfb);
10846 var gc = false, s = false;
10847 for(var i = cfb.FullPaths.length - 1; i >= 0; --i) {
10848 var _file = cfb.FileIndex[i];
10849 switch(_file.type) {
10850 case 0:
10851 if(s) gc = true;
10852 else { cfb.FileIndex.pop(); cfb.FullPaths.pop(); }
10853 break;
10854 case 1: case 2: case 5:
10855 s = true;
10856 if(isNaN(_file.R * _file.L * _file.C)) gc = true;
10857 if(_file.R > -1 && _file.L > -1 && _file.R == _file.L) gc = true;
10858 break;
10859 default: gc = true; break;
10860 }
10861 }
10862 if(!gc && !f) return;
10863
10864 var now = new Date(1987, 1, 19), j = 0;
10865 var data = [];
10866 for(i = 0; i < cfb.FullPaths.length; ++i) {
10867 if(cfb.FileIndex[i].type === 0) continue;
10868 data.push([cfb.FullPaths[i], cfb.FileIndex[i]]);
10869 }
10870 for(i = 0; i < data.length; ++i) {
10871 var dad = dirname(data[i][0]);
10872 s = false;
10873 for(j = 0; j < data.length; ++j) if(data[j][0] === dad) s = true;
10874 if(!s) data.push([dad, ({
10875 name: filename(dad).replace("/",""),
10876 type: 1,
10877 clsid: HEADER_CLSID,
10878 ct: now, mt: now,
10879 content: null
10880 })]);
10881 }
10882
10883 data.sort(function(x,y) { return namecmp(x[0], y[0]); });
10884 cfb.FullPaths = []; cfb.FileIndex = [];
10885 for(i = 0; i < data.length; ++i) { cfb.FullPaths[i] = data[i][0]; cfb.FileIndex[i] = data[i][1]; }
10886 for(i = 0; i < data.length; ++i) {
10887 var elt = cfb.FileIndex[i];
10888 var nm = cfb.FullPaths[i];
10889
10890 elt.name = filename(nm).replace("/","");
10891 elt.L = elt.R = elt.C = -(elt.color = 1);
10892 elt.size = elt.content ? elt.content.length : 0;
10893 elt.start = 0;
10894 elt.clsid = (elt.clsid || HEADER_CLSID);
10895 if(i === 0) {
10896 elt.C = data.length > 1 ? 1 : -1;
10897 elt.size = 0;
10898 elt.type = 5;
10899 } else if(nm.slice(-1) == "/") {
10900 for(j=i+1;j < data.length; ++j) if(dirname(cfb.FullPaths[j])==nm) break;
10901 elt.C = j >= data.length ? -1 : j;
10902 for(j=i+1;j < data.length; ++j) if(dirname(cfb.FullPaths[j])==dirname(nm)) break;
10903 elt.R = j >= data.length ? -1 : j;
10904 elt.type = 1;
10905 } else {
10906 if(dirname(cfb.FullPaths[i+1]||"") == dirname(nm)) elt.R = i + 1;
10907 elt.type = 2;
10908 }
10909 }
10910
10911}
10912
10913function _write(cfb, options) {
10914 var _opts = options || {};
10915 rebuild_cfb(cfb);
10916 if(_opts.fileType == 'zip') return write_zip(cfb, _opts);
10917 var L = (function(cfb){
10918 var mini_size = 0, fat_size = 0;
10919 for(var i = 0; i < cfb.FileIndex.length; ++i) {
10920 var file = cfb.FileIndex[i];
10921 if(!file.content) continue;
10922var flen = file.content.length;
10923 if(flen > 0){
10924 if(flen < 0x1000) mini_size += (flen + 0x3F) >> 6;
10925 else fat_size += (flen + 0x01FF) >> 9;
10926 }
10927 }
10928 var dir_cnt = (cfb.FullPaths.length +3) >> 2;
10929 var mini_cnt = (mini_size + 7) >> 3;
10930 var mfat_cnt = (mini_size + 0x7F) >> 7;
10931 var fat_base = mini_cnt + fat_size + dir_cnt + mfat_cnt;
10932 var fat_cnt = (fat_base + 0x7F) >> 7;
10933 var difat_cnt = fat_cnt <= 109 ? 0 : Math.ceil((fat_cnt-109)/0x7F);
10934 while(((fat_base + fat_cnt + difat_cnt + 0x7F) >> 7) > fat_cnt) difat_cnt = ++fat_cnt <= 109 ? 0 : Math.ceil((fat_cnt-109)/0x7F);
10935 var L = [1, difat_cnt, fat_cnt, mfat_cnt, dir_cnt, fat_size, mini_size, 0];
10936 cfb.FileIndex[0].size = mini_size << 6;
10937 L[7] = (cfb.FileIndex[0].start=L[0]+L[1]+L[2]+L[3]+L[4]+L[5])+((L[6]+7) >> 3);
10938 return L;
10939 })(cfb);
10940 var o = new_buf(L[7] << 9);
10941 var i = 0, T = 0;
10942 {
10943 for(i = 0; i < 8; ++i) o.write_shift(1, HEADER_SIG[i]);
10944 for(i = 0; i < 8; ++i) o.write_shift(2, 0);
10945 o.write_shift(2, 0x003E);
10946 o.write_shift(2, 0x0003);
10947 o.write_shift(2, 0xFFFE);
10948 o.write_shift(2, 0x0009);
10949 o.write_shift(2, 0x0006);
10950 for(i = 0; i < 3; ++i) o.write_shift(2, 0);
10951 o.write_shift(4, 0);
10952 o.write_shift(4, L[2]);
10953 o.write_shift(4, L[0] + L[1] + L[2] + L[3] - 1);
10954 o.write_shift(4, 0);
10955 o.write_shift(4, 1<<12);
10956 o.write_shift(4, L[3] ? L[0] + L[1] + L[2] - 1: ENDOFCHAIN);
10957 o.write_shift(4, L[3]);
10958 o.write_shift(-4, L[1] ? L[0] - 1: ENDOFCHAIN);
10959 o.write_shift(4, L[1]);
10960 for(i = 0; i < 109; ++i) o.write_shift(-4, i < L[2] ? L[1] + i : -1);
10961 }
10962 if(L[1]) {
10963 for(T = 0; T < L[1]; ++T) {
10964 for(; i < 236 + T * 127; ++i) o.write_shift(-4, i < L[2] ? L[1] + i : -1);
10965 o.write_shift(-4, T === L[1] - 1 ? ENDOFCHAIN : T + 1);
10966 }
10967 }
10968 var chainit = function(w) {
10969 for(T += w; i<T-1; ++i) o.write_shift(-4, i+1);
10970 if(w) { ++i; o.write_shift(-4, ENDOFCHAIN); }
10971 };
10972 T = i = 0;
10973 for(T+=L[1]; i<T; ++i) o.write_shift(-4, consts.DIFSECT);
10974 for(T+=L[2]; i<T; ++i) o.write_shift(-4, consts.FATSECT);
10975 chainit(L[3]);
10976 chainit(L[4]);
10977 var j = 0, flen = 0;
10978 var file = cfb.FileIndex[0];
10979 for(; j < cfb.FileIndex.length; ++j) {
10980 file = cfb.FileIndex[j];
10981 if(!file.content) continue;
10982flen = file.content.length;
10983 if(flen < 0x1000) continue;
10984 file.start = T;
10985 chainit((flen + 0x01FF) >> 9);
10986 }
10987 chainit((L[6] + 7) >> 3);
10988 while(o.l & 0x1FF) o.write_shift(-4, consts.ENDOFCHAIN);
10989 T = i = 0;
10990 for(j = 0; j < cfb.FileIndex.length; ++j) {
10991 file = cfb.FileIndex[j];
10992 if(!file.content) continue;
10993flen = file.content.length;
10994 if(!flen || flen >= 0x1000) continue;
10995 file.start = T;
10996 chainit((flen + 0x3F) >> 6);
10997 }
10998 while(o.l & 0x1FF) o.write_shift(-4, consts.ENDOFCHAIN);
10999 for(i = 0; i < L[4]<<2; ++i) {
11000 var nm = cfb.FullPaths[i];
11001 if(!nm || nm.length === 0) {
11002 for(j = 0; j < 17; ++j) o.write_shift(4, 0);
11003 for(j = 0; j < 3; ++j) o.write_shift(4, -1);
11004 for(j = 0; j < 12; ++j) o.write_shift(4, 0);
11005 continue;
11006 }
11007 file = cfb.FileIndex[i];
11008 if(i === 0) file.start = file.size ? file.start - 1 : ENDOFCHAIN;
11009 var _nm = (i === 0 && _opts.root) || file.name;
11010 flen = 2*(_nm.length+1);
11011 o.write_shift(64, _nm, "utf16le");
11012 o.write_shift(2, flen);
11013 o.write_shift(1, file.type);
11014 o.write_shift(1, file.color);
11015 o.write_shift(-4, file.L);
11016 o.write_shift(-4, file.R);
11017 o.write_shift(-4, file.C);
11018 if(!file.clsid) for(j = 0; j < 4; ++j) o.write_shift(4, 0);
11019 else o.write_shift(16, file.clsid, "hex");
11020 o.write_shift(4, file.state || 0);
11021 o.write_shift(4, 0); o.write_shift(4, 0);
11022 o.write_shift(4, 0); o.write_shift(4, 0);
11023 o.write_shift(4, file.start);
11024 o.write_shift(4, file.size); o.write_shift(4, 0);
11025 }
11026 for(i = 1; i < cfb.FileIndex.length; ++i) {
11027 file = cfb.FileIndex[i];
11028if(file.size >= 0x1000) {
11029 o.l = (file.start+1) << 9;
11030 for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]);
11031 for(; j & 0x1FF; ++j) o.write_shift(1, 0);
11032 }
11033 }
11034 for(i = 1; i < cfb.FileIndex.length; ++i) {
11035 file = cfb.FileIndex[i];
11036if(file.size > 0 && file.size < 0x1000) {
11037 for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]);
11038 for(; j & 0x3F; ++j) o.write_shift(1, 0);
11039 }
11040 }
11041 while(o.l < o.length) o.write_shift(1, 0);
11042 return o;
11043}
11044/* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */
11045function find(cfb, path) {
11046 var UCFullPaths = cfb.FullPaths.map(function(x) { return x.toUpperCase(); });
11047 var UCPaths = UCFullPaths.map(function(x) { var y = x.split("/"); return y[y.length - (x.slice(-1) == "/" ? 2 : 1)]; });
11048 var k = false;
11049 if(path.charCodeAt(0) === 47 /* "/" */) { k = true; path = UCFullPaths[0].slice(0, -1) + path; }
11050 else k = path.indexOf("/") !== -1;
11051 var UCPath = path.toUpperCase();
11052 var w = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath);
11053 if(w !== -1) return cfb.FileIndex[w];
11054
11055 var m = !UCPath.match(chr1);
11056 UCPath = UCPath.replace(chr0,'');
11057 if(m) UCPath = UCPath.replace(chr1,'!');
11058 for(w = 0; w < UCFullPaths.length; ++w) {
11059 if((m ? UCFullPaths[w].replace(chr1,'!') : UCFullPaths[w]).replace(chr0,'') == UCPath) return cfb.FileIndex[w];
11060 if((m ? UCPaths[w].replace(chr1,'!') : UCPaths[w]).replace(chr0,'') == UCPath) return cfb.FileIndex[w];
11061 }
11062 return null;
11063}
11064/** CFB Constants */
11065var MSSZ = 64; /* Mini Sector Size = 1<<6 */
11066//var MSCSZ = 4096; /* Mini Stream Cutoff Size */
11067/* 2.1 Compound File Sector Numbers and Types */
11068var ENDOFCHAIN = -2;
11069/* 2.2 Compound File Header */
11070var HEADER_SIGNATURE = 'd0cf11e0a1b11ae1';
11071var HEADER_SIG = [0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1];
11072var HEADER_CLSID = '00000000000000000000000000000000';
11073var consts = {
11074 /* 2.1 Compund File Sector Numbers and Types */
11075 MAXREGSECT: -6,
11076 DIFSECT: -4,
11077 FATSECT: -3,
11078 ENDOFCHAIN: ENDOFCHAIN,
11079 FREESECT: -1,
11080 /* 2.2 Compound File Header */
11081 HEADER_SIGNATURE: HEADER_SIGNATURE,
11082 HEADER_MINOR_VERSION: '3e00',
11083 MAXREGSID: -6,
11084 NOSTREAM: -1,
11085 HEADER_CLSID: HEADER_CLSID,
11086 /* 2.6.1 Compound File Directory Entry */
11087 EntryTypes: ['unknown','storage','stream','lockbytes','property','root']
11088};
11089
11090function write_file(cfb, filename, options) {
11091 get_fs();
11092 var o = _write(cfb, options);
11093fs.writeFileSync(filename, o);
11094}
11095
11096function a2s(o) {
11097 var out = new Array(o.length);
11098 for(var i = 0; i < o.length; ++i) out[i] = String.fromCharCode(o[i]);
11099 return out.join("");
11100}
11101
11102function write(cfb, options) {
11103 var o = _write(cfb, options);
11104 switch(options && options.type) {
11105 case "file": get_fs(); fs.writeFileSync(options.filename, (o)); return o;
11106 case "binary": return a2s(o);
11107 case "base64": return Base64.encode(a2s(o));
11108 }
11109 return o;
11110}
11111/* node < 8.1 zlib does not expose bytesRead, so default to pure JS */
11112var _zlib;
11113function use_zlib(zlib) { try {
11114 var InflateRaw = zlib.InflateRaw;
11115 var InflRaw = new InflateRaw();
11116 InflRaw._processChunk(new Uint8Array([3, 0]), InflRaw._finishFlushFlag);
11117 if(InflRaw.bytesRead) _zlib = zlib;
11118 else throw new Error("zlib does not expose bytesRead");
11119} catch(e) {console.error("cannot use native zlib: " + (e.message || e)); } }
11120
11121function _inflateRawSync(payload, usz) {
11122 if(!_zlib) return _inflate(payload, usz);
11123 var InflateRaw = _zlib.InflateRaw;
11124 var InflRaw = new InflateRaw();
11125 var out = InflRaw._processChunk(payload.slice(payload.l), InflRaw._finishFlushFlag);
11126 payload.l += InflRaw.bytesRead;
11127 return out;
11128}
11129
11130function _deflateRawSync(payload) {
11131 return _zlib ? _zlib.deflateRawSync(payload) : _deflate(payload);
11132}
11133var CLEN_ORDER = [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];
11134
11135/* LEN_ID = [ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285 ]; */
11136var LEN_LN = [ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13 , 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 ];
11137
11138/* DST_ID = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 ]; */
11139var DST_LN = [ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 ];
11140
11141function bit_swap_8(n) { var t = (((((n<<1)|(n<<11)) & 0x22110) | (((n<<5)|(n<<15)) & 0x88440))); return ((t>>16) | (t>>8) |t)&0xFF; }
11142
11143var use_typed_arrays = typeof Uint8Array !== 'undefined';
11144
11145var bitswap8 = use_typed_arrays ? new Uint8Array(1<<8) : [];
11146for(var q = 0; q < (1<<8); ++q) bitswap8[q] = bit_swap_8(q);
11147
11148function bit_swap_n(n, b) {
11149 var rev = bitswap8[n & 0xFF];
11150 if(b <= 8) return rev >>> (8-b);
11151 rev = (rev << 8) | bitswap8[(n>>8)&0xFF];
11152 if(b <= 16) return rev >>> (16-b);
11153 rev = (rev << 8) | bitswap8[(n>>16)&0xFF];
11154 return rev >>> (24-b);
11155}
11156
11157/* helpers for unaligned bit reads */
11158function read_bits_2(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 6 ? 0 : buf[h+1]<<8))>>>w)& 0x03; }
11159function read_bits_3(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 5 ? 0 : buf[h+1]<<8))>>>w)& 0x07; }
11160function read_bits_4(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 4 ? 0 : buf[h+1]<<8))>>>w)& 0x0F; }
11161function read_bits_5(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 3 ? 0 : buf[h+1]<<8))>>>w)& 0x1F; }
11162function read_bits_7(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 1 ? 0 : buf[h+1]<<8))>>>w)& 0x7F; }
11163
11164/* works up to n = 3 * 8 + 1 = 25 */
11165function read_bits_n(buf, bl, n) {
11166 var w = (bl&7), h = (bl>>>3), f = ((1<<n)-1);
11167 var v = buf[h] >>> w;
11168 if(n < 8 - w) return v & f;
11169 v |= buf[h+1]<<(8-w);
11170 if(n < 16 - w) return v & f;
11171 v |= buf[h+2]<<(16-w);
11172 if(n < 24 - w) return v & f;
11173 v |= buf[h+3]<<(24-w);
11174 return v & f;
11175}
11176
11177/* until ArrayBuffer#realloc is a thing, fake a realloc */
11178function realloc(b, sz) {
11179 var L = b.length, M = 2*L > sz ? 2*L : sz + 5, i = 0;
11180 if(L >= sz) return b;
11181 if(has_buf) {
11182 var o = new_unsafe_buf(M);
11183 // $FlowIgnore
11184 if(b.copy) b.copy(o);
11185 else for(; i < b.length; ++i) o[i] = b[i];
11186 return o;
11187 } else if(use_typed_arrays) {
11188 var a = new Uint8Array(M);
11189 if(a.set) a.set(b);
11190 else for(; i < b.length; ++i) a[i] = b[i];
11191 return a;
11192 }
11193 b.length = M;
11194 return b;
11195}
11196
11197/* zero-filled arrays for older browsers */
11198function zero_fill_array(n) {
11199 var o = new Array(n);
11200 for(var i = 0; i < n; ++i) o[i] = 0;
11201 return o;
11202}var _deflate = (function() {
11203var _deflateRaw = (function() {
11204 return function deflateRaw(data, out) {
11205 var boff = 0;
11206 while(boff < data.length) {
11207 var L = Math.min(0xFFFF, data.length - boff);
11208 var h = boff + L == data.length;
11209 /* TODO: this is only type 0 stored */
11210 out.write_shift(1, +h);
11211 out.write_shift(2, L);
11212 out.write_shift(2, (~L) & 0xFFFF);
11213 while(L-- > 0) out[out.l++] = data[boff++];
11214 }
11215 return out.l;
11216 };
11217})();
11218
11219return function(data) {
11220 var buf = new_buf(50+Math.floor(data.length*1.1));
11221 var off = _deflateRaw(data, buf);
11222 return buf.slice(0, off);
11223};
11224})();
11225/* modified inflate function also moves original read head */
11226
11227/* build tree (used for literals and lengths) */
11228function build_tree(clens, cmap, MAX) {
11229 var maxlen = 1, w = 0, i = 0, j = 0, ccode = 0, L = clens.length;
11230
11231 var bl_count = use_typed_arrays ? new Uint16Array(32) : zero_fill_array(32);
11232 for(i = 0; i < 32; ++i) bl_count[i] = 0;
11233
11234 for(i = L; i < MAX; ++i) clens[i] = 0;
11235 L = clens.length;
11236
11237 var ctree = use_typed_arrays ? new Uint16Array(L) : zero_fill_array(L); // []
11238
11239 /* build code tree */
11240 for(i = 0; i < L; ++i) {
11241 bl_count[(w = clens[i])]++;
11242 if(maxlen < w) maxlen = w;
11243 ctree[i] = 0;
11244 }
11245 bl_count[0] = 0;
11246 for(i = 1; i <= maxlen; ++i) bl_count[i+16] = (ccode = (ccode + bl_count[i-1])<<1);
11247 for(i = 0; i < L; ++i) {
11248 ccode = clens[i];
11249 if(ccode != 0) ctree[i] = bl_count[ccode+16]++;
11250 }
11251
11252 /* cmap[maxlen + 4 bits] = (off&15) + (lit<<4) reverse mapping */
11253 var cleni = 0;
11254 for(i = 0; i < L; ++i) {
11255 cleni = clens[i];
11256 if(cleni != 0) {
11257 ccode = bit_swap_n(ctree[i], maxlen)>>(maxlen-cleni);
11258 for(j = (1<<(maxlen + 4 - cleni)) - 1; j>=0; --j)
11259 cmap[ccode|(j<<cleni)] = (cleni&15) | (i<<4);
11260 }
11261 }
11262 return maxlen;
11263}
11264
11265var fix_lmap = use_typed_arrays ? new Uint16Array(512) : zero_fill_array(512);
11266var fix_dmap = use_typed_arrays ? new Uint16Array(32) : zero_fill_array(32);
11267if(!use_typed_arrays) {
11268 for(var i = 0; i < 512; ++i) fix_lmap[i] = 0;
11269 for(i = 0; i < 32; ++i) fix_dmap[i] = 0;
11270}
11271(function() {
11272 var dlens = [];
11273 var i = 0;
11274 for(;i<32; i++) dlens.push(5);
11275 build_tree(dlens, fix_dmap, 32);
11276
11277 var clens = [];
11278 i = 0;
11279 for(; i<=143; i++) clens.push(8);
11280 for(; i<=255; i++) clens.push(9);
11281 for(; i<=279; i++) clens.push(7);
11282 for(; i<=287; i++) clens.push(8);
11283 build_tree(clens, fix_lmap, 288);
11284})();
11285
11286var dyn_lmap = use_typed_arrays ? new Uint16Array(32768) : zero_fill_array(32768);
11287var dyn_dmap = use_typed_arrays ? new Uint16Array(32768) : zero_fill_array(32768);
11288var dyn_cmap = use_typed_arrays ? new Uint16Array(128) : zero_fill_array(128);
11289var dyn_len_1 = 1, dyn_len_2 = 1;
11290
11291/* 5.5.3 Expanding Huffman Codes */
11292function dyn(data, boff) {
11293 /* nomenclature from RFC1951 refers to bit values; these are offset by the implicit constant */
11294 var _HLIT = read_bits_5(data, boff) + 257; boff += 5;
11295 var _HDIST = read_bits_5(data, boff) + 1; boff += 5;
11296 var _HCLEN = read_bits_4(data, boff) + 4; boff += 4;
11297 var w = 0;
11298
11299 /* grab and store code lengths */
11300 var clens = use_typed_arrays ? new Uint8Array(19) : zero_fill_array(19);
11301 var ctree = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
11302 var maxlen = 1;
11303 var bl_count = use_typed_arrays ? new Uint8Array(8) : zero_fill_array(8);
11304 var next_code = use_typed_arrays ? new Uint8Array(8) : zero_fill_array(8);
11305 var L = clens.length; /* 19 */
11306 for(var i = 0; i < _HCLEN; ++i) {
11307 clens[CLEN_ORDER[i]] = w = read_bits_3(data, boff);
11308 if(maxlen < w) maxlen = w;
11309 bl_count[w]++;
11310 boff += 3;
11311 }
11312
11313 /* build code tree */
11314 var ccode = 0;
11315 bl_count[0] = 0;
11316 for(i = 1; i <= maxlen; ++i) next_code[i] = ccode = (ccode + bl_count[i-1])<<1;
11317 for(i = 0; i < L; ++i) if((ccode = clens[i]) != 0) ctree[i] = next_code[ccode]++;
11318 /* cmap[7 bits from stream] = (off&7) + (lit<<3) */
11319 var cleni = 0;
11320 for(i = 0; i < L; ++i) {
11321 cleni = clens[i];
11322 if(cleni != 0) {
11323 ccode = bitswap8[ctree[i]]>>(8-cleni);
11324 for(var j = (1<<(7-cleni))-1; j>=0; --j) dyn_cmap[ccode|(j<<cleni)] = (cleni&7) | (i<<3);
11325 }
11326 }
11327
11328 /* read literal and dist codes at once */
11329 var hcodes = [];
11330 maxlen = 1;
11331 for(; hcodes.length < _HLIT + _HDIST;) {
11332 ccode = dyn_cmap[read_bits_7(data, boff)];
11333 boff += ccode & 7;
11334 switch((ccode >>>= 3)) {
11335 case 16:
11336 w = 3 + read_bits_2(data, boff); boff += 2;
11337 ccode = hcodes[hcodes.length - 1];
11338 while(w-- > 0) hcodes.push(ccode);
11339 break;
11340 case 17:
11341 w = 3 + read_bits_3(data, boff); boff += 3;
11342 while(w-- > 0) hcodes.push(0);
11343 break;
11344 case 18:
11345 w = 11 + read_bits_7(data, boff); boff += 7;
11346 while(w -- > 0) hcodes.push(0);
11347 break;
11348 default:
11349 hcodes.push(ccode);
11350 if(maxlen < ccode) maxlen = ccode;
11351 break;
11352 }
11353 }
11354
11355 /* build literal / length trees */
11356 var h1 = hcodes.slice(0, _HLIT), h2 = hcodes.slice(_HLIT);
11357 for(i = _HLIT; i < 286; ++i) h1[i] = 0;
11358 for(i = _HDIST; i < 30; ++i) h2[i] = 0;
11359 dyn_len_1 = build_tree(h1, dyn_lmap, 286);
11360 dyn_len_2 = build_tree(h2, dyn_dmap, 30);
11361 return boff;
11362}
11363
11364/* return [ data, bytesRead ] */
11365function inflate(data, usz) {
11366 /* shortcircuit for empty buffer [0x03, 0x00] */
11367 if(data[0] == 3 && !(data[1] & 0x3)) { return [new_raw_buf(usz), 2]; }
11368
11369 /* bit offset */
11370 var boff = 0;
11371
11372 /* header includes final bit and type bits */
11373 var header = 0;
11374
11375 var outbuf = new_unsafe_buf(usz ? usz : (1<<18));
11376 var woff = 0;
11377 var OL = outbuf.length>>>0;
11378 var max_len_1 = 0, max_len_2 = 0;
11379
11380 while((header&1) == 0) {
11381 header = read_bits_3(data, boff); boff += 3;
11382 if((header >>> 1) == 0) {
11383 /* Stored block */
11384 if(boff & 7) boff += 8 - (boff&7);
11385 /* 2 bytes sz, 2 bytes bit inverse */
11386 var sz = data[boff>>>3] | data[(boff>>>3)+1]<<8;
11387 boff += 32;
11388 /* push sz bytes */
11389 if(!usz && OL < woff + sz) { outbuf = realloc(outbuf, woff + sz); OL = outbuf.length; }
11390 if(typeof data.copy === 'function') {
11391 // $FlowIgnore
11392 data.copy(outbuf, woff, boff>>>3, (boff>>>3)+sz);
11393 woff += sz; boff += 8*sz;
11394 } else while(sz-- > 0) { outbuf[woff++] = data[boff>>>3]; boff += 8; }
11395 continue;
11396 } else if((header >>> 1) == 1) {
11397 /* Fixed Huffman */
11398 max_len_1 = 9; max_len_2 = 5;
11399 } else {
11400 /* Dynamic Huffman */
11401 boff = dyn(data, boff);
11402 max_len_1 = dyn_len_1; max_len_2 = dyn_len_2;
11403 }
11404 if(!usz && (OL < woff + 32767)) { outbuf = realloc(outbuf, woff + 32767); OL = outbuf.length; }
11405 for(;;) { // while(true) is apparently out of vogue in modern JS circles
11406 /* ingest code and move read head */
11407 var bits = read_bits_n(data, boff, max_len_1);
11408 var code = (header>>>1) == 1 ? fix_lmap[bits] : dyn_lmap[bits];
11409 boff += code & 15; code >>>= 4;
11410 /* 0-255 are literals, 256 is end of block token, 257+ are copy tokens */
11411 if(((code>>>8)&0xFF) === 0) outbuf[woff++] = code;
11412 else if(code == 256) break;
11413 else {
11414 code -= 257;
11415 var len_eb = (code < 8) ? 0 : ((code-4)>>2); if(len_eb > 5) len_eb = 0;
11416 var tgt = woff + LEN_LN[code];
11417 /* length extra bits */
11418 if(len_eb > 0) {
11419 tgt += read_bits_n(data, boff, len_eb);
11420 boff += len_eb;
11421 }
11422
11423 /* dist code */
11424 bits = read_bits_n(data, boff, max_len_2);
11425 code = (header>>>1) == 1 ? fix_dmap[bits] : dyn_dmap[bits];
11426 boff += code & 15; code >>>= 4;
11427 var dst_eb = (code < 4 ? 0 : (code-2)>>1);
11428 var dst = DST_LN[code];
11429 /* dist extra bits */
11430 if(dst_eb > 0) {
11431 dst += read_bits_n(data, boff, dst_eb);
11432 boff += dst_eb;
11433 }
11434
11435 /* in the common case, manual byte copy is faster than TA set / Buffer copy */
11436 if(!usz && OL < tgt) { outbuf = realloc(outbuf, tgt); OL = outbuf.length; }
11437 while(woff < tgt) { outbuf[woff] = outbuf[woff - dst]; ++woff; }
11438 }
11439 }
11440 }
11441 return [usz ? outbuf : outbuf.slice(0, woff), (boff+7)>>>3];
11442}
11443
11444function _inflate(payload, usz) {
11445 var data = payload.slice(payload.l||0);
11446 var out = inflate(data, usz);
11447 payload.l += out[1];
11448 return out[0];
11449}
11450
11451function warn_or_throw(wrn, msg) {
11452 if(wrn) { if(typeof console !== 'undefined') console.error(msg); }
11453 else throw new Error(msg);
11454}
11455
11456function parse_zip(file, options) {
11457 var blob = file;
11458 prep_blob(blob, 0);
11459
11460 var FileIndex = [], FullPaths = [];
11461 var o = {
11462 FileIndex: FileIndex,
11463 FullPaths: FullPaths
11464 };
11465 init_cfb(o, { root: options.root });
11466
11467 /* find end of central directory, start just after signature */
11468 var i = blob.length - 4;
11469 while((blob[i] != 0x50 || blob[i+1] != 0x4b || blob[i+2] != 0x05 || blob[i+3] != 0x06) && i >= 0) --i;
11470 blob.l = i + 4;
11471
11472 /* parse end of central directory */
11473 blob.l += 4;
11474 var fcnt = blob.read_shift(2);
11475 blob.l += 6;
11476 var start_cd = blob.read_shift(4);
11477
11478 /* parse central directory */
11479 blob.l = start_cd;
11480
11481 for(i = 0; i < fcnt; ++i) {
11482 /* trust local file header instead of CD entry */
11483 blob.l += 20;
11484 var csz = blob.read_shift(4);
11485 var usz = blob.read_shift(4);
11486 var namelen = blob.read_shift(2);
11487 var efsz = blob.read_shift(2);
11488 var fcsz = blob.read_shift(2);
11489 blob.l += 8;
11490 var offset = blob.read_shift(4);
11491 var EF = parse_extra_field(blob.slice(blob.l+namelen, blob.l+namelen+efsz));
11492 blob.l += namelen + efsz + fcsz;
11493
11494 var L = blob.l;
11495 blob.l = offset + 4;
11496 parse_local_file(blob, csz, usz, o, EF);
11497 blob.l = L;
11498 }
11499
11500 return o;
11501}
11502
11503
11504/* head starts just after local file header signature */
11505function parse_local_file(blob, csz, usz, o, EF) {
11506 /* [local file header] */
11507 blob.l += 2;
11508 var flags = blob.read_shift(2);
11509 var meth = blob.read_shift(2);
11510 var date = parse_dos_date(blob);
11511
11512 if(flags & 0x2041) throw new Error("Unsupported ZIP encryption");
11513 var crc32 = blob.read_shift(4);
11514 var _csz = blob.read_shift(4);
11515 var _usz = blob.read_shift(4);
11516
11517 var namelen = blob.read_shift(2);
11518 var efsz = blob.read_shift(2);
11519
11520 // TODO: flags & (1<<11) // UTF8
11521 var name = ""; for(var i = 0; i < namelen; ++i) name += String.fromCharCode(blob[blob.l++]);
11522 if(efsz) {
11523 var ef = parse_extra_field(blob.slice(blob.l, blob.l + efsz));
11524 if((ef[0x5455]||{}).mt) date = ef[0x5455].mt;
11525 if(((EF||{})[0x5455]||{}).mt) date = EF[0x5455].mt;
11526 }
11527 blob.l += efsz;
11528
11529 /* [encryption header] */
11530
11531 /* [file data] */
11532 var data = blob.slice(blob.l, blob.l + _csz);
11533 switch(meth) {
11534 case 8: data = _inflateRawSync(blob, _usz); break;
11535 case 0: break;
11536 default: throw new Error("Unsupported ZIP Compression method " + meth);
11537 }
11538
11539 /* [data descriptor] */
11540 var wrn = false;
11541 if(flags & 8) {
11542 crc32 = blob.read_shift(4);
11543 if(crc32 == 0x08074b50) { crc32 = blob.read_shift(4); wrn = true; }
11544 _csz = blob.read_shift(4);
11545 _usz = blob.read_shift(4);
11546 }
11547
11548 if(_csz != csz) warn_or_throw(wrn, "Bad compressed size: " + csz + " != " + _csz);
11549 if(_usz != usz) warn_or_throw(wrn, "Bad uncompressed size: " + usz + " != " + _usz);
11550 var _crc32 = CRC32.buf(data, 0);
11551 if((crc32>>0) != (_crc32>>0)) warn_or_throw(wrn, "Bad CRC32 checksum: " + crc32 + " != " + _crc32);
11552 cfb_add(o, name, data, {unsafe: true, mt: date});
11553}
11554function write_zip(cfb, options) {
11555 var _opts = options || {};
11556 var out = [], cdirs = [];
11557 var o = new_buf(1);
11558 var method = (_opts.compression ? 8 : 0), flags = 0;
11559 var desc = false;
11560 if(desc) flags |= 8;
11561 var i = 0, j = 0;
11562
11563 var start_cd = 0, fcnt = 0;
11564 var root = cfb.FullPaths[0], fp = root, fi = cfb.FileIndex[0];
11565 var crcs = [];
11566 var sz_cd = 0;
11567
11568 for(i = 1; i < cfb.FullPaths.length; ++i) {
11569 fp = cfb.FullPaths[i].slice(root.length); fi = cfb.FileIndex[i];
11570 if(!fi.size || !fi.content || fp == "\u0001Sh33tJ5") continue;
11571 var start = start_cd;
11572
11573 /* TODO: CP437 filename */
11574 var namebuf = new_buf(fp.length);
11575 for(j = 0; j < fp.length; ++j) namebuf.write_shift(1, fp.charCodeAt(j) & 0x7F);
11576 namebuf = namebuf.slice(0, namebuf.l);
11577 crcs[fcnt] = CRC32.buf(fi.content, 0);
11578
11579 var outbuf = fi.content;
11580 if(method == 8) outbuf = _deflateRawSync(outbuf);
11581
11582 /* local file header */
11583 o = new_buf(30);
11584 o.write_shift(4, 0x04034b50);
11585 o.write_shift(2, 20);
11586 o.write_shift(2, flags);
11587 o.write_shift(2, method);
11588 /* TODO: last mod file time/date */
11589 if(fi.mt) write_dos_date(o, fi.mt);
11590 else o.write_shift(4, 0);
11591 o.write_shift(-4, (flags & 8) ? 0 : crcs[fcnt]);
11592 o.write_shift(4, (flags & 8) ? 0 : outbuf.length);
11593 o.write_shift(4, (flags & 8) ? 0 : fi.content.length);
11594 o.write_shift(2, namebuf.length);
11595 o.write_shift(2, 0);
11596
11597 start_cd += o.length;
11598 out.push(o);
11599 start_cd += namebuf.length;
11600 out.push(namebuf);
11601
11602 /* TODO: encryption header ? */
11603 start_cd += outbuf.length;
11604 out.push(outbuf);
11605
11606 /* data descriptor */
11607 if(flags & 8) {
11608 o = new_buf(12);
11609 o.write_shift(-4, crcs[fcnt]);
11610 o.write_shift(4, outbuf.length);
11611 o.write_shift(4, fi.content.length);
11612 start_cd += o.l;
11613 out.push(o);
11614 }
11615
11616 /* central directory */
11617 o = new_buf(46);
11618 o.write_shift(4, 0x02014b50);
11619 o.write_shift(2, 0);
11620 o.write_shift(2, 20);
11621 o.write_shift(2, flags);
11622 o.write_shift(2, method);
11623 o.write_shift(4, 0); /* TODO: last mod file time/date */
11624 o.write_shift(-4, crcs[fcnt]);
11625
11626 o.write_shift(4, outbuf.length);
11627 o.write_shift(4, fi.content.length);
11628 o.write_shift(2, namebuf.length);
11629 o.write_shift(2, 0);
11630 o.write_shift(2, 0);
11631 o.write_shift(2, 0);
11632 o.write_shift(2, 0);
11633 o.write_shift(4, 0);
11634 o.write_shift(4, start);
11635
11636 sz_cd += o.l;
11637 cdirs.push(o);
11638 sz_cd += namebuf.length;
11639 cdirs.push(namebuf);
11640 ++fcnt;
11641 }
11642
11643 /* end of central directory */
11644 o = new_buf(22);
11645 o.write_shift(4, 0x06054b50);
11646 o.write_shift(2, 0);
11647 o.write_shift(2, 0);
11648 o.write_shift(2, fcnt);
11649 o.write_shift(2, fcnt);
11650 o.write_shift(4, sz_cd);
11651 o.write_shift(4, start_cd);
11652 o.write_shift(2, 0);
11653
11654 return bconcat(([bconcat((out)), bconcat(cdirs), o]));
11655}
11656function cfb_new(opts) {
11657 var o = ({});
11658 init_cfb(o, opts);
11659 return o;
11660}
11661
11662function cfb_add(cfb, name, content, opts) {
11663 var unsafe = opts && opts.unsafe;
11664 if(!unsafe) init_cfb(cfb);
11665 var file = !unsafe && CFB.find(cfb, name);
11666 if(!file) {
11667 var fpath = cfb.FullPaths[0];
11668 if(name.slice(0, fpath.length) == fpath) fpath = name;
11669 else {
11670 if(fpath.slice(-1) != "/") fpath += "/";
11671 fpath = (fpath + name).replace("//","/");
11672 }
11673 file = ({name: filename(name), type: 2});
11674 cfb.FileIndex.push(file);
11675 cfb.FullPaths.push(fpath);
11676 if(!unsafe) CFB.utils.cfb_gc(cfb);
11677 }
11678file.content = (content);
11679 file.size = content ? content.length : 0;
11680 if(opts) {
11681 if(opts.CLSID) file.clsid = opts.CLSID;
11682 if(opts.mt) file.mt = opts.mt;
11683 if(opts.ct) file.ct = opts.ct;
11684 }
11685 return file;
11686}
11687
11688function cfb_del(cfb, name) {
11689 init_cfb(cfb);
11690 var file = CFB.find(cfb, name);
11691 if(file) for(var j = 0; j < cfb.FileIndex.length; ++j) if(cfb.FileIndex[j] == file) {
11692 cfb.FileIndex.splice(j, 1);
11693 cfb.FullPaths.splice(j, 1);
11694 return true;
11695 }
11696 return false;
11697}
11698
11699function cfb_mov(cfb, old_name, new_name) {
11700 init_cfb(cfb);
11701 var file = CFB.find(cfb, old_name);
11702 if(file) for(var j = 0; j < cfb.FileIndex.length; ++j) if(cfb.FileIndex[j] == file) {
11703 cfb.FileIndex[j].name = filename(new_name);
11704 cfb.FullPaths[j] = new_name;
11705 return true;
11706 }
11707 return false;
11708}
11709
11710function cfb_gc(cfb) { rebuild_cfb(cfb, true); }
11711
11712exports.find = find;
11713exports.read = read;
11714exports.parse = parse;
11715exports.write = write;
11716exports.writeFile = write_file;
11717exports.utils = {
11718 cfb_new: cfb_new,
11719 cfb_add: cfb_add,
11720 cfb_del: cfb_del,
11721 cfb_mov: cfb_mov,
11722 cfb_gc: cfb_gc,
11723 ReadShift: ReadShift,
11724 CheckField: CheckField,
11725 prep_blob: prep_blob,
11726 bconcat: bconcat,
11727 use_zlib: use_zlib,
11728 _deflateRaw: _deflate,
11729 _inflateRaw: _inflate,
11730 consts: consts
11731};
11732
11733return exports;
11734})();
11735
11736if(typeof require !== 'undefined' && typeof module !== 'undefined' && typeof DO_NOT_EXPORT_CFB === 'undefined') { module.exports = CFB; }
11737var _fs;
11738if(typeof require !== 'undefined') try { _fs = require('fs'); } catch(e) {}
11739
11740/* normalize data for blob ctor */
11741function blobify(data) {
11742 if(typeof data === "string") return s2ab(data);
11743 if(Array.isArray(data)) return a2u(data);
11744 return data;
11745}
11746/* write or download file */
11747function write_dl(fname, payload, enc) {
11748 /*global IE_SaveFile, Blob, navigator, saveAs, URL, document, File, chrome */
11749 if(typeof _fs !== 'undefined' && _fs.writeFileSync) return enc ? _fs.writeFileSync(fname, payload, enc) : _fs.writeFileSync(fname, payload);
11750 var data = (enc == "utf8") ? utf8write(payload) : payload;
11751if(typeof IE_SaveFile !== 'undefined') return IE_SaveFile(data, fname);
11752 if(typeof Blob !== 'undefined') {
11753 var blob = new Blob([blobify(data)], {type:"application/octet-stream"});
11754if(typeof navigator !== 'undefined' && navigator.msSaveBlob) return navigator.msSaveBlob(blob, fname);
11755if(typeof saveAs !== 'undefined') return saveAs(blob, fname);
11756 if(typeof URL !== 'undefined' && typeof document !== 'undefined' && document.createElement && URL.createObjectURL) {
11757 var url = URL.createObjectURL(blob);
11758if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") {
11759 if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
11760 return chrome.downloads.download({ url: url, filename: fname, saveAs: true});
11761 }
11762 var a = document.createElement("a");
11763 if(a.download != null) {
11764a.download = fname; a.href = url; document.body.appendChild(a); a.click();
11765document.body.removeChild(a);
11766 if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
11767 return url;
11768 }
11769 }
11770 }
11771 // $FlowIgnore
11772 if(typeof $ !== 'undefined' && typeof File !== 'undefined' && typeof Folder !== 'undefined') try { // extendscript
11773 // $FlowIgnore
11774 var out = File(fname); out.open("w"); out.encoding = "binary";
11775 if(Array.isArray(payload)) payload = a2s(payload);
11776 out.write(payload); out.close(); return payload;
11777 } catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; }
11778 throw new Error("cannot save file " + fname);
11779}
11780
11781/* read binary data from file */
11782function read_binary(path) {
11783 if(typeof _fs !== 'undefined') return _fs.readFileSync(path);
11784 // $FlowIgnore
11785 if(typeof $ !== 'undefined' && typeof File !== 'undefined' && typeof Folder !== 'undefined') try { // extendscript
11786 // $FlowIgnore
11787 var infile = File(path); infile.open("r"); infile.encoding = "binary";
11788 var data = infile.read(); infile.close();
11789 return data;
11790 } catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; }
11791 throw new Error("Cannot access file " + path);
11792}
11793function keys(o) {
11794 var ks = Object.keys(o), o2 = [];
11795 for(var i = 0; i < ks.length; ++i) if(o.hasOwnProperty(ks[i])) o2.push(ks[i]);
11796 return o2;
11797}
11798
11799function evert_key(obj, key) {
11800 var o = ([]), K = keys(obj);
11801 for(var i = 0; i !== K.length; ++i) if(o[obj[K[i]][key]] == null) o[obj[K[i]][key]] = K[i];
11802 return o;
11803}
11804
11805function evert(obj) {
11806 var o = ([]), K = keys(obj);
11807 for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = K[i];
11808 return o;
11809}
11810
11811function evert_num(obj) {
11812 var o = ([]), K = keys(obj);
11813 for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = parseInt(K[i],10);
11814 return o;
11815}
11816
11817function evert_arr(obj) {
11818 var o = ([]), K = keys(obj);
11819 for(var i = 0; i !== K.length; ++i) {
11820 if(o[obj[K[i]]] == null) o[obj[K[i]]] = [];
11821 o[obj[K[i]]].push(K[i]);
11822 }
11823 return o;
11824}
11825
11826var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
11827var dnthresh = basedate.getTime() + (new Date().getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000;
11828function datenum(v, date1904) {
11829 var epoch = v.getTime();
11830 if(date1904) epoch -= 1462*24*60*60*1000;
11831 return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
11832}
11833function numdate(v) {
11834 var out = new Date();
11835 out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh);
11836 return out;
11837}
11838
11839/* ISO 8601 Duration */
11840function parse_isodur(s) {
11841 var sec = 0, mt = 0, time = false;
11842 var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/);
11843 if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration");
11844 for(var i = 1; i != m.length; ++i) {
11845 if(!m[i]) continue;
11846 mt = 1;
11847 if(i > 3) time = true;
11848 switch(m[i].slice(m[i].length-1)) {
11849 case 'Y':
11850 throw new Error("Unsupported ISO Duration Field: " + m[i].slice(m[i].length-1));
11851 case 'D': mt *= 24;
11852 /* falls through */
11853 case 'H': mt *= 60;
11854 /* falls through */
11855 case 'M':
11856 if(!time) throw new Error("Unsupported ISO Duration Field: M");
11857 else mt *= 60;
11858 /* falls through */
11859 case 'S': break;
11860 }
11861 sec += mt * parseInt(m[i], 10);
11862 }
11863 return sec;
11864}
11865
11866var good_pd_date = new Date('2017-02-19T19:06:09.000Z');
11867if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17');
11868var good_pd = good_pd_date.getFullYear() == 2017;
11869/* parses a date as a local date */
11870function parseDate(str, fixdate) {
11871 var d = new Date(str);
11872 if(good_pd) {
11873if(fixdate > 0) d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000);
11874 else if(fixdate < 0) d.setTime(d.getTime() - d.getTimezoneOffset() * 60 * 1000);
11875 return d;
11876 }
11877 if(str instanceof Date) return str;
11878 if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
11879 var s = d.getFullYear();
11880 if(str.indexOf("" + s) > -1) return d;
11881 d.setFullYear(d.getFullYear() + 100); return d;
11882 }
11883 var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
11884 var out = new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
11885 if(str.indexOf("Z") > -1) out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000);
11886 return out;
11887}
11888
11889function cc2str(arr) {
11890 var o = "";
11891 for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]);
11892 return o;
11893}
11894
11895function dup(o) {
11896 if(typeof JSON != 'undefined' && !Array.isArray(o)) return JSON.parse(JSON.stringify(o));
11897 if(typeof o != 'object' || o == null) return o;
11898 if(o instanceof Date) return new Date(o.getTime());
11899 var out = {};
11900 for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]);
11901 return out;
11902}
11903
11904function fill(c,l) { var o = ""; while(o.length < l) o+=c; return o; }
11905
11906/* TODO: stress test */
11907function fuzzynum(s) {
11908 var v = Number(s);
11909 if(!isNaN(v)) return v;
11910 var wt = 1;
11911 var ss = s.replace(/([\d]),([\d])/g,"$1$2").replace(/[$]/g,"").replace(/[%]/g, function() { wt *= 100; return "";});
11912 if(!isNaN(v = Number(ss))) return v / wt;
11913 ss = ss.replace(/[(](.*)[)]/,function($$, $1) { wt = -wt; return $1;});
11914 if(!isNaN(v = Number(ss))) return v / wt;
11915 return v;
11916}
11917function fuzzydate(s) {
11918 var o = new Date(s), n = new Date(NaN);
11919 var y = o.getYear(), m = o.getMonth(), d = o.getDate();
11920 if(isNaN(d)) return n;
11921 if(y < 0 || y > 8099) return n;
11922 if((m > 0 || d > 1) && y != 101) return o;
11923 if(s.toLowerCase().match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) return o;
11924 if(s.match(/[^-0-9:,\/\\]/)) return n;
11925 return o;
11926}
11927
11928var safe_split_regex = "abacaba".split(/(:?b)/i).length == 5;
11929function split_regex(str, re, def) {
11930 if(safe_split_regex || typeof re == "string") return str.split(re);
11931 var p = str.split(re), o = [p[0]];
11932 for(var i = 1; i < p.length; ++i) { o.push(def); o.push(p[i]); }
11933 return o;
11934}
11935function getdatastr(data) {
11936 if(!data) return null;
11937 if(data.data) return debom(data.data);
11938 if(data.asNodeBuffer && has_buf) return debom(data.asNodeBuffer().toString('binary'));
11939 if(data.asBinary) return debom(data.asBinary());
11940 if(data._data && data._data.getContent) return debom(cc2str(Array.prototype.slice.call(data._data.getContent(),0)));
11941 if(data.content && data.type) return debom(cc2str(data.content));
11942 return null;
11943}
11944
11945function getdatabin(data) {
11946 if(!data) return null;
11947 if(data.data) return char_codes(data.data);
11948 if(data.asNodeBuffer && has_buf) return data.asNodeBuffer();
11949 if(data._data && data._data.getContent) {
11950 var o = data._data.getContent();
11951 if(typeof o == "string") return char_codes(o);
11952 return Array.prototype.slice.call(o);
11953 }
11954 if(data.content && data.type) return data.content;
11955 return null;
11956}
11957
11958function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getdatabin(data) : getdatastr(data); }
11959
11960/* Part 2 Section 10.1.2 "Mapping Content Types" Names are case-insensitive */
11961/* OASIS does not comment on filename case sensitivity */
11962function safegetzipfile(zip, file) {
11963 var k = zip.FullPaths || keys(zip.files);
11964 var f = file.toLowerCase(), g = f.replace(/\//g,'\\');
11965 for(var i=0; i<k.length; ++i) {
11966 var n = k[i].toLowerCase();
11967 if(f == n || g == n) return zip.files[k[i]];
11968 }
11969 return null;
11970}
11971
11972function getzipfile(zip, file) {
11973 var o = safegetzipfile(zip, file);
11974 if(o == null) throw new Error("Cannot find file " + file + " in zip");
11975 return o;
11976}
11977
11978function getzipdata(zip, file, safe) {
11979 if(!safe) return getdata(getzipfile(zip, file));
11980 if(!file) return null;
11981 try { return getzipdata(zip, file); } catch(e) { return null; }
11982}
11983
11984function getzipstr(zip, file, safe) {
11985 if(!safe) return getdatastr(getzipfile(zip, file));
11986 if(!file) return null;
11987 try { return getzipstr(zip, file); } catch(e) { return null; }
11988}
11989
11990function zipentries(zip) {
11991 var k = zip.FullPaths || keys(zip.files), o = [];
11992 for(var i = 0; i < k.length; ++i) if(k[i].slice(-1) != '/') o.push(k[i]);
11993 return o.sort();
11994}
11995
11996function zip_add_file(zip, path, content) {
11997 if(zip.FullPaths) CFB.utils.cfb_add(zip, path, content);
11998 else zip.file(path, content);
11999}
12000
12001var jszip;
12002/*global JSZipSync:true */
12003if(typeof JSZipSync !== 'undefined') jszip = JSZipSync;
12004if(typeof exports !== 'undefined') {
12005 if(typeof module !== 'undefined' && module.exports) {
12006 if(typeof jszip === 'undefined') jszip = undefined;
12007 }
12008}
12009
12010function zip_new() {
12011 if(!jszip) return CFB.utils.cfb_new();
12012 return new jszip();
12013}
12014
12015function zip_read(d, o) {
12016 var zip;
12017 if(jszip) switch(o.type) {
12018 case "base64": zip = new jszip(d, { base64:true }); break;
12019 case "binary": case "array": zip = new jszip(d, { base64:false }); break;
12020 case "buffer": zip = new jszip(d); break;
12021 default: throw new Error("Unrecognized type " + o.type);
12022 }
12023 else switch(o.type) {
12024 case "base64": zip = CFB.read(d, { type: "base64" }); break;
12025 case "binary": zip = CFB.read(d, { type: "binary" }); break;
12026 case "buffer": case "array": zip = CFB.read(d, { type: "buffer" }); break;
12027 default: throw new Error("Unrecognized type " + o.type);
12028 }
12029 return zip;
12030}
12031
12032function resolve_path(path, base) {
12033 if(path.charAt(0) == "/") return path.slice(1);
12034 var result = base.split('/');
12035 if(base.slice(-1) != "/") result.pop(); // folder path
12036 var target = path.split('/');
12037 while (target.length !== 0) {
12038 var step = target.shift();
12039 if (step === '..') result.pop();
12040 else if (step !== '.') result.push(step);
12041 }
12042 return result.join('/');
12043}
12044var XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n';
12045var attregexg=/([^"\s?>\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g;
12046var tagregex=/<[\/\?]?[a-zA-Z0-9:_-]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s?[\/\?]?>/g;
12047
12048if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g;
12049var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/;
12050function parsexmltag(tag, skip_root, skip_LC) {
12051 var z = ({});
12052 var eq = 0, c = 0;
12053 for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break;
12054 if(!skip_root) z[0] = tag.slice(0, eq);
12055 if(eq === tag.length) return z;
12056 var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1;
12057 if(m) for(i = 0; i != m.length; ++i) {
12058 cc = m[i];
12059 for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break;
12060 q = cc.slice(0,c).trim();
12061 while(cc.charCodeAt(c+1) == 32) ++c;
12062 quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0;
12063 v = cc.slice(c+1+quot, cc.length-quot);
12064 for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break;
12065 if(j===q.length) {
12066 if(q.indexOf("_") > 0) q = q.slice(0, q.indexOf("_")); // from ods
12067 z[q] = v;
12068 if(!skip_LC) z[q.toLowerCase()] = v;
12069 }
12070 else {
12071 var k = (j===5 && q.slice(0,5)==="xmlns"?"xmlns":"")+q.slice(j+1);
12072 if(z[k] && q.slice(j-3,j) == "ext") continue; // from ods
12073 z[k] = v;
12074 if(!skip_LC) z[k.toLowerCase()] = v;
12075 }
12076 }
12077 return z;
12078}
12079function strip_ns(x) { return x.replace(nsregex2, "<$1"); }
12080
12081var encodings = {
12082 '&quot;': '"',
12083 '&apos;': "'",
12084 '&gt;': '>',
12085 '&lt;': '<',
12086 '&amp;': '&'
12087};
12088var rencoding = evert(encodings);
12089//var rencstr = "&<>'\"".split("");
12090
12091// TODO: CP remap (need to read file version to determine OS)
12092var unescapexml = (function() {
12093 /* 22.4.2.4 bstr (Basic String) */
12094 var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/g, coderegex = /_x([\da-fA-F]{4})_/g;
12095 return function unescapexml(text) {
12096 var s = text + '', i = s.indexOf("<![CDATA[");
12097 if(i == -1) return s.replace(encregex, function($$, $1) { return encodings[$$]||String.fromCharCode(parseInt($1,$$.indexOf("x")>-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
12098 var j = s.indexOf("]]>");
12099 return unescapexml(s.slice(0, i)) + s.slice(i+9,j) + unescapexml(s.slice(j+3));
12100 };
12101})();
12102
12103var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g;
12104function escapexml(text){
12105 var s = text + '';
12106 return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";});
12107}
12108function escapexmltag(text){ return escapexml(text).replace(/ /g,"_x0020_"); }
12109
12110var htmlcharegex = /[\u0000-\u001f]/g;
12111function escapehtml(text){
12112 var s = text + '';
12113 return s.replace(decregex, function(y) { return rencoding[y]; }).replace(/\n/g, "<br/>").replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; });
12114}
12115
12116function escapexlml(text){
12117 var s = text + '';
12118 return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; });
12119}
12120
12121/* TODO: handle codepages */
12122var xlml_fixstr = (function() {
12123 var entregex = /&#(\d+);/g;
12124 function entrepl($$,$1) { return String.fromCharCode(parseInt($1,10)); }
12125 return function xlml_fixstr(str) { return str.replace(entregex,entrepl); };
12126})();
12127var xlml_unfixstr = (function() {
12128 return function xlml_unfixstr(str) { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); };
12129})();
12130
12131function parsexmlbool(value) {
12132 switch(value) {
12133 case 1: case true: case '1': case 'true': case 'TRUE': return true;
12134 /* case '0': case 'false': case 'FALSE':*/
12135 default: return false;
12136 }
12137}
12138
12139var utf8read = function utf8reada(orig) {
12140 var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0;
12141 while (i < orig.length) {
12142 c = orig.charCodeAt(i++);
12143 if (c < 128) { out += String.fromCharCode(c); continue; }
12144 d = orig.charCodeAt(i++);
12145 if (c>191 && c<224) { f = ((c & 31) << 6); f |= (d & 63); out += String.fromCharCode(f); continue; }
12146 e = orig.charCodeAt(i++);
12147 if (c < 240) { out += String.fromCharCode(((c & 15) << 12) | ((d & 63) << 6) | (e & 63)); continue; }
12148 f = orig.charCodeAt(i++);
12149 w = (((c & 7) << 18) | ((d & 63) << 12) | ((e & 63) << 6) | (f & 63))-65536;
12150 out += String.fromCharCode(0xD800 + ((w>>>10)&1023));
12151 out += String.fromCharCode(0xDC00 + (w&1023));
12152 }
12153 return out;
12154};
12155
12156var utf8write = function(orig) {
12157 var out = [], i = 0, c = 0, d = 0;
12158 while(i < orig.length) {
12159 c = orig.charCodeAt(i++);
12160 switch(true) {
12161 case c < 128: out.push(String.fromCharCode(c)); break;
12162 case c < 2048:
12163 out.push(String.fromCharCode(192 + (c >> 6)));
12164 out.push(String.fromCharCode(128 + (c & 63)));
12165 break;
12166 case c >= 55296 && c < 57344:
12167 c -= 55296; d = orig.charCodeAt(i++) - 56320 + (c<<10);
12168 out.push(String.fromCharCode(240 + ((d >>18) & 7)));
12169 out.push(String.fromCharCode(144 + ((d >>12) & 63)));
12170 out.push(String.fromCharCode(128 + ((d >> 6) & 63)));
12171 out.push(String.fromCharCode(128 + (d & 63)));
12172 break;
12173 default:
12174 out.push(String.fromCharCode(224 + (c >> 12)));
12175 out.push(String.fromCharCode(128 + ((c >> 6) & 63)));
12176 out.push(String.fromCharCode(128 + (c & 63)));
12177 }
12178 }
12179 return out.join("");
12180};
12181
12182if(has_buf) {
12183 var utf8readb = function utf8readb(data) {
12184 var out = Buffer.alloc(2*data.length), w, i, j = 1, k = 0, ww=0, c;
12185 for(i = 0; i < data.length; i+=j) {
12186 j = 1;
12187 if((c=data.charCodeAt(i)) < 128) w = c;
12188 else if(c < 224) { w = (c&31)*64+(data.charCodeAt(i+1)&63); j=2; }
12189 else if(c < 240) { w=(c&15)*4096+(data.charCodeAt(i+1)&63)*64+(data.charCodeAt(i+2)&63); j=3; }
12190 else { j = 4;
12191 w = (c & 7)*262144+(data.charCodeAt(i+1)&63)*4096+(data.charCodeAt(i+2)&63)*64+(data.charCodeAt(i+3)&63);
12192 w -= 65536; ww = 0xD800 + ((w>>>10)&1023); w = 0xDC00 + (w&1023);
12193 }
12194 if(ww !== 0) { out[k++] = ww&255; out[k++] = ww>>>8; ww = 0; }
12195 out[k++] = w%256; out[k++] = w>>>8;
12196 }
12197 return out.slice(0,k).toString('ucs2');
12198 };
12199 var corpus = "foo bar baz\u00e2\u0098\u0083\u00f0\u009f\u008d\u00a3";
12200 if(utf8read(corpus) == utf8readb(corpus)) utf8read = utf8readb;
12201 var utf8readc = function utf8readc(data) { return Buffer_from(data, 'binary').toString('utf8'); };
12202 if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc;
12203
12204 utf8write = function(data) { return Buffer_from(data, 'utf8').toString("binary"); };
12205}
12206
12207// matches <foo>...</foo> extracts content
12208var matchtag = (function() {
12209 var mtcache = ({});
12210 return function matchtag(f,g) {
12211 var t = f+"|"+(g||"");
12212 if(mtcache[t]) return mtcache[t];
12213 return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([\\s\\S]*?)</(?:\\w+:)?'+f+'>',((g||""))));
12214 };
12215})();
12216
12217var htmldecode = (function() {
12218 var entities = [
12219 ['nbsp', ' '], ['middot', '·'],
12220 ['quot', '"'], ['apos', "'"], ['gt', '>'], ['lt', '<'], ['amp', '&']
12221 ].map(function(x) { return [new RegExp('&' + x[0] + ';', "g"), x[1]]; });
12222 return function htmldecode(str) {
12223 var o = str
12224 // Remove new lines and spaces from start of content
12225 .replace(/^[\t\n\r ]+/, "")
12226 // Remove new lines and spaces from end of content
12227 .replace(/[\t\n\r ]+$/,"")
12228 // Added line which removes any white space characters after and before html tags
12229 .replace(/>\s+/g,">").replace(/\s+</g,"<")
12230 // Replace remaining new lines and spaces with space
12231 .replace(/[\t\n\r ]+/g, " ")
12232 // Replace <br> tags with new lines
12233 .replace(/<\s*[bB][rR]\s*\/?>/g,"\n")
12234 // Strip HTML elements
12235 .replace(/<[^>]*>/g,"");
12236 for(var i = 0; i < entities.length; ++i) o = o.replace(entities[i][0], entities[i][1]);
12237 return o;
12238 };
12239})();
12240
12241var vtregex = (function(){ var vt_cache = {};
12242 return function vt_regex(bt) {
12243 if(vt_cache[bt] !== undefined) return vt_cache[bt];
12244 return (vt_cache[bt] = new RegExp("<(?:vt:)?" + bt + ">([\\s\\S]*?)</(?:vt:)?" + bt + ">", 'g') );
12245};})();
12246var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^>]*)>([\s\S]*)</;
12247function parseVector(data, opts) {
12248 var h = parsexmltag(data);
12249
12250 var matches = data.match(vtregex(h.baseType))||[];
12251 var res = [];
12252 if(matches.length != h.size) {
12253 if(opts.WTF) throw new Error("unexpected vector length " + matches.length + " != " + h.size);
12254 return res;
12255 }
12256 matches.forEach(function(x) {
12257 var v = x.replace(vtvregex,"").match(vtmregex);
12258 if(v) res.push({v:utf8read(v[2]), t:v[1]});
12259 });
12260 return res;
12261}
12262
12263var wtregex = /(^\s|\s$|\n)/;
12264function writetag(f,g) { return '<' + f + (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f + '>'; }
12265
12266function wxt_helper(h) { return keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join(""); }
12267function writextag(f,g,h) { return '<' + f + ((h != null) ? wxt_helper(h) : "") + ((g != null) ? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '</' + f : "/") + '>';}
12268
12269function write_w3cdtf(d, t) { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } return ""; }
12270
12271function write_vt(s) {
12272 switch(typeof s) {
12273 case 'string': return writextag('vt:lpwstr', s);
12274 case 'number': return writextag((s|0)==s?'vt:i4':'vt:r8', String(s));
12275 case 'boolean': return writextag('vt:bool',s?'true':'false');
12276 }
12277 if(s instanceof Date) return writextag('vt:filetime', write_w3cdtf(s));
12278 throw new Error("Unable to serialize " + s);
12279}
12280
12281var XMLNS = ({
12282 'dc': 'http://purl.org/dc/elements/1.1/',
12283 'dcterms': 'http://purl.org/dc/terms/',
12284 'dcmitype': 'http://purl.org/dc/dcmitype/',
12285 'mx': 'http://schemas.microsoft.com/office/mac/excel/2008/main',
12286 'r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
12287 'sjs': 'http://schemas.openxmlformats.org/package/2006/sheetjs/core-properties',
12288 'vt': 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes',
12289 'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
12290 'xsd': 'http://www.w3.org/2001/XMLSchema'
12291});
12292
12293XMLNS.main = [
12294 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
12295 'http://purl.oclc.org/ooxml/spreadsheetml/main',
12296 'http://schemas.microsoft.com/office/excel/2006/main',
12297 'http://schemas.microsoft.com/office/excel/2006/2'
12298];
12299
12300var XLMLNS = ({
12301 'o': 'urn:schemas-microsoft-com:office:office',
12302 'x': 'urn:schemas-microsoft-com:office:excel',
12303 'ss': 'urn:schemas-microsoft-com:office:spreadsheet',
12304 'dt': 'uuid:C2F41010-65B3-11d1-A29F-00AA00C14882',
12305 'mv': 'http://macVmlSchemaUri',
12306 'v': 'urn:schemas-microsoft-com:vml',
12307 'html': 'http://www.w3.org/TR/REC-html40'
12308});
12309function read_double_le(b, idx) {
12310 var s = 1 - 2 * (b[idx + 7] >>> 7);
12311 var e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 0x0f);
12312 var m = (b[idx+6]&0x0f);
12313 for(var i = 5; i >= 0; --i) m = m * 256 + b[idx + i];
12314 if(e == 0x7ff) return m == 0 ? (s * Infinity) : NaN;
12315 if(e == 0) e = -1022;
12316 else { e -= 1023; m += Math.pow(2,52); }
12317 return s * Math.pow(2, e - 52) * m;
12318}
12319
12320function write_double_le(b, v, idx) {
12321 var bs = ((((v < 0) || (1/v == -Infinity)) ? 1 : 0) << 7), e = 0, m = 0;
12322 var av = bs ? (-v) : v;
12323 if(!isFinite(av)) { e = 0x7ff; m = isNaN(v) ? 0x6969 : 0; }
12324 else if(av == 0) e = m = 0;
12325 else {
12326 e = Math.floor(Math.log(av) / Math.LN2);
12327 m = av * Math.pow(2, 52 - e);
12328 if((e <= -1023) && (!isFinite(m) || (m < Math.pow(2,52)))) { e = -1022; }
12329 else { m -= Math.pow(2,52); e+=1023; }
12330 }
12331 for(var i = 0; i <= 5; ++i, m/=256) b[idx + i] = m & 0xff;
12332 b[idx + 6] = ((e & 0x0f) << 4) | (m & 0xf);
12333 b[idx + 7] = (e >> 4) | bs;
12334}
12335
12336var __toBuffer = function(bufs) { var x=[],w=10240; for(var i=0;i<bufs[0].length;++i) if(bufs[0][i]) for(var j=0,L=bufs[0][i].length;j<L;j+=w) x.push.apply(x, bufs[0][i].slice(j,j+w)); return x; };
12337var ___toBuffer = __toBuffer;
12338var __utf16le = function(b,s,e) { var ss=[]; for(var i=s; i<e; i+=2) ss.push(String.fromCharCode(__readUInt16LE(b,i))); return ss.join("").replace(chr0,''); };
12339var ___utf16le = __utf16le;
12340var __hexlify = function(b,s,l) { var ss=[]; for(var i=s; i<s+l; ++i) ss.push(("0" + b[i].toString(16)).slice(-2)); return ss.join(""); };
12341var ___hexlify = __hexlify;
12342var __utf8 = function(b,s,e) { var ss=[]; for(var i=s; i<e; i++) ss.push(String.fromCharCode(__readUInt8(b,i))); return ss.join(""); };
12343var ___utf8 = __utf8;
12344var __lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
12345var ___lpstr = __lpstr;
12346var __cpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
12347var ___cpstr = __cpstr;
12348var __lpwstr = function(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";};
12349var ___lpwstr = __lpwstr;
12350var __lpp4, ___lpp4;
12351__lpp4 = ___lpp4 = function lpp4_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";};
12352var __8lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";};
12353var ___8lpp4 = __8lpp4;
12354var __double, ___double;
12355__double = ___double = function(b, idx) { return read_double_le(b, idx);};
12356var is_buf = function is_buf_a(a) { return Array.isArray(a); };
12357
12358if(has_buf) {
12359 __utf16le = function(b,s,e) { if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); return b.toString('utf16le',s,e).replace(chr0,'')/*.replace(chr1,'!')*/; };
12360 __hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); };
12361 __lpstr = function lpstr_b(b, i) { if(!Buffer.isBuffer(b)) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
12362 __cpstr = function cpstr_b(b, i) { if(!Buffer.isBuffer(b)) return ___cpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";};
12363 __lpwstr = function lpwstr_b(b, i) { if(!Buffer.isBuffer(b)) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);};
12364 __lpp4 = function lpp4_b(b, i) { if(!Buffer.isBuffer(b)) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);};
12365 __8lpp4 = function lpp4_8b(b, i) { if(!Buffer.isBuffer(b)) return ___8lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf8',i+4,i+4+len);};
12366 __utf8 = function utf8_b(b, s, e) { return (Buffer.isBuffer(b)) ? b.toString('utf8',s,e) : ___utf8(b,s,e); };
12367 __toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);};
12368 bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); };
12369 __double = function double_(b, i) { if(Buffer.isBuffer(b)) return b.readDoubleLE(i); return ___double(b,i); };
12370 is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); };
12371}
12372
12373/* from js-xls */
12374if(typeof cptable !== 'undefined') {
12375 __utf16le = function(b,s,e) { return cptable.utils.decode(1200, b.slice(s,e)).replace(chr0, ''); };
12376 __utf8 = function(b,s,e) { return cptable.utils.decode(65001, b.slice(s,e)); };
12377 __lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_ansi, b.slice(i+4, i+4+len-1)) : "";};
12378 __cpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";};
12379 __lpwstr = function(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";};
12380 __lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";};
12381 __8lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";};
12382}
12383
12384var __readUInt8 = function(b, idx) { return b[idx]; };
12385var __readUInt16LE = function(b, idx) { return (b[idx+1]*(1<<8))+b[idx]; };
12386var __readInt16LE = function(b, idx) { var u = (b[idx+1]*(1<<8))+b[idx]; return (u < 0x8000) ? u : ((0xffff - u + 1) * -1); };
12387var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; };
12388var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; };
12389var __readInt32BE = function(b, idx) { return (b[idx]<<24)|(b[idx+1]<<16)|(b[idx+2]<<8)|b[idx+3]; };
12390
12391function ReadShift(size, t) {
12392 var o="", oI, oR, oo=[], w, vv, i, loc;
12393 switch(t) {
12394 case 'dbcs':
12395 loc = this.l;
12396 if(has_buf && Buffer.isBuffer(this)) o = this.slice(this.l, this.l+2*size).toString("utf16le");
12397 else for(i = 0; i < size; ++i) { o+=String.fromCharCode(__readUInt16LE(this, loc)); loc+=2; }
12398 size *= 2;
12399 break;
12400
12401 case 'utf8': o = __utf8(this, this.l, this.l + size); break;
12402 case 'utf16le': size *= 2; o = __utf16le(this, this.l, this.l + size); break;
12403
12404 case 'wstr':
12405 if(typeof cptable !== 'undefined') o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l+2*size));
12406 else return ReadShift.call(this, size, 'dbcs');
12407 size = 2 * size; break;
12408
12409 /* [MS-OLEDS] 2.1.4 LengthPrefixedAnsiString */
12410 case 'lpstr-ansi': o = __lpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break;
12411 case 'lpstr-cp': o = __cpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break;
12412 /* [MS-OLEDS] 2.1.5 LengthPrefixedUnicodeString */
12413 case 'lpwstr': o = __lpwstr(this, this.l); size = 4 + 2 * __readUInt32LE(this, this.l); break;
12414 /* [MS-OFFCRYPTO] 2.1.2 Length-Prefixed Padded Unicode String (UNICODE-LP-P4) */
12415 case 'lpp4': size = 4 + __readUInt32LE(this, this.l); o = __lpp4(this, this.l); if(size & 0x02) size += 2; break;
12416 /* [MS-OFFCRYPTO] 2.1.3 Length-Prefixed UTF-8 String (UTF-8-LP-P4) */
12417 case '8lpp4': size = 4 + __readUInt32LE(this, this.l); o = __8lpp4(this, this.l); if(size & 0x03) size += 4 - (size & 0x03); break;
12418
12419 case 'cstr': size = 0; o = "";
12420 while((w=__readUInt8(this, this.l + size++))!==0) oo.push(_getchar(w));
12421 o = oo.join(""); break;
12422 case '_wstr': size = 0; o = "";
12423 while((w=__readUInt16LE(this,this.l +size))!==0){oo.push(_getchar(w));size+=2;}
12424 size+=2; o = oo.join(""); break;
12425
12426 /* sbcs and dbcs support continue records in the SST way TODO codepages */
12427 case 'dbcs-cont': o = ""; loc = this.l;
12428 for(i = 0; i < size; ++i) {
12429 if(this.lens && this.lens.indexOf(loc) !== -1) {
12430 w = __readUInt8(this, loc);
12431 this.l = loc + 1;
12432 vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont');
12433 return oo.join("") + vv;
12434 }
12435 oo.push(_getchar(__readUInt16LE(this, loc)));
12436 loc+=2;
12437 } o = oo.join(""); size *= 2; break;
12438
12439 case 'cpstr':
12440 if(typeof cptable !== 'undefined') {
12441 o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l + size));
12442 break;
12443 }
12444 /* falls through */
12445 case 'sbcs-cont': o = ""; loc = this.l;
12446 for(i = 0; i != size; ++i) {
12447 if(this.lens && this.lens.indexOf(loc) !== -1) {
12448 w = __readUInt8(this, loc);
12449 this.l = loc + 1;
12450 vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont');
12451 return oo.join("") + vv;
12452 }
12453 oo.push(_getchar(__readUInt8(this, loc)));
12454 loc+=1;
12455 } o = oo.join(""); break;
12456
12457 default:
12458 switch(size) {
12459 case 1: oI = __readUInt8(this, this.l); this.l++; return oI;
12460 case 2: oI = (t === 'i' ? __readInt16LE : __readUInt16LE)(this, this.l); this.l += 2; return oI;
12461 case 4: case -4:
12462 if(t === 'i' || ((this[this.l+3] & 0x80)===0)) { oI = ((size > 0) ? __readInt32LE : __readInt32BE)(this, this.l); this.l += 4; return oI; }
12463 else { oR = __readUInt32LE(this, this.l); this.l += 4; } return oR;
12464 case 8: case -8:
12465 if(t === 'f') {
12466 if(size == 8) oR = __double(this, this.l);
12467 else oR = __double([this[this.l+7],this[this.l+6],this[this.l+5],this[this.l+4],this[this.l+3],this[this.l+2],this[this.l+1],this[this.l+0]], 0);
12468 this.l += 8; return oR;
12469 } else size = 8;
12470 /* falls through */
12471 case 16: o = __hexlify(this, this.l, size); break;
12472 }}
12473 this.l+=size; return o;
12474}
12475
12476var __writeUInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); b[idx+2] = ((val >>> 16) & 0xFF); b[idx+3] = ((val >>> 24) & 0xFF); };
12477var __writeInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >> 8) & 0xFF); b[idx+2] = ((val >> 16) & 0xFF); b[idx+3] = ((val >> 24) & 0xFF); };
12478var __writeUInt16LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); };
12479
12480function WriteShift(t, val, f) {
12481 var size = 0, i = 0;
12482 if(f === 'dbcs') {
12483for(i = 0; i != val.length; ++i) __writeUInt16LE(this, val.charCodeAt(i), this.l + 2 * i);
12484 size = 2 * val.length;
12485 } else if(f === 'sbcs') {
12486 if(typeof cptable !== 'undefined' && current_ansi == 874) {
12487 /* TODO: use tables directly, don't encode */
12488for(i = 0; i != val.length; ++i) {
12489 var cppayload = cptable.utils.encode(current_ansi, val.charAt(i));
12490 this[this.l + i] = cppayload[0];
12491 }
12492 } else {
12493val = val.replace(/[^\x00-\x7F]/g, "_");
12494for(i = 0; i != val.length; ++i) this[this.l + i] = (val.charCodeAt(i) & 0xFF);
12495 }
12496 size = val.length;
12497 } else if(f === 'hex') {
12498 for(; i < t; ++i) {
12499this[this.l++] = (parseInt(val.slice(2*i, 2*i+2), 16)||0);
12500 } return this;
12501 } else if(f === 'utf16le') {
12502var end = Math.min(this.l + t, this.length);
12503 for(i = 0; i < Math.min(val.length, t); ++i) {
12504 var cc = val.charCodeAt(i);
12505 this[this.l++] = (cc & 0xff);
12506 this[this.l++] = (cc >> 8);
12507 }
12508 while(this.l < end) this[this.l++] = 0;
12509 return this;
12510 } else switch(t) {
12511 case 1: size = 1; this[this.l] = val&0xFF; break;
12512 case 2: size = 2; this[this.l] = val&0xFF; val >>>= 8; this[this.l+1] = val&0xFF; break;
12513 case 3: size = 3; this[this.l] = val&0xFF; val >>>= 8; this[this.l+1] = val&0xFF; val >>>= 8; this[this.l+2] = val&0xFF; break;
12514 case 4: size = 4; __writeUInt32LE(this, val, this.l); break;
12515 case 8: size = 8; if(f === 'f') { write_double_le(this, val, this.l); break; }
12516 /* falls through */
12517 case 16: break;
12518 case -4: size = 4; __writeInt32LE(this, val, this.l); break;
12519 }
12520 this.l += size; return this;
12521}
12522
12523function CheckField(hexstr, fld) {
12524 var m = __hexlify(this,this.l,hexstr.length>>1);
12525 if(m !== hexstr) throw new Error(fld + 'Expected ' + hexstr + ' saw ' + m);
12526 this.l += hexstr.length>>1;
12527}
12528
12529function prep_blob(blob, pos) {
12530 blob.l = pos;
12531 blob.read_shift = ReadShift;
12532 blob.chk = CheckField;
12533 blob.write_shift = WriteShift;
12534}
12535
12536function parsenoop(blob, length) { blob.l += length; }
12537
12538function new_buf(sz) {
12539 var o = new_raw_buf(sz);
12540 prep_blob(o, 0);
12541 return o;
12542}
12543
12544/* [MS-XLSB] 2.1.4 Record */
12545function recordhopper(data, cb, opts) {
12546 if(!data) return;
12547 var tmpbyte, cntbyte, length;
12548 prep_blob(data, data.l || 0);
12549 var L = data.length, RT = 0, tgt = 0;
12550 while(data.l < L) {
12551 RT = data.read_shift(1);
12552 if(RT & 0x80) RT = (RT & 0x7F) + ((data.read_shift(1) & 0x7F)<<7);
12553 var R = XLSBRecordEnum[RT] || XLSBRecordEnum[0xFFFF];
12554 tmpbyte = data.read_shift(1);
12555 length = tmpbyte & 0x7F;
12556 for(cntbyte = 1; cntbyte <4 && (tmpbyte & 0x80); ++cntbyte) length += ((tmpbyte = data.read_shift(1)) & 0x7F)<<(7*cntbyte);
12557 tgt = data.l + length;
12558 var d = (R.f||parsenoop)(data, length, opts);
12559 data.l = tgt;
12560 if(cb(d, R.n, RT)) return;
12561 }
12562}
12563
12564/* control buffer usage for fixed-length buffers */
12565function buf_array() {
12566 var bufs = [], blksz = has_buf ? 256 : 2048;
12567 var newblk = function ba_newblk(sz) {
12568 var o = (new_buf(sz));
12569 prep_blob(o, 0);
12570 return o;
12571 };
12572
12573 var curbuf = newblk(blksz);
12574
12575 var endbuf = function ba_endbuf() {
12576 if(!curbuf) return;
12577 if(curbuf.length > curbuf.l) { curbuf = curbuf.slice(0, curbuf.l); curbuf.l = curbuf.length; }
12578 if(curbuf.length > 0) bufs.push(curbuf);
12579 curbuf = null;
12580 };
12581
12582 var next = function ba_next(sz) {
12583 if(curbuf && (sz < (curbuf.length - curbuf.l))) return curbuf;
12584 endbuf();
12585 return (curbuf = newblk(Math.max(sz+1, blksz)));
12586 };
12587
12588 var end = function ba_end() {
12589 endbuf();
12590 return __toBuffer([bufs]);
12591 };
12592
12593 var push = function ba_push(buf) { endbuf(); curbuf = buf; if(curbuf.l == null) curbuf.l = curbuf.length; next(blksz); };
12594
12595 return ({ next:next, push:push, end:end, _bufs:bufs });
12596}
12597
12598function write_record(ba, type, payload, length) {
12599 var t = +XLSBRE[type], l;
12600 if(isNaN(t)) return; // TODO: throw something here?
12601 if(!length) length = XLSBRecordEnum[t].p || (payload||[]).length || 0;
12602 l = 1 + (t >= 0x80 ? 1 : 0) + 1/* + length*/;
12603 if(length >= 0x80) ++l; if(length >= 0x4000) ++l; if(length >= 0x200000) ++l;
12604 var o = ba.next(l);
12605 if(t <= 0x7F) o.write_shift(1, t);
12606 else {
12607 o.write_shift(1, (t & 0x7F) + 0x80);
12608 o.write_shift(1, (t >> 7));
12609 }
12610 for(var i = 0; i != 4; ++i) {
12611 if(length >= 0x80) { o.write_shift(1, (length & 0x7F)+0x80); length >>= 7; }
12612 else { o.write_shift(1, length); break; }
12613 }
12614 if(length > 0 && is_buf(payload)) ba.push(payload);
12615}
12616/* XLS ranges enforced */
12617function shift_cell_xls(cell, tgt, opts) {
12618 var out = dup(cell);
12619 if(tgt.s) {
12620 if(out.cRel) out.c += tgt.s.c;
12621 if(out.rRel) out.r += tgt.s.r;
12622 } else {
12623 if(out.cRel) out.c += tgt.c;
12624 if(out.rRel) out.r += tgt.r;
12625 }
12626 if(!opts || opts.biff < 12) {
12627 while(out.c >= 0x100) out.c -= 0x100;
12628 while(out.r >= 0x10000) out.r -= 0x10000;
12629 }
12630 return out;
12631}
12632
12633function shift_range_xls(cell, range, opts) {
12634 var out = dup(cell);
12635 out.s = shift_cell_xls(out.s, range.s, opts);
12636 out.e = shift_cell_xls(out.e, range.s, opts);
12637 return out;
12638}
12639
12640function encode_cell_xls(c, biff) {
12641 if(c.cRel && c.c < 0) { c = dup(c); while(c.c < 0) c.c += (biff > 8) ? 0x4000 : 0x100; }
12642 if(c.rRel && c.r < 0) { c = dup(c); while(c.r < 0) c.r += (biff > 8) ? 0x100000 : ((biff > 5) ? 0x10000 : 0x4000); }
12643 var s = encode_cell(c);
12644 if(!c.cRel && c.cRel != null) s = fix_col(s);
12645 if(!c.rRel && c.rRel != null) s = fix_row(s);
12646 return s;
12647}
12648
12649function encode_range_xls(r, opts) {
12650 if(r.s.r == 0 && !r.s.rRel) {
12651 if(r.e.r == (opts.biff >= 12 ? 0xFFFFF : (opts.biff >= 8 ? 0x10000 : 0x4000)) && !r.e.rRel) {
12652 return (r.s.cRel ? "" : "$") + encode_col(r.s.c) + ":" + (r.e.cRel ? "" : "$") + encode_col(r.e.c);
12653 }
12654 }
12655 if(r.s.c == 0 && !r.s.cRel) {
12656 if(r.e.c == (opts.biff >= 12 ? 0xFFFF : 0xFF) && !r.e.cRel) {
12657 return (r.s.rRel ? "" : "$") + encode_row(r.s.r) + ":" + (r.e.rRel ? "" : "$") + encode_row(r.e.r);
12658 }
12659 }
12660 return encode_cell_xls(r.s, opts.biff) + ":" + encode_cell_xls(r.e, opts.biff);
12661}
12662var OFFCRYPTO = {};
12663
12664var make_offcrypto = function(O, _crypto) {
12665 var crypto;
12666 if(typeof _crypto !== 'undefined') crypto = _crypto;
12667 else if(typeof require !== 'undefined') {
12668 try { crypto = undefined; }
12669 catch(e) { crypto = null; }
12670 }
12671
12672 O.rc4 = function(key, data) {
12673 var S = new Array(256);
12674 var c = 0, i = 0, j = 0, t = 0;
12675 for(i = 0; i != 256; ++i) S[i] = i;
12676 for(i = 0; i != 256; ++i) {
12677 j = (j + S[i] + (key[i%key.length]).charCodeAt(0))&255;
12678 t = S[i]; S[i] = S[j]; S[j] = t;
12679 }
12680 // $FlowIgnore
12681 i = j = 0; var out = Buffer(data.length);
12682 for(c = 0; c != data.length; ++c) {
12683 i = (i + 1)&255;
12684 j = (j + S[i])%256;
12685 t = S[i]; S[i] = S[j]; S[j] = t;
12686 out[c] = (data[c] ^ S[(S[i]+S[j])&255]);
12687 }
12688 return out;
12689 };
12690
12691 O.md5 = function(hex) {
12692 if(!crypto) throw new Error("Unsupported crypto");
12693 return crypto.createHash('md5').update(hex).digest('hex');
12694 };
12695};
12696/*global crypto:true */
12697make_offcrypto(OFFCRYPTO, typeof crypto !== "undefined" ? crypto : undefined);
12698
12699function decode_row(rowstr) { return parseInt(unfix_row(rowstr),10) - 1; }
12700function encode_row(row) { return "" + (row + 1); }
12701function fix_row(cstr) { return cstr.replace(/([A-Z]|^)(\d+)$/,"$1$$$2"); }
12702function unfix_row(cstr) { return cstr.replace(/\$(\d+)$/,"$1"); }
12703
12704function decode_col(colstr) { var c = unfix_col(colstr), d = 0, i = 0; for(; i !== c.length; ++i) d = 26*d + c.charCodeAt(i) - 64; return d - 1; }
12705function encode_col(col) { if(col < 0) throw new Error("invalid column " + col); var s=""; for(++col; col; col=Math.floor((col-1)/26)) s = String.fromCharCode(((col-1)%26) + 65) + s; return s; }
12706function fix_col(cstr) { return cstr.replace(/^([A-Z])/,"$$$1"); }
12707function unfix_col(cstr) { return cstr.replace(/^\$([A-Z])/,"$1"); }
12708
12709function split_cell(cstr) { return cstr.replace(/(\$?[A-Z]*)(\$?\d*)/,"$1,$2").split(","); }
12710function decode_cell(cstr) { var splt = split_cell(cstr); return { c:decode_col(splt[0]), r:decode_row(splt[1]) }; }
12711function encode_cell(cell) { return encode_col(cell.c) + encode_row(cell.r); }
12712function decode_range(range) { var x =range.split(":").map(decode_cell); return {s:x[0],e:x[x.length-1]}; }
12713function encode_range(cs,ce) {
12714 if(typeof ce === 'undefined' || typeof ce === 'number') {
12715return encode_range(cs.s, cs.e);
12716 }
12717if(typeof cs !== 'string') cs = encode_cell((cs));
12718 if(typeof ce !== 'string') ce = encode_cell((ce));
12719return cs == ce ? cs : cs + ":" + ce;
12720}
12721
12722function safe_decode_range(range) {
12723 var o = {s:{c:0,r:0},e:{c:0,r:0}};
12724 var idx = 0, i = 0, cc = 0;
12725 var len = range.length;
12726 for(idx = 0; i < len; ++i) {
12727 if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
12728 idx = 26*idx + cc;
12729 }
12730 o.s.c = --idx;
12731
12732 for(idx = 0; i < len; ++i) {
12733 if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
12734 idx = 10*idx + cc;
12735 }
12736 o.s.r = --idx;
12737
12738 if(i === len || range.charCodeAt(++i) === 58) { o.e.c=o.s.c; o.e.r=o.s.r; return o; }
12739
12740 for(idx = 0; i != len; ++i) {
12741 if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break;
12742 idx = 26*idx + cc;
12743 }
12744 o.e.c = --idx;
12745
12746 for(idx = 0; i != len; ++i) {
12747 if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break;
12748 idx = 10*idx + cc;
12749 }
12750 o.e.r = --idx;
12751 return o;
12752}
12753
12754function safe_format_cell(cell, v) {
12755 var q = (cell.t == 'd' && v instanceof Date);
12756 if(cell.z != null) try { return (cell.w = SSF.format(cell.z, q ? datenum(v) : v)); } catch(e) { }
12757 try { return (cell.w = SSF.format((cell.XF||{}).numFmtId||(q ? 14 : 0), q ? datenum(v) : v)); } catch(e) { return ''+v; }
12758}
12759
12760function format_cell(cell, v, o) {
12761 if(cell == null || cell.t == null || cell.t == 'z') return "";
12762 if(cell.w !== undefined) return cell.w;
12763 if(cell.t == 'd' && !cell.z && o && o.dateNF) cell.z = o.dateNF;
12764 if(v == undefined) return safe_format_cell(cell, cell.v);
12765 return safe_format_cell(cell, v);
12766}
12767
12768function sheet_to_workbook(sheet, opts) {
12769 var n = opts && opts.sheet ? opts.sheet : "Sheet1";
12770 var sheets = {}; sheets[n] = sheet;
12771 return { SheetNames: [n], Sheets: sheets };
12772}
12773
12774function sheet_add_aoa(_ws, data, opts) {
12775 var o = opts || {};
12776 var dense = _ws ? Array.isArray(_ws) : o.dense;
12777 if(DENSE != null && dense == null) dense = DENSE;
12778 var ws = _ws || (dense ? ([]) : ({}));
12779 var _R = 0, _C = 0;
12780 if(ws && o.origin != null) {
12781 if(typeof o.origin == 'number') _R = o.origin;
12782 else {
12783 var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
12784 _R = _origin.r; _C = _origin.c;
12785 }
12786 }
12787 var range = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}});
12788 if(ws['!ref']) {
12789 var _range = safe_decode_range(ws['!ref']);
12790 range.s.c = _range.s.c;
12791 range.s.r = _range.s.r;
12792 range.e.c = Math.max(range.e.c, _range.e.c);
12793 range.e.r = Math.max(range.e.r, _range.e.r);
12794 if(_R == -1) range.e.r = _R = _range.e.r + 1;
12795 }
12796 for(var R = 0; R != data.length; ++R) {
12797 if(!data[R]) continue;
12798 if(!Array.isArray(data[R])) throw new Error("aoa_to_sheet expects an array of arrays");
12799 for(var C = 0; C != data[R].length; ++C) {
12800 if(typeof data[R][C] === 'undefined') continue;
12801 var cell = ({v: data[R][C] });
12802 var __R = _R + R, __C = _C + C;
12803 if(range.s.r > __R) range.s.r = __R;
12804 if(range.s.c > __C) range.s.c = __C;
12805 if(range.e.r < __R) range.e.r = __R;
12806 if(range.e.c < __C) range.e.c = __C;
12807 if(data[R][C] && typeof data[R][C] === 'object' && !Array.isArray(data[R][C]) && !(data[R][C] instanceof Date)) cell = data[R][C];
12808 else {
12809 if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; }
12810 if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.sheetStubs) continue; else cell.t = 'z'; }
12811 else if(typeof cell.v === 'number') cell.t = 'n';
12812 else if(typeof cell.v === 'boolean') cell.t = 'b';
12813 else if(cell.v instanceof Date) {
12814 cell.z = o.dateNF || SSF._table[14];
12815 if(o.cellDates) { cell.t = 'd'; cell.w = SSF.format(cell.z, datenum(cell.v)); }
12816 else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); }
12817 }
12818 else cell.t = 's';
12819 }
12820 if(dense) {
12821 if(!ws[__R]) ws[__R] = [];
12822 ws[__R][__C] = cell;
12823 } else {
12824 var cell_ref = encode_cell(({c:__C,r:__R}));
12825 ws[cell_ref] = cell;
12826 }
12827 }
12828 }
12829 if(range.s.c < 10000000) ws['!ref'] = encode_range(range);
12830 return ws;
12831}
12832function aoa_to_sheet(data, opts) { return sheet_add_aoa(null, data, opts); }
12833
12834function write_UInt32LE(x, o) {
12835 if(!o) o = new_buf(4);
12836 o.write_shift(4, x);
12837 return o;
12838}
12839
12840/* [MS-XLSB] 2.5.168 */
12841function parse_XLWideString(data) {
12842 var cchCharacters = data.read_shift(4);
12843 return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, 'dbcs');
12844}
12845function write_XLWideString(data, o) {
12846 var _null = false; if(o == null) { _null = true; o = new_buf(4+2*data.length); }
12847 o.write_shift(4, data.length);
12848 if(data.length > 0) o.write_shift(0, data, 'dbcs');
12849 return _null ? o.slice(0, o.l) : o;
12850}
12851
12852/* [MS-XLSB] 2.5.143 */
12853function parse_StrRun(data) {
12854 return { ich: data.read_shift(2), ifnt: data.read_shift(2) };
12855}
12856function write_StrRun(run, o) {
12857 if(!o) o = new_buf(4);
12858 o.write_shift(2, run.ich || 0);
12859 o.write_shift(2, run.ifnt || 0);
12860 return o;
12861}
12862
12863/* [MS-XLSB] 2.5.121 */
12864function parse_RichStr(data, length) {
12865 var start = data.l;
12866 var flags = data.read_shift(1);
12867 var str = parse_XLWideString(data);
12868 var rgsStrRun = [];
12869 var z = ({ t: str, h: str });
12870 if((flags & 1) !== 0) { /* fRichStr */
12871 /* TODO: formatted string */
12872 var dwSizeStrRun = data.read_shift(4);
12873 for(var i = 0; i != dwSizeStrRun; ++i) rgsStrRun.push(parse_StrRun(data));
12874 z.r = rgsStrRun;
12875 }
12876 else z.r = [{ich:0, ifnt:0}];
12877 //if((flags & 2) !== 0) { /* fExtStr */
12878 // /* TODO: phonetic string */
12879 //}
12880 data.l = start + length;
12881 return z;
12882}
12883function write_RichStr(str, o) {
12884 /* TODO: formatted string */
12885 var _null = false; if(o == null) { _null = true; o = new_buf(15+4*str.t.length); }
12886 o.write_shift(1,0);
12887 write_XLWideString(str.t, o);
12888 return _null ? o.slice(0, o.l) : o;
12889}
12890/* [MS-XLSB] 2.4.328 BrtCommentText (RichStr w/1 run) */
12891var parse_BrtCommentText = parse_RichStr;
12892function write_BrtCommentText(str, o) {
12893 /* TODO: formatted string */
12894 var _null = false; if(o == null) { _null = true; o = new_buf(23+4*str.t.length); }
12895 o.write_shift(1,1);
12896 write_XLWideString(str.t, o);
12897 o.write_shift(4,1);
12898 write_StrRun({ich:0,ifnt:0}, o);
12899 return _null ? o.slice(0, o.l) : o;
12900}
12901
12902/* [MS-XLSB] 2.5.9 */
12903function parse_XLSBCell(data) {
12904 var col = data.read_shift(4);
12905 var iStyleRef = data.read_shift(2);
12906 iStyleRef += data.read_shift(1) <<16;
12907 data.l++; //var fPhShow = data.read_shift(1);
12908 return { c:col, iStyleRef: iStyleRef };
12909}
12910function write_XLSBCell(cell, o) {
12911 if(o == null) o = new_buf(8);
12912 o.write_shift(-4, cell.c);
12913 o.write_shift(3, cell.iStyleRef || cell.s);
12914 o.write_shift(1, 0); /* fPhShow */
12915 return o;
12916}
12917
12918
12919/* [MS-XLSB] 2.5.21 */
12920var parse_XLSBCodeName = parse_XLWideString;
12921var write_XLSBCodeName = write_XLWideString;
12922
12923/* [MS-XLSB] 2.5.166 */
12924function parse_XLNullableWideString(data) {
12925 var cchCharacters = data.read_shift(4);
12926 return cchCharacters === 0 || cchCharacters === 0xFFFFFFFF ? "" : data.read_shift(cchCharacters, 'dbcs');
12927}
12928function write_XLNullableWideString(data, o) {
12929 var _null = false; if(o == null) { _null = true; o = new_buf(127); }
12930 o.write_shift(4, data.length > 0 ? data.length : 0xFFFFFFFF);
12931 if(data.length > 0) o.write_shift(0, data, 'dbcs');
12932 return _null ? o.slice(0, o.l) : o;
12933}
12934
12935/* [MS-XLSB] 2.5.165 */
12936var parse_XLNameWideString = parse_XLWideString;
12937//var write_XLNameWideString = write_XLWideString;
12938
12939/* [MS-XLSB] 2.5.114 */
12940var parse_RelID = parse_XLNullableWideString;
12941var write_RelID = write_XLNullableWideString;
12942
12943
12944/* [MS-XLS] 2.5.217 ; [MS-XLSB] 2.5.122 */
12945function parse_RkNumber(data) {
12946 var b = data.slice(data.l, data.l+4);
12947 var fX100 = (b[0] & 1), fInt = (b[0] & 2);
12948 data.l+=4;
12949 b[0] &= 0xFC; // b[0] &= ~3;
12950 var RK = fInt === 0 ? __double([0,0,0,0,b[0],b[1],b[2],b[3]],0) : __readInt32LE(b,0)>>2;
12951 return fX100 ? (RK/100) : RK;
12952}
12953function write_RkNumber(data, o) {
12954 if(o == null) o = new_buf(4);
12955 var fX100 = 0, fInt = 0, d100 = data * 100;
12956 if((data == (data | 0)) && (data >= -(1<<29)) && (data < (1 << 29))) { fInt = 1; }
12957 else if((d100 == (d100 | 0)) && (d100 >= -(1<<29)) && (d100 < (1 << 29))) { fInt = 1; fX100 = 1; }
12958 if(fInt) o.write_shift(-4, ((fX100 ? d100 : data) << 2) + (fX100 + 2));
12959 else throw new Error("unsupported RkNumber " + data); // TODO
12960}
12961
12962
12963/* [MS-XLSB] 2.5.117 RfX */
12964function parse_RfX(data ) {
12965 var cell = ({s: {}, e: {}});
12966 cell.s.r = data.read_shift(4);
12967 cell.e.r = data.read_shift(4);
12968 cell.s.c = data.read_shift(4);
12969 cell.e.c = data.read_shift(4);
12970 return cell;
12971}
12972function write_RfX(r, o) {
12973 if(!o) o = new_buf(16);
12974 o.write_shift(4, r.s.r);
12975 o.write_shift(4, r.e.r);
12976 o.write_shift(4, r.s.c);
12977 o.write_shift(4, r.e.c);
12978 return o;
12979}
12980
12981/* [MS-XLSB] 2.5.153 UncheckedRfX */
12982var parse_UncheckedRfX = parse_RfX;
12983var write_UncheckedRfX = write_RfX;
12984
12985
12986/* [MS-XLS] 2.5.342 ; [MS-XLSB] 2.5.171 */
12987/* TODO: error checking, NaN and Infinity values are not valid Xnum */
12988function parse_Xnum(data) { return data.read_shift(8, 'f'); }
12989function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); }
12990
12991/* [MS-XLSB] 2.5.97.2 */
12992var BErr = {
129930x00: "#NULL!",
129940x07: "#DIV/0!",
129950x0F: "#VALUE!",
129960x17: "#REF!",
129970x1D: "#NAME?",
129980x24: "#NUM!",
129990x2A: "#N/A",
130000x2B: "#GETTING_DATA",
130010xFF: "#WTF?"
13002};
13003var RBErr = evert_num(BErr);
13004
13005/* [MS-XLSB] 2.4.324 BrtColor */
13006function parse_BrtColor(data) {
13007 var out = {};
13008 var d = data.read_shift(1);
13009
13010 //var fValidRGB = d & 1;
13011 var xColorType = d >>> 1;
13012
13013 var index = data.read_shift(1);
13014 var nTS = data.read_shift(2, 'i');
13015 var bR = data.read_shift(1);
13016 var bG = data.read_shift(1);
13017 var bB = data.read_shift(1);
13018 data.l++; //var bAlpha = data.read_shift(1);
13019
13020 switch(xColorType) {
13021 case 0: out.auto = 1; break;
13022 case 1:
13023 out.index = index;
13024 var icv = XLSIcv[index];
13025 /* automatic pseudo index 81 */
13026 if(icv) out.rgb = rgb2Hex(icv);
13027 break;
13028 case 2:
13029 /* if(!fValidRGB) throw new Error("invalid"); */
13030 out.rgb = rgb2Hex([bR, bG, bB]);
13031 break;
13032 case 3: out.theme = index; break;
13033 }
13034 if(nTS != 0) out.tint = nTS > 0 ? nTS / 32767 : nTS / 32768;
13035
13036 return out;
13037}
13038function write_BrtColor(color, o) {
13039 if(!o) o = new_buf(8);
13040 if(!color||color.auto) { o.write_shift(4, 0); o.write_shift(4, 0); return o; }
13041 if(color.index != null) {
13042 o.write_shift(1, 0x02);
13043 o.write_shift(1, color.index);
13044 } else if(color.theme != null) {
13045 o.write_shift(1, 0x06);
13046 o.write_shift(1, color.theme);
13047 } else {
13048 o.write_shift(1, 0x05);
13049 o.write_shift(1, 0);
13050 }
13051 var nTS = color.tint || 0;
13052 if(nTS > 0) nTS *= 32767;
13053 else if(nTS < 0) nTS *= 32768;
13054 o.write_shift(2, nTS);
13055 if(!color.rgb || color.theme != null) {
13056 o.write_shift(2, 0);
13057 o.write_shift(1, 0);
13058 o.write_shift(1, 0);
13059 } else {
13060 var rgb = (color.rgb || 'FFFFFF');
13061 if(typeof rgb == 'number') rgb = ("000000" + rgb.toString(16)).slice(-6);
13062 o.write_shift(1, parseInt(rgb.slice(0,2),16));
13063 o.write_shift(1, parseInt(rgb.slice(2,4),16));
13064 o.write_shift(1, parseInt(rgb.slice(4,6),16));
13065 o.write_shift(1, 0xFF);
13066 }
13067 return o;
13068}
13069
13070/* [MS-XLSB] 2.5.52 */
13071function parse_FontFlags(data) {
13072 var d = data.read_shift(1);
13073 data.l++;
13074 var out = {
13075 fBold: d & 0x01,
13076 fItalic: d & 0x02,
13077 fUnderline: d & 0x04,
13078 fStrikeout: d & 0x08,
13079 fOutline: d & 0x10,
13080 fShadow: d & 0x20,
13081 fCondense: d & 0x40,
13082 fExtend: d & 0x80
13083 };
13084 return out;
13085}
13086function write_FontFlags(font, o) {
13087 if(!o) o = new_buf(2);
13088 var grbit =
13089 (font.italic ? 0x02 : 0) |
13090 (font.strike ? 0x08 : 0) |
13091 (font.outline ? 0x10 : 0) |
13092 (font.shadow ? 0x20 : 0) |
13093 (font.condense ? 0x40 : 0) |
13094 (font.extend ? 0x80 : 0);
13095 o.write_shift(1, grbit);
13096 o.write_shift(1, 0);
13097 return o;
13098}
13099
13100/* [MS-OLEDS] 2.3.1 and 2.3.2 */
13101function parse_ClipboardFormatOrString(o, w) {
13102 // $FlowIgnore
13103 var ClipFmt = {2:"BITMAP",3:"METAFILEPICT",8:"DIB",14:"ENHMETAFILE"};
13104 var m = o.read_shift(4);
13105 switch(m) {
13106 case 0x00000000: return "";
13107 case 0xffffffff: case 0xfffffffe: return ClipFmt[o.read_shift(4)]||"";
13108 }
13109 if(m > 0x190) throw new Error("Unsupported Clipboard: " + m.toString(16));
13110 o.l -= 4;
13111 return o.read_shift(0, w == 1 ? "lpstr" : "lpwstr");
13112}
13113function parse_ClipboardFormatOrAnsiString(o) { return parse_ClipboardFormatOrString(o, 1); }
13114function parse_ClipboardFormatOrUnicodeString(o) { return parse_ClipboardFormatOrString(o, 2); }
13115
13116/* [MS-OLEPS] 2.2 PropertyType */
13117//var VT_EMPTY = 0x0000;
13118//var VT_NULL = 0x0001;
13119var VT_I2 = 0x0002;
13120var VT_I4 = 0x0003;
13121//var VT_R4 = 0x0004;
13122//var VT_R8 = 0x0005;
13123//var VT_CY = 0x0006;
13124//var VT_DATE = 0x0007;
13125//var VT_BSTR = 0x0008;
13126//var VT_ERROR = 0x000A;
13127var VT_BOOL = 0x000B;
13128var VT_VARIANT = 0x000C;
13129//var VT_DECIMAL = 0x000E;
13130//var VT_I1 = 0x0010;
13131//var VT_UI1 = 0x0011;
13132//var VT_UI2 = 0x0012;
13133var VT_UI4 = 0x0013;
13134//var VT_I8 = 0x0014;
13135//var VT_UI8 = 0x0015;
13136//var VT_INT = 0x0016;
13137//var VT_UINT = 0x0017;
13138var VT_LPSTR = 0x001E;
13139//var VT_LPWSTR = 0x001F;
13140var VT_FILETIME = 0x0040;
13141var VT_BLOB = 0x0041;
13142//var VT_STREAM = 0x0042;
13143//var VT_STORAGE = 0x0043;
13144//var VT_STREAMED_Object = 0x0044;
13145//var VT_STORED_Object = 0x0045;
13146//var VT_BLOB_Object = 0x0046;
13147var VT_CF = 0x0047;
13148//var VT_CLSID = 0x0048;
13149//var VT_VERSIONED_STREAM = 0x0049;
13150var VT_VECTOR = 0x1000;
13151//var VT_ARRAY = 0x2000;
13152
13153var VT_STRING = 0x0050; // 2.3.3.1.11 VtString
13154var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString
13155var VT_CUSTOM = [VT_STRING, VT_USTR];
13156
13157/* [MS-OSHARED] 2.3.3.2.2.1 Document Summary Information PIDDSI */
13158var DocSummaryPIDDSI = {
131590x01: { n: 'CodePage', t: VT_I2 },
131600x02: { n: 'Category', t: VT_STRING },
131610x03: { n: 'PresentationFormat', t: VT_STRING },
131620x04: { n: 'ByteCount', t: VT_I4 },
131630x05: { n: 'LineCount', t: VT_I4 },
131640x06: { n: 'ParagraphCount', t: VT_I4 },
131650x07: { n: 'SlideCount', t: VT_I4 },
131660x08: { n: 'NoteCount', t: VT_I4 },
131670x09: { n: 'HiddenCount', t: VT_I4 },
131680x0a: { n: 'MultimediaClipCount', t: VT_I4 },
131690x0b: { n: 'ScaleCrop', t: VT_BOOL },
131700x0c: { n: 'HeadingPairs', t: VT_VECTOR | VT_VARIANT },
131710x0d: { n: 'TitlesOfParts', t: VT_VECTOR | VT_LPSTR },
131720x0e: { n: 'Manager', t: VT_STRING },
131730x0f: { n: 'Company', t: VT_STRING },
131740x10: { n: 'LinksUpToDate', t: VT_BOOL },
131750x11: { n: 'CharacterCount', t: VT_I4 },
131760x13: { n: 'SharedDoc', t: VT_BOOL },
131770x16: { n: 'HyperlinksChanged', t: VT_BOOL },
131780x17: { n: 'AppVersion', t: VT_I4, p: 'version' },
131790x18: { n: 'DigSig', t: VT_BLOB },
131800x1A: { n: 'ContentType', t: VT_STRING },
131810x1B: { n: 'ContentStatus', t: VT_STRING },
131820x1C: { n: 'Language', t: VT_STRING },
131830x1D: { n: 'Version', t: VT_STRING },
131840xFF: {}
13185};
13186
13187/* [MS-OSHARED] 2.3.3.2.1.1 Summary Information Property Set PIDSI */
13188var SummaryPIDSI = {
131890x01: { n: 'CodePage', t: VT_I2 },
131900x02: { n: 'Title', t: VT_STRING },
131910x03: { n: 'Subject', t: VT_STRING },
131920x04: { n: 'Author', t: VT_STRING },
131930x05: { n: 'Keywords', t: VT_STRING },
131940x06: { n: 'Comments', t: VT_STRING },
131950x07: { n: 'Template', t: VT_STRING },
131960x08: { n: 'LastAuthor', t: VT_STRING },
131970x09: { n: 'RevNumber', t: VT_STRING },
131980x0A: { n: 'EditTime', t: VT_FILETIME },
131990x0B: { n: 'LastPrinted', t: VT_FILETIME },
132000x0C: { n: 'CreatedDate', t: VT_FILETIME },
132010x0D: { n: 'ModifiedDate', t: VT_FILETIME },
132020x0E: { n: 'PageCount', t: VT_I4 },
132030x0F: { n: 'WordCount', t: VT_I4 },
132040x10: { n: 'CharCount', t: VT_I4 },
132050x11: { n: 'Thumbnail', t: VT_CF },
132060x12: { n: 'Application', t: VT_STRING },
132070x13: { n: 'DocSecurity', t: VT_I4 },
132080xFF: {}
13209};
13210
13211/* [MS-OLEPS] 2.18 */
13212var SpecialProperties = {
132130x80000000: { n: 'Locale', t: VT_UI4 },
132140x80000003: { n: 'Behavior', t: VT_UI4 },
132150x72627262: {}
13216};
13217
13218(function() {
13219 for(var y in SpecialProperties) if(SpecialProperties.hasOwnProperty(y))
13220 DocSummaryPIDDSI[y] = SummaryPIDSI[y] = SpecialProperties[y];
13221})();
13222
13223var DocSummaryRE = evert_key(DocSummaryPIDDSI, "n");
13224var SummaryRE = evert_key(SummaryPIDSI, "n");
13225
13226/* [MS-XLS] 2.4.63 Country/Region codes */
13227var CountryEnum = {
132280x0001: "US", // United States
132290x0002: "CA", // Canada
132300x0003: "", // Latin America (except Brazil)
132310x0007: "RU", // Russia
132320x0014: "EG", // Egypt
132330x001E: "GR", // Greece
132340x001F: "NL", // Netherlands
132350x0020: "BE", // Belgium
132360x0021: "FR", // France
132370x0022: "ES", // Spain
132380x0024: "HU", // Hungary
132390x0027: "IT", // Italy
132400x0029: "CH", // Switzerland
132410x002B: "AT", // Austria
132420x002C: "GB", // United Kingdom
132430x002D: "DK", // Denmark
132440x002E: "SE", // Sweden
132450x002F: "NO", // Norway
132460x0030: "PL", // Poland
132470x0031: "DE", // Germany
132480x0034: "MX", // Mexico
132490x0037: "BR", // Brazil
132500x003d: "AU", // Australia
132510x0040: "NZ", // New Zealand
132520x0042: "TH", // Thailand
132530x0051: "JP", // Japan
132540x0052: "KR", // Korea
132550x0054: "VN", // Viet Nam
132560x0056: "CN", // China
132570x005A: "TR", // Turkey
132580x0069: "JS", // Ramastan
132590x00D5: "DZ", // Algeria
132600x00D8: "MA", // Morocco
132610x00DA: "LY", // Libya
132620x015F: "PT", // Portugal
132630x0162: "IS", // Iceland
132640x0166: "FI", // Finland
132650x01A4: "CZ", // Czech Republic
132660x0376: "TW", // Taiwan
132670x03C1: "LB", // Lebanon
132680x03C2: "JO", // Jordan
132690x03C3: "SY", // Syria
132700x03C4: "IQ", // Iraq
132710x03C5: "KW", // Kuwait
132720x03C6: "SA", // Saudi Arabia
132730x03CB: "AE", // United Arab Emirates
132740x03CC: "IL", // Israel
132750x03CE: "QA", // Qatar
132760x03D5: "IR", // Iran
132770xFFFF: "US" // United States
13278};
13279
13280/* [MS-XLS] 2.5.127 */
13281var XLSFillPattern = [
13282 null,
13283 'solid',
13284 'mediumGray',
13285 'darkGray',
13286 'lightGray',
13287 'darkHorizontal',
13288 'darkVertical',
13289 'darkDown',
13290 'darkUp',
13291 'darkGrid',
13292 'darkTrellis',
13293 'lightHorizontal',
13294 'lightVertical',
13295 'lightDown',
13296 'lightUp',
13297 'lightGrid',
13298 'lightTrellis',
13299 'gray125',
13300 'gray0625'
13301];
13302
13303function rgbify(arr) { return arr.map(function(x) { return [(x>>16)&255,(x>>8)&255,x&255]; }); }
13304
13305/* [MS-XLS] 2.5.161 */
13306/* [MS-XLSB] 2.5.75 Icv */
13307var _XLSIcv = rgbify([
13308 /* Color Constants */
13309 0x000000,
13310 0xFFFFFF,
13311 0xFF0000,
13312 0x00FF00,
13313 0x0000FF,
13314 0xFFFF00,
13315 0xFF00FF,
13316 0x00FFFF,
13317
13318 /* Overridable Defaults */
13319 0x000000,
13320 0xFFFFFF,
13321 0xFF0000,
13322 0x00FF00,
13323 0x0000FF,
13324 0xFFFF00,
13325 0xFF00FF,
13326 0x00FFFF,
13327
13328 0x800000,
13329 0x008000,
13330 0x000080,
13331 0x808000,
13332 0x800080,
13333 0x008080,
13334 0xC0C0C0,
13335 0x808080,
13336 0x9999FF,
13337 0x993366,
13338 0xFFFFCC,
13339 0xCCFFFF,
13340 0x660066,
13341 0xFF8080,
13342 0x0066CC,
13343 0xCCCCFF,
13344
13345 0x000080,
13346 0xFF00FF,
13347 0xFFFF00,
13348 0x00FFFF,
13349 0x800080,
13350 0x800000,
13351 0x008080,
13352 0x0000FF,
13353 0x00CCFF,
13354 0xCCFFFF,
13355 0xCCFFCC,
13356 0xFFFF99,
13357 0x99CCFF,
13358 0xFF99CC,
13359 0xCC99FF,
13360 0xFFCC99,
13361
13362 0x3366FF,
13363 0x33CCCC,
13364 0x99CC00,
13365 0xFFCC00,
13366 0xFF9900,
13367 0xFF6600,
13368 0x666699,
13369 0x969696,
13370 0x003366,
13371 0x339966,
13372 0x003300,
13373 0x333300,
13374 0x993300,
13375 0x993366,
13376 0x333399,
13377 0x333333,
13378
13379 /* Other entries to appease BIFF8/12 */
13380 0xFFFFFF, /* 0x40 icvForeground ?? */
13381 0x000000, /* 0x41 icvBackground ?? */
13382 0x000000, /* 0x42 icvFrame ?? */
13383 0x000000, /* 0x43 icv3D ?? */
13384 0x000000, /* 0x44 icv3DText ?? */
13385 0x000000, /* 0x45 icv3DHilite ?? */
13386 0x000000, /* 0x46 icv3DShadow ?? */
13387 0x000000, /* 0x47 icvHilite ?? */
13388 0x000000, /* 0x48 icvCtlText ?? */
13389 0x000000, /* 0x49 icvCtlScrl ?? */
13390 0x000000, /* 0x4A icvCtlInv ?? */
13391 0x000000, /* 0x4B icvCtlBody ?? */
13392 0x000000, /* 0x4C icvCtlFrame ?? */
13393 0x000000, /* 0x4D icvCtlFore ?? */
13394 0x000000, /* 0x4E icvCtlBack ?? */
13395 0x000000, /* 0x4F icvCtlNeutral */
13396 0x000000, /* 0x50 icvInfoBk ?? */
13397 0x000000 /* 0x51 icvInfoText ?? */
13398]);
13399var XLSIcv = dup(_XLSIcv);
13400/* Parts enumerated in OPC spec, MS-XLSB and MS-XLSX */
13401/* 12.3 Part Summary <SpreadsheetML> */
13402/* 14.2 Part Summary <DrawingML> */
13403/* [MS-XLSX] 2.1 Part Enumerations ; [MS-XLSB] 2.1.7 Part Enumeration */
13404var ct2type/*{[string]:string}*/ = ({
13405 /* Workbook */
13406 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": "workbooks",
13407
13408 /* Worksheet */
13409 "application/vnd.ms-excel.binIndexWs": "TODO", /* Binary Index */
13410
13411 /* Macrosheet */
13412 "application/vnd.ms-excel.intlmacrosheet": "TODO",
13413 "application/vnd.ms-excel.binIndexMs": "TODO", /* Binary Index */
13414
13415 /* File Properties */
13416 "application/vnd.openxmlformats-package.core-properties+xml": "coreprops",
13417 "application/vnd.openxmlformats-officedocument.custom-properties+xml": "custprops",
13418 "application/vnd.openxmlformats-officedocument.extended-properties+xml": "extprops",
13419
13420 /* Custom Data Properties */
13421 "application/vnd.openxmlformats-officedocument.customXmlProperties+xml": "TODO",
13422 "application/vnd.openxmlformats-officedocument.spreadsheetml.customProperty": "TODO",
13423
13424 /* PivotTable */
13425 "application/vnd.ms-excel.pivotTable": "TODO",
13426 "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml": "TODO",
13427
13428 /* Chart Objects */
13429 "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": "TODO",
13430
13431 /* Chart Colors */
13432 "application/vnd.ms-office.chartcolorstyle+xml": "TODO",
13433
13434 /* Chart Style */
13435 "application/vnd.ms-office.chartstyle+xml": "TODO",
13436
13437 /* Chart Advanced */
13438 "application/vnd.ms-office.chartex+xml": "TODO",
13439
13440 /* Calculation Chain */
13441 "application/vnd.ms-excel.calcChain": "calcchains",
13442 "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains",
13443
13444 /* Printer Settings */
13445 "application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings": "TODO",
13446
13447 /* ActiveX */
13448 "application/vnd.ms-office.activeX": "TODO",
13449 "application/vnd.ms-office.activeX+xml": "TODO",
13450
13451 /* Custom Toolbars */
13452 "application/vnd.ms-excel.attachedToolbars": "TODO",
13453
13454 /* External Data Connections */
13455 "application/vnd.ms-excel.connections": "TODO",
13456 "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml": "TODO",
13457
13458 /* External Links */
13459 "application/vnd.ms-excel.externalLink": "links",
13460 "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml": "links",
13461
13462 /* Metadata */
13463 "application/vnd.ms-excel.sheetMetadata": "TODO",
13464 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml": "TODO",
13465
13466 /* PivotCache */
13467 "application/vnd.ms-excel.pivotCacheDefinition": "TODO",
13468 "application/vnd.ms-excel.pivotCacheRecords": "TODO",
13469 "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml": "TODO",
13470 "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml": "TODO",
13471
13472 /* Query Table */
13473 "application/vnd.ms-excel.queryTable": "TODO",
13474 "application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml": "TODO",
13475
13476 /* Shared Workbook */
13477 "application/vnd.ms-excel.userNames": "TODO",
13478 "application/vnd.ms-excel.revisionHeaders": "TODO",
13479 "application/vnd.ms-excel.revisionLog": "TODO",
13480 "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml": "TODO",
13481 "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml": "TODO",
13482 "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml": "TODO",
13483
13484 /* Single Cell Table */
13485 "application/vnd.ms-excel.tableSingleCells": "TODO",
13486 "application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml": "TODO",
13487
13488 /* Slicer */
13489 "application/vnd.ms-excel.slicer": "TODO",
13490 "application/vnd.ms-excel.slicerCache": "TODO",
13491 "application/vnd.ms-excel.slicer+xml": "TODO",
13492 "application/vnd.ms-excel.slicerCache+xml": "TODO",
13493
13494 /* Sort Map */
13495 "application/vnd.ms-excel.wsSortMap": "TODO",
13496
13497 /* Table */
13498 "application/vnd.ms-excel.table": "TODO",
13499 "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml": "TODO",
13500
13501 /* Themes */
13502 "application/vnd.openxmlformats-officedocument.theme+xml": "themes",
13503
13504 /* Theme Override */
13505 "application/vnd.openxmlformats-officedocument.themeOverride+xml": "TODO",
13506
13507 /* Timeline */
13508 "application/vnd.ms-excel.Timeline+xml": "TODO", /* verify */
13509 "application/vnd.ms-excel.TimelineCache+xml": "TODO", /* verify */
13510
13511 /* VBA */
13512 "application/vnd.ms-office.vbaProject": "vba",
13513 "application/vnd.ms-office.vbaProjectSignature": "vba",
13514
13515 /* Volatile Dependencies */
13516 "application/vnd.ms-office.volatileDependencies": "TODO",
13517 "application/vnd.openxmlformats-officedocument.spreadsheetml.volatileDependencies+xml": "TODO",
13518
13519 /* Control Properties */
13520 "application/vnd.ms-excel.controlproperties+xml": "TODO",
13521
13522 /* Data Model */
13523 "application/vnd.openxmlformats-officedocument.model+data": "TODO",
13524
13525 /* Survey */
13526 "application/vnd.ms-excel.Survey+xml": "TODO",
13527
13528 /* Drawing */
13529 "application/vnd.openxmlformats-officedocument.drawing+xml": "drawings",
13530 "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml": "TODO",
13531 "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml": "TODO",
13532 "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml": "TODO",
13533 "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml": "TODO",
13534 "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml": "TODO",
13535
13536 /* VML */
13537 "application/vnd.openxmlformats-officedocument.vmlDrawing": "TODO",
13538
13539 "application/vnd.openxmlformats-package.relationships+xml": "rels",
13540 "application/vnd.openxmlformats-officedocument.oleObject": "TODO",
13541
13542 /* Image */
13543 "image/png": "TODO",
13544
13545 "sheet": "js"
13546});
13547
13548var CT_LIST = (function(){
13549 var o = {
13550 workbooks: {
13551 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
13552 xlsm: "application/vnd.ms-excel.sheet.macroEnabled.main+xml",
13553 xlsb: "application/vnd.ms-excel.sheet.binary.macroEnabled.main",
13554 xlam: "application/vnd.ms-excel.addin.macroEnabled.main+xml",
13555 xltx: "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"
13556 },
13557 strs: { /* Shared Strings */
13558 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
13559 xlsb: "application/vnd.ms-excel.sharedStrings"
13560 },
13561 comments: { /* Comments */
13562 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
13563 xlsb: "application/vnd.ms-excel.comments"
13564 },
13565 sheets: { /* Worksheet */
13566 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
13567 xlsb: "application/vnd.ms-excel.worksheet"
13568 },
13569 charts: { /* Chartsheet */
13570 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml",
13571 xlsb: "application/vnd.ms-excel.chartsheet"
13572 },
13573 dialogs: { /* Dialogsheet */
13574 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml",
13575 xlsb: "application/vnd.ms-excel.dialogsheet"
13576 },
13577 macros: { /* Macrosheet (Excel 4.0 Macros) */
13578 xlsx: "application/vnd.ms-excel.macrosheet+xml",
13579 xlsb: "application/vnd.ms-excel.macrosheet"
13580 },
13581 styles: { /* Styles */
13582 xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
13583 xlsb: "application/vnd.ms-excel.styles"
13584 }
13585 };
13586 keys(o).forEach(function(k) { ["xlsm", "xlam"].forEach(function(v) { if(!o[k][v]) o[k][v] = o[k].xlsx; }); });
13587 keys(o).forEach(function(k){ keys(o[k]).forEach(function(v) { ct2type[o[k][v]] = k; }); });
13588 return o;
13589})();
13590
13591var type2ct/*{[string]:Array<string>}*/ = evert_arr(ct2type);
13592
13593XMLNS.CT = 'http://schemas.openxmlformats.org/package/2006/content-types';
13594
13595function new_ct() {
13596 return ({
13597 workbooks:[], sheets:[], charts:[], dialogs:[], macros:[],
13598 rels:[], strs:[], comments:[], links:[],
13599 coreprops:[], extprops:[], custprops:[], themes:[], styles:[],
13600 calcchains:[], vba: [], drawings: [],
13601 TODO:[], xmlns: "" });
13602}
13603
13604function parse_ct(data) {
13605 var ct = new_ct();
13606 if(!data || !data.match) return ct;
13607 var ctext = {};
13608 (data.match(tagregex)||[]).forEach(function(x) {
13609 var y = parsexmltag(x);
13610 switch(y[0].replace(nsregex,"<")) {
13611 case '<?xml': break;
13612 case '<Types': ct.xmlns = y['xmlns' + (y[0].match(/<(\w+):/)||["",""])[1] ]; break;
13613 case '<Default': ctext[y.Extension] = y.ContentType; break;
13614 case '<Override':
13615 if(ct[ct2type[y.ContentType]] !== undefined) ct[ct2type[y.ContentType]].push(y.PartName);
13616 break;
13617 }
13618 });
13619 if(ct.xmlns !== XMLNS.CT) throw new Error("Unknown Namespace: " + ct.xmlns);
13620 ct.calcchain = ct.calcchains.length > 0 ? ct.calcchains[0] : "";
13621 ct.sst = ct.strs.length > 0 ? ct.strs[0] : "";
13622 ct.style = ct.styles.length > 0 ? ct.styles[0] : "";
13623 ct.defaults = ctext;
13624 delete ct.calcchains;
13625 return ct;
13626}
13627
13628var CTYPE_XML_ROOT = writextag('Types', null, {
13629 'xmlns': XMLNS.CT,
13630 'xmlns:xsd': XMLNS.xsd,
13631 'xmlns:xsi': XMLNS.xsi
13632});
13633
13634var CTYPE_DEFAULTS = [
13635 ['xml', 'application/xml'],
13636 ['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
13637 ['vml', 'application/vnd.openxmlformats-officedocument.vmlDrawing'],
13638 ['data', 'application/vnd.openxmlformats-officedocument.model+data'],
13639 /* from test files */
13640 ['bmp', 'image/bmp'],
13641 ['png', 'image/png'],
13642 ['gif', 'image/gif'],
13643 ['emf', 'image/x-emf'],
13644 ['wmf', 'image/x-wmf'],
13645 ['jpg', 'image/jpeg'], ['jpeg', 'image/jpeg'],
13646 ['tif', 'image/tiff'], ['tiff', 'image/tiff'],
13647 ['pdf', 'application/pdf'],
13648 ['rels', type2ct.rels[0]]
13649].map(function(x) {
13650 return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]});
13651});
13652
13653function write_ct(ct, opts) {
13654 var o = [], v;
13655 o[o.length] = (XML_HEADER);
13656 o[o.length] = (CTYPE_XML_ROOT);
13657 o = o.concat(CTYPE_DEFAULTS);
13658
13659 /* only write first instance */
13660 var f1 = function(w) {
13661 if(ct[w] && ct[w].length > 0) {
13662 v = ct[w][0];
13663 o[o.length] = (writextag('Override', null, {
13664 'PartName': (v[0] == '/' ? "":"/") + v,
13665 'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
13666 }));
13667 }
13668 };
13669
13670 /* book type-specific */
13671 var f2 = function(w) {
13672 (ct[w]||[]).forEach(function(v) {
13673 o[o.length] = (writextag('Override', null, {
13674 'PartName': (v[0] == '/' ? "":"/") + v,
13675 'ContentType': CT_LIST[w][opts.bookType || 'xlsx']
13676 }));
13677 });
13678 };
13679
13680 /* standard type */
13681 var f3 = function(t) {
13682 (ct[t]||[]).forEach(function(v) {
13683 o[o.length] = (writextag('Override', null, {
13684 'PartName': (v[0] == '/' ? "":"/") + v,
13685 'ContentType': type2ct[t][0]
13686 }));
13687 });
13688 };
13689
13690 f1('workbooks');
13691 f2('sheets');
13692 f2('charts');
13693 f3('themes');
13694 ['strs', 'styles'].forEach(f1);
13695 ['coreprops', 'extprops', 'custprops'].forEach(f3);
13696 f3('vba');
13697 f3('comments');
13698 f3('drawings');
13699 if(o.length>2){ o[o.length] = ('</Types>'); o[1]=o[1].replace("/>",">"); }
13700 return o.join("");
13701}
13702/* 9.3 Relationships */
13703var RELS = ({
13704 WB: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
13705 SHEET: "http://sheetjs.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
13706 HLINK: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
13707 VML: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing",
13708 XPATH: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath",
13709 XMISS: "http://schemas.microsoft.com/office/2006/relationships/xlExternalLinkPath/xlPathMissing",
13710 XLINK: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLink",
13711 VBA: "http://schemas.microsoft.com/office/2006/relationships/vbaProject"
13712});
13713
13714/* 9.3.3 Representing Relationships */
13715function get_rels_path(file) {
13716 var n = file.lastIndexOf("/");
13717 return file.slice(0,n+1) + '_rels/' + file.slice(n+1) + ".rels";
13718}
13719
13720function parse_rels(data, currentFilePath) {
13721 var rels = {"!id":{}};
13722 if (!data) return rels;
13723 if (currentFilePath.charAt(0) !== '/') {
13724 currentFilePath = '/'+currentFilePath;
13725 }
13726 var hash = {};
13727
13728 (data.match(tagregex)||[]).forEach(function(x) {
13729 var y = parsexmltag(x);
13730 /* 9.3.2.2 OPC_Relationships */
13731 if (y[0] === '<Relationship') {
13732 var rel = {}; rel.Type = y.Type; rel.Target = y.Target; rel.Id = y.Id; rel.TargetMode = y.TargetMode;
13733 var canonictarget = y.TargetMode === 'External' ? y.Target : resolve_path(y.Target, currentFilePath);
13734 rels[canonictarget] = rel;
13735 hash[y.Id] = rel;
13736 }
13737 });
13738 rels["!id"] = hash;
13739 return rels;
13740}
13741
13742XMLNS.RELS = 'http://schemas.openxmlformats.org/package/2006/relationships';
13743
13744var RELS_ROOT = writextag('Relationships', null, {
13745 //'xmlns:ns0': XMLNS.RELS,
13746 'xmlns': XMLNS.RELS
13747});
13748
13749/* TODO */
13750function write_rels(rels) {
13751 var o = [XML_HEADER, RELS_ROOT];
13752 keys(rels['!id']).forEach(function(rid) {
13753 o[o.length] = (writextag('Relationship', null, rels['!id'][rid]));
13754 });
13755 if(o.length>2){ o[o.length] = ('</Relationships>'); o[1]=o[1].replace("/>",">"); }
13756 return o.join("");
13757}
13758
13759var RELS_EXTERN = [RELS.HLINK, RELS.XPATH, RELS.XMISS];
13760function add_rels(rels, rId, f, type, relobj, targetmode) {
13761 if(!relobj) relobj = {};
13762 if(!rels['!id']) rels['!id'] = {};
13763 if(rId < 0) for(rId = 1; rels['!id']['rId' + rId]; ++rId){/* empty */}
13764 relobj.Id = 'rId' + rId;
13765 relobj.Type = type;
13766 relobj.Target = f;
13767 if(targetmode) relobj.TargetMode = targetmode;
13768 else if(RELS_EXTERN.indexOf(relobj.Type) > -1) relobj.TargetMode = "External";
13769 if(rels['!id'][relobj.Id]) throw new Error("Cannot rewrite rId " + rId);
13770 rels['!id'][relobj.Id] = relobj;
13771 rels[('/' + relobj.Target).replace("//","/")] = relobj;
13772 return rId;
13773}
13774/* Open Document Format for Office Applications (OpenDocument) Version 1.2 */
13775/* Part 3 Section 4 Manifest File */
13776var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet";
13777function parse_manifest(d, opts) {
13778 var str = xlml_normalize(d);
13779 var Rn;
13780 var FEtag;
13781 while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
13782 case 'manifest': break; // 4.2 <manifest:manifest>
13783 case 'file-entry': // 4.3 <manifest:file-entry>
13784 FEtag = parsexmltag(Rn[0], false);
13785 if(FEtag.path == '/' && FEtag.type !== CT_ODS) throw new Error("This OpenDocument is not a spreadsheet");
13786 break;
13787 case 'encryption-data': // 4.4 <manifest:encryption-data>
13788 case 'algorithm': // 4.5 <manifest:algorithm>
13789 case 'start-key-generation': // 4.6 <manifest:start-key-generation>
13790 case 'key-derivation': // 4.7 <manifest:key-derivation>
13791 throw new Error("Unsupported ODS Encryption");
13792 default: if(opts && opts.WTF) throw Rn;
13793 }
13794}
13795
13796function write_manifest(manifest) {
13797 var o = [XML_HEADER];
13798 o.push('<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">\n');
13799 o.push(' <manifest:file-entry manifest:full-path="/" manifest:version="1.2" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/>\n');
13800 for(var i = 0; i < manifest.length; ++i) o.push(' <manifest:file-entry manifest:full-path="' + manifest[i][0] + '" manifest:media-type="' + manifest[i][1] + '"/>\n');
13801 o.push('</manifest:manifest>');
13802 return o.join("");
13803}
13804
13805/* Part 3 Section 6 Metadata Manifest File */
13806function write_rdf_type(file, res, tag) {
13807 return [
13808 ' <rdf:Description rdf:about="' + file + '">\n',
13809 ' <rdf:type rdf:resource="http://docs.oasis-open.org/ns/office/1.2/meta/' + (tag || "odf") + '#' + res + '"/>\n',
13810 ' </rdf:Description>\n'
13811 ].join("");
13812}
13813function write_rdf_has(base, file) {
13814 return [
13815 ' <rdf:Description rdf:about="' + base + '">\n',
13816 ' <ns0:hasPart xmlns:ns0="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" rdf:resource="' + file + '"/>\n',
13817 ' </rdf:Description>\n'
13818 ].join("");
13819}
13820function write_rdf(rdf) {
13821 var o = [XML_HEADER];
13822 o.push('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">\n');
13823 for(var i = 0; i != rdf.length; ++i) {
13824 o.push(write_rdf_type(rdf[i][0], rdf[i][1]));
13825 o.push(write_rdf_has("",rdf[i][0]));
13826 }
13827 o.push(write_rdf_type("","Document", "pkg"));
13828 o.push('</rdf:RDF>');
13829 return o.join("");
13830}
13831/* TODO: pull properties */
13832var write_meta_ods = (function() {
13833 var payload = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2"><office:meta><meta:generator>Sheet' + 'JS ' + XLSX.version + '</meta:generator></office:meta></office:document-meta>';
13834 return function wmo() {
13835 return payload;
13836 };
13837})();
13838
13839/* ECMA-376 Part II 11.1 Core Properties Part */
13840/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
13841var CORE_PROPS = [
13842 ["cp:category", "Category"],
13843 ["cp:contentStatus", "ContentStatus"],
13844 ["cp:keywords", "Keywords"],
13845 ["cp:lastModifiedBy", "LastAuthor"],
13846 ["cp:lastPrinted", "LastPrinted"],
13847 ["cp:revision", "RevNumber"],
13848 ["cp:version", "Version"],
13849 ["dc:creator", "Author"],
13850 ["dc:description", "Comments"],
13851 ["dc:identifier", "Identifier"],
13852 ["dc:language", "Language"],
13853 ["dc:subject", "Subject"],
13854 ["dc:title", "Title"],
13855 ["dcterms:created", "CreatedDate", 'date'],
13856 ["dcterms:modified", "ModifiedDate", 'date']
13857];
13858
13859XMLNS.CORE_PROPS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
13860RELS.CORE_PROPS = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties';
13861
13862var CORE_PROPS_REGEX = (function() {
13863 var r = new Array(CORE_PROPS.length);
13864 for(var i = 0; i < CORE_PROPS.length; ++i) {
13865 var f = CORE_PROPS[i];
13866 var g = "(?:"+ f[0].slice(0,f[0].indexOf(":")) +":)"+ f[0].slice(f[0].indexOf(":")+1);
13867 r[i] = new RegExp("<" + g + "[^>]*>([\\s\\S]*?)<\/" + g + ">");
13868 }
13869 return r;
13870})();
13871
13872function parse_core_props(data) {
13873 var p = {};
13874 data = utf8read(data);
13875
13876 for(var i = 0; i < CORE_PROPS.length; ++i) {
13877 var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]);
13878 if(cur != null && cur.length > 0) p[f[1]] = cur[1];
13879 if(f[2] === 'date' && p[f[1]]) p[f[1]] = parseDate(p[f[1]]);
13880 }
13881
13882 return p;
13883}
13884
13885var CORE_PROPS_XML_ROOT = writextag('cp:coreProperties', null, {
13886 //'xmlns': XMLNS.CORE_PROPS,
13887 'xmlns:cp': XMLNS.CORE_PROPS,
13888 'xmlns:dc': XMLNS.dc,
13889 'xmlns:dcterms': XMLNS.dcterms,
13890 'xmlns:dcmitype': XMLNS.dcmitype,
13891 'xmlns:xsi': XMLNS.xsi
13892});
13893
13894function cp_doit(f, g, h, o, p) {
13895 if(p[f] != null || g == null || g === "") return;
13896 p[f] = g;
13897 o[o.length] = (h ? writextag(f,g,h) : writetag(f,g));
13898}
13899
13900function write_core_props(cp, _opts) {
13901 var opts = _opts || {};
13902 var o = [XML_HEADER, CORE_PROPS_XML_ROOT], p = {};
13903 if(!cp && !opts.Props) return o.join("");
13904
13905 if(cp) {
13906 if(cp.CreatedDate != null) cp_doit("dcterms:created", typeof cp.CreatedDate === "string" ? cp.CreatedDate : write_w3cdtf(cp.CreatedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
13907 if(cp.ModifiedDate != null) cp_doit("dcterms:modified", typeof cp.ModifiedDate === "string" ? cp.ModifiedDate : write_w3cdtf(cp.ModifiedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
13908 }
13909
13910 for(var i = 0; i != CORE_PROPS.length; ++i) {
13911 var f = CORE_PROPS[i];
13912 var v = opts.Props && opts.Props[f[1]] != null ? opts.Props[f[1]] : cp ? cp[f[1]] : null;
13913 if(v === true) v = "1";
13914 else if(v === false) v = "0";
13915 else if(typeof v == "number") v = String(v);
13916 if(v != null) cp_doit(f[0], v, null, o, p);
13917 }
13918 if(o.length>2){ o[o.length] = ('</cp:coreProperties>'); o[1]=o[1].replace("/>",">"); }
13919 return o.join("");
13920}
13921/* 15.2.12.3 Extended File Properties Part */
13922/* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */
13923var EXT_PROPS = [
13924 ["Application", "Application", "string"],
13925 ["AppVersion", "AppVersion", "string"],
13926 ["Company", "Company", "string"],
13927 ["DocSecurity", "DocSecurity", "string"],
13928 ["Manager", "Manager", "string"],
13929 ["HyperlinksChanged", "HyperlinksChanged", "bool"],
13930 ["SharedDoc", "SharedDoc", "bool"],
13931 ["LinksUpToDate", "LinksUpToDate", "bool"],
13932 ["ScaleCrop", "ScaleCrop", "bool"],
13933 ["HeadingPairs", "HeadingPairs", "raw"],
13934 ["TitlesOfParts", "TitlesOfParts", "raw"]
13935];
13936
13937XMLNS.EXT_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
13938RELS.EXT_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties';
13939
13940var PseudoPropsPairs = [
13941 "Worksheets", "SheetNames",
13942 "NamedRanges", "DefinedNames",
13943 "Chartsheets", "ChartNames"
13944];
13945function load_props_pairs(HP, TOP, props, opts) {
13946 var v = [];
13947 if(typeof HP == "string") v = parseVector(HP, opts);
13948 else for(var j = 0; j < HP.length; ++j) v = v.concat(HP[j].map(function(hp) { return {v:hp}; }));
13949 var parts = (typeof TOP == "string") ? parseVector(TOP, opts).map(function (x) { return x.v; }) : TOP;
13950 var idx = 0, len = 0;
13951 if(parts.length > 0) for(var i = 0; i !== v.length; i += 2) {
13952 len = +(v[i+1].v);
13953 switch(v[i].v) {
13954 case "Worksheets":
13955 case "工作表":
13956 case "Листы":
13957 case "أوراق العمل":
13958 case "ワークシート":
13959 case "גליונות עבודה":
13960 case "Arbeitsblätter":
13961 case "Çalışma Sayfaları":
13962 case "Feuilles de calcul":
13963 case "Fogli di lavoro":
13964 case "Folhas de cálculo":
13965 case "Planilhas":
13966 case "Regneark":
13967 case "Hojas de cálculo":
13968 case "Werkbladen":
13969 props.Worksheets = len;
13970 props.SheetNames = parts.slice(idx, idx + len);
13971 break;
13972
13973 case "Named Ranges":
13974 case "Rangos con nombre":
13975 case "名前付き一覧":
13976 case "Benannte Bereiche":
13977 case "Navngivne områder":
13978 props.NamedRanges = len;
13979 props.DefinedNames = parts.slice(idx, idx + len);
13980 break;
13981
13982 case "Charts":
13983 case "Diagramme":
13984 props.Chartsheets = len;
13985 props.ChartNames = parts.slice(idx, idx + len);
13986 break;
13987 }
13988 idx += len;
13989 }
13990}
13991
13992function parse_ext_props(data, p, opts) {
13993 var q = {}; if(!p) p = {};
13994 data = utf8read(data);
13995
13996 EXT_PROPS.forEach(function(f) {
13997 switch(f[2]) {
13998 case "string": p[f[1]] = (data.match(matchtag(f[0]))||[])[1]; break;
13999 case "bool": p[f[1]] = (data.match(matchtag(f[0]))||[])[1] === "true"; break;
14000 case "raw":
14001 var cur = data.match(new RegExp("<" + f[0] + "[^>]*>([\\s\\S]*?)<\/" + f[0] + ">"));
14002 if(cur && cur.length > 0) q[f[1]] = cur[1];
14003 break;
14004 }
14005 });
14006
14007 if(q.HeadingPairs && q.TitlesOfParts) load_props_pairs(q.HeadingPairs, q.TitlesOfParts, p, opts);
14008
14009 return p;
14010}
14011
14012var EXT_PROPS_XML_ROOT = writextag('Properties', null, {
14013 'xmlns': XMLNS.EXT_PROPS,
14014 'xmlns:vt': XMLNS.vt
14015});
14016
14017function write_ext_props(cp) {
14018 var o = [], W = writextag;
14019 if(!cp) cp = {};
14020 cp.Application = "SheetJS";
14021 o[o.length] = (XML_HEADER);
14022 o[o.length] = (EXT_PROPS_XML_ROOT);
14023
14024 EXT_PROPS.forEach(function(f) {
14025 if(cp[f[1]] === undefined) return;
14026 var v;
14027 switch(f[2]) {
14028 case 'string': v = String(cp[f[1]]); break;
14029 case 'bool': v = cp[f[1]] ? 'true' : 'false'; break;
14030 }
14031 if(v !== undefined) o[o.length] = (W(f[0], v));
14032 });
14033
14034 /* TODO: HeadingPairs, TitlesOfParts */
14035 o[o.length] = (W('HeadingPairs', W('vt:vector', W('vt:variant', '<vt:lpstr>Worksheets</vt:lpstr>')+W('vt:variant', W('vt:i4', String(cp.Worksheets))), {size:2, baseType:"variant"})));
14036 o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "<vt:lpstr>" + escapexml(s) + "</vt:lpstr>"; }).join(""), {size: cp.Worksheets, baseType:"lpstr"})));
14037 if(o.length>2){ o[o.length] = ('</Properties>'); o[1]=o[1].replace("/>",">"); }
14038 return o.join("");
14039}
14040/* 15.2.12.2 Custom File Properties Part */
14041XMLNS.CUST_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties";
14042RELS.CUST_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties';
14043
14044var custregex = /<[^>]+>[^<]*/g;
14045function parse_cust_props(data, opts) {
14046 var p = {}, name = "";
14047 var m = data.match(custregex);
14048 if(m) for(var i = 0; i != m.length; ++i) {
14049 var x = m[i], y = parsexmltag(x);
14050 switch(y[0]) {
14051 case '<?xml': break;
14052 case '<Properties': break;
14053 case '<property': name = y.name; break;
14054 case '</property>': name = null; break;
14055 default: if (x.indexOf('<vt:') === 0) {
14056 var toks = x.split('>');
14057 var type = toks[0].slice(4), text = toks[1];
14058 /* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */
14059 switch(type) {
14060 case 'lpstr': case 'bstr': case 'lpwstr':
14061 p[name] = unescapexml(text);
14062 break;
14063 case 'bool':
14064 p[name] = parsexmlbool(text);
14065 break;
14066 case 'i1': case 'i2': case 'i4': case 'i8': case 'int': case 'uint':
14067 p[name] = parseInt(text, 10);
14068 break;
14069 case 'r4': case 'r8': case 'decimal':
14070 p[name] = parseFloat(text);
14071 break;
14072 case 'filetime': case 'date':
14073 p[name] = parseDate(text);
14074 break;
14075 case 'cy': case 'error':
14076 p[name] = unescapexml(text);
14077 break;
14078 default:
14079 if(type.slice(-1) == '/') break;
14080 if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks);
14081 }
14082 } else if(x.slice(0,2) === "</") {/* empty */
14083 } else if(opts.WTF) throw new Error(x);
14084 }
14085 }
14086 return p;
14087}
14088
14089var CUST_PROPS_XML_ROOT = writextag('Properties', null, {
14090 'xmlns': XMLNS.CUST_PROPS,
14091 'xmlns:vt': XMLNS.vt
14092});
14093
14094function write_cust_props(cp) {
14095 var o = [XML_HEADER, CUST_PROPS_XML_ROOT];
14096 if(!cp) return o.join("");
14097 var pid = 1;
14098 keys(cp).forEach(function custprop(k) { ++pid;
14099 o[o.length] = (writextag('property', write_vt(cp[k]), {
14100 'fmtid': '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}',
14101 'pid': pid,
14102 'name': k
14103 }));
14104 });
14105 if(o.length>2){ o[o.length] = '</Properties>'; o[1]=o[1].replace("/>",">"); }
14106 return o.join("");
14107}
14108/* Common Name -> XLML Name */
14109var XLMLDocPropsMap = {
14110 Title: 'Title',
14111 Subject: 'Subject',
14112 Author: 'Author',
14113 Keywords: 'Keywords',
14114 Comments: 'Description',
14115 LastAuthor: 'LastAuthor',
14116 RevNumber: 'Revision',
14117 Application: 'AppName',
14118 /* TotalTime: 'TotalTime', */
14119 LastPrinted: 'LastPrinted',
14120 CreatedDate: 'Created',
14121 ModifiedDate: 'LastSaved',
14122 /* Pages */
14123 /* Words */
14124 /* Characters */
14125 Category: 'Category',
14126 /* PresentationFormat */
14127 Manager: 'Manager',
14128 Company: 'Company',
14129 /* Guid */
14130 /* HyperlinkBase */
14131 /* Bytes */
14132 /* Lines */
14133 /* Paragraphs */
14134 /* CharactersWithSpaces */
14135 AppVersion: 'Version',
14136
14137 ContentStatus: 'ContentStatus', /* NOTE: missing from schema */
14138 Identifier: 'Identifier', /* NOTE: missing from schema */
14139 Language: 'Language' /* NOTE: missing from schema */
14140};
14141var evert_XLMLDPM = evert(XLMLDocPropsMap);
14142
14143function xlml_set_prop(Props, tag, val) {
14144 tag = evert_XLMLDPM[tag] || tag;
14145 Props[tag] = val;
14146}
14147
14148function xlml_write_docprops(Props, opts) {
14149 var o = [];
14150 keys(XLMLDocPropsMap).map(function(m) {
14151 for(var i = 0; i < CORE_PROPS.length; ++i) if(CORE_PROPS[i][1] == m) return CORE_PROPS[i];
14152 for(i = 0; i < EXT_PROPS.length; ++i) if(EXT_PROPS[i][1] == m) return EXT_PROPS[i];
14153 throw m;
14154 }).forEach(function(p) {
14155 if(Props[p[1]] == null) return;
14156 var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]];
14157 switch(p[2]) {
14158 case 'date': m = new Date(m).toISOString().replace(/\.\d*Z/,"Z"); break;
14159 }
14160 if(typeof m == 'number') m = String(m);
14161 else if(m === true || m === false) { m = m ? "1" : "0"; }
14162 else if(m instanceof Date) m = new Date(m).toISOString().replace(/\.\d*Z/,"");
14163 o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m));
14164 });
14165 return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o });
14166}
14167function xlml_write_custprops(Props, Custprops) {
14168 var BLACKLIST = ["Worksheets","SheetNames"];
14169 var T = 'CustomDocumentProperties';
14170 var o = [];
14171 if(Props) keys(Props).forEach(function(k) {
14172if(!Props.hasOwnProperty(k)) return;
14173 for(var i = 0; i < CORE_PROPS.length; ++i) if(k == CORE_PROPS[i][1]) return;
14174 for(i = 0; i < EXT_PROPS.length; ++i) if(k == EXT_PROPS[i][1]) return;
14175 for(i = 0; i < BLACKLIST.length; ++i) if(k == BLACKLIST[i]) return;
14176
14177 var m = Props[k];
14178 var t = "string";
14179 if(typeof m == 'number') { t = "float"; m = String(m); }
14180 else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
14181 else m = String(m);
14182 o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
14183 });
14184 if(Custprops) keys(Custprops).forEach(function(k) {
14185if(!Custprops.hasOwnProperty(k)) return;
14186 if(Props && Props.hasOwnProperty(k)) return;
14187 var m = Custprops[k];
14188 var t = "string";
14189 if(typeof m == 'number') { t = "float"; m = String(m); }
14190 else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; }
14191 else if(m instanceof Date) { t = "dateTime.tz"; m = m.toISOString(); }
14192 else m = String(m);
14193 o.push(writextag(escapexmltag(k), m, {"dt:dt":t}));
14194 });
14195 return '<' + T + ' xmlns="' + XLMLNS.o + '">' + o.join("") + '</' + T + '>';
14196}
14197/* [MS-DTYP] 2.3.3 FILETIME */
14198/* [MS-OLEDS] 2.1.3 FILETIME (Packet Version) */
14199/* [MS-OLEPS] 2.8 FILETIME (Packet Version) */
14200function parse_FILETIME(blob) {
14201 var dwLowDateTime = blob.read_shift(4), dwHighDateTime = blob.read_shift(4);
14202 return new Date(((dwHighDateTime/1e7*Math.pow(2,32) + dwLowDateTime/1e7) - 11644473600)*1000).toISOString().replace(/\.000/,"");
14203}
14204function write_FILETIME(time) {
14205 var date = (typeof time == "string") ? new Date(Date.parse(time)) : time;
14206 var t = date.getTime() / 1000 + 11644473600;
14207 var l = t % Math.pow(2,32), h = (t - l) / Math.pow(2,32);
14208 l *= 1e7; h *= 1e7;
14209 var w = (l / Math.pow(2,32)) | 0;
14210 if(w > 0) { l = l % Math.pow(2,32); h += w; }
14211 var o = new_buf(8); o.write_shift(4, l); o.write_shift(4, h); return o;
14212}
14213
14214/* [MS-OSHARED] 2.3.3.1.4 Lpstr */
14215function parse_lpstr(blob, type, pad) {
14216 var start = blob.l;
14217 var str = blob.read_shift(0, 'lpstr-cp');
14218 if(pad) while((blob.l - start) & 3) ++blob.l;
14219 return str;
14220}
14221
14222/* [MS-OSHARED] 2.3.3.1.6 Lpwstr */
14223function parse_lpwstr(blob, type, pad) {
14224 var str = blob.read_shift(0, 'lpwstr');
14225 if(pad) blob.l += (4 - ((str.length+1) & 3)) & 3;
14226 return str;
14227}
14228
14229
14230/* [MS-OSHARED] 2.3.3.1.11 VtString */
14231/* [MS-OSHARED] 2.3.3.1.12 VtUnalignedString */
14232function parse_VtStringBase(blob, stringType, pad) {
14233 if(stringType === 0x1F /*VT_LPWSTR*/) return parse_lpwstr(blob);
14234 return parse_lpstr(blob, stringType, pad);
14235}
14236
14237function parse_VtString(blob, t, pad) { return parse_VtStringBase(blob, t, pad === false ? 0: 4); }
14238function parse_VtUnalignedString(blob, t) { if(!t) throw new Error("VtUnalignedString must have positive length"); return parse_VtStringBase(blob, t, 0); }
14239
14240/* [MS-OSHARED] 2.3.3.1.9 VtVecUnalignedLpstrValue */
14241function parse_VtVecUnalignedLpstrValue(blob) {
14242 var length = blob.read_shift(4);
14243 var ret = [];
14244 for(var i = 0; i != length; ++i) ret[i] = blob.read_shift(0, 'lpstr-cp').replace(chr0,'');
14245 return ret;
14246}
14247
14248/* [MS-OSHARED] 2.3.3.1.10 VtVecUnalignedLpstr */
14249function parse_VtVecUnalignedLpstr(blob) {
14250 return parse_VtVecUnalignedLpstrValue(blob);
14251}
14252
14253/* [MS-OSHARED] 2.3.3.1.13 VtHeadingPair */
14254function parse_VtHeadingPair(blob) {
14255 var headingString = parse_TypedPropertyValue(blob, VT_USTR);
14256 var headerParts = parse_TypedPropertyValue(blob, VT_I4);
14257 return [headingString, headerParts];
14258}
14259
14260/* [MS-OSHARED] 2.3.3.1.14 VtVecHeadingPairValue */
14261function parse_VtVecHeadingPairValue(blob) {
14262 var cElements = blob.read_shift(4);
14263 var out = [];
14264 for(var i = 0; i != cElements / 2; ++i) out.push(parse_VtHeadingPair(blob));
14265 return out;
14266}
14267
14268/* [MS-OSHARED] 2.3.3.1.15 VtVecHeadingPair */
14269function parse_VtVecHeadingPair(blob) {
14270 // NOTE: When invoked, wType & padding were already consumed
14271 return parse_VtVecHeadingPairValue(blob);
14272}
14273
14274/* [MS-OLEPS] 2.18.1 Dictionary (uses 2.17, 2.16) */
14275function parse_dictionary(blob,CodePage) {
14276 var cnt = blob.read_shift(4);
14277 var dict = ({});
14278 for(var j = 0; j != cnt; ++j) {
14279 var pid = blob.read_shift(4);
14280 var len = blob.read_shift(4);
14281 dict[pid] = blob.read_shift(len, (CodePage === 0x4B0 ?'utf16le':'utf8')).replace(chr0,'').replace(chr1,'!');
14282 if(CodePage === 0x4B0 && (len % 2)) blob.l += 2;
14283 }
14284 if(blob.l & 3) blob.l = (blob.l>>2+1)<<2;
14285 return dict;
14286}
14287
14288/* [MS-OLEPS] 2.9 BLOB */
14289function parse_BLOB(blob) {
14290 var size = blob.read_shift(4);
14291 var bytes = blob.slice(blob.l,blob.l+size);
14292 blob.l += size;
14293 if((size & 3) > 0) blob.l += (4 - (size & 3)) & 3;
14294 return bytes;
14295}
14296
14297/* [MS-OLEPS] 2.11 ClipboardData */
14298function parse_ClipboardData(blob) {
14299 // TODO
14300 var o = {};
14301 o.Size = blob.read_shift(4);
14302 //o.Format = blob.read_shift(4);
14303 blob.l += o.Size + 3 - (o.Size - 1) % 4;
14304 return o;
14305}
14306
14307/* [MS-OLEPS] 2.15 TypedPropertyValue */
14308function parse_TypedPropertyValue(blob, type, _opts) {
14309 var t = blob.read_shift(2), ret, opts = _opts||{};
14310 blob.l += 2;
14311 if(type !== VT_VARIANT)
14312 if(t !== type && VT_CUSTOM.indexOf(type)===-1) throw new Error('Expected type ' + type + ' saw ' + t);
14313 switch(type === VT_VARIANT ? t : type) {
14314 case 0x02 /*VT_I2*/: ret = blob.read_shift(2, 'i'); if(!opts.raw) blob.l += 2; return ret;
14315 case 0x03 /*VT_I4*/: ret = blob.read_shift(4, 'i'); return ret;
14316 case 0x0B /*VT_BOOL*/: return blob.read_shift(4) !== 0x0;
14317 case 0x13 /*VT_UI4*/: ret = blob.read_shift(4); return ret;
14318 case 0x1E /*VT_LPSTR*/: return parse_lpstr(blob, t, 4).replace(chr0,'');
14319 case 0x1F /*VT_LPWSTR*/: return parse_lpwstr(blob);
14320 case 0x40 /*VT_FILETIME*/: return parse_FILETIME(blob);
14321 case 0x41 /*VT_BLOB*/: return parse_BLOB(blob);
14322 case 0x47 /*VT_CF*/: return parse_ClipboardData(blob);
14323 case 0x50 /*VT_STRING*/: return parse_VtString(blob, t, !opts.raw).replace(chr0,'');
14324 case 0x51 /*VT_USTR*/: return parse_VtUnalignedString(blob, t/*, 4*/).replace(chr0,'');
14325 case 0x100C /*VT_VECTOR|VT_VARIANT*/: return parse_VtVecHeadingPair(blob);
14326 case 0x101E /*VT_LPSTR*/: return parse_VtVecUnalignedLpstr(blob);
14327 default: throw new Error("TypedPropertyValue unrecognized type " + type + " " + t);
14328 }
14329}
14330function write_TypedPropertyValue(type, value) {
14331 var o = new_buf(4), p = new_buf(4);
14332 o.write_shift(4, type == 0x50 ? 0x1F : type);
14333 switch(type) {
14334 case 0x03 /*VT_I4*/: p.write_shift(-4, value); break;
14335 case 0x05 /*VT_I4*/: p = new_buf(8); p.write_shift(8, value, 'f'); break;
14336 case 0x0B /*VT_BOOL*/: p.write_shift(4, value ? 0x01 : 0x00); break;
14337 case 0x40 /*VT_FILETIME*/: p = write_FILETIME(value); break;
14338 case 0x1F /*VT_LPWSTR*/:
14339 case 0x50 /*VT_STRING*/:
14340p = new_buf(4 + 2 * (value.length + 1) + (value.length % 2 ? 0 : 2));
14341 p.write_shift(4, value.length + 1);
14342 p.write_shift(0, value, "dbcs");
14343 while(p.l != p.length) p.write_shift(1, 0);
14344 break;
14345 default: throw new Error("TypedPropertyValue unrecognized type " + type + " " + value);
14346 }
14347 return bconcat([o, p]);
14348}
14349
14350/* [MS-OLEPS] 2.20 PropertySet */
14351function parse_PropertySet(blob, PIDSI) {
14352 var start_addr = blob.l;
14353 var size = blob.read_shift(4);
14354 var NumProps = blob.read_shift(4);
14355 var Props = [], i = 0;
14356 var CodePage = 0;
14357 var Dictionary = -1, DictObj = ({});
14358 for(i = 0; i != NumProps; ++i) {
14359 var PropID = blob.read_shift(4);
14360 var Offset = blob.read_shift(4);
14361 Props[i] = [PropID, Offset + start_addr];
14362 }
14363 Props.sort(function(x,y) { return x[1] - y[1]; });
14364 var PropH = {};
14365 for(i = 0; i != NumProps; ++i) {
14366 if(blob.l !== Props[i][1]) {
14367 var fail = true;
14368 if(i>0 && PIDSI) switch(PIDSI[Props[i-1][0]].t) {
14369 case 0x02 /*VT_I2*/: if(blob.l+2 === Props[i][1]) { blob.l+=2; fail = false; } break;
14370 case 0x50 /*VT_STRING*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
14371 case 0x100C /*VT_VECTOR|VT_VARIANT*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break;
14372 }
14373 if((!PIDSI||i==0) && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; }
14374 if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i);
14375 }
14376 if(PIDSI) {
14377 var piddsi = PIDSI[Props[i][0]];
14378 PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t, {raw:true});
14379 if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + ("0000" + String(PropH[piddsi.n] & 0xFFFF)).slice(-4);
14380 if(piddsi.n == "CodePage") switch(PropH[piddsi.n]) {
14381 case 0: PropH[piddsi.n] = 1252;
14382 /* falls through */
14383 case 874:
14384 case 932:
14385 case 936:
14386 case 949:
14387 case 950:
14388 case 1250:
14389 case 1251:
14390 case 1253:
14391 case 1254:
14392 case 1255:
14393 case 1256:
14394 case 1257:
14395 case 1258:
14396 case 10000:
14397 case 1200:
14398 case 1201:
14399 case 1252:
14400 case 65000: case -536:
14401 case 65001: case -535:
14402 set_cp(CodePage = (PropH[piddsi.n]>>>0) & 0xFFFF); break;
14403 default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]);
14404 }
14405 } else {
14406 if(Props[i][0] === 0x1) {
14407 CodePage = PropH.CodePage = (parse_TypedPropertyValue(blob, VT_I2));
14408 set_cp(CodePage);
14409 if(Dictionary !== -1) {
14410 var oldpos = blob.l;
14411 blob.l = Props[Dictionary][1];
14412 DictObj = parse_dictionary(blob,CodePage);
14413 blob.l = oldpos;
14414 }
14415 } else if(Props[i][0] === 0) {
14416 if(CodePage === 0) { Dictionary = i; blob.l = Props[i+1][1]; continue; }
14417 DictObj = parse_dictionary(blob,CodePage);
14418 } else {
14419 var name = DictObj[Props[i][0]];
14420 var val;
14421 /* [MS-OSHARED] 2.3.3.2.3.1.2 + PROPVARIANT */
14422 switch(blob[blob.l]) {
14423 case 0x41 /*VT_BLOB*/: blob.l += 4; val = parse_BLOB(blob); break;
14424 case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break;
14425 case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break;
14426 case 0x03 /*VT_I4*/: blob.l += 4; val = blob.read_shift(4, 'i'); break;
14427 case 0x13 /*VT_UI4*/: blob.l += 4; val = blob.read_shift(4); break;
14428 case 0x05 /*VT_R8*/: blob.l += 4; val = blob.read_shift(8, 'f'); break;
14429 case 0x0B /*VT_BOOL*/: blob.l += 4; val = parsebool(blob, 4); break;
14430 case 0x40 /*VT_FILETIME*/: blob.l += 4; val = parseDate(parse_FILETIME(blob)); break;
14431 default: throw new Error("unparsed value: " + blob[blob.l]);
14432 }
14433 PropH[name] = val;
14434 }
14435 }
14436 }
14437 blob.l = start_addr + size; /* step ahead to skip padding */
14438 return PropH;
14439}
14440var XLSPSSkip = [ "CodePage", "Thumbnail", "_PID_LINKBASE", "_PID_HLINKS", "SystemIdentifier", "FMTID" ].concat(PseudoPropsPairs);
14441function guess_property_type(val) {
14442 switch(typeof val) {
14443 case "boolean": return 0x0B;
14444 case "number": return ((val|0)==val) ? 0x03 : 0x05;
14445 case "string": return 0x1F;
14446 case "object": if(val instanceof Date) return 0x40; break;
14447 }
14448 return -1;
14449}
14450function write_PropertySet(entries, RE, PIDSI) {
14451 var hdr = new_buf(8), piao = [], prop = [];
14452 var sz = 8, i = 0;
14453
14454 var pr = new_buf(8), pio = new_buf(8);
14455 pr.write_shift(4, 0x0002);
14456 pr.write_shift(4, 0x04B0);
14457 pio.write_shift(4, 0x0001);
14458 prop.push(pr); piao.push(pio);
14459 sz += 8 + pr.length;
14460
14461 if(!RE) {
14462 pio = new_buf(8);
14463 pio.write_shift(4, 0);
14464 piao.unshift(pio);
14465
14466 var bufs = [new_buf(4)];
14467 bufs[0].write_shift(4, entries.length);
14468 for(i = 0; i < entries.length; ++i) {
14469 var value = entries[i][0];
14470 pr = new_buf(4 + 4 + 2 * (value.length + 1) + (value.length % 2 ? 0 : 2));
14471 pr.write_shift(4, i+2);
14472 pr.write_shift(4, value.length + 1);
14473 pr.write_shift(0, value, "dbcs");
14474 while(pr.l != pr.length) pr.write_shift(1, 0);
14475 bufs.push(pr);
14476 }
14477 pr = bconcat(bufs);
14478 prop.unshift(pr);
14479 sz += 8 + pr.length;
14480 }
14481
14482 for(i = 0; i < entries.length; ++i) {
14483 if(RE && !RE[entries[i][0]]) continue;
14484 if(XLSPSSkip.indexOf(entries[i][0]) > -1) continue;
14485 if(entries[i][1] == null) continue;
14486
14487 var val = entries[i][1], idx = 0;
14488 if(RE) {
14489 idx = +RE[entries[i][0]];
14490 var pinfo = (PIDSI)[idx];
14491 if(pinfo.p == "version" && typeof val == "string") {
14492var arr = val.split(".");
14493 val = ((+arr[0])<<16) + ((+arr[1])||0);
14494 }
14495 pr = write_TypedPropertyValue(pinfo.t, val);
14496 } else {
14497 var T = guess_property_type(val);
14498 if(T == -1) { T = 0x1F; val = String(val); }
14499 pr = write_TypedPropertyValue(T, val);
14500 }
14501 prop.push(pr);
14502
14503 pio = new_buf(8);
14504 pio.write_shift(4, !RE ? 2+i : idx);
14505 piao.push(pio);
14506
14507 sz += 8 + pr.length;
14508 }
14509
14510 var w = 8 * (prop.length + 1);
14511 for(i = 0; i < prop.length; ++i) { piao[i].write_shift(4, w); w += prop[i].length; }
14512 hdr.write_shift(4, sz);
14513 hdr.write_shift(4, prop.length);
14514 return bconcat([hdr].concat(piao).concat(prop));
14515}
14516
14517/* [MS-OLEPS] 2.21 PropertySetStream */
14518function parse_PropertySetStream(file, PIDSI, clsid) {
14519 var blob = file.content;
14520 if(!blob) return ({});
14521 prep_blob(blob, 0);
14522
14523 var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0;
14524 blob.chk('feff', 'Byte Order: ');
14525
14526 /*var vers = */blob.read_shift(2); // TODO: check version
14527 var SystemIdentifier = blob.read_shift(4);
14528 var CLSID = blob.read_shift(16);
14529 if(CLSID !== CFB.utils.consts.HEADER_CLSID && CLSID !== clsid) throw new Error("Bad PropertySet CLSID " + CLSID);
14530 NumSets = blob.read_shift(4);
14531 if(NumSets !== 1 && NumSets !== 2) throw new Error("Unrecognized #Sets: " + NumSets);
14532 FMTID0 = blob.read_shift(16); Offset0 = blob.read_shift(4);
14533
14534 if(NumSets === 1 && Offset0 !== blob.l) throw new Error("Length mismatch: " + Offset0 + " !== " + blob.l);
14535 else if(NumSets === 2) { FMTID1 = blob.read_shift(16); Offset1 = blob.read_shift(4); }
14536 var PSet0 = parse_PropertySet(blob, PIDSI);
14537
14538 var rval = ({ SystemIdentifier: SystemIdentifier });
14539 for(var y in PSet0) rval[y] = PSet0[y];
14540 //rval.blob = blob;
14541 rval.FMTID = FMTID0;
14542 //rval.PSet0 = PSet0;
14543 if(NumSets === 1) return rval;
14544 if(Offset1 - blob.l == 2) blob.l += 2;
14545 if(blob.l !== Offset1) throw new Error("Length mismatch 2: " + blob.l + " !== " + Offset1);
14546 var PSet1;
14547 try { PSet1 = parse_PropertySet(blob, null); } catch(e) {/* empty */}
14548 for(y in PSet1) rval[y] = PSet1[y];
14549 rval.FMTID = [FMTID0, FMTID1]; // TODO: verify FMTID0/1
14550 return rval;
14551}
14552function write_PropertySetStream(entries, clsid, RE, PIDSI, entries2, clsid2) {
14553 var hdr = new_buf(entries2 ? 68 : 48);
14554 var bufs = [hdr];
14555 hdr.write_shift(2, 0xFFFE);
14556 hdr.write_shift(2, 0x0000); /* TODO: type 1 props */
14557 hdr.write_shift(4, 0x32363237);
14558 hdr.write_shift(16, CFB.utils.consts.HEADER_CLSID, "hex");
14559 hdr.write_shift(4, (entries2 ? 2 : 1));
14560 hdr.write_shift(16, clsid, "hex");
14561 hdr.write_shift(4, (entries2 ? 68 : 48));
14562 var ps0 = write_PropertySet(entries, RE, PIDSI);
14563 bufs.push(ps0);
14564
14565 if(entries2) {
14566 var ps1 = write_PropertySet(entries2, null, null);
14567 hdr.write_shift(16, clsid2, "hex");
14568 hdr.write_shift(4, 68 + ps0.length);
14569 bufs.push(ps1);
14570 }
14571 return bconcat(bufs);
14572}
14573
14574function parsenoop2(blob, length) { blob.read_shift(length); return null; }
14575function writezeroes(n, o) { if(!o) o=new_buf(n); for(var j=0; j<n; ++j) o.write_shift(1, 0); return o; }
14576
14577function parslurp(blob, length, cb) {
14578 var arr = [], target = blob.l + length;
14579 while(blob.l < target) arr.push(cb(blob, target - blob.l));
14580 if(target !== blob.l) throw new Error("Slurp error");
14581 return arr;
14582}
14583
14584function parsebool(blob, length) { return blob.read_shift(length) === 0x1; }
14585function writebool(v, o) { if(!o) o=new_buf(2); o.write_shift(2, +!!v); return o; }
14586
14587function parseuint16(blob) { return blob.read_shift(2, 'u'); }
14588function writeuint16(v, o) { if(!o) o=new_buf(2); o.write_shift(2, v); return o; }
14589function parseuint16a(blob, length) { return parslurp(blob,length,parseuint16);}
14590
14591/* --- 2.5 Structures --- */
14592
14593/* [MS-XLS] 2.5.10 Bes (boolean or error) */
14594function parse_Bes(blob) {
14595 var v = blob.read_shift(1), t = blob.read_shift(1);
14596 return t === 0x01 ? v : v === 0x01;
14597}
14598function write_Bes(v, t, o) {
14599 if(!o) o = new_buf(2);
14600 o.write_shift(1, +v);
14601 o.write_shift(1, ((t == 'e') ? 1 : 0));
14602 return o;
14603}
14604
14605/* [MS-XLS] 2.5.240 ShortXLUnicodeString */
14606function parse_ShortXLUnicodeString(blob, length, opts) {
14607 var cch = blob.read_shift(opts && opts.biff >= 12 ? 2 : 1);
14608 var encoding = 'sbcs-cont';
14609 var cp = current_codepage;
14610 if(opts && opts.biff >= 8) current_codepage = 1200;
14611 if(!opts || opts.biff == 8 ) {
14612 var fHighByte = blob.read_shift(1);
14613 if(fHighByte) { encoding = 'dbcs-cont'; }
14614 } else if(opts.biff == 12) {
14615 encoding = 'wstr';
14616 }
14617 if(opts.biff >= 2 && opts.biff <= 5) encoding = 'cpstr';
14618 var o = cch ? blob.read_shift(cch, encoding) : "";
14619 current_codepage = cp;
14620 return o;
14621}
14622
14623/* 2.5.293 XLUnicodeRichExtendedString */
14624function parse_XLUnicodeRichExtendedString(blob) {
14625 var cp = current_codepage;
14626 current_codepage = 1200;
14627 var cch = blob.read_shift(2), flags = blob.read_shift(1);
14628 var /*fHighByte = flags & 0x1,*/ fExtSt = flags & 0x4, fRichSt = flags & 0x8;
14629 var width = 1 + (flags & 0x1); // 0x0 -> utf8, 0x1 -> dbcs
14630 var cRun = 0, cbExtRst;
14631 var z = {};
14632 if(fRichSt) cRun = blob.read_shift(2);
14633 if(fExtSt) cbExtRst = blob.read_shift(4);
14634 var encoding = width == 2 ? 'dbcs-cont' : 'sbcs-cont';
14635 var msg = cch === 0 ? "" : blob.read_shift(cch, encoding);
14636 if(fRichSt) blob.l += 4 * cRun; //TODO: parse this
14637 if(fExtSt) blob.l += cbExtRst; //TODO: parse this
14638 z.t = msg;
14639 if(!fRichSt) { z.raw = "<t>" + z.t + "</t>"; z.r = z.t; }
14640 current_codepage = cp;
14641 return z;
14642}
14643
14644/* 2.5.296 XLUnicodeStringNoCch */
14645function parse_XLUnicodeStringNoCch(blob, cch, opts) {
14646 var retval;
14647 if(opts) {
14648 if(opts.biff >= 2 && opts.biff <= 5) return blob.read_shift(cch, 'cpstr');
14649 if(opts.biff >= 12) return blob.read_shift(cch, 'dbcs-cont');
14650 }
14651 var fHighByte = blob.read_shift(1);
14652 if(fHighByte===0) { retval = blob.read_shift(cch, 'sbcs-cont'); }
14653 else { retval = blob.read_shift(cch, 'dbcs-cont'); }
14654 return retval;
14655}
14656
14657/* 2.5.294 XLUnicodeString */
14658function parse_XLUnicodeString(blob, length, opts) {
14659 var cch = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
14660 if(cch === 0) { blob.l++; return ""; }
14661 return parse_XLUnicodeStringNoCch(blob, cch, opts);
14662}
14663/* BIFF5 override */
14664function parse_XLUnicodeString2(blob, length, opts) {
14665 if(opts.biff > 5) return parse_XLUnicodeString(blob, length, opts);
14666 var cch = blob.read_shift(1);
14667 if(cch === 0) { blob.l++; return ""; }
14668 return blob.read_shift(cch, (opts.biff <= 4 || !blob.lens ) ? 'cpstr' : 'sbcs-cont');
14669}
14670/* TODO: BIFF5 and lower, codepage awareness */
14671function write_XLUnicodeString(str, opts, o) {
14672 if(!o) o = new_buf(3 + 2 * str.length);
14673 o.write_shift(2, str.length);
14674 o.write_shift(1, 1);
14675 o.write_shift(31, str, 'utf16le');
14676 return o;
14677}
14678
14679/* [MS-XLS] 2.5.61 ControlInfo */
14680function parse_ControlInfo(blob) {
14681 var flags = blob.read_shift(1);
14682 blob.l++;
14683 var accel = blob.read_shift(2);
14684 blob.l += 2;
14685 return [flags, accel];
14686}
14687
14688/* [MS-OSHARED] 2.3.7.6 URLMoniker TODO: flags */
14689function parse_URLMoniker(blob) {
14690 var len = blob.read_shift(4), start = blob.l;
14691 var extra = false;
14692 if(len > 24) {
14693 /* look ahead */
14694 blob.l += len - 24;
14695 if(blob.read_shift(16) === "795881f43b1d7f48af2c825dc4852763") extra = true;
14696 blob.l = start;
14697 }
14698 var url = blob.read_shift((extra?len-24:len)>>1, 'utf16le').replace(chr0,"");
14699 if(extra) blob.l += 24;
14700 return url;
14701}
14702
14703/* [MS-OSHARED] 2.3.7.8 FileMoniker TODO: all fields */
14704function parse_FileMoniker(blob) {
14705 blob.l += 2; //var cAnti = blob.read_shift(2);
14706 var ansiPath = blob.read_shift(0, 'lpstr-ansi');
14707 blob.l += 2; //var endServer = blob.read_shift(2);
14708 if(blob.read_shift(2) != 0xDEAD) throw new Error("Bad FileMoniker");
14709 var sz = blob.read_shift(4);
14710 if(sz === 0) return ansiPath.replace(/\\/g,"/");
14711 var bytes = blob.read_shift(4);
14712 if(blob.read_shift(2) != 3) throw new Error("Bad FileMoniker");
14713 var unicodePath = blob.read_shift(bytes>>1, 'utf16le').replace(chr0,"");
14714 return unicodePath;
14715}
14716
14717/* [MS-OSHARED] 2.3.7.2 HyperlinkMoniker TODO: all the monikers */
14718function parse_HyperlinkMoniker(blob, length) {
14719 var clsid = blob.read_shift(16); length -= 16;
14720 switch(clsid) {
14721 case "e0c9ea79f9bace118c8200aa004ba90b": return parse_URLMoniker(blob, length);
14722 case "0303000000000000c000000000000046": return parse_FileMoniker(blob, length);
14723 default: throw new Error("Unsupported Moniker " + clsid);
14724 }
14725}
14726
14727/* [MS-OSHARED] 2.3.7.9 HyperlinkString */
14728function parse_HyperlinkString(blob) {
14729 var len = blob.read_shift(4);
14730 var o = len > 0 ? blob.read_shift(len, 'utf16le').replace(chr0, "") : "";
14731 return o;
14732}
14733
14734/* [MS-OSHARED] 2.3.7.1 Hyperlink Object */
14735function parse_Hyperlink(blob, length) {
14736 var end = blob.l + length;
14737 var sVer = blob.read_shift(4);
14738 if(sVer !== 2) throw new Error("Unrecognized streamVersion: " + sVer);
14739 var flags = blob.read_shift(2);
14740 blob.l += 2;
14741 var displayName, targetFrameName, moniker, oleMoniker, Loc="", guid, fileTime;
14742 if(flags & 0x0010) displayName = parse_HyperlinkString(blob, end - blob.l);
14743 if(flags & 0x0080) targetFrameName = parse_HyperlinkString(blob, end - blob.l);
14744 if((flags & 0x0101) === 0x0101) moniker = parse_HyperlinkString(blob, end - blob.l);
14745 if((flags & 0x0101) === 0x0001) oleMoniker = parse_HyperlinkMoniker(blob, end - blob.l);
14746 if(flags & 0x0008) Loc = parse_HyperlinkString(blob, end - blob.l);
14747 if(flags & 0x0020) guid = blob.read_shift(16);
14748 if(flags & 0x0040) fileTime = parse_FILETIME(blob/*, 8*/);
14749 blob.l = end;
14750 var target = targetFrameName||moniker||oleMoniker||"";
14751 if(target && Loc) target+="#"+Loc;
14752 if(!target) target = "#" + Loc;
14753 var out = ({Target:target});
14754 if(guid) out.guid = guid;
14755 if(fileTime) out.time = fileTime;
14756 if(displayName) out.Tooltip = displayName;
14757 return out;
14758}
14759function write_Hyperlink(hl) {
14760 var out = new_buf(512), i = 0;
14761 var Target = hl.Target;
14762 var F = Target.indexOf("#") > -1 ? 0x1f : 0x17;
14763 switch(Target.charAt(0)) { case "#": F=0x1c; break; case ".": F&=~2; break; }
14764 out.write_shift(4,2); out.write_shift(4, F);
14765 var data = [8,6815827,6619237,4849780,83]; for(i = 0; i < data.length; ++i) out.write_shift(4, data[i]);
14766 if(F == 0x1C) {
14767 Target = Target.slice(1);
14768 out.write_shift(4, Target.length + 1);
14769 for(i = 0; i < Target.length; ++i) out.write_shift(2, Target.charCodeAt(i));
14770 out.write_shift(2, 0);
14771 } else if(F & 0x02) {
14772 data = "e0 c9 ea 79 f9 ba ce 11 8c 82 00 aa 00 4b a9 0b".split(" ");
14773 for(i = 0; i < data.length; ++i) out.write_shift(1, parseInt(data[i], 16));
14774 out.write_shift(4, 2*(Target.length + 1));
14775 for(i = 0; i < Target.length; ++i) out.write_shift(2, Target.charCodeAt(i));
14776 out.write_shift(2, 0);
14777 } else {
14778 data = "03 03 00 00 00 00 00 00 c0 00 00 00 00 00 00 46".split(" ");
14779 for(i = 0; i < data.length; ++i) out.write_shift(1, parseInt(data[i], 16));
14780 var P = 0;
14781 while(Target.slice(P*3,P*3+3)=="../"||Target.slice(P*3,P*3+3)=="..\\") ++P;
14782 out.write_shift(2, P);
14783 out.write_shift(4, Target.length + 1);
14784 for(i = 0; i < Target.length; ++i) out.write_shift(1, Target.charCodeAt(i) & 0xFF);
14785 out.write_shift(1, 0);
14786 out.write_shift(2, 0xFFFF);
14787 out.write_shift(2, 0xDEAD);
14788 for(i = 0; i < 6; ++i) out.write_shift(4, 0);
14789 }
14790 return out.slice(0, out.l);
14791}
14792
14793/* 2.5.178 LongRGBA */
14794function parse_LongRGBA(blob) { var r = blob.read_shift(1), g = blob.read_shift(1), b = blob.read_shift(1), a = blob.read_shift(1); return [r,g,b,a]; }
14795
14796/* 2.5.177 LongRGB */
14797function parse_LongRGB(blob, length) { var x = parse_LongRGBA(blob, length); x[3] = 0; return x; }
14798
14799
14800/* [MS-XLS] 2.5.19 */
14801function parse_XLSCell(blob) {
14802 var rw = blob.read_shift(2); // 0-indexed
14803 var col = blob.read_shift(2);
14804 var ixfe = blob.read_shift(2);
14805 return ({r:rw, c:col, ixfe:ixfe});
14806}
14807function write_XLSCell(R, C, ixfe, o) {
14808 if(!o) o = new_buf(6);
14809 o.write_shift(2, R);
14810 o.write_shift(2, C);
14811 o.write_shift(2, ixfe||0);
14812 return o;
14813}
14814
14815/* [MS-XLS] 2.5.134 */
14816function parse_frtHeader(blob) {
14817 var rt = blob.read_shift(2);
14818 var flags = blob.read_shift(2); // TODO: parse these flags
14819 blob.l += 8;
14820 return {type: rt, flags: flags};
14821}
14822
14823
14824
14825function parse_OptXLUnicodeString(blob, length, opts) { return length === 0 ? "" : parse_XLUnicodeString2(blob, length, opts); }
14826
14827/* [MS-XLS] 2.5.344 */
14828function parse_XTI(blob, length, opts) {
14829 var w = opts.biff > 8 ? 4 : 2;
14830 var iSupBook = blob.read_shift(w), itabFirst = blob.read_shift(w,'i'), itabLast = blob.read_shift(w,'i');
14831 return [iSupBook, itabFirst, itabLast];
14832}
14833
14834/* [MS-XLS] 2.5.218 */
14835function parse_RkRec(blob) {
14836 var ixfe = blob.read_shift(2);
14837 var RK = parse_RkNumber(blob);
14838 return [ixfe, RK];
14839}
14840
14841/* [MS-XLS] 2.5.1 */
14842function parse_AddinUdf(blob, length, opts) {
14843 blob.l += 4; length -= 4;
14844 var l = blob.l + length;
14845 var udfName = parse_ShortXLUnicodeString(blob, length, opts);
14846 var cb = blob.read_shift(2);
14847 l -= blob.l;
14848 if(cb !== l) throw new Error("Malformed AddinUdf: padding = " + l + " != " + cb);
14849 blob.l += cb;
14850 return udfName;
14851}
14852
14853/* [MS-XLS] 2.5.209 TODO: Check sizes */
14854function parse_Ref8U(blob) {
14855 var rwFirst = blob.read_shift(2);
14856 var rwLast = blob.read_shift(2);
14857 var colFirst = blob.read_shift(2);
14858 var colLast = blob.read_shift(2);
14859 return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}};
14860}
14861function write_Ref8U(r, o) {
14862 if(!o) o = new_buf(8);
14863 o.write_shift(2, r.s.r);
14864 o.write_shift(2, r.e.r);
14865 o.write_shift(2, r.s.c);
14866 o.write_shift(2, r.e.c);
14867 return o;
14868}
14869
14870/* [MS-XLS] 2.5.211 */
14871function parse_RefU(blob) {
14872 var rwFirst = blob.read_shift(2);
14873 var rwLast = blob.read_shift(2);
14874 var colFirst = blob.read_shift(1);
14875 var colLast = blob.read_shift(1);
14876 return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}};
14877}
14878
14879/* [MS-XLS] 2.5.207 */
14880var parse_Ref = parse_RefU;
14881
14882/* [MS-XLS] 2.5.143 */
14883function parse_FtCmo(blob) {
14884 blob.l += 4;
14885 var ot = blob.read_shift(2);
14886 var id = blob.read_shift(2);
14887 var flags = blob.read_shift(2);
14888 blob.l+=12;
14889 return [id, ot, flags];
14890}
14891
14892/* [MS-XLS] 2.5.149 */
14893function parse_FtNts(blob) {
14894 var out = {};
14895 blob.l += 4;
14896 blob.l += 16; // GUID TODO
14897 out.fSharedNote = blob.read_shift(2);
14898 blob.l += 4;
14899 return out;
14900}
14901
14902/* [MS-XLS] 2.5.142 */
14903function parse_FtCf(blob) {
14904 var out = {};
14905 blob.l += 4;
14906 blob.cf = blob.read_shift(2);
14907 return out;
14908}
14909
14910/* [MS-XLS] 2.5.140 - 2.5.154 and friends */
14911function parse_FtSkip(blob) { blob.l += 2; blob.l += blob.read_shift(2); }
14912var FtTab = {
149130x00: parse_FtSkip, /* FtEnd */
149140x04: parse_FtSkip, /* FtMacro */
149150x05: parse_FtSkip, /* FtButton */
149160x06: parse_FtSkip, /* FtGmo */
149170x07: parse_FtCf, /* FtCf */
149180x08: parse_FtSkip, /* FtPioGrbit */
149190x09: parse_FtSkip, /* FtPictFmla */
149200x0A: parse_FtSkip, /* FtCbls */
149210x0B: parse_FtSkip, /* FtRbo */
149220x0C: parse_FtSkip, /* FtSbs */
149230x0D: parse_FtNts, /* FtNts */
149240x0E: parse_FtSkip, /* FtSbsFmla */
149250x0F: parse_FtSkip, /* FtGboData */
149260x10: parse_FtSkip, /* FtEdoData */
149270x11: parse_FtSkip, /* FtRboData */
149280x12: parse_FtSkip, /* FtCblsData */
149290x13: parse_FtSkip, /* FtLbsData */
149300x14: parse_FtSkip, /* FtCblsFmla */
149310x15: parse_FtCmo
14932};
14933function parse_FtArray(blob, length) {
14934 var tgt = blob.l + length;
14935 var fts = [];
14936 while(blob.l < tgt) {
14937 var ft = blob.read_shift(2);
14938 blob.l-=2;
14939 try {
14940 fts.push(FtTab[ft](blob, tgt - blob.l));
14941 } catch(e) { blob.l = tgt; return fts; }
14942 }
14943 if(blob.l != tgt) blob.l = tgt; //throw new Error("bad Object Ft-sequence");
14944 return fts;
14945}
14946
14947/* --- 2.4 Records --- */
14948
14949/* [MS-XLS] 2.4.21 */
14950function parse_BOF(blob, length) {
14951 var o = {BIFFVer:0, dt:0};
14952 o.BIFFVer = blob.read_shift(2); length -= 2;
14953 if(length >= 2) { o.dt = blob.read_shift(2); blob.l -= 2; }
14954 switch(o.BIFFVer) {
14955 case 0x0600: /* BIFF8 */
14956 case 0x0500: /* BIFF5 */
14957 case 0x0400: /* BIFF4 */
14958 case 0x0300: /* BIFF3 */
14959 case 0x0200: /* BIFF2 */
14960 case 0x0002: case 0x0007: /* BIFF2 */
14961 break;
14962 default: if(length > 6) throw new Error("Unexpected BIFF Ver " + o.BIFFVer);
14963 }
14964
14965 blob.read_shift(length);
14966 return o;
14967}
14968function write_BOF(wb, t, o) {
14969 var h = 0x0600, w = 16;
14970 switch(o.bookType) {
14971 case 'biff8': break;
14972 case 'biff5': h = 0x0500; w = 8; break;
14973 case 'biff4': h = 0x0004; w = 6; break;
14974 case 'biff3': h = 0x0003; w = 6; break;
14975 case 'biff2': h = 0x0002; w = 4; break;
14976 case 'xla': break;
14977 default: throw new Error("unsupported BIFF version");
14978 }
14979 var out = new_buf(w);
14980 out.write_shift(2, h);
14981 out.write_shift(2, t);
14982 if(w > 4) out.write_shift(2, 0x7262);
14983 if(w > 6) out.write_shift(2, 0x07CD);
14984 if(w > 8) {
14985 out.write_shift(2, 0xC009);
14986 out.write_shift(2, 0x0001);
14987 out.write_shift(2, 0x0706);
14988 out.write_shift(2, 0x0000);
14989 }
14990 return out;
14991}
14992
14993
14994/* [MS-XLS] 2.4.146 */
14995function parse_InterfaceHdr(blob, length) {
14996 if(length === 0) return 0x04b0;
14997 if((blob.read_shift(2))!==0x04b0){/* empty */}
14998 return 0x04b0;
14999}
15000
15001
15002/* [MS-XLS] 2.4.349 */
15003function parse_WriteAccess(blob, length, opts) {
15004 if(opts.enc) { blob.l += length; return ""; }
15005 var l = blob.l;
15006 // TODO: make sure XLUnicodeString doesnt overrun
15007 var UserName = parse_XLUnicodeString2(blob, 0, opts);
15008 blob.read_shift(length + l - blob.l);
15009 return UserName;
15010}
15011function write_WriteAccess(s, opts) {
15012 var b8 = !opts || opts.biff == 8;
15013 var o = new_buf(b8 ? 112 : 54);
15014 o.write_shift(opts.biff == 8 ? 2 : 1, 7);
15015 if(b8) o.write_shift(1, 0);
15016 o.write_shift(4, 0x33336853);
15017 o.write_shift(4, (0x00534A74 | (b8 ? 0 : 0x20000000)));
15018 while(o.l < o.length) o.write_shift(1, (b8 ? 0 : 32));
15019 return o;
15020}
15021
15022/* [MS-XLS] 2.4.351 */
15023function parse_WsBool(blob, length, opts) {
15024 var flags = opts && opts.biff == 8 || length == 2 ? blob.read_shift(2) : (blob.l += length, 0);
15025 return { fDialog: flags & 0x10 };
15026}
15027
15028/* [MS-XLS] 2.4.28 */
15029function parse_BoundSheet8(blob, length, opts) {
15030 var pos = blob.read_shift(4);
15031 var hidden = blob.read_shift(1) & 0x03;
15032 var dt = blob.read_shift(1);
15033 switch(dt) {
15034 case 0: dt = 'Worksheet'; break;
15035 case 1: dt = 'Macrosheet'; break;
15036 case 2: dt = 'Chartsheet'; break;
15037 case 6: dt = 'VBAModule'; break;
15038 }
15039 var name = parse_ShortXLUnicodeString(blob, 0, opts);
15040 if(name.length === 0) name = "Sheet1";
15041 return { pos:pos, hs:hidden, dt:dt, name:name };
15042}
15043function write_BoundSheet8(data, opts) {
15044 var w = (!opts || opts.biff >= 8 ? 2 : 1);
15045 var o = new_buf(8 + w * data.name.length);
15046 o.write_shift(4, data.pos);
15047 o.write_shift(1, data.hs || 0);
15048 o.write_shift(1, data.dt);
15049 o.write_shift(1, data.name.length);
15050 if(opts.biff >= 8) o.write_shift(1, 1);
15051 o.write_shift(w * data.name.length, data.name, opts.biff < 8 ? 'sbcs' : 'utf16le');
15052 var out = o.slice(0, o.l);
15053 out.l = o.l; return out;
15054}
15055
15056/* [MS-XLS] 2.4.265 TODO */
15057function parse_SST(blob, length) {
15058 var end = blob.l + length;
15059 var cnt = blob.read_shift(4);
15060 var ucnt = blob.read_shift(4);
15061 var strs = ([]);
15062 for(var i = 0; i != ucnt && blob.l < end; ++i) {
15063 strs.push(parse_XLUnicodeRichExtendedString(blob));
15064 }
15065 strs.Count = cnt; strs.Unique = ucnt;
15066 return strs;
15067}
15068
15069/* [MS-XLS] 2.4.107 */
15070function parse_ExtSST(blob, length) {
15071 var extsst = {};
15072 extsst.dsst = blob.read_shift(2);
15073 blob.l += length-2;
15074 return extsst;
15075}
15076
15077
15078/* [MS-XLS] 2.4.221 TODO: check BIFF2-4 */
15079function parse_Row(blob) {
15080 var z = ({});
15081 z.r = blob.read_shift(2);
15082 z.c = blob.read_shift(2);
15083 z.cnt = blob.read_shift(2) - z.c;
15084 var miyRw = blob.read_shift(2);
15085 blob.l += 4; // reserved(2), unused(2)
15086 var flags = blob.read_shift(1); // various flags
15087 blob.l += 3; // reserved(8), ixfe(12), flags(4)
15088 if(flags & 0x07) z.level = flags & 0x07;
15089 // collapsed: flags & 0x10
15090 if(flags & 0x20) z.hidden = true;
15091 if(flags & 0x40) z.hpt = miyRw / 20;
15092 return z;
15093}
15094
15095
15096/* [MS-XLS] 2.4.125 */
15097function parse_ForceFullCalculation(blob) {
15098 var header = parse_frtHeader(blob);
15099 if(header.type != 0x08A3) throw new Error("Invalid Future Record " + header.type);
15100 var fullcalc = blob.read_shift(4);
15101 return fullcalc !== 0x0;
15102}
15103
15104
15105
15106
15107
15108/* [MS-XLS] 2.4.215 rt */
15109function parse_RecalcId(blob) {
15110 blob.read_shift(2);
15111 return blob.read_shift(4);
15112}
15113
15114/* [MS-XLS] 2.4.87 */
15115function parse_DefaultRowHeight(blob, length, opts) {
15116 var f = 0;
15117 if(!(opts && opts.biff == 2)) {
15118 f = blob.read_shift(2);
15119 }
15120 var miyRw = blob.read_shift(2);
15121 if((opts && opts.biff == 2)) {
15122 f = 1 - (miyRw >> 15); miyRw &= 0x7fff;
15123 }
15124 var fl = {Unsynced:f&1,DyZero:(f&2)>>1,ExAsc:(f&4)>>2,ExDsc:(f&8)>>3};
15125 return [fl, miyRw];
15126}
15127
15128/* [MS-XLS] 2.4.345 TODO */
15129function parse_Window1(blob) {
15130 var xWn = blob.read_shift(2), yWn = blob.read_shift(2), dxWn = blob.read_shift(2), dyWn = blob.read_shift(2);
15131 var flags = blob.read_shift(2), iTabCur = blob.read_shift(2), iTabFirst = blob.read_shift(2);
15132 var ctabSel = blob.read_shift(2), wTabRatio = blob.read_shift(2);
15133 return { Pos: [xWn, yWn], Dim: [dxWn, dyWn], Flags: flags, CurTab: iTabCur,
15134 FirstTab: iTabFirst, Selected: ctabSel, TabRatio: wTabRatio };
15135}
15136function write_Window1() {
15137 var o = new_buf(18);
15138 o.write_shift(2, 0);
15139 o.write_shift(2, 0);
15140 o.write_shift(2, 0x7260);
15141 o.write_shift(2, 0x44c0);
15142 o.write_shift(2, 0x38);
15143 o.write_shift(2, 0);
15144 o.write_shift(2, 0);
15145 o.write_shift(2, 1);
15146 o.write_shift(2, 0x01f4);
15147 return o;
15148}
15149/* [MS-XLS] 2.4.346 TODO */
15150function parse_Window2(blob, length, opts) {
15151 if(opts && opts.biff >= 2 && opts.biff < 8) return {};
15152 var f = blob.read_shift(2);
15153 return { RTL: f & 0x40 };
15154}
15155function write_Window2(view) {
15156 var o = new_buf(18), f = 0x6b6;
15157 if(view && view.RTL) f |= 0x40;
15158 o.write_shift(2, f);
15159 o.write_shift(4, 0);
15160 o.write_shift(4, 64);
15161 o.write_shift(4, 0);
15162 o.write_shift(4, 0);
15163 return o;
15164}
15165
15166/* [MS-XLS] 2.4.189 TODO */
15167function parse_Pane(/*blob, length, opts*/) {
15168}
15169
15170/* [MS-XLS] 2.4.122 TODO */
15171function parse_Font(blob, length, opts) {
15172 var o = {
15173 dyHeight: blob.read_shift(2),
15174 fl: blob.read_shift(2)
15175 };
15176 switch((opts && opts.biff) || 8) {
15177 case 2: break;
15178 case 3: case 4: blob.l += 2; break;
15179 default: blob.l += 10; break;
15180 }
15181 o.name = parse_ShortXLUnicodeString(blob, 0, opts);
15182 return o;
15183}
15184function write_Font(data, opts) {
15185 var name = data.name || "Arial";
15186 var b5 = (opts && (opts.biff == 5)), w = (b5 ? (15 + name.length) : (16 + 2 * name.length));
15187 var o = new_buf(w);
15188 o.write_shift(2, (data.sz || 12) * 20);
15189 o.write_shift(4, 0);
15190 o.write_shift(2, 400);
15191 o.write_shift(4, 0);
15192 o.write_shift(2, 0);
15193 o.write_shift(1, name.length);
15194 if(!b5) o.write_shift(1, 1);
15195 o.write_shift((b5 ? 1 : 2) * name.length, name, (b5 ? "sbcs" : "utf16le"));
15196 return o;
15197}
15198
15199/* [MS-XLS] 2.4.149 */
15200function parse_LabelSst(blob) {
15201 var cell = parse_XLSCell(blob);
15202 cell.isst = blob.read_shift(4);
15203 return cell;
15204}
15205
15206/* [MS-XLS] 2.4.148 */
15207function parse_Label(blob, length, opts) {
15208 var target = blob.l + length;
15209 var cell = parse_XLSCell(blob, 6);
15210 if(opts.biff == 2) blob.l++;
15211 var str = parse_XLUnicodeString(blob, target - blob.l, opts);
15212 cell.val = str;
15213 return cell;
15214}
15215function write_Label(R, C, v, os, opts) {
15216 var b8 = !opts || opts.biff == 8;
15217 var o = new_buf(6 + 2 + (+b8) + (1 + b8) * v.length);
15218 write_XLSCell(R, C, os, o);
15219 o.write_shift(2, v.length);
15220 if(b8) o.write_shift(1, 1);
15221 o.write_shift((1 + b8) * v.length, v, b8 ? 'utf16le' : 'sbcs');
15222 return o;
15223}
15224
15225
15226/* [MS-XLS] 2.4.126 Number Formats */
15227function parse_Format(blob, length, opts) {
15228 var numFmtId = blob.read_shift(2);
15229 var fmtstr = parse_XLUnicodeString2(blob, 0, opts);
15230 return [numFmtId, fmtstr];
15231}
15232function write_Format(i, f, opts, o) {
15233 var b5 = (opts && (opts.biff == 5));
15234 if(!o) o = new_buf(b5 ? (3 + f.length) : (5 + 2 * f.length));
15235 o.write_shift(2, i);
15236 o.write_shift((b5 ? 1 : 2), f.length);
15237 if(!b5) o.write_shift(1, 1);
15238 o.write_shift((b5 ? 1 : 2) * f.length, f, (b5 ? 'sbcs' : 'utf16le'));
15239 var out = (o.length > o.l) ? o.slice(0, o.l) : o;
15240 if(out.l == null) out.l = out.length;
15241 return out;
15242}
15243var parse_BIFF2Format = parse_XLUnicodeString2;
15244
15245/* [MS-XLS] 2.4.90 */
15246function parse_Dimensions(blob, length, opts) {
15247 var end = blob.l + length;
15248 var w = opts.biff == 8 || !opts.biff ? 4 : 2;
15249 var r = blob.read_shift(w), R = blob.read_shift(w);
15250 var c = blob.read_shift(2), C = blob.read_shift(2);
15251 blob.l = end;
15252 return {s: {r:r, c:c}, e: {r:R, c:C}};
15253}
15254function write_Dimensions(range, opts) {
15255 var w = opts.biff == 8 || !opts.biff ? 4 : 2;
15256 var o = new_buf(2*w + 6);
15257 o.write_shift(w, range.s.r);
15258 o.write_shift(w, range.e.r + 1);
15259 o.write_shift(2, range.s.c);
15260 o.write_shift(2, range.e.c + 1);
15261 o.write_shift(2, 0);
15262 return o;
15263}
15264
15265/* [MS-XLS] 2.4.220 */
15266function parse_RK(blob) {
15267 var rw = blob.read_shift(2), col = blob.read_shift(2);
15268 var rkrec = parse_RkRec(blob);
15269 return {r:rw, c:col, ixfe:rkrec[0], rknum:rkrec[1]};
15270}
15271
15272/* [MS-XLS] 2.4.175 */
15273function parse_MulRk(blob, length) {
15274 var target = blob.l + length - 2;
15275 var rw = blob.read_shift(2), col = blob.read_shift(2);
15276 var rkrecs = [];
15277 while(blob.l < target) rkrecs.push(parse_RkRec(blob));
15278 if(blob.l !== target) throw new Error("MulRK read error");
15279 var lastcol = blob.read_shift(2);
15280 if(rkrecs.length != lastcol - col + 1) throw new Error("MulRK length mismatch");
15281 return {r:rw, c:col, C:lastcol, rkrec:rkrecs};
15282}
15283/* [MS-XLS] 2.4.174 */
15284function parse_MulBlank(blob, length) {
15285 var target = blob.l + length - 2;
15286 var rw = blob.read_shift(2), col = blob.read_shift(2);
15287 var ixfes = [];
15288 while(blob.l < target) ixfes.push(blob.read_shift(2));
15289 if(blob.l !== target) throw new Error("MulBlank read error");
15290 var lastcol = blob.read_shift(2);
15291 if(ixfes.length != lastcol - col + 1) throw new Error("MulBlank length mismatch");
15292 return {r:rw, c:col, C:lastcol, ixfe:ixfes};
15293}
15294
15295/* [MS-XLS] 2.5.20 2.5.249 TODO: interpret values here */
15296function parse_CellStyleXF(blob, length, style, opts) {
15297 var o = {};
15298 var a = blob.read_shift(4), b = blob.read_shift(4);
15299 var c = blob.read_shift(4), d = blob.read_shift(2);
15300 o.patternType = XLSFillPattern[c >> 26];
15301
15302 if(!opts.cellStyles) return o;
15303 o.alc = a & 0x07;
15304 o.fWrap = (a >> 3) & 0x01;
15305 o.alcV = (a >> 4) & 0x07;
15306 o.fJustLast = (a >> 7) & 0x01;
15307 o.trot = (a >> 8) & 0xFF;
15308 o.cIndent = (a >> 16) & 0x0F;
15309 o.fShrinkToFit = (a >> 20) & 0x01;
15310 o.iReadOrder = (a >> 22) & 0x02;
15311 o.fAtrNum = (a >> 26) & 0x01;
15312 o.fAtrFnt = (a >> 27) & 0x01;
15313 o.fAtrAlc = (a >> 28) & 0x01;
15314 o.fAtrBdr = (a >> 29) & 0x01;
15315 o.fAtrPat = (a >> 30) & 0x01;
15316 o.fAtrProt = (a >> 31) & 0x01;
15317
15318 o.dgLeft = b & 0x0F;
15319 o.dgRight = (b >> 4) & 0x0F;
15320 o.dgTop = (b >> 8) & 0x0F;
15321 o.dgBottom = (b >> 12) & 0x0F;
15322 o.icvLeft = (b >> 16) & 0x7F;
15323 o.icvRight = (b >> 23) & 0x7F;
15324 o.grbitDiag = (b >> 30) & 0x03;
15325
15326 o.icvTop = c & 0x7F;
15327 o.icvBottom = (c >> 7) & 0x7F;
15328 o.icvDiag = (c >> 14) & 0x7F;
15329 o.dgDiag = (c >> 21) & 0x0F;
15330
15331 o.icvFore = d & 0x7F;
15332 o.icvBack = (d >> 7) & 0x7F;
15333 o.fsxButton = (d >> 14) & 0x01;
15334 return o;
15335}
15336//function parse_CellXF(blob, length, opts) {return parse_CellStyleXF(blob,length,0, opts);}
15337//function parse_StyleXF(blob, length, opts) {return parse_CellStyleXF(blob,length,1, opts);}
15338
15339/* [MS-XLS] 2.4.353 TODO: actually do this right */
15340function parse_XF(blob, length, opts) {
15341 var o = {};
15342 o.ifnt = blob.read_shift(2); o.numFmtId = blob.read_shift(2); o.flags = blob.read_shift(2);
15343 o.fStyle = (o.flags >> 2) & 0x01;
15344 length -= 6;
15345 o.data = parse_CellStyleXF(blob, length, o.fStyle, opts);
15346 return o;
15347}
15348function write_XF(data, ixfeP, opts, o) {
15349 var b5 = (opts && (opts.biff == 5));
15350 if(!o) o = new_buf(b5 ? 16 : 20);
15351 o.write_shift(2, 0);
15352 if(data.style) {
15353 o.write_shift(2, (data.numFmtId||0));
15354 o.write_shift(2, 0xFFF4);
15355 } else {
15356 o.write_shift(2, (data.numFmtId||0));
15357 o.write_shift(2, (ixfeP<<4));
15358 }
15359 o.write_shift(4, 0);
15360 o.write_shift(4, 0);
15361 if(!b5) o.write_shift(4, 0);
15362 o.write_shift(2, 0);
15363 return o;
15364}
15365
15366/* [MS-XLS] 2.4.134 */
15367function parse_Guts(blob) {
15368 blob.l += 4;
15369 var out = [blob.read_shift(2), blob.read_shift(2)];
15370 if(out[0] !== 0) out[0]--;
15371 if(out[1] !== 0) out[1]--;
15372 if(out[0] > 7 || out[1] > 7) throw new Error("Bad Gutters: " + out.join("|"));
15373 return out;
15374}
15375function write_Guts(guts) {
15376 var o = new_buf(8);
15377 o.write_shift(4, 0);
15378 o.write_shift(2, guts[0] ? guts[0] + 1 : 0);
15379 o.write_shift(2, guts[1] ? guts[1] + 1 : 0);
15380 return o;
15381}
15382
15383/* [MS-XLS] 2.4.24 */
15384function parse_BoolErr(blob, length, opts) {
15385 var cell = parse_XLSCell(blob, 6);
15386 if(opts.biff == 2) ++blob.l;
15387 var val = parse_Bes(blob, 2);
15388 cell.val = val;
15389 cell.t = (val === true || val === false) ? 'b' : 'e';
15390 return cell;
15391}
15392function write_BoolErr(R, C, v, os, opts, t) {
15393 var o = new_buf(8);
15394 write_XLSCell(R, C, os, o);
15395 write_Bes(v, t, o);
15396 return o;
15397}
15398
15399/* [MS-XLS] 2.4.180 Number */
15400function parse_Number(blob) {
15401 var cell = parse_XLSCell(blob, 6);
15402 var xnum = parse_Xnum(blob, 8);
15403 cell.val = xnum;
15404 return cell;
15405}
15406function write_Number(R, C, v, os) {
15407 var o = new_buf(14);
15408 write_XLSCell(R, C, os, o);
15409 write_Xnum(v, o);
15410 return o;
15411}
15412
15413var parse_XLHeaderFooter = parse_OptXLUnicodeString; // TODO: parse 2.4.136
15414
15415/* [MS-XLS] 2.4.271 */
15416function parse_SupBook(blob, length, opts) {
15417 var end = blob.l + length;
15418 var ctab = blob.read_shift(2);
15419 var cch = blob.read_shift(2);
15420 opts.sbcch = cch;
15421 if(cch == 0x0401 || cch == 0x3A01) return [cch, ctab];
15422 if(cch < 0x01 || cch >0xff) throw new Error("Unexpected SupBook type: "+cch);
15423 var virtPath = parse_XLUnicodeStringNoCch(blob, cch);
15424 /* TODO: 2.5.277 Virtual Path */
15425 var rgst = [];
15426 while(end > blob.l) rgst.push(parse_XLUnicodeString(blob));
15427 return [cch, ctab, virtPath, rgst];
15428}
15429
15430/* [MS-XLS] 2.4.105 TODO */
15431function parse_ExternName(blob, length, opts) {
15432 var flags = blob.read_shift(2);
15433 var body;
15434 var o = ({
15435 fBuiltIn: flags & 0x01,
15436 fWantAdvise: (flags >>> 1) & 0x01,
15437 fWantPict: (flags >>> 2) & 0x01,
15438 fOle: (flags >>> 3) & 0x01,
15439 fOleLink: (flags >>> 4) & 0x01,
15440 cf: (flags >>> 5) & 0x3FF,
15441 fIcon: flags >>> 15 & 0x01
15442 });
15443 if(opts.sbcch === 0x3A01) body = parse_AddinUdf(blob, length-2, opts);
15444 //else throw new Error("unsupported SupBook cch: " + opts.sbcch);
15445 o.body = body || blob.read_shift(length-2);
15446 if(typeof body === "string") o.Name = body;
15447 return o;
15448}
15449
15450/* [MS-XLS] 2.4.150 TODO */
15451var XLSLblBuiltIn = [
15452 "_xlnm.Consolidate_Area",
15453 "_xlnm.Auto_Open",
15454 "_xlnm.Auto_Close",
15455 "_xlnm.Extract",
15456 "_xlnm.Database",
15457 "_xlnm.Criteria",
15458 "_xlnm.Print_Area",
15459 "_xlnm.Print_Titles",
15460 "_xlnm.Recorder",
15461 "_xlnm.Data_Form",
15462 "_xlnm.Auto_Activate",
15463 "_xlnm.Auto_Deactivate",
15464 "_xlnm.Sheet_Title",
15465 "_xlnm._FilterDatabase"
15466];
15467function parse_Lbl(blob, length, opts) {
15468 var target = blob.l + length;
15469 var flags = blob.read_shift(2);
15470 var chKey = blob.read_shift(1);
15471 var cch = blob.read_shift(1);
15472 var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
15473 var itab = 0;
15474 if(!opts || opts.biff >= 5) {
15475 if(opts.biff != 5) blob.l += 2;
15476 itab = blob.read_shift(2);
15477 if(opts.biff == 5) blob.l += 2;
15478 blob.l += 4;
15479 }
15480 var name = parse_XLUnicodeStringNoCch(blob, cch, opts);
15481 if(flags & 0x20) name = XLSLblBuiltIn[name.charCodeAt(0)];
15482 var npflen = target - blob.l; if(opts && opts.biff == 2) --npflen;
15483 var rgce = target == blob.l || cce === 0 ? [] : parse_NameParsedFormula(blob, npflen, opts, cce);
15484 return {
15485 chKey: chKey,
15486 Name: name,
15487 itab: itab,
15488 rgce: rgce
15489 };
15490}
15491
15492/* [MS-XLS] 2.4.106 TODO: verify filename encoding */
15493function parse_ExternSheet(blob, length, opts) {
15494 if(opts.biff < 8) return parse_BIFF5ExternSheet(blob, length, opts);
15495 var o = [], target = blob.l + length, len = blob.read_shift(opts.biff > 8 ? 4 : 2);
15496 while(len-- !== 0) o.push(parse_XTI(blob, opts.biff > 8 ? 12 : 6, opts));
15497 // [iSupBook, itabFirst, itabLast];
15498 if(blob.l != target) throw new Error("Bad ExternSheet: " + blob.l + " != " + target);
15499 return o;
15500}
15501function parse_BIFF5ExternSheet(blob, length, opts) {
15502 if(blob[blob.l + 1] == 0x03) blob[blob.l]++;
15503 var o = parse_ShortXLUnicodeString(blob, length, opts);
15504 return o.charCodeAt(0) == 0x03 ? o.slice(1) : o;
15505}
15506
15507/* [MS-XLS] 2.4.176 TODO: check older biff */
15508function parse_NameCmt(blob, length, opts) {
15509 if(opts.biff < 8) { blob.l += length; return; }
15510 var cchName = blob.read_shift(2);
15511 var cchComment = blob.read_shift(2);
15512 var name = parse_XLUnicodeStringNoCch(blob, cchName, opts);
15513 var comment = parse_XLUnicodeStringNoCch(blob, cchComment, opts);
15514 return [name, comment];
15515}
15516
15517/* [MS-XLS] 2.4.260 */
15518function parse_ShrFmla(blob, length, opts) {
15519 var ref = parse_RefU(blob, 6);
15520 blob.l++;
15521 var cUse = blob.read_shift(1);
15522 length -= 8;
15523 return [parse_SharedParsedFormula(blob, length, opts), cUse, ref];
15524}
15525
15526/* [MS-XLS] 2.4.4 TODO */
15527function parse_Array(blob, length, opts) {
15528 var ref = parse_Ref(blob, 6);
15529 /* TODO: fAlwaysCalc */
15530 switch(opts.biff) {
15531 case 2: blob.l ++; length -= 7; break;
15532 case 3: case 4: blob.l += 2; length -= 8; break;
15533 default: blob.l += 6; length -= 12;
15534 }
15535 return [ref, parse_ArrayParsedFormula(blob, length, opts, ref)];
15536}
15537
15538/* [MS-XLS] 2.4.173 */
15539function parse_MTRSettings(blob) {
15540 var fMTREnabled = blob.read_shift(4) !== 0x00;
15541 var fUserSetThreadCount = blob.read_shift(4) !== 0x00;
15542 var cUserThreadCount = blob.read_shift(4);
15543 return [fMTREnabled, fUserSetThreadCount, cUserThreadCount];
15544}
15545
15546/* [MS-XLS] 2.5.186 TODO: BIFF5 */
15547function parse_NoteSh(blob, length, opts) {
15548 if(opts.biff < 8) return;
15549 var row = blob.read_shift(2), col = blob.read_shift(2);
15550 var flags = blob.read_shift(2), idObj = blob.read_shift(2);
15551 var stAuthor = parse_XLUnicodeString2(blob, 0, opts);
15552 if(opts.biff < 8) blob.read_shift(1);
15553 return [{r:row,c:col}, stAuthor, idObj, flags];
15554}
15555
15556/* [MS-XLS] 2.4.179 */
15557function parse_Note(blob, length, opts) {
15558 /* TODO: Support revisions */
15559 return parse_NoteSh(blob, length, opts);
15560}
15561
15562/* [MS-XLS] 2.4.168 */
15563function parse_MergeCells(blob, length) {
15564 var merges = [];
15565 var cmcs = blob.read_shift(2);
15566 while (cmcs--) merges.push(parse_Ref8U(blob,length));
15567 return merges;
15568}
15569function write_MergeCells(merges) {
15570 var o = new_buf(2 + merges.length * 8);
15571 o.write_shift(2, merges.length);
15572 for(var i = 0; i < merges.length; ++i) write_Ref8U(merges[i], o);
15573 return o;
15574}
15575
15576/* [MS-XLS] 2.4.181 TODO: parse all the things! */
15577function parse_Obj(blob, length, opts) {
15578 if(opts && opts.biff < 8) return parse_BIFF5Obj(blob, length, opts);
15579 var cmo = parse_FtCmo(blob, 22); // id, ot, flags
15580 var fts = parse_FtArray(blob, length-22, cmo[1]);
15581 return { cmo: cmo, ft:fts };
15582}
15583/* from older spec */
15584var parse_BIFF5OT = [];
15585parse_BIFF5OT[0x08] = function(blob, length) {
15586 var tgt = blob.l + length;
15587 blob.l += 10; // todo
15588 var cf = blob.read_shift(2);
15589 blob.l += 4;
15590 blob.l += 2; //var cbPictFmla = blob.read_shift(2);
15591 blob.l += 2;
15592 blob.l += 2; //var grbit = blob.read_shift(2);
15593 blob.l += 4;
15594 var cchName = blob.read_shift(1);
15595 blob.l += cchName; // TODO: stName
15596 blob.l = tgt; // TODO: fmla
15597 return { fmt:cf };
15598};
15599
15600function parse_BIFF5Obj(blob, length, opts) {
15601 blob.l += 4; //var cnt = blob.read_shift(4);
15602 var ot = blob.read_shift(2);
15603 var id = blob.read_shift(2);
15604 var grbit = blob.read_shift(2);
15605 blob.l += 2; //var colL = blob.read_shift(2);
15606 blob.l += 2; //var dxL = blob.read_shift(2);
15607 blob.l += 2; //var rwT = blob.read_shift(2);
15608 blob.l += 2; //var dyT = blob.read_shift(2);
15609 blob.l += 2; //var colR = blob.read_shift(2);
15610 blob.l += 2; //var dxR = blob.read_shift(2);
15611 blob.l += 2; //var rwB = blob.read_shift(2);
15612 blob.l += 2; //var dyB = blob.read_shift(2);
15613 blob.l += 2; //var cbMacro = blob.read_shift(2);
15614 blob.l += 6;
15615 length -= 36;
15616 var fts = [];
15617 fts.push((parse_BIFF5OT[ot]||parsenoop)(blob, length, opts));
15618 return { cmo: [id, ot, grbit], ft:fts };
15619}
15620
15621/* [MS-XLS] 2.4.329 TODO: parse properly */
15622function parse_TxO(blob, length, opts) {
15623 var s = blob.l;
15624 var texts = "";
15625try {
15626 blob.l += 4;
15627 var ot = (opts.lastobj||{cmo:[0,0]}).cmo[1];
15628 var controlInfo; // eslint-disable-line no-unused-vars
15629 if([0,5,7,11,12,14].indexOf(ot) == -1) blob.l += 6;
15630 else controlInfo = parse_ControlInfo(blob, 6, opts);
15631 var cchText = blob.read_shift(2);
15632 /*var cbRuns = */blob.read_shift(2);
15633 /*var ifntEmpty = */parseuint16(blob, 2);
15634 var len = blob.read_shift(2);
15635 blob.l += len;
15636 //var fmla = parse_ObjFmla(blob, s + length - blob.l);
15637
15638 for(var i = 1; i < blob.lens.length-1; ++i) {
15639 if(blob.l-s != blob.lens[i]) throw new Error("TxO: bad continue record");
15640 var hdr = blob[blob.l];
15641 var t = parse_XLUnicodeStringNoCch(blob, blob.lens[i+1]-blob.lens[i]-1);
15642 texts += t;
15643 if(texts.length >= (hdr ? cchText : 2*cchText)) break;
15644 }
15645 if(texts.length !== cchText && texts.length !== cchText*2) {
15646 throw new Error("cchText: " + cchText + " != " + texts.length);
15647 }
15648
15649 blob.l = s + length;
15650 /* [MS-XLS] 2.5.272 TxORuns */
15651// var rgTxoRuns = [];
15652// for(var j = 0; j != cbRuns/8-1; ++j) blob.l += 8;
15653// var cchText2 = blob.read_shift(2);
15654// if(cchText2 !== cchText) throw new Error("TxOLastRun mismatch: " + cchText2 + " " + cchText);
15655// blob.l += 6;
15656// if(s + length != blob.l) throw new Error("TxO " + (s + length) + ", at " + blob.l);
15657 return { t: texts };
15658} catch(e) { blob.l = s + length; return { t: texts }; }
15659}
15660
15661/* [MS-XLS] 2.4.140 */
15662function parse_HLink(blob, length) {
15663 var ref = parse_Ref8U(blob, 8);
15664 blob.l += 16; /* CLSID */
15665 var hlink = parse_Hyperlink(blob, length-24);
15666 return [ref, hlink];
15667}
15668function write_HLink(hl) {
15669 var O = new_buf(24);
15670 var ref = decode_cell(hl[0]);
15671 O.write_shift(2, ref.r); O.write_shift(2, ref.r);
15672 O.write_shift(2, ref.c); O.write_shift(2, ref.c);
15673 var clsid = "d0 c9 ea 79 f9 ba ce 11 8c 82 00 aa 00 4b a9 0b".split(" ");
15674 for(var i = 0; i < 16; ++i) O.write_shift(1, parseInt(clsid[i], 16));
15675 return bconcat([O, write_Hyperlink(hl[1])]);
15676}
15677
15678
15679/* [MS-XLS] 2.4.141 */
15680function parse_HLinkTooltip(blob, length) {
15681 blob.read_shift(2);
15682 var ref = parse_Ref8U(blob, 8);
15683 var wzTooltip = blob.read_shift((length-10)/2, 'dbcs-cont');
15684 wzTooltip = wzTooltip.replace(chr0,"");
15685 return [ref, wzTooltip];
15686}
15687function write_HLinkTooltip(hl) {
15688 var TT = hl[1].Tooltip;
15689 var O = new_buf(10 + 2 * (TT.length + 1));
15690 O.write_shift(2, 0x0800);
15691 var ref = decode_cell(hl[0]);
15692 O.write_shift(2, ref.r); O.write_shift(2, ref.r);
15693 O.write_shift(2, ref.c); O.write_shift(2, ref.c);
15694 for(var i = 0; i < TT.length; ++i) O.write_shift(2, TT.charCodeAt(i));
15695 O.write_shift(2, 0);
15696 return O;
15697}
15698
15699/* [MS-XLS] 2.4.63 */
15700function parse_Country(blob) {
15701 var o = [0,0], d;
15702 d = blob.read_shift(2); o[0] = CountryEnum[d] || d;
15703 d = blob.read_shift(2); o[1] = CountryEnum[d] || d;
15704 return o;
15705}
15706function write_Country(o) {
15707 if(!o) o = new_buf(4);
15708 o.write_shift(2, 0x01);
15709 o.write_shift(2, 0x01);
15710 return o;
15711}
15712
15713/* [MS-XLS] 2.4.50 ClrtClient */
15714function parse_ClrtClient(blob) {
15715 var ccv = blob.read_shift(2);
15716 var o = [];
15717 while(ccv-->0) o.push(parse_LongRGB(blob, 8));
15718 return o;
15719}
15720
15721/* [MS-XLS] 2.4.188 */
15722function parse_Palette(blob) {
15723 var ccv = blob.read_shift(2);
15724 var o = [];
15725 while(ccv-->0) o.push(parse_LongRGB(blob, 8));
15726 return o;
15727}
15728
15729/* [MS-XLS] 2.4.354 */
15730function parse_XFCRC(blob) {
15731 blob.l += 2;
15732 var o = {cxfs:0, crc:0};
15733 o.cxfs = blob.read_shift(2);
15734 o.crc = blob.read_shift(4);
15735 return o;
15736}
15737
15738/* [MS-XLS] 2.4.53 TODO: parse flags */
15739/* [MS-XLSB] 2.4.323 TODO: parse flags */
15740function parse_ColInfo(blob, length, opts) {
15741 if(!opts.cellStyles) return parsenoop(blob, length);
15742 var w = opts && opts.biff >= 12 ? 4 : 2;
15743 var colFirst = blob.read_shift(w);
15744 var colLast = blob.read_shift(w);
15745 var coldx = blob.read_shift(w);
15746 var ixfe = blob.read_shift(w);
15747 var flags = blob.read_shift(2);
15748 if(w == 2) blob.l += 2;
15749 var o = ({s:colFirst, e:colLast, w:coldx, ixfe:ixfe, flags:flags});
15750 if(opts.biff >= 5 || !opts.biff) o.level = (flags >> 8) & 0x7;
15751 return o;
15752}
15753
15754/* [MS-XLS] 2.4.257 */
15755function parse_Setup(blob, length) {
15756 var o = {};
15757 if(length < 32) return o;
15758 blob.l += 16;
15759 o.header = parse_Xnum(blob, 8);
15760 o.footer = parse_Xnum(blob, 8);
15761 blob.l += 2;
15762 return o;
15763}
15764
15765/* [MS-XLS] 2.4.261 */
15766function parse_ShtProps(blob, length, opts) {
15767 var def = {area:false};
15768 if(opts.biff != 5) { blob.l += length; return def; }
15769 var d = blob.read_shift(1); blob.l += 3;
15770 if((d & 0x10)) def.area = true;
15771 return def;
15772}
15773
15774/* [MS-XLS] 2.4.241 */
15775function write_RRTabId(n) {
15776 var out = new_buf(2 * n);
15777 for(var i = 0; i < n; ++i) out.write_shift(2, i+1);
15778 return out;
15779}
15780
15781var parse_Blank = parse_XLSCell; /* [MS-XLS] 2.4.20 Just the cell */
15782var parse_Scl = parseuint16a; /* [MS-XLS] 2.4.247 num, den */
15783var parse_String = parse_XLUnicodeString; /* [MS-XLS] 2.4.268 */
15784
15785/* --- Specific to versions before BIFF8 --- */
15786function parse_ImData(blob) {
15787 var cf = blob.read_shift(2);
15788 var env = blob.read_shift(2);
15789 var lcb = blob.read_shift(4);
15790 var o = {fmt:cf, env:env, len:lcb, data:blob.slice(blob.l,blob.l+lcb)};
15791 blob.l += lcb;
15792 return o;
15793}
15794
15795/* BIFF2_??? where ??? is the name from [XLS] */
15796function parse_BIFF2STR(blob, length, opts) {
15797 var cell = parse_XLSCell(blob, 6);
15798 ++blob.l;
15799 var str = parse_XLUnicodeString2(blob, length-7, opts);
15800 cell.t = 'str';
15801 cell.val = str;
15802 return cell;
15803}
15804
15805function parse_BIFF2NUM(blob) {
15806 var cell = parse_XLSCell(blob, 6);
15807 ++blob.l;
15808 var num = parse_Xnum(blob, 8);
15809 cell.t = 'n';
15810 cell.val = num;
15811 return cell;
15812}
15813function write_BIFF2NUM(r, c, val) {
15814 var out = new_buf(15);
15815 write_BIFF2Cell(out, r, c);
15816 out.write_shift(8, val, 'f');
15817 return out;
15818}
15819
15820function parse_BIFF2INT(blob) {
15821 var cell = parse_XLSCell(blob, 6);
15822 ++blob.l;
15823 var num = blob.read_shift(2);
15824 cell.t = 'n';
15825 cell.val = num;
15826 return cell;
15827}
15828function write_BIFF2INT(r, c, val) {
15829 var out = new_buf(9);
15830 write_BIFF2Cell(out, r, c);
15831 out.write_shift(2, val);
15832 return out;
15833}
15834
15835function parse_BIFF2STRING(blob) {
15836 var cch = blob.read_shift(1);
15837 if(cch === 0) { blob.l++; return ""; }
15838 return blob.read_shift(cch, 'sbcs-cont');
15839}
15840
15841/* TODO: convert to BIFF8 font struct */
15842function parse_BIFF2FONTXTRA(blob, length) {
15843 blob.l += 6; // unknown
15844 blob.l += 2; // font weight "bls"
15845 blob.l += 1; // charset
15846 blob.l += 3; // unknown
15847 blob.l += 1; // font family
15848 blob.l += length - 13;
15849}
15850
15851/* TODO: parse rich text runs */
15852function parse_RString(blob, length, opts) {
15853 var end = blob.l + length;
15854 var cell = parse_XLSCell(blob, 6);
15855 var cch = blob.read_shift(2);
15856 var str = parse_XLUnicodeStringNoCch(blob, cch, opts);
15857 blob.l = end;
15858 cell.t = 'str';
15859 cell.val = str;
15860 return cell;
15861}
15862/* from js-harb (C) 2014-present SheetJS */
15863var DBF = (function() {
15864var dbf_codepage_map = {
15865 /* Code Pages Supported by Visual FoxPro */
158660x01: 437, 0x02: 850,
158670x03: 1252, 0x04: 10000,
158680x64: 852, 0x65: 866,
158690x66: 865, 0x67: 861,
158700x68: 895, 0x69: 620,
158710x6A: 737, 0x6B: 857,
158720x78: 950, 0x79: 949,
158730x7A: 936, 0x7B: 932,
158740x7C: 874, 0x7D: 1255,
158750x7E: 1256, 0x96: 10007,
158760x97: 10029, 0x98: 10006,
158770xC8: 1250, 0xC9: 1251,
158780xCA: 1254, 0xCB: 1253,
15879
15880 /* shapefile DBF extension */
158810x00: 20127, 0x08: 865,
158820x09: 437, 0x0A: 850,
158830x0B: 437, 0x0D: 437,
158840x0E: 850, 0x0F: 437,
158850x10: 850, 0x11: 437,
158860x12: 850, 0x13: 932,
158870x14: 850, 0x15: 437,
158880x16: 850, 0x17: 865,
158890x18: 437, 0x19: 437,
158900x1A: 850, 0x1B: 437,
158910x1C: 863, 0x1D: 850,
158920x1F: 852, 0x22: 852,
158930x23: 852, 0x24: 860,
158940x25: 850, 0x26: 866,
158950x37: 850, 0x40: 852,
158960x4D: 936, 0x4E: 949,
158970x4F: 950, 0x50: 874,
158980x57: 1252, 0x58: 1252,
158990x59: 1252,
15900
159010xFF: 16969
15902};
15903var dbf_reverse_map = evert({
159040x01: 437, 0x02: 850,
159050x03: 1252, 0x04: 10000,
159060x64: 852, 0x65: 866,
159070x66: 865, 0x67: 861,
159080x68: 895, 0x69: 620,
159090x6A: 737, 0x6B: 857,
159100x78: 950, 0x79: 949,
159110x7A: 936, 0x7B: 932,
159120x7C: 874, 0x7D: 1255,
159130x7E: 1256, 0x96: 10007,
159140x97: 10029, 0x98: 10006,
159150xC8: 1250, 0xC9: 1251,
159160xCA: 1254, 0xCB: 1253,
159170x00: 20127
15918});
15919/* TODO: find an actual specification */
15920function dbf_to_aoa(buf, opts) {
15921 var out = [];
15922 /* TODO: browser based */
15923 var d = (new_raw_buf(1));
15924 switch(opts.type) {
15925 case 'base64': d = s2a(Base64.decode(buf)); break;
15926 case 'binary': d = s2a(buf); break;
15927 case 'buffer':
15928 case 'array': d = buf; break;
15929 }
15930 prep_blob(d, 0);
15931 /* header */
15932 var ft = d.read_shift(1);
15933 var memo = false;
15934 var vfp = false, l7 = false;
15935 switch(ft) {
15936 case 0x02: case 0x03: break;
15937 case 0x30: vfp = true; memo = true; break;
15938 case 0x31: vfp = true; break;
15939 case 0x83: memo = true; break;
15940 case 0x8B: memo = true; break;
15941 case 0x8C: memo = true; l7 = true; break;
15942 case 0xF5: memo = true; break;
15943 default: throw new Error("DBF Unsupported Version: " + ft.toString(16));
15944 }
15945 var /*filedate = new Date(),*/ nrow = 0, fpos = 0;
15946 if(ft == 0x02) nrow = d.read_shift(2);
15947 /*filedate = new Date(d.read_shift(1) + 1900, d.read_shift(1) - 1, d.read_shift(1));*/d.l += 3;
15948 if(ft != 0x02) nrow = d.read_shift(4);
15949 if(ft != 0x02) fpos = d.read_shift(2);
15950 var rlen = d.read_shift(2);
15951
15952 var /*flags = 0,*/ current_cp = 1252;
15953 if(ft != 0x02) {
15954 d.l+=16;
15955 /*flags = */d.read_shift(1);
15956 //if(memo && ((flags & 0x02) === 0)) throw new Error("DBF Flags " + flags.toString(16) + " ft " + ft.toString(16));
15957
15958 /* codepage present in FoxPro */
15959 if(d[d.l] !== 0) current_cp = dbf_codepage_map[d[d.l]];
15960 d.l+=1;
15961
15962 d.l+=2;
15963 }
15964 if(l7) d.l += 36;
15965var fields = [], field = ({});
15966 var hend = fpos - 10 - (vfp ? 264 : 0), ww = l7 ? 32 : 11;
15967 while(ft == 0x02 ? d.l < d.length && d[d.l] != 0x0d: d.l < hend) {
15968 field = ({});
15969 field.name = cptable.utils.decode(current_cp, d.slice(d.l, d.l+ww)).replace(/[\u0000\r\n].*$/g,"");
15970 d.l += ww;
15971 field.type = String.fromCharCode(d.read_shift(1));
15972 if(ft != 0x02 && !l7) field.offset = d.read_shift(4);
15973 field.len = d.read_shift(1);
15974 if(ft == 0x02) field.offset = d.read_shift(2);
15975 field.dec = d.read_shift(1);
15976 if(field.name.length) fields.push(field);
15977 if(ft != 0x02) d.l += l7 ? 13 : 14;
15978 switch(field.type) {
15979 case 'B': // VFP Double
15980 if((!vfp || field.len != 8) && opts.WTF) console.log('Skipping ' + field.name + ':' + field.type);
15981 break;
15982 case 'G': // General
15983 case 'P': // Picture
15984 if(opts.WTF) console.log('Skipping ' + field.name + ':' + field.type);
15985 break;
15986 case 'C': // character
15987 case 'D': // date
15988 case 'F': // floating point
15989 case 'I': // long
15990 case 'L': // boolean
15991 case 'M': // memo
15992 case 'N': // number
15993 case 'O': // double
15994 case 'T': // datetime
15995 case 'Y': // currency
15996 case '0': // VFP _NullFlags
15997 case '@': // timestamp
15998 case '+': // autoincrement
15999 break;
16000 default: throw new Error('Unknown Field Type: ' + field.type);
16001 }
16002 }
16003 if(d[d.l] !== 0x0D) d.l = fpos-1;
16004 else if(ft == 0x02) d.l = 0x209;
16005 if(ft != 0x02) {
16006 if(d.read_shift(1) !== 0x0D) throw new Error("DBF Terminator not found " + d.l + " " + d[d.l]);
16007 d.l = fpos;
16008 }
16009 /* data */
16010 var R = 0, C = 0;
16011 out[0] = [];
16012 for(C = 0; C != fields.length; ++C) out[0][C] = fields[C].name;
16013 while(nrow-- > 0) {
16014 if(d[d.l] === 0x2A) { d.l+=rlen; continue; }
16015 ++d.l;
16016 out[++R] = []; C = 0;
16017 for(C = 0; C != fields.length; ++C) {
16018 var dd = d.slice(d.l, d.l+fields[C].len); d.l+=fields[C].len;
16019 prep_blob(dd, 0);
16020 var s = cptable.utils.decode(current_cp, dd);
16021 switch(fields[C].type) {
16022 case 'C':
16023 out[R][C] = cptable.utils.decode(current_cp, dd);
16024 out[R][C] = out[R][C].trim();
16025 break;
16026 case 'D':
16027 if(s.length === 8) out[R][C] = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8));
16028 else out[R][C] = s;
16029 break;
16030 case 'F': out[R][C] = parseFloat(s.trim()); break;
16031 case '+': case 'I': out[R][C] = l7 ? dd.read_shift(-4, 'i') ^ 0x80000000 : dd.read_shift(4, 'i'); break;
16032 case 'L': switch(s.toUpperCase()) {
16033 case 'Y': case 'T': out[R][C] = true; break;
16034 case 'N': case 'F': out[R][C] = false; break;
16035 case ' ': case '?': out[R][C] = false; break; /* NOTE: technically uninitialized */
16036 default: throw new Error("DBF Unrecognized L:|" + s + "|");
16037 } break;
16038 case 'M': /* TODO: handle memo files */
16039 if(!memo) throw new Error("DBF Unexpected MEMO for type " + ft.toString(16));
16040 out[R][C] = "##MEMO##" + (l7 ? parseInt(s.trim(), 10): dd.read_shift(4));
16041 break;
16042 case 'N': out[R][C] = +s.replace(/\u0000/g,"").trim(); break;
16043 case '@': out[R][C] = new Date(dd.read_shift(-8, 'f') - 0x388317533400); break;
16044 case 'T': out[R][C] = new Date((dd.read_shift(4) - 0x253D8C) * 0x5265C00 + dd.read_shift(4)); break;
16045 case 'Y': out[R][C] = dd.read_shift(4,'i')/1e4; break;
16046 case 'O': out[R][C] = -dd.read_shift(-8, 'f'); break;
16047 case 'B': if(vfp && fields[C].len == 8) { out[R][C] = dd.read_shift(8,'f'); break; }
16048 /* falls through */
16049 case 'G': case 'P': dd.l += fields[C].len; break;
16050 case '0':
16051 if(fields[C].name === '_NullFlags') break;
16052 /* falls through */
16053 default: throw new Error("DBF Unsupported data type " + fields[C].type);
16054 }
16055 }
16056 }
16057 if(ft != 0x02) if(d.l < d.length && d[d.l++] != 0x1A) throw new Error("DBF EOF Marker missing " + (d.l-1) + " of " + d.length + " " + d[d.l-1].toString(16));
16058 if(opts && opts.sheetRows) out = out.slice(0, opts.sheetRows);
16059 return out;
16060}
16061
16062function dbf_to_sheet(buf, opts) {
16063 var o = opts || {};
16064 if(!o.dateNF) o.dateNF = "yyyymmdd";
16065 return aoa_to_sheet(dbf_to_aoa(buf, o), o);
16066}
16067
16068function dbf_to_workbook(buf, opts) {
16069 try { return sheet_to_workbook(dbf_to_sheet(buf, opts), opts); }
16070 catch(e) { if(opts && opts.WTF) throw e; }
16071 return ({SheetNames:[],Sheets:{}});
16072}
16073
16074var _RLEN = { 'B': 8, 'C': 250, 'L': 1, 'D': 8, '?': 0, '': 0 };
16075function sheet_to_dbf(ws, opts) {
16076 var o = opts || {};
16077 if(+o.codepage >= 0) set_cp(+o.codepage);
16078 if(o.type == "string") throw new Error("Cannot write DBF to JS string");
16079 var ba = buf_array();
16080 var aoa = sheet_to_json(ws, {header:1, raw:true, cellDates:true});
16081 var headers = aoa[0], data = aoa.slice(1);
16082 var i = 0, j = 0, hcnt = 0, rlen = 1;
16083 for(i = 0; i < headers.length; ++i) {
16084 if(i == null) continue;
16085 ++hcnt;
16086 if(typeof headers[i] === 'number') headers[i] = headers[i].toString(10);
16087 if(typeof headers[i] !== 'string') throw new Error("DBF Invalid column name " + headers[i] + " |" + (typeof headers[i]) + "|");
16088 if(headers.indexOf(headers[i]) !== i) for(j=0; j<1024;++j)
16089 if(headers.indexOf(headers[i] + "_" + j) == -1) { headers[i] += "_" + j; break; }
16090 }
16091 var range = safe_decode_range(ws['!ref']);
16092 var coltypes = [];
16093 for(i = 0; i <= range.e.c - range.s.c; ++i) {
16094 var col = [];
16095 for(j=0; j < data.length; ++j) {
16096 if(data[j][i] != null) col.push(data[j][i]);
16097 }
16098 if(col.length == 0 || headers[i] == null) { coltypes[i] = '?'; continue; }
16099 var guess = '', _guess = '';
16100 for(j = 0; j < col.length; ++j) {
16101 switch(typeof col[j]) {
16102 /* TODO: check if L2 compat is desired */
16103 case 'number': _guess = 'B'; break;
16104 case 'string': _guess = 'C'; break;
16105 case 'boolean': _guess = 'L'; break;
16106 case 'object': _guess = col[j] instanceof Date ? 'D' : 'C'; break;
16107 default: _guess = 'C';
16108 }
16109 guess = guess && guess != _guess ? 'C' : _guess;
16110 if(guess == 'C') break;
16111 }
16112 rlen += _RLEN[guess] || 0;
16113 coltypes[i] = guess;
16114 }
16115
16116 var h = ba.next(32);
16117 h.write_shift(4, 0x13021130);
16118 h.write_shift(4, data.length);
16119 h.write_shift(2, 296 + 32 * hcnt);
16120 h.write_shift(2, rlen);
16121 for(i=0; i < 4; ++i) h.write_shift(4, 0);
16122 h.write_shift(4, 0x00000000 | ((+dbf_reverse_map[current_ansi] || 0x03)<<8));
16123
16124 for(i = 0, j = 0; i < headers.length; ++i) {
16125 if(headers[i] == null) continue;
16126 var hf = ba.next(32);
16127 var _f = (headers[i].slice(-10) + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00").slice(0, 11);
16128 hf.write_shift(1, _f, "sbcs");
16129 hf.write_shift(1, coltypes[i] == '?' ? 'C' : coltypes[i], "sbcs");
16130 hf.write_shift(4, j);
16131 hf.write_shift(1, _RLEN[coltypes[i]] || 0);
16132 hf.write_shift(1, 0);
16133 hf.write_shift(1, 0x02);
16134 hf.write_shift(4, 0);
16135 hf.write_shift(1, 0);
16136 hf.write_shift(4, 0);
16137 hf.write_shift(4, 0);
16138 j += _RLEN[coltypes[i]] || 0;
16139 }
16140
16141 var hb = ba.next(264);
16142 hb.write_shift(4, 0x0000000D);
16143 for(i=0; i < 65;++i) hb.write_shift(4, 0x00000000);
16144 for(i=0; i < data.length; ++i) {
16145 var rout = ba.next(rlen);
16146 rout.write_shift(1, 0);
16147 for(j=0; j<headers.length; ++j) {
16148 if(headers[j] == null) continue;
16149 switch(coltypes[j]) {
16150 case 'L': rout.write_shift(1, data[i][j] == null ? 0x3F : data[i][j] ? 0x54 : 0x46); break;
16151 case 'B': rout.write_shift(8, data[i][j]||0, 'f'); break;
16152 case 'D':
16153 if(!data[i][j]) rout.write_shift(8, "00000000", "sbcs");
16154 else {
16155 rout.write_shift(4, ("0000"+data[i][j].getFullYear()).slice(-4), "sbcs");
16156 rout.write_shift(2, ("00"+(data[i][j].getMonth()+1)).slice(-2), "sbcs");
16157 rout.write_shift(2, ("00"+data[i][j].getDate()).slice(-2), "sbcs");
16158 } break;
16159 case 'C':
16160 var _s = String(data[i][j]||"");
16161 rout.write_shift(1, _s, "sbcs");
16162 for(hcnt=0; hcnt < 250-_s.length; ++hcnt) rout.write_shift(1, 0x20); break;
16163 }
16164 }
16165 // data
16166 }
16167 ba.next(1).write_shift(1, 0x1A);
16168 return ba.end();
16169}
16170 return {
16171 to_workbook: dbf_to_workbook,
16172 to_sheet: dbf_to_sheet,
16173 from_sheet: sheet_to_dbf
16174 };
16175})();
16176
16177var SYLK = (function() {
16178 /* TODO: stress test sequences */
16179 var sylk_escapes = ({
16180 AA:'À', BA:'Á', CA:'Â', DA:195, HA:'Ä', JA:197,
16181 AE:'È', BE:'É', CE:'Ê', HE:'Ë',
16182 AI:'Ì', BI:'Í', CI:'Î', HI:'Ï',
16183 AO:'Ò', BO:'Ó', CO:'Ô', DO:213, HO:'Ö',
16184 AU:'Ù', BU:'Ú', CU:'Û', HU:'Ü',
16185 Aa:'à', Ba:'á', Ca:'â', Da:227, Ha:'ä', Ja:229,
16186 Ae:'è', Be:'é', Ce:'ê', He:'ë',
16187 Ai:'ì', Bi:'í', Ci:'î', Hi:'ï',
16188 Ao:'ò', Bo:'ó', Co:'ô', Do:245, Ho:'ö',
16189 Au:'ù', Bu:'ú', Cu:'û', Hu:'ü',
16190 KC:'Ç', Kc:'ç', q:'æ', z:'œ', a:'Æ', j:'Œ',
16191 DN:209, Dn:241, Hy:255,
16192 S:169, c:170, R:174, B:180,
161930:176, 1:177, 2:178,
161943:179, 5:181, 6:182,
161957:183, Q:185, k:186, b:208, i:216, l:222, s:240, y:248,
16196 "!":161, '"':162, "#":163, "(":164, "%":165, "'":167, "H ":168,
16197 "+":171, ";":187, "<":188, "=":189, ">":190, "?":191, "{":223
16198 });
16199 var sylk_char_regex = new RegExp("\u001BN(" + keys(sylk_escapes).join("|").replace(/\|\|\|/, "|\\||").replace(/([?()+])/g,"\\$1") + "|\\|)", "gm");
16200 var sylk_char_fn = function(_, $1){ var o = sylk_escapes[$1]; return typeof o == "number" ? _getansi(o) : o; };
16201 var decode_sylk_char = function($$, $1, $2) { var newcc = (($1.charCodeAt(0) - 0x20)<<4) | ($2.charCodeAt(0) - 0x30); return newcc == 59 ? $$ : _getansi(newcc); };
16202 sylk_escapes["|"] = 254;
16203 /* TODO: find an actual specification */
16204 function sylk_to_aoa(d, opts) {
16205 switch(opts.type) {
16206 case 'base64': return sylk_to_aoa_str(Base64.decode(d), opts);
16207 case 'binary': return sylk_to_aoa_str(d, opts);
16208 case 'buffer': return sylk_to_aoa_str(d.toString('binary'), opts);
16209 case 'array': return sylk_to_aoa_str(cc2str(d), opts);
16210 }
16211 throw new Error("Unrecognized type " + opts.type);
16212 }
16213 function sylk_to_aoa_str(str, opts) {
16214 var records = str.split(/[\n\r]+/), R = -1, C = -1, ri = 0, rj = 0, arr = [];
16215 var formats = [];
16216 var next_cell_format = null;
16217 var sht = {}, rowinfo = [], colinfo = [], cw = [];
16218 var Mval = 0, j;
16219 if(+opts.codepage >= 0) set_cp(+opts.codepage);
16220 for (; ri !== records.length; ++ri) {
16221 Mval = 0;
16222 var rstr=records[ri].trim().replace(/\x1B([\x20-\x2F])([\x30-\x3F])/g, decode_sylk_char).replace(sylk_char_regex, sylk_char_fn);
16223 var record=rstr.replace(/;;/g, "\u0000").split(";").map(function(x) { return x.replace(/\u0000/g, ";"); });
16224 var RT=record[0], val;
16225 if(rstr.length > 0) switch(RT) {
16226 case 'ID': break; /* header */
16227 case 'E': break; /* EOF */
16228 case 'B': break; /* dimensions */
16229 case 'O': break; /* options? */
16230 case 'P':
16231 if(record[1].charAt(0) == 'P')
16232 formats.push(rstr.slice(3).replace(/;;/g, ";"));
16233 break;
16234 case 'C':
16235 var C_seen_K = false, C_seen_X = false;
16236 for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
16237 case 'X': C = parseInt(record[rj].slice(1))-1; C_seen_X = true; break;
16238 case 'Y':
16239 R = parseInt(record[rj].slice(1))-1; if(!C_seen_X) C = 0;
16240 for(j = arr.length; j <= R; ++j) arr[j] = [];
16241 break;
16242 case 'K':
16243 val = record[rj].slice(1);
16244 if(val.charAt(0) === '"') val = val.slice(1,val.length - 1);
16245 else if(val === 'TRUE') val = true;
16246 else if(val === 'FALSE') val = false;
16247 else if(!isNaN(fuzzynum(val))) {
16248 val = fuzzynum(val);
16249 if(next_cell_format !== null && SSF.is_date(next_cell_format)) val = numdate(val);
16250 } else if(!isNaN(fuzzydate(val).getDate())) {
16251 val = parseDate(val);
16252 }
16253 if(typeof cptable !== 'undefined' && typeof val == "string" && ((opts||{}).type != "string") && (opts||{}).codepage) val = cptable.utils.decode(opts.codepage, val);
16254 C_seen_K = true;
16255 break;
16256 case 'E':
16257 var formula = rc_to_a1(record[rj].slice(1), {r:R,c:C});
16258 arr[R][C] = [arr[R][C], formula];
16259 break;
16260 default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
16261 }
16262 if(C_seen_K) { arr[R][C] = val; next_cell_format = null; }
16263 break;
16264 case 'F':
16265 var F_seen = 0;
16266 for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
16267 case 'X': C = parseInt(record[rj].slice(1))-1; ++F_seen; break;
16268 case 'Y':
16269 R = parseInt(record[rj].slice(1))-1; /*C = 0;*/
16270 for(j = arr.length; j <= R; ++j) arr[j] = [];
16271 break;
16272 case 'M': Mval = parseInt(record[rj].slice(1)) / 20; break;
16273 case 'F': break; /* ??? */
16274 case 'G': break; /* hide grid */
16275 case 'P':
16276 next_cell_format = formats[parseInt(record[rj].slice(1))];
16277 break;
16278 case 'S': break; /* cell style */
16279 case 'D': break; /* column */
16280 case 'N': break; /* font */
16281 case 'W':
16282 cw = record[rj].slice(1).split(" ");
16283 for(j = parseInt(cw[0], 10); j <= parseInt(cw[1], 10); ++j) {
16284 Mval = parseInt(cw[2], 10);
16285 colinfo[j-1] = Mval === 0 ? {hidden:true}: {wch:Mval}; process_col(colinfo[j-1]);
16286 } break;
16287 case 'C': /* default column format */
16288 C = parseInt(record[rj].slice(1))-1;
16289 if(!colinfo[C]) colinfo[C] = {};
16290 break;
16291 case 'R': /* row properties */
16292 R = parseInt(record[rj].slice(1))-1;
16293 if(!rowinfo[R]) rowinfo[R] = {};
16294 if(Mval > 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); }
16295 else if(Mval === 0) rowinfo[R].hidden = true;
16296 break;
16297 default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
16298 }
16299 if(F_seen < 1) next_cell_format = null; break;
16300 default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr);
16301 }
16302 }
16303 if(rowinfo.length > 0) sht['!rows'] = rowinfo;
16304 if(colinfo.length > 0) sht['!cols'] = colinfo;
16305 if(opts && opts.sheetRows) arr = arr.slice(0, opts.sheetRows);
16306 return [arr, sht];
16307 }
16308
16309 function sylk_to_sheet(d, opts) {
16310 var aoasht = sylk_to_aoa(d, opts);
16311 var aoa = aoasht[0], ws = aoasht[1];
16312 var o = aoa_to_sheet(aoa, opts);
16313 keys(ws).forEach(function(k) { o[k] = ws[k]; });
16314 return o;
16315 }
16316
16317 function sylk_to_workbook(d, opts) { return sheet_to_workbook(sylk_to_sheet(d, opts), opts); }
16318
16319 function write_ws_cell_sylk(cell, ws, R, C) {
16320 var o = "C;Y" + (R+1) + ";X" + (C+1) + ";K";
16321 switch(cell.t) {
16322 case 'n':
16323 o += (cell.v||0);
16324 if(cell.f && !cell.F) o += ";E" + a1_to_rc(cell.f, {r:R, c:C}); break;
16325 case 'b': o += cell.v ? "TRUE" : "FALSE"; break;
16326 case 'e': o += cell.w || cell.v; break;
16327 case 'd': o += '"' + (cell.w || cell.v) + '"'; break;
16328 case 's': o += '"' + cell.v.replace(/"/g,"") + '"'; break;
16329 }
16330 return o;
16331 }
16332
16333 function write_ws_cols_sylk(out, cols) {
16334 cols.forEach(function(col, i) {
16335 var rec = "F;W" + (i+1) + " " + (i+1) + " ";
16336 if(col.hidden) rec += "0";
16337 else {
16338 if(typeof col.width == 'number') col.wpx = width2px(col.width);
16339 if(typeof col.wpx == 'number') col.wch = px2char(col.wpx);
16340 if(typeof col.wch == 'number') rec += Math.round(col.wch);
16341 }
16342 if(rec.charAt(rec.length - 1) != " ") out.push(rec);
16343 });
16344 }
16345
16346 function write_ws_rows_sylk(out, rows) {
16347 rows.forEach(function(row, i) {
16348 var rec = "F;";
16349 if(row.hidden) rec += "M0;";
16350 else if(row.hpt) rec += "M" + 20 * row.hpt + ";";
16351 else if(row.hpx) rec += "M" + 20 * px2pt(row.hpx) + ";";
16352 if(rec.length > 2) out.push(rec + "R" + (i+1));
16353 });
16354 }
16355
16356 function sheet_to_sylk(ws, opts) {
16357 var preamble = ["ID;PWXL;N;E"], o = [];
16358 var r = safe_decode_range(ws['!ref']), cell;
16359 var dense = Array.isArray(ws);
16360 var RS = "\r\n";
16361
16362 preamble.push("P;PGeneral");
16363 preamble.push("F;P0;DG0G8;M255");
16364 if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
16365 if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
16366
16367 preamble.push("B;Y" + (r.e.r - r.s.r + 1) + ";X" + (r.e.c - r.s.c + 1) + ";D" + [r.s.c,r.s.r,r.e.c,r.e.r].join(" "));
16368 for(var R = r.s.r; R <= r.e.r; ++R) {
16369 for(var C = r.s.c; C <= r.e.c; ++C) {
16370 var coord = encode_cell({r:R,c:C});
16371 cell = dense ? (ws[R]||[])[C]: ws[coord];
16372 if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
16373 o.push(write_ws_cell_sylk(cell, ws, R, C, opts));
16374 }
16375 }
16376 return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS;
16377 }
16378
16379 return {
16380 to_workbook: sylk_to_workbook,
16381 to_sheet: sylk_to_sheet,
16382 from_sheet: sheet_to_sylk
16383 };
16384})();
16385
16386var DIF = (function() {
16387 function dif_to_aoa(d, opts) {
16388 switch(opts.type) {
16389 case 'base64': return dif_to_aoa_str(Base64.decode(d), opts);
16390 case 'binary': return dif_to_aoa_str(d, opts);
16391 case 'buffer': return dif_to_aoa_str(d.toString('binary'), opts);
16392 case 'array': return dif_to_aoa_str(cc2str(d), opts);
16393 }
16394 throw new Error("Unrecognized type " + opts.type);
16395 }
16396 function dif_to_aoa_str(str, opts) {
16397 var records = str.split('\n'), R = -1, C = -1, ri = 0, arr = [];
16398 for (; ri !== records.length; ++ri) {
16399 if (records[ri].trim() === 'BOT') { arr[++R] = []; C = 0; continue; }
16400 if (R < 0) continue;
16401 var metadata = records[ri].trim().split(",");
16402 var type = metadata[0], value = metadata[1];
16403 ++ri;
16404 var data = records[ri].trim();
16405 switch (+type) {
16406 case -1:
16407 if (data === 'BOT') { arr[++R] = []; C = 0; continue; }
16408 else if (data !== 'EOD') throw new Error("Unrecognized DIF special command " + data);
16409 break;
16410 case 0:
16411 if(data === 'TRUE') arr[R][C] = true;
16412 else if(data === 'FALSE') arr[R][C] = false;
16413 else if(!isNaN(fuzzynum(value))) arr[R][C] = fuzzynum(value);
16414 else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value);
16415 else arr[R][C] = value;
16416 ++C; break;
16417 case 1:
16418 data = data.slice(1,data.length-1);
16419 arr[R][C++] = data !== '' ? data : null;
16420 break;
16421 }
16422 if (data === 'EOD') break;
16423 }
16424 if(opts && opts.sheetRows) arr = arr.slice(0, opts.sheetRows);
16425 return arr;
16426 }
16427
16428 function dif_to_sheet(str, opts) { return aoa_to_sheet(dif_to_aoa(str, opts), opts); }
16429 function dif_to_workbook(str, opts) { return sheet_to_workbook(dif_to_sheet(str, opts), opts); }
16430
16431 var sheet_to_dif = (function() {
16432 var push_field = function pf(o, topic, v, n, s) {
16433 o.push(topic);
16434 o.push(v + "," + n);
16435 o.push('"' + s.replace(/"/g,'""') + '"');
16436 };
16437 var push_value = function po(o, type, v, s) {
16438 o.push(type + "," + v);
16439 o.push(type == 1 ? '"' + s.replace(/"/g,'""') + '"' : s);
16440 };
16441 return function sheet_to_dif(ws) {
16442 var o = [];
16443 var r = safe_decode_range(ws['!ref']), cell;
16444 var dense = Array.isArray(ws);
16445 push_field(o, "TABLE", 0, 1, "sheetjs");
16446 push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,"");
16447 push_field(o, "TUPLES", 0, r.e.c - r.s.c + 1,"");
16448 push_field(o, "DATA", 0, 0,"");
16449 for(var R = r.s.r; R <= r.e.r; ++R) {
16450 push_value(o, -1, 0, "BOT");
16451 for(var C = r.s.c; C <= r.e.c; ++C) {
16452 var coord = encode_cell({r:R,c:C});
16453 cell = dense ? (ws[R]||[])[C] : ws[coord];
16454 if(!cell) { push_value(o, 1, 0, ""); continue;}
16455 switch(cell.t) {
16456 case 'n':
16457 var val = DIF_XL ? cell.w : cell.v;
16458 if(!val && cell.v != null) val = cell.v;
16459 if(val == null) {
16460 if(DIF_XL && cell.f && !cell.F) push_value(o, 1, 0, "=" + cell.f);
16461 else push_value(o, 1, 0, "");
16462 }
16463 else push_value(o, 0, val, "V");
16464 break;
16465 case 'b':
16466 push_value(o, 0, cell.v ? 1 : 0, cell.v ? "TRUE" : "FALSE");
16467 break;
16468 case 's':
16469 push_value(o, 1, 0, (!DIF_XL || isNaN(cell.v)) ? cell.v : '="' + cell.v + '"');
16470 break;
16471 case 'd':
16472 if(!cell.w) cell.w = SSF.format(cell.z || SSF._table[14], datenum(parseDate(cell.v)));
16473 if(DIF_XL) push_value(o, 0, cell.w, "V");
16474 else push_value(o, 1, 0, cell.w);
16475 break;
16476 default: push_value(o, 1, 0, "");
16477 }
16478 }
16479 }
16480 push_value(o, -1, 0, "EOD");
16481 var RS = "\r\n";
16482 var oo = o.join(RS);
16483 //while((oo.length & 0x7F) != 0) oo += "\0";
16484 return oo;
16485 };
16486 })();
16487 return {
16488 to_workbook: dif_to_workbook,
16489 to_sheet: dif_to_sheet,
16490 from_sheet: sheet_to_dif
16491 };
16492})();
16493
16494var ETH = (function() {
16495 function decode(s) { return s.replace(/\\b/g,"\\").replace(/\\c/g,":").replace(/\\n/g,"\n"); }
16496 function encode(s) { return s.replace(/\\/g, "\\b").replace(/:/g, "\\c").replace(/\n/g,"\\n"); }
16497
16498 function eth_to_aoa(str, opts) {
16499 var records = str.split('\n'), R = -1, C = -1, ri = 0, arr = [];
16500 for (; ri !== records.length; ++ri) {
16501 var record = records[ri].trim().split(":");
16502 if(record[0] !== 'cell') continue;
16503 var addr = decode_cell(record[1]);
16504 if(arr.length <= addr.r) for(R = arr.length; R <= addr.r; ++R) if(!arr[R]) arr[R] = [];
16505 R = addr.r; C = addr.c;
16506 switch(record[2]) {
16507 case 't': arr[R][C] = decode(record[3]); break;
16508 case 'v': arr[R][C] = +record[3]; break;
16509 case 'vtf': var _f = record[record.length - 1];
16510 /* falls through */
16511 case 'vtc':
16512 switch(record[3]) {
16513 case 'nl': arr[R][C] = +record[4] ? true : false; break;
16514 default: arr[R][C] = +record[4]; break;
16515 }
16516 if(record[2] == 'vtf') arr[R][C] = [arr[R][C], _f];
16517 }
16518 }
16519 if(opts && opts.sheetRows) arr = arr.slice(0, opts.sheetRows);
16520 return arr;
16521 }
16522
16523 function eth_to_sheet(d, opts) { return aoa_to_sheet(eth_to_aoa(d, opts), opts); }
16524 function eth_to_workbook(d, opts) { return sheet_to_workbook(eth_to_sheet(d, opts), opts); }
16525
16526 var header = [
16527 "socialcalc:version:1.5",
16528 "MIME-Version: 1.0",
16529 "Content-Type: multipart/mixed; boundary=SocialCalcSpreadsheetControlSave"
16530 ].join("\n");
16531
16532 var sep = [
16533 "--SocialCalcSpreadsheetControlSave",
16534 "Content-type: text/plain; charset=UTF-8"
16535 ].join("\n") + "\n";
16536
16537 /* TODO: the other parts */
16538 var meta = [
16539 "# SocialCalc Spreadsheet Control Save",
16540 "part:sheet"
16541 ].join("\n");
16542
16543 var end = "--SocialCalcSpreadsheetControlSave--";
16544
16545 function sheet_to_eth_data(ws) {
16546 if(!ws || !ws['!ref']) return "";
16547 var o = [], oo = [], cell, coord = "";
16548 var r = decode_range(ws['!ref']);
16549 var dense = Array.isArray(ws);
16550 for(var R = r.s.r; R <= r.e.r; ++R) {
16551 for(var C = r.s.c; C <= r.e.c; ++C) {
16552 coord = encode_cell({r:R,c:C});
16553 cell = dense ? (ws[R]||[])[C] : ws[coord];
16554 if(!cell || cell.v == null || cell.t === 'z') continue;
16555 oo = ["cell", coord, 't'];
16556 switch(cell.t) {
16557 case 's': case 'str': oo.push(encode(cell.v)); break;
16558 case 'n':
16559 if(!cell.f) { oo[2]='v'; oo[3]=cell.v; }
16560 else { oo[2]='vtf'; oo[3]='n'; oo[4]=cell.v; oo[5]=encode(cell.f); }
16561 break;
16562 case 'b':
16563 oo[2] = 'vt'+(cell.f?'f':'c'); oo[3]='nl'; oo[4]=cell.v?"1":"0";
16564 oo[5] = encode(cell.f||(cell.v?'TRUE':'FALSE'));
16565 break;
16566 case 'd':
16567 var t = datenum(parseDate(cell.v));
16568 oo[2] = 'vtc'; oo[3] = 'nd'; oo[4] = ""+t;
16569 oo[5] = cell.w || SSF.format(cell.z || SSF._table[14], t);
16570 break;
16571 case 'e': continue;
16572 }
16573 o.push(oo.join(":"));
16574 }
16575 }
16576 o.push("sheet:c:" + (r.e.c-r.s.c+1) + ":r:" + (r.e.r-r.s.r+1) + ":tvf:1");
16577 o.push("valueformat:1:text-wiki");
16578 //o.push("copiedfrom:" + ws['!ref']); // clipboard only
16579 return o.join("\n");
16580 }
16581
16582 function sheet_to_eth(ws) {
16583 return [header, sep, meta, sep, sheet_to_eth_data(ws), end].join("\n");
16584 // return ["version:1.5", sheet_to_eth_data(ws)].join("\n"); // clipboard form
16585 }
16586
16587 return {
16588 to_workbook: eth_to_workbook,
16589 to_sheet: eth_to_sheet,
16590 from_sheet: sheet_to_eth
16591 };
16592})();
16593
16594var PRN = (function() {
16595 function set_text_arr(data, arr, R, C, o) {
16596 if(o.raw) arr[R][C] = data;
16597 else if(data === 'TRUE') arr[R][C] = true;
16598 else if(data === 'FALSE') arr[R][C] = false;
16599 else if(data === ""){/* empty */}
16600 else if(!isNaN(fuzzynum(data))) arr[R][C] = fuzzynum(data);
16601 else if(!isNaN(fuzzydate(data).getDate())) arr[R][C] = parseDate(data);
16602 else arr[R][C] = data;
16603 }
16604
16605 function prn_to_aoa_str(f, opts) {
16606 var o = opts || {};
16607 var arr = ([]);
16608 if(!f || f.length === 0) return arr;
16609 var lines = f.split(/[\r\n]/);
16610 var L = lines.length - 1;
16611 while(L >= 0 && lines[L].length === 0) --L;
16612 var start = 10, idx = 0;
16613 var R = 0;
16614 for(; R <= L; ++R) {
16615 idx = lines[R].indexOf(" ");
16616 if(idx == -1) idx = lines[R].length; else idx++;
16617 start = Math.max(start, idx);
16618 }
16619 for(R = 0; R <= L; ++R) {
16620 arr[R] = [];
16621 /* TODO: confirm that widths are always 10 */
16622 var C = 0;
16623 set_text_arr(lines[R].slice(0, start).trim(), arr, R, C, o);
16624 for(C = 1; C <= (lines[R].length - start)/10 + 1; ++C)
16625 set_text_arr(lines[R].slice(start+(C-1)*10,start+C*10).trim(),arr,R,C,o);
16626 }
16627 if(o.sheetRows) arr = arr.slice(0, o.sheetRows);
16628 return arr;
16629 }
16630
16631 // List of accepted CSV separators
16632 var guess_seps = {
166330x2C: ',',
166340x09: "\t",
166350x3B: ';'
16636 };
16637
16638 // CSV separator weights to be used in case of equal numbers
16639 var guess_sep_weights = {
166400x2C: 3,
166410x09: 2,
166420x3B: 1
16643 };
16644
16645 function guess_sep(str) {
16646 var cnt = {}, instr = false, end = 0, cc = 0;
16647 for(;end < str.length;++end) {
16648 if((cc=str.charCodeAt(end)) == 0x22) instr = !instr;
16649 else if(!instr && cc in guess_seps) cnt[cc] = (cnt[cc]||0)+1;
16650 }
16651
16652 cc = [];
16653 for(end in cnt) if ( cnt.hasOwnProperty(end) ) {
16654 cc.push([ cnt[end], end ]);
16655 }
16656
16657 if ( !cc.length ) {
16658 cnt = guess_sep_weights;
16659 for(end in cnt) if ( cnt.hasOwnProperty(end) ) {
16660 cc.push([ cnt[end], end ]);
16661 }
16662 }
16663
16664 cc.sort(function(a, b) { return a[0] - b[0] || guess_sep_weights[a[1]] - guess_sep_weights[b[1]]; });
16665
16666 return guess_seps[cc.pop()[1]];
16667 }
16668
16669 function dsv_to_sheet_str(str, opts) {
16670 var o = opts || {};
16671 var sep = "";
16672 if(DENSE != null && o.dense == null) o.dense = DENSE;
16673 var ws = o.dense ? ([]) : ({});
16674 var range = ({s: {c:0, r:0}, e: {c:0, r:0}});
16675
16676 if(str.slice(0,4) == "sep=" && str.charCodeAt(5) == 10) { sep = str.charAt(4); str = str.slice(6); }
16677 else sep = guess_sep(str.slice(0,1024));
16678 var R = 0, C = 0, v = 0;
16679 var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0;
16680 str = str.replace(/\r\n/mg, "\n");
16681 var _re = o.dateNF != null ? dateNF_regex(o.dateNF) : null;
16682 function finish_cell() {
16683 var s = str.slice(start, end);
16684 var cell = ({});
16685 if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
16686 if(s.length === 0) cell.t = 'z';
16687 else if(o.raw) { cell.t = 's'; cell.v = s; }
16688 else if(s.trim().length === 0) { cell.t = 's'; cell.v = s; }
16689 else if(s.charCodeAt(0) == 0x3D) {
16690 if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); }
16691 else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.slice(1); }
16692 else { cell.t = 's'; cell.v = s; } }
16693 else if(s == "TRUE") { cell.t = 'b'; cell.v = true; }
16694 else if(s == "FALSE") { cell.t = 'b'; cell.v = false; }
16695 else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; if(o.cellText !== false) cell.w = s; cell.v = v; }
16696 else if(!isNaN(fuzzydate(s).getDate()) || _re && s.match(_re)) {
16697 cell.z = o.dateNF || SSF._table[14];
16698 var k = 0;
16699 if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; }
16700 if(o.cellDates) { cell.t = 'd'; cell.v = parseDate(s, k); }
16701 else { cell.t = 'n'; cell.v = datenum(parseDate(s, k)); }
16702 if(o.cellText !== false) cell.w = SSF.format(cell.z, cell.v instanceof Date ? datenum(cell.v):cell.v);
16703 if(!o.cellNF) delete cell.z;
16704 } else {
16705 cell.t = 's';
16706 cell.v = s;
16707 }
16708 if(cell.t == 'z'){}
16709 else if(o.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = cell; }
16710 else ws[encode_cell({c:C,r:R})] = cell;
16711 start = end+1;
16712 if(range.e.c < C) range.e.c = C;
16713 if(range.e.r < R) range.e.r = R;
16714 if(cc == sepcc) ++C; else { C = 0; ++R; if(o.sheetRows && o.sheetRows <= R) return true; }
16715 }
16716 outer: for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) {
16717 case 0x22: instr = !instr; break;
16718 case sepcc: case 0x0a: case 0x0d: if(!instr && finish_cell()) break outer; break;
16719 default: break;
16720 }
16721 if(end - start > 0) finish_cell();
16722
16723 ws['!ref'] = encode_range(range);
16724 return ws;
16725 }
16726
16727 function prn_to_sheet_str(str, opts) {
16728 if(str.slice(0,4) == "sep=") return dsv_to_sheet_str(str, opts);
16729 if(str.indexOf("\t") >= 0 || str.indexOf(",") >= 0 || str.indexOf(";") >= 0) return dsv_to_sheet_str(str, opts);
16730 return aoa_to_sheet(prn_to_aoa_str(str, opts), opts);
16731 }
16732
16733 function prn_to_sheet(d, opts) {
16734 var str = "", bytes = opts.type == 'string' ? [0,0,0,0] : firstbyte(d, opts);
16735 switch(opts.type) {
16736 case 'base64': str = Base64.decode(d); break;
16737 case 'binary': str = d; break;
16738 case 'buffer':
16739 if(opts.codepage == 65001) str = d.toString('utf8');
16740 else if(opts.codepage && typeof cptable !== 'undefined') str = cptable.utils.decode(opts.codepage, d);
16741 else str = d.toString('binary');
16742 break;
16743 case 'array': str = cc2str(d); break;
16744 case 'string': str = d; break;
16745 default: throw new Error("Unrecognized type " + opts.type);
16746 }
16747 if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str.slice(3));
16748 else if((opts.type == 'binary') && typeof cptable !== 'undefined' && opts.codepage) str = cptable.utils.decode(opts.codepage, cptable.utils.encode(1252,str));
16749 if(str.slice(0,19) == "socialcalc:version:") return ETH.to_sheet(opts.type == 'string' ? str : utf8read(str), opts);
16750 return prn_to_sheet_str(str, opts);
16751 }
16752
16753 function prn_to_workbook(d, opts) { return sheet_to_workbook(prn_to_sheet(d, opts), opts); }
16754
16755 function sheet_to_prn(ws) {
16756 var o = [];
16757 var r = safe_decode_range(ws['!ref']), cell;
16758 var dense = Array.isArray(ws);
16759 for(var R = r.s.r; R <= r.e.r; ++R) {
16760 var oo = [];
16761 for(var C = r.s.c; C <= r.e.c; ++C) {
16762 var coord = encode_cell({r:R,c:C});
16763 cell = dense ? (ws[R]||[])[C] : ws[coord];
16764 if(!cell || cell.v == null) { oo.push(" "); continue; }
16765 var w = (cell.w || (format_cell(cell), cell.w) || "").slice(0,10);
16766 while(w.length < 10) w += " ";
16767 oo.push(w + (C === 0 ? " " : ""));
16768 }
16769 o.push(oo.join(""));
16770 }
16771 return o.join("\n");
16772 }
16773
16774 return {
16775 to_workbook: prn_to_workbook,
16776 to_sheet: prn_to_sheet,
16777 from_sheet: sheet_to_prn
16778 };
16779})();
16780
16781/* Excel defaults to SYLK but warns if data is not valid */
16782function read_wb_ID(d, opts) {
16783 var o = opts || {}, OLD_WTF = !!o.WTF; o.WTF = true;
16784 try {
16785 var out = SYLK.to_workbook(d, o);
16786 o.WTF = OLD_WTF;
16787 return out;
16788 } catch(e) {
16789 o.WTF = OLD_WTF;
16790 if(!e.message.match(/SYLK bad record ID/) && OLD_WTF) throw e;
16791 return PRN.to_workbook(d, opts);
16792 }
16793}
16794
16795var WK_ = (function() {
16796 function lotushopper(data, cb, opts) {
16797 if(!data) return;
16798 prep_blob(data, data.l || 0);
16799 var Enum = opts.Enum || WK1Enum;
16800 while(data.l < data.length) {
16801 var RT = data.read_shift(2);
16802 var R = Enum[RT] || Enum[0xFF];
16803 var length = data.read_shift(2);
16804 var tgt = data.l + length;
16805 var d = (R.f||parsenoop)(data, length, opts);
16806 data.l = tgt;
16807 if(cb(d, R.n, RT)) return;
16808 }
16809 }
16810
16811 function lotus_to_workbook(d, opts) {
16812 switch(opts.type) {
16813 case 'base64': return lotus_to_workbook_buf(s2a(Base64.decode(d)), opts);
16814 case 'binary': return lotus_to_workbook_buf(s2a(d), opts);
16815 case 'buffer':
16816 case 'array': return lotus_to_workbook_buf(d, opts);
16817 }
16818 throw "Unsupported type " + opts.type;
16819 }
16820
16821 function lotus_to_workbook_buf(d, opts) {
16822 if(!d) return d;
16823 var o = opts || {};
16824 if(DENSE != null && o.dense == null) o.dense = DENSE;
16825 var s = ((o.dense ? [] : {})), n = "Sheet1", sidx = 0;
16826 var sheets = {}, snames = [n];
16827
16828 var refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
16829 var sheetRows = o.sheetRows || 0;
16830
16831 if(d[2] == 0x02) o.Enum = WK1Enum;
16832 else if(d[2] == 0x1a) o.Enum = WK3Enum;
16833 else if(d[2] == 0x0e) { o.Enum = WK3Enum; o.qpro = true; d.l = 0; }
16834 else throw new Error("Unrecognized LOTUS BOF " + d[2]);
16835 lotushopper(d, function(val, Rn, RT) {
16836 if(d[2] == 0x02) switch(RT) {
16837 case 0x00:
16838 o.vers = val;
16839 if(val >= 0x1000) o.qpro = true;
16840 break;
16841 case 0x06: refguess = val; break; /* RANGE */
16842 case 0x0F: /* LABEL */
16843 if(!o.qpro) val[1].v = val[1].v.slice(1);
16844 /* falls through */
16845 case 0x0D: /* INTEGER */
16846 case 0x0E: /* NUMBER */
16847 case 0x10: /* FORMULA */
16848 case 0x33: /* STRING */
16849 /* TODO: actual translation of the format code */
16850 if(RT == 0x0E && (val[2] & 0x70) == 0x70 && (val[2] & 0x0F) > 1 && (val[2] & 0x0F) < 15) {
16851 val[1].z = o.dateNF || SSF._table[14];
16852 if(o.cellDates) { val[1].t = 'd'; val[1].v = numdate(val[1].v); }
16853 }
16854 if(o.dense) {
16855 if(!s[val[0].r]) s[val[0].r] = [];
16856 s[val[0].r][val[0].c] = val[1];
16857 } else s[encode_cell(val[0])] = val[1];
16858 break;
16859 } else switch(RT) {
16860 case 0x16: /* LABEL16 */
16861 val[1].v = val[1].v.slice(1);
16862 /* falls through */
16863 case 0x17: /* NUMBER17 */
16864 case 0x18: /* NUMBER18 */
16865 case 0x19: /* FORMULA19 */
16866 case 0x25: /* NUMBER25 */
16867 case 0x27: /* NUMBER27 */
16868 case 0x28: /* FORMULA28 */
16869 if(val[3] > sidx) {
16870 s["!ref"] = encode_range(refguess);
16871 sheets[n] = s;
16872 s = (o.dense ? [] : {});
16873 refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
16874 sidx = val[3]; n = "Sheet" + (sidx + 1);
16875 snames.push(n);
16876 }
16877 if(sheetRows > 0 && val[0].r >= sheetRows) break;
16878 if(o.dense) {
16879 if(!s[val[0].r]) s[val[0].r] = [];
16880 s[val[0].r][val[0].c] = val[1];
16881 } else s[encode_cell(val[0])] = val[1];
16882 if(refguess.e.c < val[0].c) refguess.e.c = val[0].c;
16883 if(refguess.e.r < val[0].r) refguess.e.r = val[0].r;
16884 break;
16885 default: break;
16886 }
16887 }, o);
16888
16889 s["!ref"] = encode_range(refguess);
16890 sheets[n] = s;
16891 return { SheetNames: snames, Sheets:sheets };
16892 }
16893
16894 function parse_RANGE(blob) {
16895 var o = {s:{c:0,r:0},e:{c:0,r:0}};
16896 o.s.c = blob.read_shift(2);
16897 o.s.r = blob.read_shift(2);
16898 o.e.c = blob.read_shift(2);
16899 o.e.r = blob.read_shift(2);
16900 if(o.s.c == 0xFFFF) o.s.c = o.e.c = o.s.r = o.e.r = 0;
16901 return o;
16902 }
16903
16904 function parse_cell(blob, length, opts) {
16905 var o = [{c:0,r:0}, {t:'n',v:0}, 0];
16906 if(opts.qpro && opts.vers != 0x5120) {
16907 o[0].c = blob.read_shift(1);
16908 blob.l++;
16909 o[0].r = blob.read_shift(2);
16910 blob.l+=2;
16911 } else {
16912 o[2] = blob.read_shift(1);
16913 o[0].c = blob.read_shift(2); o[0].r = blob.read_shift(2);
16914 }
16915 return o;
16916 }
16917
16918 function parse_LABEL(blob, length, opts) {
16919 var tgt = blob.l + length;
16920 var o = parse_cell(blob, length, opts);
16921 o[1].t = 's';
16922 if(opts.vers == 0x5120) {
16923 blob.l++;
16924 var len = blob.read_shift(1);
16925 o[1].v = blob.read_shift(len, 'utf8');
16926 return o;
16927 }
16928 if(opts.qpro) blob.l++;
16929 o[1].v = blob.read_shift(tgt - blob.l, 'cstr');
16930 return o;
16931 }
16932
16933 function parse_INTEGER(blob, length, opts) {
16934 var o = parse_cell(blob, length, opts);
16935 o[1].v = blob.read_shift(2, 'i');
16936 return o;
16937 }
16938
16939 function parse_NUMBER(blob, length, opts) {
16940 var o = parse_cell(blob, length, opts);
16941 o[1].v = blob.read_shift(8, 'f');
16942 return o;
16943 }
16944
16945 function parse_FORMULA(blob, length, opts) {
16946 var tgt = blob.l + length;
16947 var o = parse_cell(blob, length, opts);
16948 /* TODO: formula */
16949 o[1].v = blob.read_shift(8, 'f');
16950 if(opts.qpro) blob.l = tgt;
16951 else {
16952 var flen = blob.read_shift(2);
16953 blob.l += flen;
16954 }
16955 return o;
16956 }
16957
16958 function parse_cell_3(blob) {
16959 var o = [{c:0,r:0}, {t:'n',v:0}, 0];
16960 o[0].r = blob.read_shift(2); o[3] = blob[blob.l++]; o[0].c = blob[blob.l++];
16961 return o;
16962 }
16963
16964 function parse_LABEL_16(blob, length) {
16965 var o = parse_cell_3(blob, length);
16966 o[1].t = 's';
16967 o[1].v = blob.read_shift(length - 4, 'cstr');
16968 return o;
16969 }
16970
16971 function parse_NUMBER_18(blob, length) {
16972 var o = parse_cell_3(blob, length);
16973 o[1].v = blob.read_shift(2);
16974 var v = o[1].v >> 1;
16975 /* TODO: figure out all of the corner cases */
16976 if(o[1].v & 0x1) {
16977 switch(v & 0x07) {
16978 case 1: v = (v >> 3) * 500; break;
16979 case 2: v = (v >> 3) / 20; break;
16980 case 4: v = (v >> 3) / 2000; break;
16981 case 6: v = (v >> 3) / 16; break;
16982 case 7: v = (v >> 3) / 64; break;
16983 default: throw "unknown NUMBER_18 encoding " + (v & 0x07);
16984 }
16985 }
16986 o[1].v = v;
16987 return o;
16988 }
16989
16990 function parse_NUMBER_17(blob, length) {
16991 var o = parse_cell_3(blob, length);
16992 var v1 = blob.read_shift(4);
16993 var v2 = blob.read_shift(4);
16994 var e = blob.read_shift(2);
16995 if(e == 0xFFFF) { o[1].v = 0; return o; }
16996 var s = e & 0x8000; e = (e&0x7FFF) - 16446;
16997 o[1].v = (s*2 - 1) * ((e > 0 ? (v2 << e) : (v2 >>> -e)) + (e > -32 ? (v1 << (e + 32)) : (v1 >>> -(e + 32))));
16998 return o;
16999 }
17000
17001 function parse_FORMULA_19(blob, length) {
17002 var o = parse_NUMBER_17(blob, 14);
17003 blob.l += length - 14; /* TODO: formula */
17004 return o;
17005 }
17006
17007 function parse_NUMBER_25(blob, length) {
17008 var o = parse_cell_3(blob, length);
17009 var v1 = blob.read_shift(4);
17010 o[1].v = v1 >> 6;
17011 return o;
17012 }
17013
17014 function parse_NUMBER_27(blob, length) {
17015 var o = parse_cell_3(blob, length);
17016 var v1 = blob.read_shift(8,'f');
17017 o[1].v = v1;
17018 return o;
17019 }
17020
17021 function parse_FORMULA_28(blob, length) {
17022 var o = parse_NUMBER_27(blob, 14);
17023 blob.l += length - 10; /* TODO: formula */
17024 return o;
17025 }
17026
17027 var WK1Enum = {
170280x0000: { n:"BOF", f:parseuint16 },
170290x0001: { n:"EOF" },
170300x0002: { n:"CALCMODE" },
170310x0003: { n:"CALCORDER" },
170320x0004: { n:"SPLIT" },
170330x0005: { n:"SYNC" },
170340x0006: { n:"RANGE", f:parse_RANGE },
170350x0007: { n:"WINDOW1" },
170360x0008: { n:"COLW1" },
170370x0009: { n:"WINTWO" },
170380x000A: { n:"COLW2" },
170390x000B: { n:"NAME" },
170400x000C: { n:"BLANK" },
170410x000D: { n:"INTEGER", f:parse_INTEGER },
170420x000E: { n:"NUMBER", f:parse_NUMBER },
170430x000F: { n:"LABEL", f:parse_LABEL },
170440x0010: { n:"FORMULA", f:parse_FORMULA },
170450x0018: { n:"TABLE" },
170460x0019: { n:"ORANGE" },
170470x001A: { n:"PRANGE" },
170480x001B: { n:"SRANGE" },
170490x001C: { n:"FRANGE" },
170500x001D: { n:"KRANGE1" },
170510x0020: { n:"HRANGE" },
170520x0023: { n:"KRANGE2" },
170530x0024: { n:"PROTEC" },
170540x0025: { n:"FOOTER" },
170550x0026: { n:"HEADER" },
170560x0027: { n:"SETUP" },
170570x0028: { n:"MARGINS" },
170580x0029: { n:"LABELFMT" },
170590x002A: { n:"TITLES" },
170600x002B: { n:"SHEETJS" },
170610x002D: { n:"GRAPH" },
170620x002E: { n:"NGRAPH" },
170630x002F: { n:"CALCCOUNT" },
170640x0030: { n:"UNFORMATTED" },
170650x0031: { n:"CURSORW12" },
170660x0032: { n:"WINDOW" },
170670x0033: { n:"STRING", f:parse_LABEL },
170680x0037: { n:"PASSWORD" },
170690x0038: { n:"LOCKED" },
170700x003C: { n:"QUERY" },
170710x003D: { n:"QUERYNAME" },
170720x003E: { n:"PRINT" },
170730x003F: { n:"PRINTNAME" },
170740x0040: { n:"GRAPH2" },
170750x0041: { n:"GRAPHNAME" },
170760x0042: { n:"ZOOM" },
170770x0043: { n:"SYMSPLIT" },
170780x0044: { n:"NSROWS" },
170790x0045: { n:"NSCOLS" },
170800x0046: { n:"RULER" },
170810x0047: { n:"NNAME" },
170820x0048: { n:"ACOMM" },
170830x0049: { n:"AMACRO" },
170840x004A: { n:"PARSE" },
170850x00FF: { n:"", f:parsenoop }
17086 };
17087
17088 var WK3Enum = {
170890x0000: { n:"BOF" },
170900x0001: { n:"EOF" },
170910x0003: { n:"??" },
170920x0004: { n:"??" },
170930x0005: { n:"??" },
170940x0006: { n:"??" },
170950x0007: { n:"??" },
170960x0009: { n:"??" },
170970x000a: { n:"??" },
170980x000b: { n:"??" },
170990x000c: { n:"??" },
171000x000e: { n:"??" },
171010x000f: { n:"??" },
171020x0010: { n:"??" },
171030x0011: { n:"??" },
171040x0012: { n:"??" },
171050x0013: { n:"??" },
171060x0015: { n:"??" },
171070x0016: { n:"LABEL16", f:parse_LABEL_16},
171080x0017: { n:"NUMBER17", f:parse_NUMBER_17 },
171090x0018: { n:"NUMBER18", f:parse_NUMBER_18 },
171100x0019: { n:"FORMULA19", f:parse_FORMULA_19},
171110x001a: { n:"??" },
171120x001b: { n:"??" },
171130x001c: { n:"??" },
171140x001d: { n:"??" },
171150x001e: { n:"??" },
171160x001f: { n:"??" },
171170x0021: { n:"??" },
171180x0025: { n:"NUMBER25", f:parse_NUMBER_25 },
171190x0027: { n:"NUMBER27", f:parse_NUMBER_27 },
171200x0028: { n:"FORMULA28", f:parse_FORMULA_28 },
171210x00FF: { n:"", f:parsenoop }
17122 };
17123 return {
17124 to_workbook: lotus_to_workbook
17125 };
17126})();
17127/* 18.4.7 rPr CT_RPrElt */
17128function parse_rpr(rpr) {
17129 var font = {}, m = rpr.match(tagregex), i = 0;
17130 var pass = false;
17131 if(m) for(;i!=m.length; ++i) {
17132 var y = parsexmltag(m[i]);
17133 switch(y[0].replace(/\w*:/g,"")) {
17134 /* 18.8.12 condense CT_BooleanProperty */
17135 /* ** not required . */
17136 case '<condense': break;
17137 /* 18.8.17 extend CT_BooleanProperty */
17138 /* ** not required . */
17139 case '<extend': break;
17140 /* 18.8.36 shadow CT_BooleanProperty */
17141 /* ** not required . */
17142 case '<shadow':
17143 if(!y.val) break;
17144 /* falls through */
17145 case '<shadow>':
17146 case '<shadow/>': font.shadow = 1; break;
17147 case '</shadow>': break;
17148
17149 /* 18.4.1 charset CT_IntProperty TODO */
17150 case '<charset':
17151 if(y.val == '1') break;
17152 font.cp = CS2CP[parseInt(y.val, 10)];
17153 break;
17154
17155 /* 18.4.2 outline CT_BooleanProperty TODO */
17156 case '<outline':
17157 if(!y.val) break;
17158 /* falls through */
17159 case '<outline>':
17160 case '<outline/>': font.outline = 1; break;
17161 case '</outline>': break;
17162
17163 /* 18.4.5 rFont CT_FontName */
17164 case '<rFont': font.name = y.val; break;
17165
17166 /* 18.4.11 sz CT_FontSize */
17167 case '<sz': font.sz = y.val; break;
17168
17169 /* 18.4.10 strike CT_BooleanProperty */
17170 case '<strike':
17171 if(!y.val) break;
17172 /* falls through */
17173 case '<strike>':
17174 case '<strike/>': font.strike = 1; break;
17175 case '</strike>': break;
17176
17177 /* 18.4.13 u CT_UnderlineProperty */
17178 case '<u':
17179 if(!y.val) break;
17180 switch(y.val) {
17181 case 'double': font.uval = "double"; break;
17182 case 'singleAccounting': font.uval = "single-accounting"; break;
17183 case 'doubleAccounting': font.uval = "double-accounting"; break;
17184 }
17185 /* falls through */
17186 case '<u>':
17187 case '<u/>': font.u = 1; break;
17188 case '</u>': break;
17189
17190 /* 18.8.2 b */
17191 case '<b':
17192 if(y.val == '0') break;
17193 /* falls through */
17194 case '<b>':
17195 case '<b/>': font.b = 1; break;
17196 case '</b>': break;
17197
17198 /* 18.8.26 i */
17199 case '<i':
17200 if(y.val == '0') break;
17201 /* falls through */
17202 case '<i>':
17203 case '<i/>': font.i = 1; break;
17204 case '</i>': break;
17205
17206 /* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */
17207 case '<color':
17208 if(y.rgb) font.color = y.rgb.slice(2,8);
17209 break;
17210
17211 /* 18.8.18 family ST_FontFamily */
17212 case '<family': font.family = y.val; break;
17213
17214 /* 18.4.14 vertAlign CT_VerticalAlignFontProperty TODO */
17215 case '<vertAlign': font.valign = y.val; break;
17216
17217 /* 18.8.35 scheme CT_FontScheme TODO */
17218 case '<scheme': break;
17219
17220 /* 18.2.10 extLst CT_ExtensionList ? */
17221 case '<extLst': case '<extLst>': case '</extLst>': break;
17222 case '<ext': pass = true; break;
17223 case '</ext>': pass = false; break;
17224 default:
17225 if(y[0].charCodeAt(1) !== 47 && !pass) throw new Error('Unrecognized rich format ' + y[0]);
17226 }
17227 }
17228 return font;
17229}
17230
17231var parse_rs = (function() {
17232 var tregex = matchtag("t"), rpregex = matchtag("rPr");
17233 /* 18.4.4 r CT_RElt */
17234 function parse_r(r) {
17235 /* 18.4.12 t ST_Xstring */
17236 var t = r.match(tregex)/*, cp = 65001*/;
17237 if(!t) return {t:"s", v:""};
17238
17239 var o = ({t:'s', v:unescapexml(t[1])});
17240 var rpr = r.match(rpregex);
17241 if(rpr) o.s = parse_rpr(rpr[1]);
17242 return o;
17243 }
17244 var rregex = /<(?:\w+:)?r>/g, rend = /<\/(?:\w+:)?r>/;
17245 return function parse_rs(rs) {
17246 return rs.replace(rregex,"").split(rend).map(parse_r).filter(function(r) { return r.v; });
17247 };
17248})();
17249
17250
17251/* Parse a list of <r> tags */
17252var rs_to_html = (function parse_rs_factory() {
17253 var nlregex = /(\r\n|\n)/g;
17254 function parse_rpr2(font, intro, outro) {
17255 var style = [];
17256
17257 if(font.u) style.push("text-decoration: underline;");
17258 if(font.uval) style.push("text-underline-style:" + font.uval + ";");
17259 if(font.sz) style.push("font-size:" + font.sz + "pt;");
17260 if(font.outline) style.push("text-effect: outline;");
17261 if(font.shadow) style.push("text-shadow: auto;");
17262 intro.push('<span style="' + style.join("") + '">');
17263
17264 if(font.b) { intro.push("<b>"); outro.push("</b>"); }
17265 if(font.i) { intro.push("<i>"); outro.push("</i>"); }
17266 if(font.strike) { intro.push("<s>"); outro.push("</s>"); }
17267
17268 var align = font.valign || "";
17269 if(align == "superscript" || align == "super") align = "sup";
17270 else if(align == "subscript") align = "sub";
17271 if(align != "") { intro.push("<" + align + ">"); outro.push("</" + align + ">"); }
17272
17273 outro.push("</span>");
17274 return font;
17275 }
17276
17277 /* 18.4.4 r CT_RElt */
17278 function r_to_html(r) {
17279 var terms = [[],r.v,[]];
17280 if(!r.v) return "";
17281
17282 if(r.s) parse_rpr2(r.s, terms[0], terms[2]);
17283
17284 return terms[0].join("") + terms[1].replace(nlregex,'<br/>') + terms[2].join("");
17285 }
17286
17287 return function parse_rs(rs) {
17288 return rs.map(r_to_html).join("");
17289 };
17290})();
17291
17292/* 18.4.8 si CT_Rst */
17293var sitregex = /<(?:\w+:)?t[^>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r>/;
17294var sirphregex = /<(?:\w+:)?rPh.*?>([\s\S]*?)<\/(?:\w+:)?rPh>/g;
17295function parse_si(x, opts) {
17296 var html = opts ? opts.cellHTML : true;
17297 var z = {};
17298 if(!x) return null;
17299 //var y;
17300 /* 18.4.12 t ST_Xstring (Plaintext String) */
17301 // TODO: is whitespace actually valid here?
17302 if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) {
17303 z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||""));
17304 z.r = utf8read(x);
17305 if(html) z.h = escapehtml(z.t);
17306 }
17307 /* 18.4.4 r CT_RElt (Rich Text Run) */
17308 else if((/*y = */x.match(sirregex))) {
17309 z.r = utf8read(x);
17310 z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")));
17311 if(html) z.h = rs_to_html(parse_rs(z.r));
17312 }
17313 /* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
17314 /* 18.4.6 rPh CT_PhoneticRun (TODO: needed for Asian support) */
17315 return z;
17316}
17317
17318/* 18.4 Shared String Table */
17319var sstr0 = /<(?:\w+:)?sst([^>]*)>([\s\S]*)<\/(?:\w+:)?sst>/;
17320var sstr1 = /<(?:\w+:)?(?:si|sstItem)>/g;
17321var sstr2 = /<\/(?:\w+:)?(?:si|sstItem)>/;
17322function parse_sst_xml(data, opts) {
17323 var s = ([]), ss = "";
17324 if(!data) return s;
17325 /* 18.4.9 sst CT_Sst */
17326 var sst = data.match(sstr0);
17327 if(sst) {
17328 ss = sst[2].replace(sstr1,"").split(sstr2);
17329 for(var i = 0; i != ss.length; ++i) {
17330 var o = parse_si(ss[i].trim(), opts);
17331 if(o != null) s[s.length] = o;
17332 }
17333 sst = parsexmltag(sst[1]); s.Count = sst.count; s.Unique = sst.uniqueCount;
17334 }
17335 return s;
17336}
17337
17338RELS.SST = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings";
17339var straywsregex = /^\s|\s$|[\t\n\r]/;
17340function write_sst_xml(sst, opts) {
17341 if(!opts.bookSST) return "";
17342 var o = [XML_HEADER];
17343 o[o.length] = (writextag('sst', null, {
17344 xmlns: XMLNS.main[0],
17345 count: sst.Count,
17346 uniqueCount: sst.Unique
17347 }));
17348 for(var i = 0; i != sst.length; ++i) { if(sst[i] == null) continue;
17349 var s = sst[i];
17350 var sitag = "<si>";
17351 if(s.r) sitag += s.r;
17352 else {
17353 sitag += "<t";
17354 if(!s.t) s.t = "";
17355 if(s.t.match(straywsregex)) sitag += ' xml:space="preserve"';
17356 sitag += ">" + escapexml(s.t) + "</t>";
17357 }
17358 sitag += "</si>";
17359 o[o.length] = (sitag);
17360 }
17361 if(o.length>2){ o[o.length] = ('</sst>'); o[1]=o[1].replace("/>",">"); }
17362 return o.join("");
17363}
17364/* [MS-XLSB] 2.4.221 BrtBeginSst */
17365function parse_BrtBeginSst(data) {
17366 return [data.read_shift(4), data.read_shift(4)];
17367}
17368
17369/* [MS-XLSB] 2.1.7.45 Shared Strings */
17370function parse_sst_bin(data, opts) {
17371 var s = ([]);
17372 var pass = false;
17373 recordhopper(data, function hopper_sst(val, R_n, RT) {
17374 switch(RT) {
17375 case 0x009F: /* 'BrtBeginSst' */
17376 s.Count = val[0]; s.Unique = val[1]; break;
17377 case 0x0013: /* 'BrtSSTItem' */
17378 s.push(val); break;
17379 case 0x00A0: /* 'BrtEndSst' */
17380 return true;
17381
17382 case 0x0023: /* 'BrtFRTBegin' */
17383 pass = true; break;
17384 case 0x0024: /* 'BrtFRTEnd' */
17385 pass = false; break;
17386
17387 default:
17388 if(R_n.indexOf("Begin") > 0){/* empty */}
17389 else if(R_n.indexOf("End") > 0){/* empty */}
17390 if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
17391 }
17392 });
17393 return s;
17394}
17395
17396function write_BrtBeginSst(sst, o) {
17397 if(!o) o = new_buf(8);
17398 o.write_shift(4, sst.Count);
17399 o.write_shift(4, sst.Unique);
17400 return o;
17401}
17402
17403var write_BrtSSTItem = write_RichStr;
17404
17405function write_sst_bin(sst) {
17406 var ba = buf_array();
17407 write_record(ba, "BrtBeginSst", write_BrtBeginSst(sst));
17408 for(var i = 0; i < sst.length; ++i) write_record(ba, "BrtSSTItem", write_BrtSSTItem(sst[i]));
17409 /* FRTSST */
17410 write_record(ba, "BrtEndSst");
17411 return ba.end();
17412}
17413function _JS2ANSI(str) {
17414 if(typeof cptable !== 'undefined') return cptable.utils.encode(current_ansi, str);
17415 var o = [], oo = str.split("");
17416 for(var i = 0; i < oo.length; ++i) o[i] = oo[i].charCodeAt(0);
17417 return o;
17418}
17419
17420/* [MS-OFFCRYPTO] 2.1.4 Version */
17421function parse_CRYPTOVersion(blob, length) {
17422 var o = {};
17423 o.Major = blob.read_shift(2);
17424 o.Minor = blob.read_shift(2);
17425if(length >= 4) blob.l += length - 4;
17426 return o;
17427}
17428
17429/* [MS-OFFCRYPTO] 2.1.5 DataSpaceVersionInfo */
17430function parse_DataSpaceVersionInfo(blob) {
17431 var o = {};
17432 o.id = blob.read_shift(0, 'lpp4');
17433 o.R = parse_CRYPTOVersion(blob, 4);
17434 o.U = parse_CRYPTOVersion(blob, 4);
17435 o.W = parse_CRYPTOVersion(blob, 4);
17436 return o;
17437}
17438
17439/* [MS-OFFCRYPTO] 2.1.6.1 DataSpaceMapEntry Structure */
17440function parse_DataSpaceMapEntry(blob) {
17441 var len = blob.read_shift(4);
17442 var end = blob.l + len - 4;
17443 var o = {};
17444 var cnt = blob.read_shift(4);
17445 var comps = [];
17446 /* [MS-OFFCRYPTO] 2.1.6.2 DataSpaceReferenceComponent Structure */
17447 while(cnt-- > 0) comps.push({ t: blob.read_shift(4), v: blob.read_shift(0, 'lpp4') });
17448 o.name = blob.read_shift(0, 'lpp4');
17449 o.comps = comps;
17450 if(blob.l != end) throw new Error("Bad DataSpaceMapEntry: " + blob.l + " != " + end);
17451 return o;
17452}
17453
17454/* [MS-OFFCRYPTO] 2.1.6 DataSpaceMap */
17455function parse_DataSpaceMap(blob) {
17456 var o = [];
17457 blob.l += 4; // must be 0x8
17458 var cnt = blob.read_shift(4);
17459 while(cnt-- > 0) o.push(parse_DataSpaceMapEntry(blob));
17460 return o;
17461}
17462
17463/* [MS-OFFCRYPTO] 2.1.7 DataSpaceDefinition */
17464function parse_DataSpaceDefinition(blob) {
17465 var o = [];
17466 blob.l += 4; // must be 0x8
17467 var cnt = blob.read_shift(4);
17468 while(cnt-- > 0) o.push(blob.read_shift(0, 'lpp4'));
17469 return o;
17470}
17471
17472/* [MS-OFFCRYPTO] 2.1.8 DataSpaceDefinition */
17473function parse_TransformInfoHeader(blob) {
17474 var o = {};
17475 /*var len = */blob.read_shift(4);
17476 blob.l += 4; // must be 0x1
17477 o.id = blob.read_shift(0, 'lpp4');
17478 o.name = blob.read_shift(0, 'lpp4');
17479 o.R = parse_CRYPTOVersion(blob, 4);
17480 o.U = parse_CRYPTOVersion(blob, 4);
17481 o.W = parse_CRYPTOVersion(blob, 4);
17482 return o;
17483}
17484
17485function parse_Primary(blob) {
17486 /* [MS-OFFCRYPTO] 2.2.6 IRMDSTransformInfo */
17487 var hdr = parse_TransformInfoHeader(blob);
17488 /* [MS-OFFCRYPTO] 2.1.9 EncryptionTransformInfo */
17489 hdr.ename = blob.read_shift(0, '8lpp4');
17490 hdr.blksz = blob.read_shift(4);
17491 hdr.cmode = blob.read_shift(4);
17492 if(blob.read_shift(4) != 0x04) throw new Error("Bad !Primary record");
17493 return hdr;
17494}
17495
17496/* [MS-OFFCRYPTO] 2.3.2 Encryption Header */
17497function parse_EncryptionHeader(blob, length) {
17498 var tgt = blob.l + length;
17499 var o = {};
17500 o.Flags = (blob.read_shift(4) & 0x3F);
17501 blob.l += 4;
17502 o.AlgID = blob.read_shift(4);
17503 var valid = false;
17504 switch(o.AlgID) {
17505 case 0x660E: case 0x660F: case 0x6610: valid = (o.Flags == 0x24); break;
17506 case 0x6801: valid = (o.Flags == 0x04); break;
17507 case 0: valid = (o.Flags == 0x10 || o.Flags == 0x04 || o.Flags == 0x24); break;
17508 default: throw 'Unrecognized encryption algorithm: ' + o.AlgID;
17509 }
17510 if(!valid) throw new Error("Encryption Flags/AlgID mismatch");
17511 o.AlgIDHash = blob.read_shift(4);
17512 o.KeySize = blob.read_shift(4);
17513 o.ProviderType = blob.read_shift(4);
17514 blob.l += 8;
17515 o.CSPName = blob.read_shift((tgt-blob.l)>>1, 'utf16le');
17516 blob.l = tgt;
17517 return o;
17518}
17519
17520/* [MS-OFFCRYPTO] 2.3.3 Encryption Verifier */
17521function parse_EncryptionVerifier(blob, length) {
17522 var o = {}, tgt = blob.l + length;
17523 blob.l += 4; // SaltSize must be 0x10
17524 o.Salt = blob.slice(blob.l, blob.l+16); blob.l += 16;
17525 o.Verifier = blob.slice(blob.l, blob.l+16); blob.l += 16;
17526 /*var sz = */blob.read_shift(4);
17527 o.VerifierHash = blob.slice(blob.l, tgt); blob.l = tgt;
17528 return o;
17529}
17530
17531/* [MS-OFFCRYPTO] 2.3.4.* EncryptionInfo Stream */
17532function parse_EncryptionInfo(blob) {
17533 var vers = parse_CRYPTOVersion(blob);
17534 switch(vers.Minor) {
17535 case 0x02: return [vers.Minor, parse_EncInfoStd(blob, vers)];
17536 case 0x03: return [vers.Minor, parse_EncInfoExt(blob, vers)];
17537 case 0x04: return [vers.Minor, parse_EncInfoAgl(blob, vers)];
17538 }
17539 throw new Error("ECMA-376 Encrypted file unrecognized Version: " + vers.Minor);
17540}
17541
17542/* [MS-OFFCRYPTO] 2.3.4.5 EncryptionInfo Stream (Standard Encryption) */
17543function parse_EncInfoStd(blob) {
17544 var flags = blob.read_shift(4);
17545 if((flags & 0x3F) != 0x24) throw new Error("EncryptionInfo mismatch");
17546 var sz = blob.read_shift(4);
17547 //var tgt = blob.l + sz;
17548 var hdr = parse_EncryptionHeader(blob, sz);
17549 var verifier = parse_EncryptionVerifier(blob, blob.length - blob.l);
17550 return { t:"Std", h:hdr, v:verifier };
17551}
17552/* [MS-OFFCRYPTO] 2.3.4.6 EncryptionInfo Stream (Extensible Encryption) */
17553function parse_EncInfoExt() { throw new Error("File is password-protected: ECMA-376 Extensible"); }
17554/* [MS-OFFCRYPTO] 2.3.4.10 EncryptionInfo Stream (Agile Encryption) */
17555function parse_EncInfoAgl(blob) {
17556 var KeyData = ["saltSize","blockSize","keyBits","hashSize","cipherAlgorithm","cipherChaining","hashAlgorithm","saltValue"];
17557 blob.l+=4;
17558 var xml = blob.read_shift(blob.length - blob.l, 'utf8');
17559 var o = {};
17560 xml.replace(tagregex, function xml_agile(x) {
17561 var y = parsexmltag(x);
17562 switch(strip_ns(y[0])) {
17563 case '<?xml': break;
17564 case '<encryption': case '</encryption>': break;
17565 case '<keyData': KeyData.forEach(function(k) { o[k] = y[k]; }); break;
17566 case '<dataIntegrity': o.encryptedHmacKey = y.encryptedHmacKey; o.encryptedHmacValue = y.encryptedHmacValue; break;
17567 case '<keyEncryptors>': case '<keyEncryptors': o.encs = []; break;
17568 case '</keyEncryptors>': break;
17569
17570 case '<keyEncryptor': o.uri = y.uri; break;
17571 case '</keyEncryptor>': break;
17572 case '<encryptedKey': o.encs.push(y); break;
17573 default: throw y[0];
17574 }
17575 });
17576 return o;
17577}
17578
17579/* [MS-OFFCRYPTO] 2.3.5.1 RC4 CryptoAPI Encryption Header */
17580function parse_RC4CryptoHeader(blob, length) {
17581 var o = {};
17582 var vers = o.EncryptionVersionInfo = parse_CRYPTOVersion(blob, 4); length -= 4;
17583 if(vers.Minor != 2) throw new Error('unrecognized minor version code: ' + vers.Minor);
17584 if(vers.Major > 4 || vers.Major < 2) throw new Error('unrecognized major version code: ' + vers.Major);
17585 o.Flags = blob.read_shift(4); length -= 4;
17586 var sz = blob.read_shift(4); length -= 4;
17587 o.EncryptionHeader = parse_EncryptionHeader(blob, sz); length -= sz;
17588 o.EncryptionVerifier = parse_EncryptionVerifier(blob, length);
17589 return o;
17590}
17591/* [MS-OFFCRYPTO] 2.3.6.1 RC4 Encryption Header */
17592function parse_RC4Header(blob) {
17593 var o = {};
17594 var vers = o.EncryptionVersionInfo = parse_CRYPTOVersion(blob, 4);
17595 if(vers.Major != 1 || vers.Minor != 1) throw 'unrecognized version code ' + vers.Major + ' : ' + vers.Minor;
17596 o.Salt = blob.read_shift(16);
17597 o.EncryptedVerifier = blob.read_shift(16);
17598 o.EncryptedVerifierHash = blob.read_shift(16);
17599 return o;
17600}
17601
17602/* [MS-OFFCRYPTO] 2.3.7.1 Binary Document Password Verifier Derivation */
17603function crypto_CreatePasswordVerifier_Method1(Password) {
17604 var Verifier = 0x0000, PasswordArray;
17605 var PasswordDecoded = _JS2ANSI(Password);
17606 var len = PasswordDecoded.length + 1, i, PasswordByte;
17607 var Intermediate1, Intermediate2, Intermediate3;
17608 PasswordArray = new_raw_buf(len);
17609 PasswordArray[0] = PasswordDecoded.length;
17610 for(i = 1; i != len; ++i) PasswordArray[i] = PasswordDecoded[i-1];
17611 for(i = len-1; i >= 0; --i) {
17612 PasswordByte = PasswordArray[i];
17613 Intermediate1 = ((Verifier & 0x4000) === 0x0000) ? 0 : 1;
17614 Intermediate2 = (Verifier << 1) & 0x7FFF;
17615 Intermediate3 = Intermediate1 | Intermediate2;
17616 Verifier = Intermediate3 ^ PasswordByte;
17617 }
17618 return Verifier ^ 0xCE4B;
17619}
17620
17621/* [MS-OFFCRYPTO] 2.3.7.2 Binary Document XOR Array Initialization */
17622var crypto_CreateXorArray_Method1 = (function() {
17623 var PadArray = [0xBB, 0xFF, 0xFF, 0xBA, 0xFF, 0xFF, 0xB9, 0x80, 0x00, 0xBE, 0x0F, 0x00, 0xBF, 0x0F, 0x00];
17624 var InitialCode = [0xE1F0, 0x1D0F, 0xCC9C, 0x84C0, 0x110C, 0x0E10, 0xF1CE, 0x313E, 0x1872, 0xE139, 0xD40F, 0x84F9, 0x280C, 0xA96A, 0x4EC3];
17625 var XorMatrix = [0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09, 0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF, 0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0, 0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40, 0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5, 0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A, 0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9, 0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0, 0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC, 0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10, 0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168, 0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C, 0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD, 0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC, 0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4];
17626 var Ror = function(Byte) { return ((Byte/2) | (Byte*128)) & 0xFF; };
17627 var XorRor = function(byte1, byte2) { return Ror(byte1 ^ byte2); };
17628 var CreateXorKey_Method1 = function(Password) {
17629 var XorKey = InitialCode[Password.length - 1];
17630 var CurrentElement = 0x68;
17631 for(var i = Password.length-1; i >= 0; --i) {
17632 var Char = Password[i];
17633 for(var j = 0; j != 7; ++j) {
17634 if(Char & 0x40) XorKey ^= XorMatrix[CurrentElement];
17635 Char *= 2; --CurrentElement;
17636 }
17637 }
17638 return XorKey;
17639 };
17640 return function(password) {
17641 var Password = _JS2ANSI(password);
17642 var XorKey = CreateXorKey_Method1(Password);
17643 var Index = Password.length;
17644 var ObfuscationArray = new_raw_buf(16);
17645 for(var i = 0; i != 16; ++i) ObfuscationArray[i] = 0x00;
17646 var Temp, PasswordLastChar, PadIndex;
17647 if((Index & 1) === 1) {
17648 Temp = XorKey >> 8;
17649 ObfuscationArray[Index] = XorRor(PadArray[0], Temp);
17650 --Index;
17651 Temp = XorKey & 0xFF;
17652 PasswordLastChar = Password[Password.length - 1];
17653 ObfuscationArray[Index] = XorRor(PasswordLastChar, Temp);
17654 }
17655 while(Index > 0) {
17656 --Index;
17657 Temp = XorKey >> 8;
17658 ObfuscationArray[Index] = XorRor(Password[Index], Temp);
17659 --Index;
17660 Temp = XorKey & 0xFF;
17661 ObfuscationArray[Index] = XorRor(Password[Index], Temp);
17662 }
17663 Index = 15;
17664 PadIndex = 15 - Password.length;
17665 while(PadIndex > 0) {
17666 Temp = XorKey >> 8;
17667 ObfuscationArray[Index] = XorRor(PadArray[PadIndex], Temp);
17668 --Index;
17669 --PadIndex;
17670 Temp = XorKey & 0xFF;
17671 ObfuscationArray[Index] = XorRor(Password[Index], Temp);
17672 --Index;
17673 --PadIndex;
17674 }
17675 return ObfuscationArray;
17676 };
17677})();
17678
17679/* [MS-OFFCRYPTO] 2.3.7.3 Binary Document XOR Data Transformation Method 1 */
17680var crypto_DecryptData_Method1 = function(password, Data, XorArrayIndex, XorArray, O) {
17681 /* If XorArray is set, use it; if O is not set, make changes in-place */
17682 if(!O) O = Data;
17683 if(!XorArray) XorArray = crypto_CreateXorArray_Method1(password);
17684 var Index, Value;
17685 for(Index = 0; Index != Data.length; ++Index) {
17686 Value = Data[Index];
17687 Value ^= XorArray[XorArrayIndex];
17688 Value = ((Value>>5) | (Value<<3)) & 0xFF;
17689 O[Index] = Value;
17690 ++XorArrayIndex;
17691 }
17692 return [O, XorArrayIndex, XorArray];
17693};
17694
17695var crypto_MakeXorDecryptor = function(password) {
17696 var XorArrayIndex = 0, XorArray = crypto_CreateXorArray_Method1(password);
17697 return function(Data) {
17698 var O = crypto_DecryptData_Method1("", Data, XorArrayIndex, XorArray);
17699 XorArrayIndex = O[1];
17700 return O[0];
17701 };
17702};
17703
17704/* 2.5.343 */
17705function parse_XORObfuscation(blob, length, opts, out) {
17706 var o = ({ key: parseuint16(blob), verificationBytes: parseuint16(blob) });
17707 if(opts.password) o.verifier = crypto_CreatePasswordVerifier_Method1(opts.password);
17708 out.valid = o.verificationBytes === o.verifier;
17709 if(out.valid) out.insitu = crypto_MakeXorDecryptor(opts.password);
17710 return o;
17711}
17712
17713/* 2.4.117 */
17714function parse_FilePassHeader(blob, length, oo) {
17715 var o = oo || {}; o.Info = blob.read_shift(2); blob.l -= 2;
17716 if(o.Info === 1) o.Data = parse_RC4Header(blob, length);
17717 else o.Data = parse_RC4CryptoHeader(blob, length);
17718 return o;
17719}
17720function parse_FilePass(blob, length, opts) {
17721 var o = ({ Type: opts.biff >= 8 ? blob.read_shift(2) : 0 }); /* wEncryptionType */
17722 if(o.Type) parse_FilePassHeader(blob, length-2, o);
17723 else parse_XORObfuscation(blob, opts.biff >= 8 ? length : length - 2, opts, o);
17724 return o;
17725}
17726
17727
17728var RTF = (function() {
17729 function rtf_to_sheet(d, opts) {
17730 switch(opts.type) {
17731 case 'base64': return rtf_to_sheet_str(Base64.decode(d), opts);
17732 case 'binary': return rtf_to_sheet_str(d, opts);
17733 case 'buffer': return rtf_to_sheet_str(d.toString('binary'), opts);
17734 case 'array': return rtf_to_sheet_str(cc2str(d), opts);
17735 }
17736 throw new Error("Unrecognized type " + opts.type);
17737 }
17738
17739 function rtf_to_sheet_str(str, opts) {
17740 var o = opts || {};
17741 var ws = o.dense ? ([]) : ({});
17742 var range = ({s: {c:0, r:0}, e: {c:0, r:0}});
17743
17744 // TODO: parse
17745 if(!str.match(/\\trowd/)) throw new Error("RTF missing table");
17746
17747 ws['!ref'] = encode_range(range);
17748 return ws;
17749 }
17750
17751 function rtf_to_workbook(d, opts) { return sheet_to_workbook(rtf_to_sheet(d, opts), opts); }
17752
17753 /* TODO: this is a stub */
17754 function sheet_to_rtf(ws) {
17755 var o = ["{\\rtf1\\ansi"];
17756 var r = safe_decode_range(ws['!ref']), cell;
17757 var dense = Array.isArray(ws);
17758 for(var R = r.s.r; R <= r.e.r; ++R) {
17759 o.push("\\trowd\\trautofit1");
17760 for(var C = r.s.c; C <= r.e.c; ++C) o.push("\\cellx" + (C+1));
17761 o.push("\\pard\\intbl");
17762 for(C = r.s.c; C <= r.e.c; ++C) {
17763 var coord = encode_cell({r:R,c:C});
17764 cell = dense ? (ws[R]||[])[C]: ws[coord];
17765 if(!cell || cell.v == null && (!cell.f || cell.F)) continue;
17766 o.push(" " + (cell.w || (format_cell(cell), cell.w)));
17767 o.push("\\cell");
17768 }
17769 o.push("\\pard\\intbl\\row");
17770 }
17771 return o.join("") + "}";
17772 }
17773
17774 return {
17775 to_workbook: rtf_to_workbook,
17776 to_sheet: rtf_to_sheet,
17777 from_sheet: sheet_to_rtf
17778 };
17779})();
17780function hex2RGB(h) {
17781 var o = h.slice(h[0]==="#"?1:0).slice(0,6);
17782 return [parseInt(o.slice(0,2),16),parseInt(o.slice(2,4),16),parseInt(o.slice(4,6),16)];
17783}
17784function rgb2Hex(rgb) {
17785 for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]);
17786 return o.toString(16).toUpperCase().slice(1);
17787}
17788
17789function rgb2HSL(rgb) {
17790 var R = rgb[0]/255, G = rgb[1]/255, B=rgb[2]/255;
17791 var M = Math.max(R, G, B), m = Math.min(R, G, B), C = M - m;
17792 if(C === 0) return [0, 0, R];
17793
17794 var H6 = 0, S = 0, L2 = (M + m);
17795 S = C / (L2 > 1 ? 2 - L2 : L2);
17796 switch(M){
17797 case R: H6 = ((G - B) / C + 6)%6; break;
17798 case G: H6 = ((B - R) / C + 2); break;
17799 case B: H6 = ((R - G) / C + 4); break;
17800 }
17801 return [H6 / 6, S, L2 / 2];
17802}
17803
17804function hsl2RGB(hsl){
17805 var H = hsl[0], S = hsl[1], L = hsl[2];
17806 var C = S * 2 * (L < 0.5 ? L : 1 - L), m = L - C/2;
17807 var rgb = [m,m,m], h6 = 6*H;
17808
17809 var X;
17810 if(S !== 0) switch(h6|0) {
17811 case 0: case 6: X = C * h6; rgb[0] += C; rgb[1] += X; break;
17812 case 1: X = C * (2 - h6); rgb[0] += X; rgb[1] += C; break;
17813 case 2: X = C * (h6 - 2); rgb[1] += C; rgb[2] += X; break;
17814 case 3: X = C * (4 - h6); rgb[1] += X; rgb[2] += C; break;
17815 case 4: X = C * (h6 - 4); rgb[2] += C; rgb[0] += X; break;
17816 case 5: X = C * (6 - h6); rgb[2] += X; rgb[0] += C; break;
17817 }
17818 for(var i = 0; i != 3; ++i) rgb[i] = Math.round(rgb[i]*255);
17819 return rgb;
17820}
17821
17822/* 18.8.3 bgColor tint algorithm */
17823function rgb_tint(hex, tint) {
17824 if(tint === 0) return hex;
17825 var hsl = rgb2HSL(hex2RGB(hex));
17826 if (tint < 0) hsl[2] = hsl[2] * (1 + tint);
17827 else hsl[2] = 1 - (1 - hsl[2]) * (1 - tint);
17828 return rgb2Hex(hsl2RGB(hsl));
17829}
17830
17831/* 18.3.1.13 width calculations */
17832/* [MS-OI29500] 2.1.595 Column Width & Formatting */
17833var DEF_MDW = 6, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
17834function width2px(width) { return Math.floor(( width + (Math.round(128/MDW))/256 )* MDW ); }
17835function px2char(px) { return (Math.floor((px - 5)/MDW * 100 + 0.5))/100; }
17836function char2width(chr) { return (Math.round((chr * MDW + 5)/MDW*256))/256; }
17837//function px2char_(px) { return (((px - 5)/MDW * 100 + 0.5))/100; }
17838//function char2width_(chr) { return (((chr * MDW + 5)/MDW*256))/256; }
17839function cycle_width(collw) { return char2width(px2char(width2px(collw))); }
17840/* XLSX/XLSB/XLS specify width in units of MDW */
17841function find_mdw_colw(collw) {
17842 var delta = Math.abs(collw - cycle_width(collw)), _MDW = MDW;
17843 if(delta > 0.005) for(MDW=MIN_MDW; MDW<MAX_MDW; ++MDW) if(Math.abs(collw - cycle_width(collw)) <= delta) { delta = Math.abs(collw - cycle_width(collw)); _MDW = MDW; }
17844 MDW = _MDW;
17845}
17846/* XLML specifies width in terms of pixels */
17847/*function find_mdw_wpx(wpx) {
17848 var delta = Infinity, guess = 0, _MDW = MIN_MDW;
17849 for(MDW=MIN_MDW; MDW<MAX_MDW; ++MDW) {
17850 guess = char2width_(px2char_(wpx))*256;
17851 guess = (guess) % 1;
17852 if(guess > 0.5) guess--;
17853 if(Math.abs(guess) < delta) { delta = Math.abs(guess); _MDW = MDW; }
17854 }
17855 MDW = _MDW;
17856}*/
17857
17858function process_col(coll) {
17859 if(coll.width) {
17860 coll.wpx = width2px(coll.width);
17861 coll.wch = px2char(coll.wpx);
17862 coll.MDW = MDW;
17863 } else if(coll.wpx) {
17864 coll.wch = px2char(coll.wpx);
17865 coll.width = char2width(coll.wch);
17866 coll.MDW = MDW;
17867 } else if(typeof coll.wch == 'number') {
17868 coll.width = char2width(coll.wch);
17869 coll.wpx = width2px(coll.width);
17870 coll.MDW = MDW;
17871 }
17872 if(coll.customWidth) delete coll.customWidth;
17873}
17874
17875var DEF_PPI = 96, PPI = DEF_PPI;
17876function px2pt(px) { return px * 96 / PPI; }
17877function pt2px(pt) { return pt * PPI / 96; }
17878
17879/* [MS-EXSPXML3] 2.4.54 ST_enmPattern */
17880var XLMLPatternTypeMap = {
17881 "None": "none",
17882 "Solid": "solid",
17883 "Gray50": "mediumGray",
17884 "Gray75": "darkGray",
17885 "Gray25": "lightGray",
17886 "HorzStripe": "darkHorizontal",
17887 "VertStripe": "darkVertical",
17888 "ReverseDiagStripe": "darkDown",
17889 "DiagStripe": "darkUp",
17890 "DiagCross": "darkGrid",
17891 "ThickDiagCross": "darkTrellis",
17892 "ThinHorzStripe": "lightHorizontal",
17893 "ThinVertStripe": "lightVertical",
17894 "ThinReverseDiagStripe": "lightDown",
17895 "ThinHorzCross": "lightGrid"
17896};
17897
17898/* 18.8.5 borders CT_Borders */
17899function parse_borders(t, styles, themes, opts) {
17900 styles.Borders = [];
17901 var border = {};
17902 var pass = false;
17903 (t[0].match(tagregex)||[]).forEach(function(x) {
17904 var y = parsexmltag(x);
17905 switch(strip_ns(y[0])) {
17906 case '<borders': case '<borders>': case '</borders>': break;
17907
17908 /* 18.8.4 border CT_Border */
17909 case '<border': case '<border>': case '<border/>':
17910 border = {};
17911 if(y.diagonalUp) border.diagonalUp = parsexmlbool(y.diagonalUp);
17912 if(y.diagonalDown) border.diagonalDown = parsexmlbool(y.diagonalDown);
17913 styles.Borders.push(border);
17914 break;
17915 case '</border>': break;
17916
17917 /* note: not in spec, appears to be CT_BorderPr */
17918 case '<left/>': break;
17919 case '<left': case '<left>': break;
17920 case '</left>': break;
17921
17922 /* note: not in spec, appears to be CT_BorderPr */
17923 case '<right/>': break;
17924 case '<right': case '<right>': break;
17925 case '</right>': break;
17926
17927 /* 18.8.43 top CT_BorderPr */
17928 case '<top/>': break;
17929 case '<top': case '<top>': break;
17930 case '</top>': break;
17931
17932 /* 18.8.6 bottom CT_BorderPr */
17933 case '<bottom/>': break;
17934 case '<bottom': case '<bottom>': break;
17935 case '</bottom>': break;
17936
17937 /* 18.8.13 diagonal CT_BorderPr */
17938 case '<diagonal': case '<diagonal>': case '<diagonal/>': break;
17939 case '</diagonal>': break;
17940
17941 /* 18.8.25 horizontal CT_BorderPr */
17942 case '<horizontal': case '<horizontal>': case '<horizontal/>': break;
17943 case '</horizontal>': break;
17944
17945 /* 18.8.44 vertical CT_BorderPr */
17946 case '<vertical': case '<vertical>': case '<vertical/>': break;
17947 case '</vertical>': break;
17948
17949 /* 18.8.37 start CT_BorderPr */
17950 case '<start': case '<start>': case '<start/>': break;
17951 case '</start>': break;
17952
17953 /* 18.8.16 end CT_BorderPr */
17954 case '<end': case '<end>': case '<end/>': break;
17955 case '</end>': break;
17956
17957 /* 18.8.? color CT_Color */
17958 case '<color': case '<color>':
17959 break;
17960 case '<color/>': case '</color>': break;
17961
17962 /* 18.2.10 extLst CT_ExtensionList ? */
17963 case '<extLst': case '<extLst>': case '</extLst>': break;
17964 case '<ext': pass = true; break;
17965 case '</ext>': pass = false; break;
17966 default: if(opts && opts.WTF) {
17967 if(!pass) throw new Error('unrecognized ' + y[0] + ' in borders');
17968 }
17969 }
17970 });
17971}
17972
17973/* 18.8.21 fills CT_Fills */
17974function parse_fills(t, styles, themes, opts) {
17975 styles.Fills = [];
17976 var fill = {};
17977 var pass = false;
17978 (t[0].match(tagregex)||[]).forEach(function(x) {
17979 var y = parsexmltag(x);
17980 switch(strip_ns(y[0])) {
17981 case '<fills': case '<fills>': case '</fills>': break;
17982
17983 /* 18.8.20 fill CT_Fill */
17984 case '<fill>': case '<fill': case '<fill/>':
17985 fill = {}; styles.Fills.push(fill); break;
17986 case '</fill>': break;
17987
17988 /* 18.8.24 gradientFill CT_GradientFill */
17989 case '<gradientFill>': break;
17990 case '<gradientFill':
17991 case '</gradientFill>': styles.Fills.push(fill); fill = {}; break;
17992
17993 /* 18.8.32 patternFill CT_PatternFill */
17994 case '<patternFill': case '<patternFill>':
17995 if(y.patternType) fill.patternType = y.patternType;
17996 break;
17997 case '<patternFill/>': case '</patternFill>': break;
17998
17999 /* 18.8.3 bgColor CT_Color */
18000 case '<bgColor':
18001 if(!fill.bgColor) fill.bgColor = {};
18002 if(y.indexed) fill.bgColor.indexed = parseInt(y.indexed, 10);
18003 if(y.theme) fill.bgColor.theme = parseInt(y.theme, 10);
18004 if(y.tint) fill.bgColor.tint = parseFloat(y.tint);
18005 /* Excel uses ARGB strings */
18006 if(y.rgb) fill.bgColor.rgb = y.rgb.slice(-6);
18007 break;
18008 case '<bgColor/>': case '</bgColor>': break;
18009
18010 /* 18.8.19 fgColor CT_Color */
18011 case '<fgColor':
18012 if(!fill.fgColor) fill.fgColor = {};
18013 if(y.theme) fill.fgColor.theme = parseInt(y.theme, 10);
18014 if(y.tint) fill.fgColor.tint = parseFloat(y.tint);
18015 /* Excel uses ARGB strings */
18016 if(y.rgb != null) fill.fgColor.rgb = y.rgb.slice(-6);
18017 break;
18018 case '<fgColor/>': case '</fgColor>': break;
18019
18020 /* 18.8.38 stop CT_GradientStop */
18021 case '<stop': case '<stop/>': break;
18022 case '</stop>': break;
18023
18024 /* 18.8.? color CT_Color */
18025 case '<color': case '<color/>': break;
18026 case '</color>': break;
18027
18028 /* 18.2.10 extLst CT_ExtensionList ? */
18029 case '<extLst': case '<extLst>': case '</extLst>': break;
18030 case '<ext': pass = true; break;
18031 case '</ext>': pass = false; break;
18032 default: if(opts && opts.WTF) {
18033 if(!pass) throw new Error('unrecognized ' + y[0] + ' in fills');
18034 }
18035 }
18036 });
18037}
18038
18039/* 18.8.23 fonts CT_Fonts */
18040function parse_fonts(t, styles, themes, opts) {
18041 styles.Fonts = [];
18042 var font = {};
18043 var pass = false;
18044 (t[0].match(tagregex)||[]).forEach(function(x) {
18045 var y = parsexmltag(x);
18046 switch(strip_ns(y[0])) {
18047 case '<fonts': case '<fonts>': case '</fonts>': break;
18048
18049 /* 18.8.22 font CT_Font */
18050 case '<font': case '<font>': break;
18051 case '</font>': case '<font/>':
18052 styles.Fonts.push(font);
18053 font = {};
18054 break;
18055
18056 /* 18.8.29 name CT_FontName */
18057 case '<name': if(y.val) font.name = y.val; break;
18058 case '<name/>': case '</name>': break;
18059
18060 /* 18.8.2 b CT_BooleanProperty */
18061 case '<b': font.bold = y.val ? parsexmlbool(y.val) : 1; break;
18062 case '<b/>': font.bold = 1; break;
18063
18064 /* 18.8.26 i CT_BooleanProperty */
18065 case '<i': font.italic = y.val ? parsexmlbool(y.val) : 1; break;
18066 case '<i/>': font.italic = 1; break;
18067
18068 /* 18.4.13 u CT_UnderlineProperty */
18069 case '<u':
18070 switch(y.val) {
18071 case "none": font.underline = 0x00; break;
18072 case "single": font.underline = 0x01; break;
18073 case "double": font.underline = 0x02; break;
18074 case "singleAccounting": font.underline = 0x21; break;
18075 case "doubleAccounting": font.underline = 0x22; break;
18076 } break;
18077 case '<u/>': font.underline = 1; break;
18078
18079 /* 18.4.10 strike CT_BooleanProperty */
18080 case '<strike': font.strike = y.val ? parsexmlbool(y.val) : 1; break;
18081 case '<strike/>': font.strike = 1; break;
18082
18083 /* 18.4.2 outline CT_BooleanProperty */
18084 case '<outline': font.outline = y.val ? parsexmlbool(y.val) : 1; break;
18085 case '<outline/>': font.outline = 1; break;
18086
18087 /* 18.8.36 shadow CT_BooleanProperty */
18088 case '<shadow': font.shadow = y.val ? parsexmlbool(y.val) : 1; break;
18089 case '<shadow/>': font.shadow = 1; break;
18090
18091 /* 18.8.12 condense CT_BooleanProperty */
18092 case '<condense': font.condense = y.val ? parsexmlbool(y.val) : 1; break;
18093 case '<condense/>': font.condense = 1; break;
18094
18095 /* 18.8.17 extend CT_BooleanProperty */
18096 case '<extend': font.extend = y.val ? parsexmlbool(y.val) : 1; break;
18097 case '<extend/>': font.extend = 1; break;
18098
18099 /* 18.4.11 sz CT_FontSize */
18100 case '<sz': if(y.val) font.sz = +y.val; break;
18101 case '<sz/>': case '</sz>': break;
18102
18103 /* 18.4.14 vertAlign CT_VerticalAlignFontProperty */
18104 case '<vertAlign': if(y.val) font.vertAlign = y.val; break;
18105 case '<vertAlign/>': case '</vertAlign>': break;
18106
18107 /* 18.8.18 family CT_FontFamily */
18108 case '<family': if(y.val) font.family = parseInt(y.val,10); break;
18109 case '<family/>': case '</family>': break;
18110
18111 /* 18.8.35 scheme CT_FontScheme */
18112 case '<scheme': if(y.val) font.scheme = y.val; break;
18113 case '<scheme/>': case '</scheme>': break;
18114
18115 /* 18.4.1 charset CT_IntProperty */
18116 case '<charset':
18117 if(y.val == '1') break;
18118 y.codepage = CS2CP[parseInt(y.val, 10)];
18119 break;
18120
18121 /* 18.?.? color CT_Color */
18122 case '<color':
18123 if(!font.color) font.color = {};
18124 if(y.auto) font.color.auto = parsexmlbool(y.auto);
18125
18126 if(y.rgb) font.color.rgb = y.rgb.slice(-6);
18127 else if(y.indexed) {
18128 font.color.index = parseInt(y.indexed, 10);
18129 var icv = XLSIcv[font.color.index];
18130 if(font.color.index == 81) icv = XLSIcv[1];
18131 if(!icv) throw new Error(x);
18132 font.color.rgb = icv[0].toString(16) + icv[1].toString(16) + icv[2].toString(16);
18133 } else if(y.theme) {
18134 font.color.theme = parseInt(y.theme, 10);
18135 if(y.tint) font.color.tint = parseFloat(y.tint);
18136 if(y.theme && themes.themeElements && themes.themeElements.clrScheme) {
18137 font.color.rgb = rgb_tint(themes.themeElements.clrScheme[font.color.theme].rgb, font.color.tint || 0);
18138 }
18139 }
18140
18141 break;
18142 case '<color/>': case '</color>': break;
18143
18144 /* note: sometimes mc:AlternateContent appears bare */
18145 case '<AlternateContent': pass = true; break;
18146 case '</AlternateContent>': pass = false; break;
18147
18148 /* 18.2.10 extLst CT_ExtensionList ? */
18149 case '<extLst': case '<extLst>': case '</extLst>': break;
18150 case '<ext': pass = true; break;
18151 case '</ext>': pass = false; break;
18152 default: if(opts && opts.WTF) {
18153 if(!pass) throw new Error('unrecognized ' + y[0] + ' in fonts');
18154 }
18155 }
18156 });
18157}
18158
18159/* 18.8.31 numFmts CT_NumFmts */
18160function parse_numFmts(t, styles, opts) {
18161 styles.NumberFmt = [];
18162 var k/*Array<number>*/ = (keys(SSF._table));
18163 for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
18164 var m = t[0].match(tagregex);
18165 if(!m) return;
18166 for(i=0; i < m.length; ++i) {
18167 var y = parsexmltag(m[i]);
18168 switch(strip_ns(y[0])) {
18169 case '<numFmts': case '</numFmts>': case '<numFmts/>': case '<numFmts>': break;
18170 case '<numFmt': {
18171 var f=unescapexml(utf8read(y.formatCode)), j=parseInt(y.numFmtId,10);
18172 styles.NumberFmt[j] = f;
18173 if(j>0) {
18174 if(j > 0x188) {
18175 for(j = 0x188; j > 0x3c; --j) if(styles.NumberFmt[j] == null) break;
18176 styles.NumberFmt[j] = f;
18177 }
18178 SSF.load(f,j);
18179 }
18180 } break;
18181 case '</numFmt>': break;
18182 default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in numFmts');
18183 }
18184 }
18185}
18186
18187function write_numFmts(NF) {
18188 var o = ["<numFmts>"];
18189 [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
18190 for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) o[o.length] = (writextag('numFmt',null,{numFmtId:i,formatCode:escapexml(NF[i])}));
18191 });
18192 if(o.length === 1) return "";
18193 o[o.length] = ("</numFmts>");
18194 o[0] = writextag('numFmts', null, { count:o.length-2 }).replace("/>", ">");
18195 return o.join("");
18196}
18197
18198/* 18.8.10 cellXfs CT_CellXfs */
18199var cellXF_uint = [ "numFmtId", "fillId", "fontId", "borderId", "xfId" ];
18200var cellXF_bool = [ "applyAlignment", "applyBorder", "applyFill", "applyFont", "applyNumberFormat", "applyProtection", "pivotButton", "quotePrefix" ];
18201function parse_cellXfs(t, styles, opts) {
18202 styles.CellXf = [];
18203 var xf;
18204 var pass = false;
18205 (t[0].match(tagregex)||[]).forEach(function(x) {
18206 var y = parsexmltag(x), i = 0;
18207 switch(strip_ns(y[0])) {
18208 case '<cellXfs': case '<cellXfs>': case '<cellXfs/>': case '</cellXfs>': break;
18209
18210 /* 18.8.45 xf CT_Xf */
18211 case '<xf': case '<xf/>':
18212 xf = y;
18213 delete xf[0];
18214 for(i = 0; i < cellXF_uint.length; ++i) if(xf[cellXF_uint[i]])
18215 xf[cellXF_uint[i]] = parseInt(xf[cellXF_uint[i]], 10);
18216 for(i = 0; i < cellXF_bool.length; ++i) if(xf[cellXF_bool[i]])
18217 xf[cellXF_bool[i]] = parsexmlbool(xf[cellXF_bool[i]]);
18218 if(xf.numFmtId > 0x188) {
18219 for(i = 0x188; i > 0x3c; --i) if(styles.NumberFmt[xf.numFmtId] == styles.NumberFmt[i]) { xf.numFmtId = i; break; }
18220 }
18221 styles.CellXf.push(xf); break;
18222 case '</xf>': break;
18223
18224 /* 18.8.1 alignment CT_CellAlignment */
18225 case '<alignment': case '<alignment/>':
18226 var alignment = {};
18227 if(y.vertical) alignment.vertical = y.vertical;
18228 if(y.horizontal) alignment.horizontal = y.horizontal;
18229 if(y.textRotation != null) alignment.textRotation = y.textRotation;
18230 if(y.indent) alignment.indent = y.indent;
18231 if(y.wrapText) alignment.wrapText = parsexmlbool(y.wrapText);
18232 xf.alignment = alignment;
18233 break;
18234 case '</alignment>': break;
18235
18236 /* 18.8.33 protection CT_CellProtection */
18237 case '<protection':
18238 break;
18239 case '</protection>': case '<protection/>': break;
18240
18241 /* note: sometimes mc:AlternateContent appears bare */
18242 case '<AlternateContent': pass = true; break;
18243 case '</AlternateContent>': pass = false; break;
18244
18245 /* 18.2.10 extLst CT_ExtensionList ? */
18246 case '<extLst': case '<extLst>': case '</extLst>': break;
18247 case '<ext': pass = true; break;
18248 case '</ext>': pass = false; break;
18249 default: if(opts && opts.WTF) {
18250 if(!pass) throw new Error('unrecognized ' + y[0] + ' in cellXfs');
18251 }
18252 }
18253 });
18254}
18255
18256function write_cellXfs(cellXfs) {
18257 var o = [];
18258 o[o.length] = (writextag('cellXfs',null));
18259 cellXfs.forEach(function(c) {
18260 o[o.length] = (writextag('xf', null, c));
18261 });
18262 o[o.length] = ("</cellXfs>");
18263 if(o.length === 2) return "";
18264 o[0] = writextag('cellXfs',null, {count:o.length-2}).replace("/>",">");
18265 return o.join("");
18266}
18267
18268/* 18.8 Styles CT_Stylesheet*/
18269var parse_sty_xml= (function make_pstyx() {
18270var numFmtRegex = /<(?:\w+:)?numFmts([^>]*)>[\S\s]*?<\/(?:\w+:)?numFmts>/;
18271var cellXfRegex = /<(?:\w+:)?cellXfs([^>]*)>[\S\s]*?<\/(?:\w+:)?cellXfs>/;
18272var fillsRegex = /<(?:\w+:)?fills([^>]*)>[\S\s]*?<\/(?:\w+:)?fills>/;
18273var fontsRegex = /<(?:\w+:)?fonts([^>]*)>[\S\s]*?<\/(?:\w+:)?fonts>/;
18274var bordersRegex = /<(?:\w+:)?borders([^>]*)>[\S\s]*?<\/(?:\w+:)?borders>/;
18275
18276return function parse_sty_xml(data, themes, opts) {
18277 var styles = {};
18278 if(!data) return styles;
18279 data = data.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
18280 /* 18.8.39 styleSheet CT_Stylesheet */
18281 var t;
18282
18283 /* 18.8.31 numFmts CT_NumFmts ? */
18284 if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts);
18285
18286 /* 18.8.23 fonts CT_Fonts ? */
18287 if((t=data.match(fontsRegex))) parse_fonts(t, styles, themes, opts);
18288
18289 /* 18.8.21 fills CT_Fills ? */
18290 if((t=data.match(fillsRegex))) parse_fills(t, styles, themes, opts);
18291
18292 /* 18.8.5 borders CT_Borders ? */
18293 if((t=data.match(bordersRegex))) parse_borders(t, styles, themes, opts);
18294
18295 /* 18.8.9 cellStyleXfs CT_CellStyleXfs ? */
18296
18297 /* 18.8.10 cellXfs CT_CellXfs ? */
18298 if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts);
18299
18300 /* 18.8.8 cellStyles CT_CellStyles ? */
18301 /* 18.8.15 dxfs CT_Dxfs ? */
18302 /* 18.8.42 tableStyles CT_TableStyles ? */
18303 /* 18.8.11 colors CT_Colors ? */
18304 /* 18.2.10 extLst CT_ExtensionList ? */
18305
18306 return styles;
18307};
18308})();
18309
18310var STYLES_XML_ROOT = writextag('styleSheet', null, {
18311 'xmlns': XMLNS.main[0],
18312 'xmlns:vt': XMLNS.vt
18313});
18314
18315RELS.STY = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
18316
18317function write_sty_xml(wb, opts) {
18318 var o = [XML_HEADER, STYLES_XML_ROOT], w;
18319 if(wb.SSF && (w = write_numFmts(wb.SSF)) != null) o[o.length] = w;
18320 o[o.length] = ('<fonts count="1"><font><sz val="12"/><color theme="1"/><name val="Calibri"/><family val="2"/><scheme val="minor"/></font></fonts>');
18321 o[o.length] = ('<fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills>');
18322 o[o.length] = ('<borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders>');
18323 o[o.length] = ('<cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs>');
18324 if((w = write_cellXfs(opts.cellXfs))) o[o.length] = (w);
18325 o[o.length] = ('<cellStyles count="1"><cellStyle name="Normal" xfId="0" builtinId="0"/></cellStyles>');
18326 o[o.length] = ('<dxfs count="0"/>');
18327 o[o.length] = ('<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleMedium4"/>');
18328
18329 if(o.length>2){ o[o.length] = ('</styleSheet>'); o[1]=o[1].replace("/>",">"); }
18330 return o.join("");
18331}
18332/* [MS-XLSB] 2.4.657 BrtFmt */
18333function parse_BrtFmt(data, length) {
18334 var numFmtId = data.read_shift(2);
18335 var stFmtCode = parse_XLWideString(data,length-2);
18336 return [numFmtId, stFmtCode];
18337}
18338function write_BrtFmt(i, f, o) {
18339 if(!o) o = new_buf(6 + 4 * f.length);
18340 o.write_shift(2, i);
18341 write_XLWideString(f, o);
18342 var out = (o.length > o.l) ? o.slice(0, o.l) : o;
18343 if(o.l == null) o.l = o.length;
18344 return out;
18345}
18346
18347/* [MS-XLSB] 2.4.659 BrtFont TODO */
18348function parse_BrtFont(data, length, opts) {
18349 var out = ({});
18350
18351 out.sz = data.read_shift(2) / 20;
18352
18353 var grbit = parse_FontFlags(data, 2, opts);
18354 if(grbit.fItalic) out.italic = 1;
18355 if(grbit.fCondense) out.condense = 1;
18356 if(grbit.fExtend) out.extend = 1;
18357 if(grbit.fShadow) out.shadow = 1;
18358 if(grbit.fOutline) out.outline = 1;
18359 if(grbit.fStrikeout) out.strike = 1;
18360
18361 var bls = data.read_shift(2);
18362 if(bls === 0x02BC) out.bold = 1;
18363
18364 switch(data.read_shift(2)) {
18365 /* case 0: out.vertAlign = "baseline"; break; */
18366 case 1: out.vertAlign = "superscript"; break;
18367 case 2: out.vertAlign = "subscript"; break;
18368 }
18369
18370 var underline = data.read_shift(1);
18371 if(underline != 0) out.underline = underline;
18372
18373 var family = data.read_shift(1);
18374 if(family > 0) out.family = family;
18375
18376 var bCharSet = data.read_shift(1);
18377 if(bCharSet > 0) out.charset = bCharSet;
18378
18379 data.l++;
18380 out.color = parse_BrtColor(data, 8);
18381
18382 switch(data.read_shift(1)) {
18383 /* case 0: out.scheme = "none": break; */
18384 case 1: out.scheme = "major"; break;
18385 case 2: out.scheme = "minor"; break;
18386 }
18387
18388 out.name = parse_XLWideString(data, length - 21);
18389
18390 return out;
18391}
18392function write_BrtFont(font, o) {
18393 if(!o) o = new_buf(25+4*32);
18394 o.write_shift(2, font.sz * 20);
18395 write_FontFlags(font, o);
18396 o.write_shift(2, font.bold ? 0x02BC : 0x0190);
18397 var sss = 0;
18398 if(font.vertAlign == "superscript") sss = 1;
18399 else if(font.vertAlign == "subscript") sss = 2;
18400 o.write_shift(2, sss);
18401 o.write_shift(1, font.underline || 0);
18402 o.write_shift(1, font.family || 0);
18403 o.write_shift(1, font.charset || 0);
18404 o.write_shift(1, 0);
18405 write_BrtColor(font.color, o);
18406 var scheme = 0;
18407 if(font.scheme == "major") scheme = 1;
18408 if(font.scheme == "minor") scheme = 2;
18409 o.write_shift(1, scheme);
18410 write_XLWideString(font.name, o);
18411 return o.length > o.l ? o.slice(0, o.l) : o;
18412}
18413
18414/* [MS-XLSB] 2.4.650 BrtFill */
18415var XLSBFillPTNames = [
18416 "none",
18417 "solid",
18418 "mediumGray",
18419 "darkGray",
18420 "lightGray",
18421 "darkHorizontal",
18422 "darkVertical",
18423 "darkDown",
18424 "darkUp",
18425 "darkGrid",
18426 "darkTrellis",
18427 "lightHorizontal",
18428 "lightVertical",
18429 "lightDown",
18430 "lightUp",
18431 "lightGrid",
18432 "lightTrellis",
18433 "gray125",
18434 "gray0625"
18435];
18436var rev_XLSBFillPTNames = (evert(XLSBFillPTNames));
18437/* TODO: gradient fill representation */
18438var parse_BrtFill = parsenoop;
18439function write_BrtFill(fill, o) {
18440 if(!o) o = new_buf(4*3 + 8*7 + 16*1);
18441 var fls = rev_XLSBFillPTNames[fill.patternType];
18442 if(fls == null) fls = 0x28;
18443 o.write_shift(4, fls);
18444 var j = 0;
18445 if(fls != 0x28) {
18446 /* TODO: custom FG Color */
18447 write_BrtColor({auto:1}, o);
18448 /* TODO: custom BG Color */
18449 write_BrtColor({auto:1}, o);
18450
18451 for(; j < 12; ++j) o.write_shift(4, 0);
18452 } else {
18453 for(; j < 4; ++j) o.write_shift(4, 0);
18454
18455 for(; j < 12; ++j) o.write_shift(4, 0); /* TODO */
18456 /* iGradientType */
18457 /* xnumDegree */
18458 /* xnumFillToLeft */
18459 /* xnumFillToRight */
18460 /* xnumFillToTop */
18461 /* xnumFillToBottom */
18462 /* cNumStop */
18463 /* xfillGradientStop */
18464 }
18465 return o.length > o.l ? o.slice(0, o.l) : o;
18466}
18467
18468/* [MS-XLSB] 2.4.824 BrtXF */
18469function parse_BrtXF(data, length) {
18470 var tgt = data.l + length;
18471 var ixfeParent = data.read_shift(2);
18472 var ifmt = data.read_shift(2);
18473 data.l = tgt;
18474 return {ixfe:ixfeParent, numFmtId:ifmt };
18475}
18476function write_BrtXF(data, ixfeP, o) {
18477 if(!o) o = new_buf(16);
18478 o.write_shift(2, ixfeP||0);
18479 o.write_shift(2, data.numFmtId||0);
18480 o.write_shift(2, 0); /* iFont */
18481 o.write_shift(2, 0); /* iFill */
18482 o.write_shift(2, 0); /* ixBorder */
18483 o.write_shift(1, 0); /* trot */
18484 o.write_shift(1, 0); /* indent */
18485 var flow = 0;
18486 o.write_shift(1, flow); /* flags */
18487 o.write_shift(1, 0); /* flags */
18488 o.write_shift(1, 0); /* xfGrbitAtr */
18489 o.write_shift(1, 0);
18490 return o;
18491}
18492
18493/* [MS-XLSB] 2.5.4 Blxf TODO */
18494function write_Blxf(data, o) {
18495 if(!o) o = new_buf(10);
18496 o.write_shift(1, 0); /* dg */
18497 o.write_shift(1, 0);
18498 o.write_shift(4, 0); /* color */
18499 o.write_shift(4, 0); /* color */
18500 return o;
18501}
18502/* [MS-XLSB] 2.4.302 BrtBorder TODO */
18503var parse_BrtBorder = parsenoop;
18504function write_BrtBorder(border, o) {
18505 if(!o) o = new_buf(51);
18506 o.write_shift(1, 0); /* diagonal */
18507 write_Blxf(null, o); /* top */
18508 write_Blxf(null, o); /* bottom */
18509 write_Blxf(null, o); /* left */
18510 write_Blxf(null, o); /* right */
18511 write_Blxf(null, o); /* diag */
18512 return o.length > o.l ? o.slice(0, o.l) : o;
18513}
18514
18515/* [MS-XLSB] 2.4.763 BrtStyle TODO */
18516function write_BrtStyle(style, o) {
18517 if(!o) o = new_buf(12+4*10);
18518 o.write_shift(4, style.xfId);
18519 o.write_shift(2, 1);
18520 o.write_shift(1, +style.builtinId);
18521 o.write_shift(1, 0); /* iLevel */
18522 write_XLNullableWideString(style.name || "", o);
18523 return o.length > o.l ? o.slice(0, o.l) : o;
18524}
18525
18526/* [MS-XLSB] 2.4.272 BrtBeginTableStyles */
18527function write_BrtBeginTableStyles(cnt, defTableStyle, defPivotStyle) {
18528 var o = new_buf(4+256*2*4);
18529 o.write_shift(4, cnt);
18530 write_XLNullableWideString(defTableStyle, o);
18531 write_XLNullableWideString(defPivotStyle, o);
18532 return o.length > o.l ? o.slice(0, o.l) : o;
18533}
18534
18535/* [MS-XLSB] 2.1.7.50 Styles */
18536function parse_sty_bin(data, themes, opts) {
18537 var styles = {};
18538 styles.NumberFmt = ([]);
18539 for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y];
18540
18541 styles.CellXf = [];
18542 styles.Fonts = [];
18543 var state = [];
18544 var pass = false;
18545 recordhopper(data, function hopper_sty(val, R_n, RT) {
18546 switch(RT) {
18547 case 0x002C: /* 'BrtFmt' */
18548 styles.NumberFmt[val[0]] = val[1]; SSF.load(val[1], val[0]);
18549 break;
18550 case 0x002B: /* 'BrtFont' */
18551 styles.Fonts.push(val);
18552 if(val.color.theme != null && themes && themes.themeElements && themes.themeElements.clrScheme) {
18553 val.color.rgb = rgb_tint(themes.themeElements.clrScheme[val.color.theme].rgb, val.color.tint || 0);
18554 }
18555 break;
18556 case 0x0401: /* 'BrtKnownFonts' */ break;
18557 case 0x002D: /* 'BrtFill' */
18558 break;
18559 case 0x002E: /* 'BrtBorder' */
18560 break;
18561 case 0x002F: /* 'BrtXF' */
18562 if(state[state.length - 1] == "BrtBeginCellXFs") {
18563 styles.CellXf.push(val);
18564 }
18565 break;
18566 case 0x0030: /* 'BrtStyle' */
18567 case 0x01FB: /* 'BrtDXF' */
18568 case 0x023C: /* 'BrtMRUColor' */
18569 case 0x01DB: /* 'BrtIndexedColor': */
18570 break;
18571
18572 case 0x0493: /* 'BrtDXF14' */
18573 case 0x0836: /* 'BrtDXF15' */
18574 case 0x046A: /* 'BrtSlicerStyleElement' */
18575 case 0x0200: /* 'BrtTableStyleElement' */
18576 case 0x082F: /* 'BrtTimelineStyleElement' */
18577 case 0x0C00: /* 'BrtUid' */
18578 break;
18579
18580 case 0x0023: /* 'BrtFRTBegin' */
18581 pass = true; break;
18582 case 0x0024: /* 'BrtFRTEnd' */
18583 pass = false; break;
18584 case 0x0025: /* 'BrtACBegin' */
18585 state.push(R_n); pass = true; break;
18586 case 0x0026: /* 'BrtACEnd' */
18587 state.pop(); pass = false; break;
18588
18589 default:
18590 if((R_n||"").indexOf("Begin") > 0) state.push(R_n);
18591 else if((R_n||"").indexOf("End") > 0) state.pop();
18592 else if(!pass || (opts.WTF && state[state.length-1] != "BrtACBegin")) throw new Error("Unexpected record " + RT + " " + R_n);
18593 }
18594 });
18595 return styles;
18596}
18597
18598function write_FMTS_bin(ba, NF) {
18599 if(!NF) return;
18600 var cnt = 0;
18601 [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
18602for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) ++cnt;
18603 });
18604
18605 if(cnt == 0) return;
18606 write_record(ba, "BrtBeginFmts", write_UInt32LE(cnt));
18607 [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
18608for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_record(ba, "BrtFmt", write_BrtFmt(i, NF[i]));
18609 });
18610 write_record(ba, "BrtEndFmts");
18611}
18612
18613function write_FONTS_bin(ba) {
18614 var cnt = 1;
18615
18616 if(cnt == 0) return;
18617 write_record(ba, "BrtBeginFonts", write_UInt32LE(cnt));
18618 write_record(ba, "BrtFont", write_BrtFont({
18619 sz:12,
18620 color: {theme:1},
18621 name: "Calibri",
18622 family: 2,
18623 scheme: "minor"
18624 }));
18625 /* 1*65491BrtFont [ACFONTS] */
18626 write_record(ba, "BrtEndFonts");
18627}
18628
18629function write_FILLS_bin(ba) {
18630 var cnt = 2;
18631
18632 if(cnt == 0) return;
18633 write_record(ba, "BrtBeginFills", write_UInt32LE(cnt));
18634 write_record(ba, "BrtFill", write_BrtFill({patternType:"none"}));
18635 write_record(ba, "BrtFill", write_BrtFill({patternType:"gray125"}));
18636 /* 1*65431BrtFill */
18637 write_record(ba, "BrtEndFills");
18638}
18639
18640function write_BORDERS_bin(ba) {
18641 var cnt = 1;
18642
18643 if(cnt == 0) return;
18644 write_record(ba, "BrtBeginBorders", write_UInt32LE(cnt));
18645 write_record(ba, "BrtBorder", write_BrtBorder({}));
18646 /* 1*65430BrtBorder */
18647 write_record(ba, "BrtEndBorders");
18648}
18649
18650function write_CELLSTYLEXFS_bin(ba) {
18651 var cnt = 1;
18652 write_record(ba, "BrtBeginCellStyleXFs", write_UInt32LE(cnt));
18653 write_record(ba, "BrtXF", write_BrtXF({
18654 numFmtId: 0,
18655 fontId: 0,
18656 fillId: 0,
18657 borderId: 0
18658 }, 0xFFFF));
18659 /* 1*65430(BrtXF *FRT) */
18660 write_record(ba, "BrtEndCellStyleXFs");
18661}
18662
18663function write_CELLXFS_bin(ba, data) {
18664 write_record(ba, "BrtBeginCellXFs", write_UInt32LE(data.length));
18665 data.forEach(function(c) { write_record(ba, "BrtXF", write_BrtXF(c,0)); });
18666 /* 1*65430(BrtXF *FRT) */
18667 write_record(ba, "BrtEndCellXFs");
18668}
18669
18670function write_STYLES_bin(ba) {
18671 var cnt = 1;
18672
18673 write_record(ba, "BrtBeginStyles", write_UInt32LE(cnt));
18674 write_record(ba, "BrtStyle", write_BrtStyle({
18675 xfId:0,
18676 builtinId:0,
18677 name:"Normal"
18678 }));
18679 /* 1*65430(BrtStyle *FRT) */
18680 write_record(ba, "BrtEndStyles");
18681}
18682
18683function write_DXFS_bin(ba) {
18684 var cnt = 0;
18685
18686 write_record(ba, "BrtBeginDXFs", write_UInt32LE(cnt));
18687 /* *2147483647(BrtDXF *FRT) */
18688 write_record(ba, "BrtEndDXFs");
18689}
18690
18691function write_TABLESTYLES_bin(ba) {
18692 var cnt = 0;
18693
18694 write_record(ba, "BrtBeginTableStyles", write_BrtBeginTableStyles(cnt, "TableStyleMedium9", "PivotStyleMedium4"));
18695 /* *TABLESTYLE */
18696 write_record(ba, "BrtEndTableStyles");
18697}
18698
18699function write_COLORPALETTE_bin() {
18700 return;
18701 /* BrtBeginColorPalette [INDEXEDCOLORS] [MRUCOLORS] BrtEndColorPalette */
18702}
18703
18704/* [MS-XLSB] 2.1.7.50 Styles */
18705function write_sty_bin(wb, opts) {
18706 var ba = buf_array();
18707 write_record(ba, "BrtBeginStyleSheet");
18708 write_FMTS_bin(ba, wb.SSF);
18709 write_FONTS_bin(ba, wb);
18710 write_FILLS_bin(ba, wb);
18711 write_BORDERS_bin(ba, wb);
18712 write_CELLSTYLEXFS_bin(ba, wb);
18713 write_CELLXFS_bin(ba, opts.cellXfs);
18714 write_STYLES_bin(ba, wb);
18715 write_DXFS_bin(ba, wb);
18716 write_TABLESTYLES_bin(ba, wb);
18717 write_COLORPALETTE_bin(ba, wb);
18718 /* FRTSTYLESHEET*/
18719 write_record(ba, "BrtEndStyleSheet");
18720 return ba.end();
18721}
18722RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
18723
18724/* 20.1.6.2 clrScheme CT_ColorScheme */
18725function parse_clrScheme(t, themes, opts) {
18726 themes.themeElements.clrScheme = [];
18727 var color = {};
18728 (t[0].match(tagregex)||[]).forEach(function(x) {
18729 var y = parsexmltag(x);
18730 switch(y[0]) {
18731 /* 20.1.6.2 clrScheme (Color Scheme) CT_ColorScheme */
18732 case '<a:clrScheme': case '</a:clrScheme>': break;
18733
18734 /* 20.1.2.3.32 srgbClr CT_SRgbColor */
18735 case '<a:srgbClr':
18736 color.rgb = y.val; break;
18737
18738 /* 20.1.2.3.33 sysClr CT_SystemColor */
18739 case '<a:sysClr':
18740 color.rgb = y.lastClr; break;
18741
18742 /* 20.1.4.1.1 accent1 (Accent 1) */
18743 /* 20.1.4.1.2 accent2 (Accent 2) */
18744 /* 20.1.4.1.3 accent3 (Accent 3) */
18745 /* 20.1.4.1.4 accent4 (Accent 4) */
18746 /* 20.1.4.1.5 accent5 (Accent 5) */
18747 /* 20.1.4.1.6 accent6 (Accent 6) */
18748 /* 20.1.4.1.9 dk1 (Dark 1) */
18749 /* 20.1.4.1.10 dk2 (Dark 2) */
18750 /* 20.1.4.1.15 folHlink (Followed Hyperlink) */
18751 /* 20.1.4.1.19 hlink (Hyperlink) */
18752 /* 20.1.4.1.22 lt1 (Light 1) */
18753 /* 20.1.4.1.23 lt2 (Light 2) */
18754 case '<a:dk1>': case '</a:dk1>':
18755 case '<a:lt1>': case '</a:lt1>':
18756 case '<a:dk2>': case '</a:dk2>':
18757 case '<a:lt2>': case '</a:lt2>':
18758 case '<a:accent1>': case '</a:accent1>':
18759 case '<a:accent2>': case '</a:accent2>':
18760 case '<a:accent3>': case '</a:accent3>':
18761 case '<a:accent4>': case '</a:accent4>':
18762 case '<a:accent5>': case '</a:accent5>':
18763 case '<a:accent6>': case '</a:accent6>':
18764 case '<a:hlink>': case '</a:hlink>':
18765 case '<a:folHlink>': case '</a:folHlink>':
18766 if (y[0].charAt(1) === '/') {
18767 themes.themeElements.clrScheme.push(color);
18768 color = {};
18769 } else {
18770 color.name = y[0].slice(3, y[0].length - 1);
18771 }
18772 break;
18773
18774 default: if(opts && opts.WTF) throw new Error('Unrecognized ' + y[0] + ' in clrScheme');
18775 }
18776 });
18777}
18778
18779/* 20.1.4.1.18 fontScheme CT_FontScheme */
18780function parse_fontScheme() { }
18781
18782/* 20.1.4.1.15 fmtScheme CT_StyleMatrix */
18783function parse_fmtScheme() { }
18784
18785var clrsregex = /<a:clrScheme([^>]*)>[\s\S]*<\/a:clrScheme>/;
18786var fntsregex = /<a:fontScheme([^>]*)>[\s\S]*<\/a:fontScheme>/;
18787var fmtsregex = /<a:fmtScheme([^>]*)>[\s\S]*<\/a:fmtScheme>/;
18788
18789/* 20.1.6.10 themeElements CT_BaseStyles */
18790function parse_themeElements(data, themes, opts) {
18791 themes.themeElements = {};
18792
18793 var t;
18794
18795 [
18796 /* clrScheme CT_ColorScheme */
18797 ['clrScheme', clrsregex, parse_clrScheme],
18798 /* fontScheme CT_FontScheme */
18799 ['fontScheme', fntsregex, parse_fontScheme],
18800 /* fmtScheme CT_StyleMatrix */
18801 ['fmtScheme', fmtsregex, parse_fmtScheme]
18802 ].forEach(function(m) {
18803 if(!(t=data.match(m[1]))) throw new Error(m[0] + ' not found in themeElements');
18804 m[2](t, themes, opts);
18805 });
18806}
18807
18808var themeltregex = /<a:themeElements([^>]*)>[\s\S]*<\/a:themeElements>/;
18809
18810/* 14.2.7 Theme Part */
18811function parse_theme_xml(data, opts) {
18812 /* 20.1.6.9 theme CT_OfficeStyleSheet */
18813 if(!data || data.length === 0) return parse_theme_xml(write_theme());
18814
18815 var t;
18816 var themes = {};
18817
18818 /* themeElements CT_BaseStyles */
18819 if(!(t=data.match(themeltregex))) throw new Error('themeElements not found in theme');
18820 parse_themeElements(t[0], themes, opts);
18821 themes.raw = data;
18822 return themes;
18823}
18824
18825function write_theme(Themes, opts) {
18826 if(opts && opts.themeXLSX) return opts.themeXLSX;
18827 if(Themes && typeof Themes.raw == "string") return Themes.raw;
18828 var o = [XML_HEADER];
18829 o[o.length] = '<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">';
18830 o[o.length] = '<a:themeElements>';
18831
18832 o[o.length] = '<a:clrScheme name="Office">';
18833 o[o.length] = '<a:dk1><a:sysClr val="windowText" lastClr="000000"/></a:dk1>';
18834 o[o.length] = '<a:lt1><a:sysClr val="window" lastClr="FFFFFF"/></a:lt1>';
18835 o[o.length] = '<a:dk2><a:srgbClr val="1F497D"/></a:dk2>';
18836 o[o.length] = '<a:lt2><a:srgbClr val="EEECE1"/></a:lt2>';
18837 o[o.length] = '<a:accent1><a:srgbClr val="4F81BD"/></a:accent1>';
18838 o[o.length] = '<a:accent2><a:srgbClr val="C0504D"/></a:accent2>';
18839 o[o.length] = '<a:accent3><a:srgbClr val="9BBB59"/></a:accent3>';
18840 o[o.length] = '<a:accent4><a:srgbClr val="8064A2"/></a:accent4>';
18841 o[o.length] = '<a:accent5><a:srgbClr val="4BACC6"/></a:accent5>';
18842 o[o.length] = '<a:accent6><a:srgbClr val="F79646"/></a:accent6>';
18843 o[o.length] = '<a:hlink><a:srgbClr val="0000FF"/></a:hlink>';
18844 o[o.length] = '<a:folHlink><a:srgbClr val="800080"/></a:folHlink>';
18845 o[o.length] = '</a:clrScheme>';
18846
18847 o[o.length] = '<a:fontScheme name="Office">';
18848 o[o.length] = '<a:majorFont>';
18849 o[o.length] = '<a:latin typeface="Cambria"/>';
18850 o[o.length] = '<a:ea typeface=""/>';
18851 o[o.length] = '<a:cs typeface=""/>';
18852 o[o.length] = '<a:font script="Jpan" typeface="MS Pゴシック"/>';
18853 o[o.length] = '<a:font script="Hang" typeface="맑은 고딕"/>';
18854 o[o.length] = '<a:font script="Hans" typeface="宋体"/>';
18855 o[o.length] = '<a:font script="Hant" typeface="新細明體"/>';
18856 o[o.length] = '<a:font script="Arab" typeface="Times New Roman"/>';
18857 o[o.length] = '<a:font script="Hebr" typeface="Times New Roman"/>';
18858 o[o.length] = '<a:font script="Thai" typeface="Tahoma"/>';
18859 o[o.length] = '<a:font script="Ethi" typeface="Nyala"/>';
18860 o[o.length] = '<a:font script="Beng" typeface="Vrinda"/>';
18861 o[o.length] = '<a:font script="Gujr" typeface="Shruti"/>';
18862 o[o.length] = '<a:font script="Khmr" typeface="MoolBoran"/>';
18863 o[o.length] = '<a:font script="Knda" typeface="Tunga"/>';
18864 o[o.length] = '<a:font script="Guru" typeface="Raavi"/>';
18865 o[o.length] = '<a:font script="Cans" typeface="Euphemia"/>';
18866 o[o.length] = '<a:font script="Cher" typeface="Plantagenet Cherokee"/>';
18867 o[o.length] = '<a:font script="Yiii" typeface="Microsoft Yi Baiti"/>';
18868 o[o.length] = '<a:font script="Tibt" typeface="Microsoft Himalaya"/>';
18869 o[o.length] = '<a:font script="Thaa" typeface="MV Boli"/>';
18870 o[o.length] = '<a:font script="Deva" typeface="Mangal"/>';
18871 o[o.length] = '<a:font script="Telu" typeface="Gautami"/>';
18872 o[o.length] = '<a:font script="Taml" typeface="Latha"/>';
18873 o[o.length] = '<a:font script="Syrc" typeface="Estrangelo Edessa"/>';
18874 o[o.length] = '<a:font script="Orya" typeface="Kalinga"/>';
18875 o[o.length] = '<a:font script="Mlym" typeface="Kartika"/>';
18876 o[o.length] = '<a:font script="Laoo" typeface="DokChampa"/>';
18877 o[o.length] = '<a:font script="Sinh" typeface="Iskoola Pota"/>';
18878 o[o.length] = '<a:font script="Mong" typeface="Mongolian Baiti"/>';
18879 o[o.length] = '<a:font script="Viet" typeface="Times New Roman"/>';
18880 o[o.length] = '<a:font script="Uigh" typeface="Microsoft Uighur"/>';
18881 o[o.length] = '<a:font script="Geor" typeface="Sylfaen"/>';
18882 o[o.length] = '</a:majorFont>';
18883 o[o.length] = '<a:minorFont>';
18884 o[o.length] = '<a:latin typeface="Calibri"/>';
18885 o[o.length] = '<a:ea typeface=""/>';
18886 o[o.length] = '<a:cs typeface=""/>';
18887 o[o.length] = '<a:font script="Jpan" typeface="MS Pゴシック"/>';
18888 o[o.length] = '<a:font script="Hang" typeface="맑은 고딕"/>';
18889 o[o.length] = '<a:font script="Hans" typeface="宋体"/>';
18890 o[o.length] = '<a:font script="Hant" typeface="新細明體"/>';
18891 o[o.length] = '<a:font script="Arab" typeface="Arial"/>';
18892 o[o.length] = '<a:font script="Hebr" typeface="Arial"/>';
18893 o[o.length] = '<a:font script="Thai" typeface="Tahoma"/>';
18894 o[o.length] = '<a:font script="Ethi" typeface="Nyala"/>';
18895 o[o.length] = '<a:font script="Beng" typeface="Vrinda"/>';
18896 o[o.length] = '<a:font script="Gujr" typeface="Shruti"/>';
18897 o[o.length] = '<a:font script="Khmr" typeface="DaunPenh"/>';
18898 o[o.length] = '<a:font script="Knda" typeface="Tunga"/>';
18899 o[o.length] = '<a:font script="Guru" typeface="Raavi"/>';
18900 o[o.length] = '<a:font script="Cans" typeface="Euphemia"/>';
18901 o[o.length] = '<a:font script="Cher" typeface="Plantagenet Cherokee"/>';
18902 o[o.length] = '<a:font script="Yiii" typeface="Microsoft Yi Baiti"/>';
18903 o[o.length] = '<a:font script="Tibt" typeface="Microsoft Himalaya"/>';
18904 o[o.length] = '<a:font script="Thaa" typeface="MV Boli"/>';
18905 o[o.length] = '<a:font script="Deva" typeface="Mangal"/>';
18906 o[o.length] = '<a:font script="Telu" typeface="Gautami"/>';
18907 o[o.length] = '<a:font script="Taml" typeface="Latha"/>';
18908 o[o.length] = '<a:font script="Syrc" typeface="Estrangelo Edessa"/>';
18909 o[o.length] = '<a:font script="Orya" typeface="Kalinga"/>';
18910 o[o.length] = '<a:font script="Mlym" typeface="Kartika"/>';
18911 o[o.length] = '<a:font script="Laoo" typeface="DokChampa"/>';
18912 o[o.length] = '<a:font script="Sinh" typeface="Iskoola Pota"/>';
18913 o[o.length] = '<a:font script="Mong" typeface="Mongolian Baiti"/>';
18914 o[o.length] = '<a:font script="Viet" typeface="Arial"/>';
18915 o[o.length] = '<a:font script="Uigh" typeface="Microsoft Uighur"/>';
18916 o[o.length] = '<a:font script="Geor" typeface="Sylfaen"/>';
18917 o[o.length] = '</a:minorFont>';
18918 o[o.length] = '</a:fontScheme>';
18919
18920 o[o.length] = '<a:fmtScheme name="Office">';
18921 o[o.length] = '<a:fillStyleLst>';
18922 o[o.length] = '<a:solidFill><a:schemeClr val="phClr"/></a:solidFill>';
18923 o[o.length] = '<a:gradFill rotWithShape="1">';
18924 o[o.length] = '<a:gsLst>';
18925 o[o.length] = '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="50000"/><a:satMod val="300000"/></a:schemeClr></a:gs>';
18926 o[o.length] = '<a:gs pos="35000"><a:schemeClr val="phClr"><a:tint val="37000"/><a:satMod val="300000"/></a:schemeClr></a:gs>';
18927 o[o.length] = '<a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="15000"/><a:satMod val="350000"/></a:schemeClr></a:gs>';
18928 o[o.length] = '</a:gsLst>';
18929 o[o.length] = '<a:lin ang="16200000" scaled="1"/>';
18930 o[o.length] = '</a:gradFill>';
18931 o[o.length] = '<a:gradFill rotWithShape="1">';
18932 o[o.length] = '<a:gsLst>';
18933 o[o.length] = '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="100000"/><a:shade val="100000"/><a:satMod val="130000"/></a:schemeClr></a:gs>';
18934 o[o.length] = '<a:gs pos="100000"><a:schemeClr val="phClr"><a:tint val="50000"/><a:shade val="100000"/><a:satMod val="350000"/></a:schemeClr></a:gs>';
18935 o[o.length] = '</a:gsLst>';
18936 o[o.length] = '<a:lin ang="16200000" scaled="0"/>';
18937 o[o.length] = '</a:gradFill>';
18938 o[o.length] = '</a:fillStyleLst>';
18939 o[o.length] = '<a:lnStyleLst>';
18940 o[o.length] = '<a:ln w="9525" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"><a:shade val="95000"/><a:satMod val="105000"/></a:schemeClr></a:solidFill><a:prstDash val="solid"/></a:ln>';
18941 o[o.length] = '<a:ln w="25400" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/></a:ln>';
18942 o[o.length] = '<a:ln w="38100" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/></a:ln>';
18943 o[o.length] = '</a:lnStyleLst>';
18944 o[o.length] = '<a:effectStyleLst>';
18945 o[o.length] = '<a:effectStyle>';
18946 o[o.length] = '<a:effectLst>';
18947 o[o.length] = '<a:outerShdw blurRad="40000" dist="20000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="38000"/></a:srgbClr></a:outerShdw>';
18948 o[o.length] = '</a:effectLst>';
18949 o[o.length] = '</a:effectStyle>';
18950 o[o.length] = '<a:effectStyle>';
18951 o[o.length] = '<a:effectLst>';
18952 o[o.length] = '<a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000"/></a:srgbClr></a:outerShdw>';
18953 o[o.length] = '</a:effectLst>';
18954 o[o.length] = '</a:effectStyle>';
18955 o[o.length] = '<a:effectStyle>';
18956 o[o.length] = '<a:effectLst>';
18957 o[o.length] = '<a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0"><a:srgbClr val="000000"><a:alpha val="35000"/></a:srgbClr></a:outerShdw>';
18958 o[o.length] = '</a:effectLst>';
18959 o[o.length] = '<a:scene3d><a:camera prst="orthographicFront"><a:rot lat="0" lon="0" rev="0"/></a:camera><a:lightRig rig="threePt" dir="t"><a:rot lat="0" lon="0" rev="1200000"/></a:lightRig></a:scene3d>';
18960 o[o.length] = '<a:sp3d><a:bevelT w="63500" h="25400"/></a:sp3d>';
18961 o[o.length] = '</a:effectStyle>';
18962 o[o.length] = '</a:effectStyleLst>';
18963 o[o.length] = '<a:bgFillStyleLst>';
18964 o[o.length] = '<a:solidFill><a:schemeClr val="phClr"/></a:solidFill>';
18965 o[o.length] = '<a:gradFill rotWithShape="1">';
18966 o[o.length] = '<a:gsLst>';
18967 o[o.length] = '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="40000"/><a:satMod val="350000"/></a:schemeClr></a:gs>';
18968 o[o.length] = '<a:gs pos="40000"><a:schemeClr val="phClr"><a:tint val="45000"/><a:shade val="99000"/><a:satMod val="350000"/></a:schemeClr></a:gs>';
18969 o[o.length] = '<a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="20000"/><a:satMod val="255000"/></a:schemeClr></a:gs>';
18970 o[o.length] = '</a:gsLst>';
18971 o[o.length] = '<a:path path="circle"><a:fillToRect l="50000" t="-80000" r="50000" b="180000"/></a:path>';
18972 o[o.length] = '</a:gradFill>';
18973 o[o.length] = '<a:gradFill rotWithShape="1">';
18974 o[o.length] = '<a:gsLst>';
18975 o[o.length] = '<a:gs pos="0"><a:schemeClr val="phClr"><a:tint val="80000"/><a:satMod val="300000"/></a:schemeClr></a:gs>';
18976 o[o.length] = '<a:gs pos="100000"><a:schemeClr val="phClr"><a:shade val="30000"/><a:satMod val="200000"/></a:schemeClr></a:gs>';
18977 o[o.length] = '</a:gsLst>';
18978 o[o.length] = '<a:path path="circle"><a:fillToRect l="50000" t="50000" r="50000" b="50000"/></a:path>';
18979 o[o.length] = '</a:gradFill>';
18980 o[o.length] = '</a:bgFillStyleLst>';
18981 o[o.length] = '</a:fmtScheme>';
18982 o[o.length] = '</a:themeElements>';
18983
18984 o[o.length] = '<a:objectDefaults>';
18985 o[o.length] = '<a:spDef>';
18986 o[o.length] = '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="1"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="3"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="2"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="lt1"/></a:fontRef></a:style>';
18987 o[o.length] = '</a:spDef>';
18988 o[o.length] = '<a:lnDef>';
18989 o[o.length] = '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="2"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="0"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="1"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="tx1"/></a:fontRef></a:style>';
18990 o[o.length] = '</a:lnDef>';
18991 o[o.length] = '</a:objectDefaults>';
18992 o[o.length] = '<a:extraClrSchemeLst/>';
18993 o[o.length] = '</a:theme>';
18994 return o.join("");
18995}
18996/* [MS-XLS] 2.4.326 TODO: payload is a zip file */
18997function parse_Theme(blob, length, opts) {
18998 var end = blob.l + length;
18999 var dwThemeVersion = blob.read_shift(4);
19000 if(dwThemeVersion === 124226) return;
19001 if(!opts.cellStyles || !jszip) { blob.l = end; return; }
19002 var data = blob.slice(blob.l);
19003 blob.l = end;
19004 var zip; try { zip = new jszip(data); } catch(e) { return; }
19005 var themeXML = getzipstr(zip, "theme/theme/theme1.xml", true);
19006 if(!themeXML) return;
19007 return parse_theme_xml(themeXML, opts);
19008}
19009
19010/* 2.5.49 */
19011function parse_ColorTheme(blob) { return blob.read_shift(4); }
19012
19013/* 2.5.155 */
19014function parse_FullColorExt(blob) {
19015 var o = {};
19016 o.xclrType = blob.read_shift(2);
19017 o.nTintShade = blob.read_shift(2);
19018 switch(o.xclrType) {
19019 case 0: blob.l += 4; break;
19020 case 1: o.xclrValue = parse_IcvXF(blob, 4); break;
19021 case 2: o.xclrValue = parse_LongRGBA(blob, 4); break;
19022 case 3: o.xclrValue = parse_ColorTheme(blob, 4); break;
19023 case 4: blob.l += 4; break;
19024 }
19025 blob.l += 8;
19026 return o;
19027}
19028
19029/* 2.5.164 TODO: read 7 bits*/
19030function parse_IcvXF(blob, length) {
19031 return parsenoop(blob, length);
19032}
19033
19034/* 2.5.280 */
19035function parse_XFExtGradient(blob, length) {
19036 return parsenoop(blob, length);
19037}
19038
19039/* [MS-XLS] 2.5.108 */
19040function parse_ExtProp(blob) {
19041 var extType = blob.read_shift(2);
19042 var cb = blob.read_shift(2) - 4;
19043 var o = [extType];
19044 switch(extType) {
19045 case 0x04: case 0x05: case 0x07: case 0x08:
19046 case 0x09: case 0x0A: case 0x0B: case 0x0D:
19047 o[1] = parse_FullColorExt(blob, cb); break;
19048 case 0x06: o[1] = parse_XFExtGradient(blob, cb); break;
19049 case 0x0E: case 0x0F: o[1] = blob.read_shift(cb === 1 ? 1 : 2); break;
19050 default: throw new Error("Unrecognized ExtProp type: " + extType + " " + cb);
19051 }
19052 return o;
19053}
19054
19055/* 2.4.355 */
19056function parse_XFExt(blob, length) {
19057 var end = blob.l + length;
19058 blob.l += 2;
19059 var ixfe = blob.read_shift(2);
19060 blob.l += 2;
19061 var cexts = blob.read_shift(2);
19062 var ext = [];
19063 while(cexts-- > 0) ext.push(parse_ExtProp(blob, end-blob.l));
19064 return {ixfe:ixfe, ext:ext};
19065}
19066
19067/* xf is an XF, see parse_XFExt for xfext */
19068function update_xfext(xf, xfext) {
19069 xfext.forEach(function(xfe) {
19070 switch(xfe[0]) { /* 2.5.108 extPropData */
19071 case 0x04: break; /* foreground color */
19072 case 0x05: break; /* background color */
19073 case 0x06: break; /* gradient fill */
19074 case 0x07: break; /* top cell border color */
19075 case 0x08: break; /* bottom cell border color */
19076 case 0x09: break; /* left cell border color */
19077 case 0x0a: break; /* right cell border color */
19078 case 0x0b: break; /* diagonal cell border color */
19079 case 0x0d: /* text color */
19080 break;
19081 case 0x0e: break; /* font scheme */
19082 case 0x0f: break; /* indentation level */
19083 }
19084 });
19085}
19086
19087/* 18.6 Calculation Chain */
19088function parse_cc_xml(data) {
19089 var d = [];
19090 if(!data) return d;
19091 var i = 1;
19092 (data.match(tagregex)||[]).forEach(function(x) {
19093 var y = parsexmltag(x);
19094 switch(y[0]) {
19095 case '<?xml': break;
19096 /* 18.6.2 calcChain CT_CalcChain 1 */
19097 case '<calcChain': case '<calcChain>': case '</calcChain>': break;
19098 /* 18.6.1 c CT_CalcCell 1 */
19099 case '<c': delete y[0]; if(y.i) i = y.i; else y.i = i; d.push(y); break;
19100 }
19101 });
19102 return d;
19103}
19104
19105//function write_cc_xml(data, opts) { }
19106
19107/* [MS-XLSB] 2.6.4.1 */
19108function parse_BrtCalcChainItem$(data) {
19109 var out = {};
19110 out.i = data.read_shift(4);
19111 var cell = {};
19112 cell.r = data.read_shift(4);
19113 cell.c = data.read_shift(4);
19114 out.r = encode_cell(cell);
19115 var flags = data.read_shift(1);
19116 if(flags & 0x2) out.l = '1';
19117 if(flags & 0x8) out.a = '1';
19118 return out;
19119}
19120
19121/* 18.6 Calculation Chain */
19122function parse_cc_bin(data, name, opts) {
19123 var out = [];
19124 var pass = false;
19125 recordhopper(data, function hopper_cc(val, R_n, RT) {
19126 switch(RT) {
19127 case 0x003F: /* 'BrtCalcChainItem$' */
19128 out.push(val); break;
19129
19130 default:
19131 if((R_n||"").indexOf("Begin") > 0){/* empty */}
19132 else if((R_n||"").indexOf("End") > 0){/* empty */}
19133 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
19134 }
19135 });
19136 return out;
19137}
19138
19139//function write_cc_bin(data, opts) { }
19140/* 18.14 Supplementary Workbook Data */
19141function parse_xlink_xml() {
19142 //var opts = _opts || {};
19143 //if(opts.WTF) throw "XLSX External Link";
19144}
19145
19146/* [MS-XLSB] 2.1.7.25 External Link */
19147function parse_xlink_bin(data, rel, name, _opts) {
19148 if(!data) return data;
19149 var opts = _opts || {};
19150
19151 var pass = false, end = false;
19152
19153 recordhopper(data, function xlink_parse(val, R_n, RT) {
19154 if(end) return;
19155 switch(RT) {
19156 case 0x0167: /* 'BrtSupTabs' */
19157 case 0x016B: /* 'BrtExternTableStart' */
19158 case 0x016C: /* 'BrtExternTableEnd' */
19159 case 0x016E: /* 'BrtExternRowHdr' */
19160 case 0x016F: /* 'BrtExternCellBlank' */
19161 case 0x0170: /* 'BrtExternCellReal' */
19162 case 0x0171: /* 'BrtExternCellBool' */
19163 case 0x0172: /* 'BrtExternCellError' */
19164 case 0x0173: /* 'BrtExternCellString' */
19165 case 0x01D8: /* 'BrtExternValueMeta' */
19166 case 0x0241: /* 'BrtSupNameStart' */
19167 case 0x0242: /* 'BrtSupNameValueStart' */
19168 case 0x0243: /* 'BrtSupNameValueEnd' */
19169 case 0x0244: /* 'BrtSupNameNum' */
19170 case 0x0245: /* 'BrtSupNameErr' */
19171 case 0x0246: /* 'BrtSupNameSt' */
19172 case 0x0247: /* 'BrtSupNameNil' */
19173 case 0x0248: /* 'BrtSupNameBool' */
19174 case 0x0249: /* 'BrtSupNameFmla' */
19175 case 0x024A: /* 'BrtSupNameBits' */
19176 case 0x024B: /* 'BrtSupNameEnd' */
19177 break;
19178
19179 case 0x0023: /* 'BrtFRTBegin' */
19180 pass = true; break;
19181 case 0x0024: /* 'BrtFRTEnd' */
19182 pass = false; break;
19183
19184 default:
19185 if((R_n||"").indexOf("Begin") > 0){/* empty */}
19186 else if((R_n||"").indexOf("End") > 0){/* empty */}
19187 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT.toString(16) + " " + R_n);
19188 }
19189 }, opts);
19190}
19191/* 20.5 DrawingML - SpreadsheetML Drawing */
19192RELS.IMG = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
19193RELS.DRAW = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing";
19194
19195/* 20.5.2.35 wsDr CT_Drawing */
19196function parse_drawing(data, rels) {
19197 if(!data) return "??";
19198 /*
19199 Chartsheet Drawing:
19200 - 20.5.2.35 wsDr CT_Drawing
19201 - 20.5.2.1 absoluteAnchor CT_AbsoluteAnchor
19202 - 20.5.2.16 graphicFrame CT_GraphicalObjectFrame
19203 - 20.1.2.2.16 graphic CT_GraphicalObject
19204 - 20.1.2.2.17 graphicData CT_GraphicalObjectData
19205 - chart reference
19206 the actual type is based on the URI of the graphicData
19207 TODO: handle embedded charts and other types of graphics
19208 */
19209 var id = (data.match(/<c:chart [^>]*r:id="([^"]*)"/)||["",""])[1];
19210
19211 return rels['!id'][id].Target;
19212}
19213
19214/* L.5.5.2 SpreadsheetML Comments + VML Schema */
19215var _shapeid = 1024;
19216function write_comments_vml(rId, comments) {
19217 var csize = [21600, 21600];
19218 /* L.5.2.1.2 Path Attribute */
19219 var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(",");
19220 var o = [
19221 writextag("xml", null, { 'xmlns:v': XLMLNS.v, 'xmlns:o': XLMLNS.o, 'xmlns:x': XLMLNS.x, 'xmlns:mv': XLMLNS.mv }).replace(/\/>/,">"),
19222 writextag("o:shapelayout", writextag("o:idmap", null, {'v:ext':"edit", 'data':rId}), {'v:ext':"edit"}),
19223 writextag("v:shapetype", [
19224 writextag("v:stroke", null, {joinstyle:"miter"}),
19225 writextag("v:path", null, {gradientshapeok:"t", 'o:connecttype':"rect"})
19226 ].join(""), {id:"_x0000_t202", 'o:spt':202, coordsize:csize.join(","),path:bbox})
19227 ];
19228 while(_shapeid < rId * 1000) _shapeid += 1000;
19229
19230 comments.forEach(function(x) {
19231 var c = decode_cell(x[0]);
19232 var fillopts = {'color2':"#BEFF82", 'type':"gradient"};
19233 if(fillopts.type == "gradient") fillopts.angle = "-180";
19234 var fillparm = fillopts.type == "gradient" ? writextag("o:fill", null, {type:"gradientUnscaled", 'v:ext':"view"}) : null;
19235 var fillxml = writextag('v:fill', fillparm, fillopts);
19236
19237 var shadata = ({on:"t", 'obscured':"t"});
19238 ++_shapeid;
19239
19240 o = o.concat([
19241 '<v:shape' + wxt_helper({
19242 id:'_x0000_s' + _shapeid,
19243 type:"#_x0000_t202",
19244 style:"position:absolute; margin-left:80pt;margin-top:5pt;width:104pt;height:64pt;z-index:10" + (x[1].hidden ? ";visibility:hidden" : "") ,
19245 fillcolor:"#ECFAD4",
19246 strokecolor:"#edeaa1"
19247 }) + '>',
19248 fillxml,
19249 writextag("v:shadow", null, shadata),
19250 writextag("v:path", null, {'o:connecttype':"none"}),
19251 '<v:textbox><div style="text-align:left"></div></v:textbox>',
19252 '<x:ClientData ObjectType="Note">',
19253 '<x:MoveWithCells/>',
19254 '<x:SizeWithCells/>',
19255 /* Part 4 19.4.2.3 Anchor (Anchor) */
19256 writetag('x:Anchor', [c.c+1, 0, c.r+1, 0, c.c+3, 20, c.r+5, 20].join(",")),
19257 writetag('x:AutoFill', "False"),
19258 writetag('x:Row', String(c.r)),
19259 writetag('x:Column', String(c.c)),
19260 x[1].hidden ? '' : '<x:Visible/>',
19261 '</x:ClientData>',
19262 '</v:shape>'
19263 ]); });
19264 o.push('</xml>');
19265 return o.join("");
19266}
19267RELS.CMNT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
19268
19269function sheet_insert_comments(sheet, comments) {
19270 var dense = Array.isArray(sheet);
19271 var cell;
19272 comments.forEach(function(comment) {
19273 var r = decode_cell(comment.ref);
19274 if(dense) {
19275 if(!sheet[r.r]) sheet[r.r] = [];
19276 cell = sheet[r.r][r.c];
19277 } else cell = sheet[comment.ref];
19278 if (!cell) {
19279 cell = ({t:"z"});
19280 if(dense) sheet[r.r][r.c] = cell;
19281 else sheet[comment.ref] = cell;
19282 var range = safe_decode_range(sheet["!ref"]||"BDWGO1000001:A1");
19283 if(range.s.r > r.r) range.s.r = r.r;
19284 if(range.e.r < r.r) range.e.r = r.r;
19285 if(range.s.c > r.c) range.s.c = r.c;
19286 if(range.e.c < r.c) range.e.c = r.c;
19287 var encoded = encode_range(range);
19288 if (encoded !== sheet["!ref"]) sheet["!ref"] = encoded;
19289 }
19290
19291 if (!cell.c) cell.c = [];
19292 var o = ({a: comment.author, t: comment.t, r: comment.r});
19293 if(comment.h) o.h = comment.h;
19294 cell.c.push(o);
19295 });
19296}
19297
19298/* 18.7 Comments */
19299function parse_comments_xml(data, opts) {
19300 /* 18.7.6 CT_Comments */
19301 if(data.match(/<(?:\w+:)?comments *\/>/)) return [];
19302 var authors = [];
19303 var commentList = [];
19304 var authtag = data.match(/<(?:\w+:)?authors>([\s\S]*)<\/(?:\w+:)?authors>/);
19305 if(authtag && authtag[1]) authtag[1].split(/<\/\w*:?author>/).forEach(function(x) {
19306 if(x === "" || x.trim() === "") return;
19307 var a = x.match(/<(?:\w+:)?author[^>]*>(.*)/);
19308 if(a) authors.push(a[1]);
19309 });
19310 var cmnttag = data.match(/<(?:\w+:)?commentList>([\s\S]*)<\/(?:\w+:)?commentList>/);
19311 if(cmnttag && cmnttag[1]) cmnttag[1].split(/<\/\w*:?comment>/).forEach(function(x) {
19312 if(x === "" || x.trim() === "") return;
19313 var cm = x.match(/<(?:\w+:)?comment[^>]*>/);
19314 if(!cm) return;
19315 var y = parsexmltag(cm[0]);
19316 var comment = ({ author: y.authorId && authors[y.authorId] || "sheetjsghost", ref: y.ref, guid: y.guid });
19317 var cell = decode_cell(y.ref);
19318 if(opts.sheetRows && opts.sheetRows <= cell.r) return;
19319 var textMatch = x.match(/<(?:\w+:)?text>([\s\S]*)<\/(?:\w+:)?text>/);
19320 var rt = !!textMatch && !!textMatch[1] && parse_si(textMatch[1]) || {r:"",t:"",h:""};
19321 comment.r = rt.r;
19322 if(rt.r == "<t></t>") rt.t = rt.h = "";
19323 comment.t = rt.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n");
19324 if(opts.cellHTML) comment.h = rt.h;
19325 commentList.push(comment);
19326 });
19327 return commentList;
19328}
19329
19330var CMNT_XML_ROOT = writextag('comments', null, { 'xmlns': XMLNS.main[0] });
19331function write_comments_xml(data) {
19332 var o = [XML_HEADER, CMNT_XML_ROOT];
19333
19334 var iauthor = [];
19335 o.push("<authors>");
19336 data.forEach(function(x) { x[1].forEach(function(w) { var a = escapexml(w.a);
19337 if(iauthor.indexOf(a) > -1) return;
19338 iauthor.push(a);
19339 o.push("<author>" + a + "</author>");
19340 }); });
19341 o.push("</authors>");
19342 o.push("<commentList>");
19343 data.forEach(function(d) {
19344 d[1].forEach(function(c) {
19345 /* 18.7.3 CT_Comment */
19346 o.push('<comment ref="' + d[0] + '" authorId="' + iauthor.indexOf(escapexml(c.a)) + '"><text>');
19347 o.push(writetag("t", c.t == null ? "" : escapexml(c.t)));
19348 o.push('</text></comment>');
19349 });
19350 });
19351 o.push("</commentList>");
19352 if(o.length>2) { o[o.length] = ('</comments>'); o[1]=o[1].replace("/>",">"); }
19353 return o.join("");
19354}
19355/* [MS-XLSB] 2.4.28 BrtBeginComment */
19356function parse_BrtBeginComment(data) {
19357 var out = {};
19358 out.iauthor = data.read_shift(4);
19359 var rfx = parse_UncheckedRfX(data, 16);
19360 out.rfx = rfx.s;
19361 out.ref = encode_cell(rfx.s);
19362 data.l += 16; /*var guid = parse_GUID(data); */
19363 return out;
19364}
19365function write_BrtBeginComment(data, o) {
19366 if(o == null) o = new_buf(36);
19367 o.write_shift(4, data[1].iauthor);
19368 write_UncheckedRfX((data[0]), o);
19369 o.write_shift(4, 0);
19370 o.write_shift(4, 0);
19371 o.write_shift(4, 0);
19372 o.write_shift(4, 0);
19373 return o;
19374}
19375
19376/* [MS-XLSB] 2.4.327 BrtCommentAuthor */
19377var parse_BrtCommentAuthor = parse_XLWideString;
19378function write_BrtCommentAuthor(data) { return write_XLWideString(data.slice(0, 54)); }
19379
19380/* [MS-XLSB] 2.1.7.8 Comments */
19381function parse_comments_bin(data, opts) {
19382 var out = [];
19383 var authors = [];
19384 var c = {};
19385 var pass = false;
19386 recordhopper(data, function hopper_cmnt(val, R_n, RT) {
19387 switch(RT) {
19388 case 0x0278: /* 'BrtCommentAuthor' */
19389 authors.push(val); break;
19390 case 0x027B: /* 'BrtBeginComment' */
19391 c = val; break;
19392 case 0x027D: /* 'BrtCommentText' */
19393 c.t = val.t; c.h = val.h; c.r = val.r; break;
19394 case 0x027C: /* 'BrtEndComment' */
19395 c.author = authors[c.iauthor];
19396 delete (c).iauthor;
19397 if(opts.sheetRows && c.rfx && opts.sheetRows <= c.rfx.r) break;
19398 if(!c.t) c.t = "";
19399 delete c.rfx; out.push(c); break;
19400
19401 case 0x0C00: /* 'BrtUid' */
19402 break;
19403
19404 case 0x0023: /* 'BrtFRTBegin' */
19405 pass = true; break;
19406 case 0x0024: /* 'BrtFRTEnd' */
19407 pass = false; break;
19408 case 0x0025: /* 'BrtACBegin' */ break;
19409 case 0x0026: /* 'BrtACEnd' */ break;
19410
19411
19412 default:
19413 if((R_n||"").indexOf("Begin") > 0){/* empty */}
19414 else if((R_n||"").indexOf("End") > 0){/* empty */}
19415 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
19416 }
19417 });
19418 return out;
19419}
19420
19421function write_comments_bin(data) {
19422 var ba = buf_array();
19423 var iauthor = [];
19424 write_record(ba, "BrtBeginComments");
19425
19426 write_record(ba, "BrtBeginCommentAuthors");
19427 data.forEach(function(comment) {
19428 comment[1].forEach(function(c) {
19429 if(iauthor.indexOf(c.a) > -1) return;
19430 iauthor.push(c.a.slice(0,54));
19431 write_record(ba, "BrtCommentAuthor", write_BrtCommentAuthor(c.a));
19432 });
19433 });
19434 write_record(ba, "BrtEndCommentAuthors");
19435
19436 write_record(ba, "BrtBeginCommentList");
19437 data.forEach(function(comment) {
19438 comment[1].forEach(function(c) {
19439 c.iauthor = iauthor.indexOf(c.a);
19440 var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])};
19441 write_record(ba, "BrtBeginComment", write_BrtBeginComment([range, c]));
19442 if(c.t && c.t.length > 0) write_record(ba, "BrtCommentText", write_BrtCommentText(c));
19443 write_record(ba, "BrtEndComment");
19444 delete c.iauthor;
19445 });
19446 });
19447 write_record(ba, "BrtEndCommentList");
19448
19449 write_record(ba, "BrtEndComments");
19450 return ba.end();
19451}
19452var CT_VBA = "application/vnd.ms-office.vbaProject";
19453function make_vba_xls(cfb) {
19454 var newcfb = CFB.utils.cfb_new({root:"R"});
19455 cfb.FullPaths.forEach(function(p, i) {
19456 if(p.slice(-1) === "/" || !p.match(/_VBA_PROJECT_CUR/)) return;
19457 var newpath = p.replace(/^[^\/]*/,"R").replace(/\/_VBA_PROJECT_CUR\u0000*/, "");
19458 CFB.utils.cfb_add(newcfb, newpath, cfb.FileIndex[i].content);
19459 });
19460 return CFB.write(newcfb);
19461}
19462
19463function fill_vba_xls(cfb, vba) {
19464 vba.FullPaths.forEach(function(p, i) {
19465 if(i == 0) return;
19466 var newpath = p.replace(/[^\/]*[\/]/, "/_VBA_PROJECT_CUR/");
19467 if(newpath.slice(-1) !== "/") CFB.utils.cfb_add(cfb, newpath, vba.FileIndex[i].content);
19468 });
19469}
19470
19471var VBAFMTS = [ "xlsb", "xlsm", "xlam", "biff8", "xla" ];
19472
19473RELS.DS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet";
19474RELS.MS = "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet";
19475
19476/* macro and dialog sheet stubs */
19477function parse_ds_bin() { return {'!type':'dialog'}; }
19478function parse_ds_xml() { return {'!type':'dialog'}; }
19479function parse_ms_bin() { return {'!type':'macro'}; }
19480function parse_ms_xml() { return {'!type':'macro'}; }
19481/* TODO: it will be useful to parse the function str */
19482var rc_to_a1 = (function(){
19483 var rcregex = /(^|[^A-Za-z_])R(\[?-?\d+\]|[1-9]\d*|)C(\[?-?\d+\]|[1-9]\d*|)(?![A-Za-z0-9_])/g;
19484 var rcbase = ({r:0,c:0});
19485 function rcfunc($$,$1,$2,$3) {
19486 var cRel = false, rRel = false;
19487
19488 if($2.length == 0) rRel = true;
19489 else if($2.charAt(0) == "[") { rRel = true; $2 = $2.slice(1, -1); }
19490
19491 if($3.length == 0) cRel = true;
19492 else if($3.charAt(0) == "[") { cRel = true; $3 = $3.slice(1, -1); }
19493
19494 var R = $2.length>0?parseInt($2,10)|0:0, C = $3.length>0?parseInt($3,10)|0:0;
19495
19496 if(cRel) C += rcbase.c; else --C;
19497 if(rRel) R += rcbase.r; else --R;
19498 return $1 + (cRel ? "" : "$") + encode_col(C) + (rRel ? "" : "$") + encode_row(R);
19499 }
19500 return function rc_to_a1(fstr, base) {
19501 rcbase = base;
19502 return fstr.replace(rcregex, rcfunc);
19503 };
19504})();
19505
19506var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)([1-9]\d{0,5}|10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6])(?![_.\(A-Za-z0-9])/g;
19507var a1_to_rc =(function(){
19508 return function a1_to_rc(fstr, base) {
19509 return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) {
19510 var c = decode_col($3) - ($2 ? 0 : base.c);
19511 var r = decode_row($5) - ($4 ? 0 : base.r);
19512 var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1));
19513 var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1));
19514 return $1 + "R" + R + "C" + C;
19515 });
19516 };
19517})();
19518
19519/* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */
19520function shift_formula_str(f, delta) {
19521 return f.replace(crefregex, function($0, $1, $2, $3, $4, $5) {
19522 return $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r));
19523 });
19524}
19525
19526function shift_formula_xlsx(f, range, cell) {
19527 var r = decode_range(range), s = r.s, c = decode_cell(cell);
19528 var delta = {r:c.r - s.r, c:c.c - s.c};
19529 return shift_formula_str(f, delta);
19530}
19531
19532/* TODO: parse formula */
19533function fuzzyfmla(f) {
19534 if(f.length == 1) return false;
19535 return true;
19536}
19537
19538function _xlfn(f) {
19539 return f.replace(/_xlfn\./g,"");
19540}
19541function parseread1(blob) { blob.l+=1; return; }
19542
19543/* [MS-XLS] 2.5.51 */
19544function parse_ColRelU(blob, length) {
19545 var c = blob.read_shift(length == 1 ? 1 : 2);
19546 return [c & 0x3FFF, (c >> 14) & 1, (c >> 15) & 1];
19547}
19548
19549/* [MS-XLS] 2.5.198.105 ; [MS-XLSB] 2.5.97.89 */
19550function parse_RgceArea(blob, length, opts) {
19551 var w = 2;
19552 if(opts) {
19553 if(opts.biff >= 2 && opts.biff <= 5) return parse_RgceArea_BIFF2(blob, length, opts);
19554 else if(opts.biff == 12) w = 4;
19555 }
19556 var r=blob.read_shift(w), R=blob.read_shift(w);
19557 var c=parse_ColRelU(blob, 2);
19558 var C=parse_ColRelU(blob, 2);
19559 return { s:{r:r, c:c[0], cRel:c[1], rRel:c[2]}, e:{r:R, c:C[0], cRel:C[1], rRel:C[2]} };
19560}
19561/* BIFF 2-5 encodes flags in the row field */
19562function parse_RgceArea_BIFF2(blob) {
19563 var r=parse_ColRelU(blob, 2), R=parse_ColRelU(blob, 2);
19564 var c=blob.read_shift(1);
19565 var C=blob.read_shift(1);
19566 return { s:{r:r[0], c:c, cRel:r[1], rRel:r[2]}, e:{r:R[0], c:C, cRel:R[1], rRel:R[2]} };
19567}
19568
19569/* [MS-XLS] 2.5.198.105 ; [MS-XLSB] 2.5.97.90 */
19570function parse_RgceAreaRel(blob, length, opts) {
19571 if(opts.biff < 8) return parse_RgceArea_BIFF2(blob, length, opts);
19572 var r=blob.read_shift(opts.biff == 12 ? 4 : 2), R=blob.read_shift(opts.biff == 12 ? 4 : 2);
19573 var c=parse_ColRelU(blob, 2);
19574 var C=parse_ColRelU(blob, 2);
19575 return { s:{r:r, c:c[0], cRel:c[1], rRel:c[2]}, e:{r:R, c:C[0], cRel:C[1], rRel:C[2]} };
19576}
19577
19578/* [MS-XLS] 2.5.198.109 ; [MS-XLSB] 2.5.97.91 */
19579function parse_RgceLoc(blob, length, opts) {
19580 if(opts && opts.biff >= 2 && opts.biff <= 5) return parse_RgceLoc_BIFF2(blob, length, opts);
19581 var r = blob.read_shift(opts && opts.biff == 12 ? 4 : 2);
19582 var c = parse_ColRelU(blob, 2);
19583 return {r:r, c:c[0], cRel:c[1], rRel:c[2]};
19584}
19585function parse_RgceLoc_BIFF2(blob) {
19586 var r = parse_ColRelU(blob, 2);
19587 var c = blob.read_shift(1);
19588 return {r:r[0], c:c, cRel:r[1], rRel:r[2]};
19589}
19590
19591/* [MS-XLS] 2.5.198.107, 2.5.47 */
19592function parse_RgceElfLoc(blob) {
19593 var r = blob.read_shift(2);
19594 var c = blob.read_shift(2);
19595 return {r:r, c:c & 0xFF, fQuoted:!!(c & 0x4000), cRel:c>>15, rRel:c>>15 };
19596}
19597
19598/* [MS-XLS] 2.5.198.111 ; [MS-XLSB] 2.5.97.92 TODO */
19599function parse_RgceLocRel(blob, length, opts) {
19600 var biff = opts && opts.biff ? opts.biff : 8;
19601 if(biff >= 2 && biff <= 5) return parse_RgceLocRel_BIFF2(blob, length, opts);
19602 var r = blob.read_shift(biff >= 12 ? 4 : 2);
19603 var cl = blob.read_shift(2);
19604 var cRel = (cl & 0x4000) >> 14, rRel = (cl & 0x8000) >> 15;
19605 cl &= 0x3FFF;
19606 if(rRel == 1) while(r > 0x7FFFF) r -= 0x100000;
19607 if(cRel == 1) while(cl > 0x1FFF) cl = cl - 0x4000;
19608 return {r:r,c:cl,cRel:cRel,rRel:rRel};
19609}
19610function parse_RgceLocRel_BIFF2(blob) {
19611 var rl = blob.read_shift(2);
19612 var c = blob.read_shift(1);
19613 var rRel = (rl & 0x8000) >> 15, cRel = (rl & 0x4000) >> 14;
19614 rl &= 0x3FFF;
19615 if(rRel == 1 && rl >= 0x2000) rl = rl - 0x4000;
19616 if(cRel == 1 && c >= 0x80) c = c - 0x100;
19617 return {r:rl,c:c,cRel:cRel,rRel:rRel};
19618}
19619
19620/* [MS-XLS] 2.5.198.27 ; [MS-XLSB] 2.5.97.18 */
19621function parse_PtgArea(blob, length, opts) {
19622 var type = (blob[blob.l++] & 0x60) >> 5;
19623 var area = parse_RgceArea(blob, opts.biff >= 2 && opts.biff <= 5 ? 6 : 8, opts);
19624 return [type, area];
19625}
19626
19627/* [MS-XLS] 2.5.198.28 ; [MS-XLSB] 2.5.97.19 */
19628function parse_PtgArea3d(blob, length, opts) {
19629 var type = (blob[blob.l++] & 0x60) >> 5;
19630 var ixti = blob.read_shift(2, 'i');
19631 var w = 8;
19632 if(opts) switch(opts.biff) {
19633 case 5: blob.l += 12; w = 6; break;
19634 case 12: w = 12; break;
19635 }
19636 var area = parse_RgceArea(blob, w, opts);
19637 return [type, ixti, area];
19638}
19639
19640/* [MS-XLS] 2.5.198.29 ; [MS-XLSB] 2.5.97.20 */
19641function parse_PtgAreaErr(blob, length, opts) {
19642 var type = (blob[blob.l++] & 0x60) >> 5;
19643 blob.l += opts && (opts.biff > 8) ? 12 : (opts.biff < 8 ? 6 : 8);
19644 return [type];
19645}
19646/* [MS-XLS] 2.5.198.30 ; [MS-XLSB] 2.5.97.21 */
19647function parse_PtgAreaErr3d(blob, length, opts) {
19648 var type = (blob[blob.l++] & 0x60) >> 5;
19649 var ixti = blob.read_shift(2);
19650 var w = 8;
19651 if(opts) switch(opts.biff) {
19652 case 5: blob.l += 12; w = 6; break;
19653 case 12: w = 12; break;
19654 }
19655 blob.l += w;
19656 return [type, ixti];
19657}
19658
19659/* [MS-XLS] 2.5.198.31 ; [MS-XLSB] 2.5.97.22 */
19660function parse_PtgAreaN(blob, length, opts) {
19661 var type = (blob[blob.l++] & 0x60) >> 5;
19662 var area = parse_RgceAreaRel(blob, length - 1, opts);
19663 return [type, area];
19664}
19665
19666/* [MS-XLS] 2.5.198.32 ; [MS-XLSB] 2.5.97.23 */
19667function parse_PtgArray(blob, length, opts) {
19668 var type = (blob[blob.l++] & 0x60) >> 5;
19669 blob.l += opts.biff == 2 ? 6 : opts.biff == 12 ? 14 : 7;
19670 return [type];
19671}
19672
19673/* [MS-XLS] 2.5.198.33 ; [MS-XLSB] 2.5.97.24 */
19674function parse_PtgAttrBaxcel(blob) {
19675 var bitSemi = blob[blob.l+1] & 0x01; /* 1 = volatile */
19676 var bitBaxcel = 1;
19677 blob.l += 4;
19678 return [bitSemi, bitBaxcel];
19679}
19680
19681/* [MS-XLS] 2.5.198.34 ; [MS-XLSB] 2.5.97.25 */
19682function parse_PtgAttrChoose(blob, length, opts) {
19683 blob.l +=2;
19684 var offset = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
19685 var o = [];
19686 /* offset is 1 less than the number of elements */
19687 for(var i = 0; i <= offset; ++i) o.push(blob.read_shift(opts && opts.biff == 2 ? 1 : 2));
19688 return o;
19689}
19690
19691/* [MS-XLS] 2.5.198.35 ; [MS-XLSB] 2.5.97.26 */
19692function parse_PtgAttrGoto(blob, length, opts) {
19693 var bitGoto = (blob[blob.l+1] & 0xFF) ? 1 : 0;
19694 blob.l += 2;
19695 return [bitGoto, blob.read_shift(opts && opts.biff == 2 ? 1 : 2)];
19696}
19697
19698/* [MS-XLS] 2.5.198.36 ; [MS-XLSB] 2.5.97.27 */
19699function parse_PtgAttrIf(blob, length, opts) {
19700 var bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0;
19701 blob.l += 2;
19702 return [bitIf, blob.read_shift(opts && opts.biff == 2 ? 1 : 2)];
19703}
19704
19705/* [MS-XLSB] 2.5.97.28 */
19706function parse_PtgAttrIfError(blob) {
19707 var bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0;
19708 blob.l += 2;
19709 return [bitIf, blob.read_shift(2)];
19710}
19711
19712/* [MS-XLS] 2.5.198.37 ; [MS-XLSB] 2.5.97.29 */
19713function parse_PtgAttrSemi(blob, length, opts) {
19714 var bitSemi = (blob[blob.l+1] & 0xFF) ? 1 : 0;
19715 blob.l += opts && opts.biff == 2 ? 3 : 4;
19716 return [bitSemi];
19717}
19718
19719/* [MS-XLS] 2.5.198.40 ; [MS-XLSB] 2.5.97.32 */
19720function parse_PtgAttrSpaceType(blob) {
19721 var type = blob.read_shift(1), cch = blob.read_shift(1);
19722 return [type, cch];
19723}
19724
19725/* [MS-XLS] 2.5.198.38 ; [MS-XLSB] 2.5.97.30 */
19726function parse_PtgAttrSpace(blob) {
19727 blob.read_shift(2);
19728 return parse_PtgAttrSpaceType(blob, 2);
19729}
19730
19731/* [MS-XLS] 2.5.198.39 ; [MS-XLSB] 2.5.97.31 */
19732function parse_PtgAttrSpaceSemi(blob) {
19733 blob.read_shift(2);
19734 return parse_PtgAttrSpaceType(blob, 2);
19735}
19736
19737/* [MS-XLS] 2.5.198.84 ; [MS-XLSB] 2.5.97.68 TODO */
19738function parse_PtgRef(blob, length, opts) {
19739 //var ptg = blob[blob.l] & 0x1F;
19740 var type = (blob[blob.l] & 0x60)>>5;
19741 blob.l += 1;
19742 var loc = parse_RgceLoc(blob, 0, opts);
19743 return [type, loc];
19744}
19745
19746/* [MS-XLS] 2.5.198.88 ; [MS-XLSB] 2.5.97.72 TODO */
19747function parse_PtgRefN(blob, length, opts) {
19748 var type = (blob[blob.l] & 0x60)>>5;
19749 blob.l += 1;
19750 var loc = parse_RgceLocRel(blob, 0, opts);
19751 return [type, loc];
19752}
19753
19754/* [MS-XLS] 2.5.198.85 ; [MS-XLSB] 2.5.97.69 TODO */
19755function parse_PtgRef3d(blob, length, opts) {
19756 var type = (blob[blob.l] & 0x60)>>5;
19757 blob.l += 1;
19758 var ixti = blob.read_shift(2); // XtiIndex
19759 if(opts && opts.biff == 5) blob.l += 12;
19760 var loc = parse_RgceLoc(blob, 0, opts); // TODO: or RgceLocRel
19761 return [type, ixti, loc];
19762}
19763
19764
19765/* [MS-XLS] 2.5.198.62 ; [MS-XLSB] 2.5.97.45 TODO */
19766function parse_PtgFunc(blob, length, opts) {
19767 //var ptg = blob[blob.l] & 0x1F;
19768 var type = (blob[blob.l] & 0x60)>>5;
19769 blob.l += 1;
19770 var iftab = blob.read_shift(opts && opts.biff <= 3 ? 1 : 2);
19771 return [FtabArgc[iftab], Ftab[iftab], type];
19772}
19773/* [MS-XLS] 2.5.198.63 ; [MS-XLSB] 2.5.97.46 TODO */
19774function parse_PtgFuncVar(blob, length, opts) {
19775 var type = blob[blob.l++];
19776 var cparams = blob.read_shift(1), tab = opts && opts.biff <= 3 ? [(type == 0x58 ? -1 : 0), blob.read_shift(1)]: parsetab(blob);
19777 return [cparams, (tab[0] === 0 ? Ftab : Cetab)[tab[1]]];
19778}
19779
19780function parsetab(blob) {
19781 return [blob[blob.l+1]>>7, blob.read_shift(2) & 0x7FFF];
19782}
19783
19784/* [MS-XLS] 2.5.198.41 ; [MS-XLSB] 2.5.97.33 */
19785function parse_PtgAttrSum(blob, length, opts) {
19786 blob.l += opts && opts.biff == 2 ? 3 : 4; return;
19787}
19788
19789/* [MS-XLS] 2.5.198.58 ; [MS-XLSB] 2.5.97.40 */
19790function parse_PtgExp(blob, length, opts) {
19791 blob.l++;
19792 if(opts && opts.biff == 12) return [blob.read_shift(4, 'i'), 0];
19793 var row = blob.read_shift(2);
19794 var col = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
19795 return [row, col];
19796}
19797
19798/* [MS-XLS] 2.5.198.57 ; [MS-XLSB] 2.5.97.39 */
19799function parse_PtgErr(blob) { blob.l++; return BErr[blob.read_shift(1)]; }
19800
19801/* [MS-XLS] 2.5.198.66 ; [MS-XLSB] 2.5.97.49 */
19802function parse_PtgInt(blob) { blob.l++; return blob.read_shift(2); }
19803
19804/* [MS-XLS] 2.5.198.42 ; [MS-XLSB] 2.5.97.34 */
19805function parse_PtgBool(blob) { blob.l++; return blob.read_shift(1)!==0;}
19806
19807/* [MS-XLS] 2.5.198.79 ; [MS-XLSB] 2.5.97.63 */
19808function parse_PtgNum(blob) { blob.l++; return parse_Xnum(blob, 8); }
19809
19810/* [MS-XLS] 2.5.198.89 ; [MS-XLSB] 2.5.97.74 */
19811function parse_PtgStr(blob, length, opts) { blob.l++; return parse_ShortXLUnicodeString(blob, length-1, opts); }
19812
19813/* [MS-XLS] 2.5.192.112 + 2.5.192.11{3,4,5,6,7} */
19814/* [MS-XLSB] 2.5.97.93 + 2.5.97.9{4,5,6,7} */
19815function parse_SerAr(blob, biff) {
19816 var val = [blob.read_shift(1)];
19817 if(biff == 12) switch(val[0]) {
19818 case 0x02: val[0] = 0x04; break; /* SerBool */
19819 case 0x04: val[0] = 0x10; break; /* SerErr */
19820 case 0x00: val[0] = 0x01; break; /* SerNum */
19821 case 0x01: val[0] = 0x02; break; /* SerStr */
19822 }
19823 switch(val[0]) {
19824 case 0x04: /* SerBool -- boolean */
19825 val[1] = parsebool(blob, 1) ? 'TRUE' : 'FALSE';
19826 if(biff != 12) blob.l += 7; break;
19827 case 0x25: /* appears to be an alias */
19828 case 0x10: /* SerErr -- error */
19829 val[1] = BErr[blob[blob.l]];
19830 blob.l += ((biff == 12) ? 4 : 8); break;
19831 case 0x00: /* SerNil -- honestly, I'm not sure how to reproduce this */
19832 blob.l += 8; break;
19833 case 0x01: /* SerNum -- Xnum */
19834 val[1] = parse_Xnum(blob, 8); break;
19835 case 0x02: /* SerStr -- XLUnicodeString (<256 chars) */
19836 val[1] = parse_XLUnicodeString2(blob, 0, {biff:biff > 0 && biff < 8 ? 2 : biff}); break;
19837 default: throw new Error("Bad SerAr: " + val[0]); /* Unreachable */
19838 }
19839 return val;
19840}
19841
19842/* [MS-XLS] 2.5.198.61 ; [MS-XLSB] 2.5.97.44 */
19843function parse_PtgExtraMem(blob, cce, opts) {
19844 var count = blob.read_shift((opts.biff == 12) ? 4 : 2);
19845 var out = [];
19846 for(var i = 0; i != count; ++i) out.push(((opts.biff == 12) ? parse_UncheckedRfX : parse_Ref8U)(blob, 8));
19847 return out;
19848}
19849
19850/* [MS-XLS] 2.5.198.59 ; [MS-XLSB] 2.5.97.41 */
19851function parse_PtgExtraArray(blob, length, opts) {
19852 var rows = 0, cols = 0;
19853 if(opts.biff == 12) {
19854 rows = blob.read_shift(4); // DRw
19855 cols = blob.read_shift(4); // DCol
19856 } else {
19857 cols = 1 + blob.read_shift(1); //DColByteU
19858 rows = 1 + blob.read_shift(2); //DRw
19859 }
19860 if(opts.biff >= 2 && opts.biff < 8) { --rows; if(--cols == 0) cols = 0x100; }
19861 // $FlowIgnore
19862 for(var i = 0, o = []; i != rows && (o[i] = []); ++i)
19863 for(var j = 0; j != cols; ++j) o[i][j] = parse_SerAr(blob, opts.biff);
19864 return o;
19865}
19866
19867/* [MS-XLS] 2.5.198.76 ; [MS-XLSB] 2.5.97.60 */
19868function parse_PtgName(blob, length, opts) {
19869 var type = (blob.read_shift(1) >>> 5) & 0x03;
19870 var w = (!opts || (opts.biff >= 8)) ? 4 : 2;
19871 var nameindex = blob.read_shift(w);
19872 switch(opts.biff) {
19873 case 2: blob.l += 5; break;
19874 case 3: case 4: blob.l += 8; break;
19875 case 5: blob.l += 12; break;
19876 }
19877 return [type, 0, nameindex];
19878}
19879
19880/* [MS-XLS] 2.5.198.77 ; [MS-XLSB] 2.5.97.61 */
19881function parse_PtgNameX(blob, length, opts) {
19882 if(opts.biff == 5) return parse_PtgNameX_BIFF5(blob, length, opts);
19883 var type = (blob.read_shift(1) >>> 5) & 0x03;
19884 var ixti = blob.read_shift(2); // XtiIndex
19885 var nameindex = blob.read_shift(4);
19886 return [type, ixti, nameindex];
19887}
19888function parse_PtgNameX_BIFF5(blob) {
19889 var type = (blob.read_shift(1) >>> 5) & 0x03;
19890 var ixti = blob.read_shift(2, 'i'); // XtiIndex
19891 blob.l += 8;
19892 var nameindex = blob.read_shift(2);
19893 blob.l += 12;
19894 return [type, ixti, nameindex];
19895}
19896
19897/* [MS-XLS] 2.5.198.70 ; [MS-XLSB] 2.5.97.54 */
19898function parse_PtgMemArea(blob, length, opts) {
19899 var type = (blob.read_shift(1) >>> 5) & 0x03;
19900 blob.l += (opts && opts.biff == 2 ? 3 : 4);
19901 var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
19902 return [type, cce];
19903}
19904
19905/* [MS-XLS] 2.5.198.72 ; [MS-XLSB] 2.5.97.56 */
19906function parse_PtgMemFunc(blob, length, opts) {
19907 var type = (blob.read_shift(1) >>> 5) & 0x03;
19908 var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2);
19909 return [type, cce];
19910}
19911
19912
19913/* [MS-XLS] 2.5.198.86 ; [MS-XLSB] 2.5.97.69 */
19914function parse_PtgRefErr(blob, length, opts) {
19915 var type = (blob.read_shift(1) >>> 5) & 0x03;
19916 blob.l += 4;
19917 if(opts.biff < 8) blob.l--;
19918 if(opts.biff == 12) blob.l += 2;
19919 return [type];
19920}
19921
19922/* [MS-XLS] 2.5.198.87 ; [MS-XLSB] 2.5.97.71 */
19923function parse_PtgRefErr3d(blob, length, opts) {
19924 var type = (blob[blob.l++] & 0x60) >> 5;
19925 var ixti = blob.read_shift(2);
19926 var w = 4;
19927 if(opts) switch(opts.biff) {
19928 case 5: w = 15; break;
19929 case 12: w = 6; break;
19930 }
19931 blob.l += w;
19932 return [type, ixti];
19933}
19934
19935/* [MS-XLS] 2.5.198.71 ; [MS-XLSB] 2.5.97.55 */
19936var parse_PtgMemErr = parsenoop;
19937/* [MS-XLS] 2.5.198.73 ; [MS-XLSB] 2.5.97.57 */
19938var parse_PtgMemNoMem = parsenoop;
19939/* [MS-XLS] 2.5.198.92 */
19940var parse_PtgTbl = parsenoop;
19941
19942function parse_PtgElfLoc(blob, length, opts) {
19943 blob.l += 2;
19944 return [parse_RgceElfLoc(blob, 4, opts)];
19945}
19946function parse_PtgElfNoop(blob) {
19947 blob.l += 6;
19948 return [];
19949}
19950/* [MS-XLS] 2.5.198.46 */
19951var parse_PtgElfCol = parse_PtgElfLoc;
19952/* [MS-XLS] 2.5.198.47 */
19953var parse_PtgElfColS = parse_PtgElfNoop;
19954/* [MS-XLS] 2.5.198.48 */
19955var parse_PtgElfColSV = parse_PtgElfNoop;
19956/* [MS-XLS] 2.5.198.49 */
19957var parse_PtgElfColV = parse_PtgElfLoc;
19958/* [MS-XLS] 2.5.198.50 */
19959function parse_PtgElfLel(blob) {
19960 blob.l += 2;
19961 return [parseuint16(blob), blob.read_shift(2) & 0x01];
19962}
19963/* [MS-XLS] 2.5.198.51 */
19964var parse_PtgElfRadical = parse_PtgElfLoc;
19965/* [MS-XLS] 2.5.198.52 */
19966var parse_PtgElfRadicalLel = parse_PtgElfLel;
19967/* [MS-XLS] 2.5.198.53 */
19968var parse_PtgElfRadicalS = parse_PtgElfNoop;
19969/* [MS-XLS] 2.5.198.54 */
19970var parse_PtgElfRw = parse_PtgElfLoc;
19971/* [MS-XLS] 2.5.198.55 */
19972var parse_PtgElfRwV = parse_PtgElfLoc;
19973
19974/* [MS-XLSB] 2.5.97.52 TODO */
19975var PtgListRT = [
19976 "Data",
19977 "All",
19978 "Headers",
19979 "??",
19980 "?Data2",
19981 "??",
19982 "?DataHeaders",
19983 "??",
19984 "Totals",
19985 "??",
19986 "??",
19987 "??",
19988 "?DataTotals",
19989 "??",
19990 "??",
19991 "??",
19992 "?Current"
19993];
19994function parse_PtgList(blob) {
19995 blob.l += 2;
19996 var ixti = blob.read_shift(2);
19997 var flags = blob.read_shift(2);
19998 var idx = blob.read_shift(4);
19999 var c = blob.read_shift(2);
20000 var C = blob.read_shift(2);
20001 var rt = PtgListRT[(flags >> 2) & 0x1F];
20002 return {ixti: ixti, coltype:(flags&0x3), rt:rt, idx:idx, c:c, C:C};
20003}
20004/* [MS-XLS] 2.5.198.91 ; [MS-XLSB] 2.5.97.76 */
20005function parse_PtgSxName(blob) {
20006 blob.l += 2;
20007 return [blob.read_shift(4)];
20008}
20009
20010/* [XLS] old spec */
20011function parse_PtgSheet(blob, length, opts) {
20012 blob.l += 5;
20013 blob.l += 2;
20014 blob.l += (opts.biff == 2 ? 1 : 4);
20015 return ["PTGSHEET"];
20016}
20017function parse_PtgEndSheet(blob, length, opts) {
20018 blob.l += (opts.biff == 2 ? 4 : 5);
20019 return ["PTGENDSHEET"];
20020}
20021function parse_PtgMemAreaN(blob) {
20022 var type = (blob.read_shift(1) >>> 5) & 0x03;
20023 var cce = blob.read_shift(2);
20024 return [type, cce];
20025}
20026function parse_PtgMemNoMemN(blob) {
20027 var type = (blob.read_shift(1) >>> 5) & 0x03;
20028 var cce = blob.read_shift(2);
20029 return [type, cce];
20030}
20031function parse_PtgAttrNoop(blob) {
20032 blob.l += 4;
20033 return [0, 0];
20034}
20035
20036/* [MS-XLS] 2.5.198.25 ; [MS-XLSB] 2.5.97.16 */
20037var PtgTypes = {
200380x01: { n:'PtgExp', f:parse_PtgExp },
200390x02: { n:'PtgTbl', f:parse_PtgTbl },
200400x03: { n:'PtgAdd', f:parseread1 },
200410x04: { n:'PtgSub', f:parseread1 },
200420x05: { n:'PtgMul', f:parseread1 },
200430x06: { n:'PtgDiv', f:parseread1 },
200440x07: { n:'PtgPower', f:parseread1 },
200450x08: { n:'PtgConcat', f:parseread1 },
200460x09: { n:'PtgLt', f:parseread1 },
200470x0A: { n:'PtgLe', f:parseread1 },
200480x0B: { n:'PtgEq', f:parseread1 },
200490x0C: { n:'PtgGe', f:parseread1 },
200500x0D: { n:'PtgGt', f:parseread1 },
200510x0E: { n:'PtgNe', f:parseread1 },
200520x0F: { n:'PtgIsect', f:parseread1 },
200530x10: { n:'PtgUnion', f:parseread1 },
200540x11: { n:'PtgRange', f:parseread1 },
200550x12: { n:'PtgUplus', f:parseread1 },
200560x13: { n:'PtgUminus', f:parseread1 },
200570x14: { n:'PtgPercent', f:parseread1 },
200580x15: { n:'PtgParen', f:parseread1 },
200590x16: { n:'PtgMissArg', f:parseread1 },
200600x17: { n:'PtgStr', f:parse_PtgStr },
200610x1A: { n:'PtgSheet', f:parse_PtgSheet },
200620x1B: { n:'PtgEndSheet', f:parse_PtgEndSheet },
200630x1C: { n:'PtgErr', f:parse_PtgErr },
200640x1D: { n:'PtgBool', f:parse_PtgBool },
200650x1E: { n:'PtgInt', f:parse_PtgInt },
200660x1F: { n:'PtgNum', f:parse_PtgNum },
200670x20: { n:'PtgArray', f:parse_PtgArray },
200680x21: { n:'PtgFunc', f:parse_PtgFunc },
200690x22: { n:'PtgFuncVar', f:parse_PtgFuncVar },
200700x23: { n:'PtgName', f:parse_PtgName },
200710x24: { n:'PtgRef', f:parse_PtgRef },
200720x25: { n:'PtgArea', f:parse_PtgArea },
200730x26: { n:'PtgMemArea', f:parse_PtgMemArea },
200740x27: { n:'PtgMemErr', f:parse_PtgMemErr },
200750x28: { n:'PtgMemNoMem', f:parse_PtgMemNoMem },
200760x29: { n:'PtgMemFunc', f:parse_PtgMemFunc },
200770x2A: { n:'PtgRefErr', f:parse_PtgRefErr },
200780x2B: { n:'PtgAreaErr', f:parse_PtgAreaErr },
200790x2C: { n:'PtgRefN', f:parse_PtgRefN },
200800x2D: { n:'PtgAreaN', f:parse_PtgAreaN },
200810x2E: { n:'PtgMemAreaN', f:parse_PtgMemAreaN },
200820x2F: { n:'PtgMemNoMemN', f:parse_PtgMemNoMemN },
200830x39: { n:'PtgNameX', f:parse_PtgNameX },
200840x3A: { n:'PtgRef3d', f:parse_PtgRef3d },
200850x3B: { n:'PtgArea3d', f:parse_PtgArea3d },
200860x3C: { n:'PtgRefErr3d', f:parse_PtgRefErr3d },
200870x3D: { n:'PtgAreaErr3d', f:parse_PtgAreaErr3d },
200880xFF: {}
20089};
20090/* These are duplicated in the PtgTypes table */
20091var PtgDupes = {
200920x40: 0x20, 0x60: 0x20,
200930x41: 0x21, 0x61: 0x21,
200940x42: 0x22, 0x62: 0x22,
200950x43: 0x23, 0x63: 0x23,
200960x44: 0x24, 0x64: 0x24,
200970x45: 0x25, 0x65: 0x25,
200980x46: 0x26, 0x66: 0x26,
200990x47: 0x27, 0x67: 0x27,
201000x48: 0x28, 0x68: 0x28,
201010x49: 0x29, 0x69: 0x29,
201020x4A: 0x2A, 0x6A: 0x2A,
201030x4B: 0x2B, 0x6B: 0x2B,
201040x4C: 0x2C, 0x6C: 0x2C,
201050x4D: 0x2D, 0x6D: 0x2D,
201060x4E: 0x2E, 0x6E: 0x2E,
201070x4F: 0x2F, 0x6F: 0x2F,
201080x58: 0x22, 0x78: 0x22,
201090x59: 0x39, 0x79: 0x39,
201100x5A: 0x3A, 0x7A: 0x3A,
201110x5B: 0x3B, 0x7B: 0x3B,
201120x5C: 0x3C, 0x7C: 0x3C,
201130x5D: 0x3D, 0x7D: 0x3D
20114};
20115(function(){for(var y in PtgDupes) PtgTypes[y] = PtgTypes[PtgDupes[y]];})();
20116
20117var Ptg18 = {
201180x01: { n:'PtgElfLel', f:parse_PtgElfLel },
201190x02: { n:'PtgElfRw', f:parse_PtgElfRw },
201200x03: { n:'PtgElfCol', f:parse_PtgElfCol },
201210x06: { n:'PtgElfRwV', f:parse_PtgElfRwV },
201220x07: { n:'PtgElfColV', f:parse_PtgElfColV },
201230x0A: { n:'PtgElfRadical', f:parse_PtgElfRadical },
201240x0B: { n:'PtgElfRadicalS', f:parse_PtgElfRadicalS },
201250x0D: { n:'PtgElfColS', f:parse_PtgElfColS },
201260x0F: { n:'PtgElfColSV', f:parse_PtgElfColSV },
201270x10: { n:'PtgElfRadicalLel', f:parse_PtgElfRadicalLel },
201280x19: { n:'PtgList', f:parse_PtgList },
201290x1D: { n:'PtgSxName', f:parse_PtgSxName },
201300xFF: {}
20131};
20132var Ptg19 = {
201330x00: { n:'PtgAttrNoop', f:parse_PtgAttrNoop },
201340x01: { n:'PtgAttrSemi', f:parse_PtgAttrSemi },
201350x02: { n:'PtgAttrIf', f:parse_PtgAttrIf },
201360x04: { n:'PtgAttrChoose', f:parse_PtgAttrChoose },
201370x08: { n:'PtgAttrGoto', f:parse_PtgAttrGoto },
201380x10: { n:'PtgAttrSum', f:parse_PtgAttrSum },
201390x20: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel },
201400x40: { n:'PtgAttrSpace', f:parse_PtgAttrSpace },
201410x41: { n:'PtgAttrSpaceSemi', f:parse_PtgAttrSpaceSemi },
201420x80: { n:'PtgAttrIfError', f:parse_PtgAttrIfError },
201430xFF: {}
20144};
20145Ptg19[0x21] = Ptg19[0x20];
20146
20147/* [MS-XLS] 2.5.198.103 ; [MS-XLSB] 2.5.97.87 */
20148function parse_RgbExtra(blob, length, rgce, opts) {
20149 if(opts.biff < 8) return parsenoop(blob, length);
20150 var target = blob.l + length;
20151 var o = [];
20152 for(var i = 0; i !== rgce.length; ++i) {
20153 switch(rgce[i][0]) {
20154 case 'PtgArray': /* PtgArray -> PtgExtraArray */
20155 rgce[i][1] = parse_PtgExtraArray(blob, 0, opts);
20156 o.push(rgce[i][1]);
20157 break;
20158 case 'PtgMemArea': /* PtgMemArea -> PtgExtraMem */
20159 rgce[i][2] = parse_PtgExtraMem(blob, rgce[i][1], opts);
20160 o.push(rgce[i][2]);
20161 break;
20162 case 'PtgExp': /* PtgExp -> PtgExtraCol */
20163 if(opts && opts.biff == 12) {
20164 rgce[i][1][1] = blob.read_shift(4);
20165 o.push(rgce[i][1]);
20166 } break;
20167 case 'PtgList': /* TODO: PtgList -> PtgExtraList */
20168 case 'PtgElfRadicalS': /* TODO: PtgElfRadicalS -> PtgExtraElf */
20169 case 'PtgElfColS': /* TODO: PtgElfColS -> PtgExtraElf */
20170 case 'PtgElfColSV': /* TODO: PtgElfColSV -> PtgExtraElf */
20171 throw "Unsupported " + rgce[i][0];
20172 default: break;
20173 }
20174 }
20175 length = target - blob.l;
20176 /* note: this is technically an error but Excel disregards */
20177 //if(target !== blob.l && blob.l !== target - length) throw new Error(target + " != " + blob.l);
20178 if(length !== 0) o.push(parsenoop(blob, length));
20179 return o;
20180}
20181
20182/* [MS-XLS] 2.5.198.104 ; [MS-XLSB] 2.5.97.88 */
20183function parse_Rgce(blob, length, opts) {
20184 var target = blob.l + length;
20185 var R, id, ptgs = [];
20186 while(target != blob.l) {
20187 length = target - blob.l;
20188 id = blob[blob.l];
20189 R = PtgTypes[id];
20190 if(id === 0x18 || id === 0x19) R = (id === 0x18 ? Ptg18 : Ptg19)[blob[blob.l + 1]];
20191 if(!R || !R.f) { /*ptgs.push*/(parsenoop(blob, length)); }
20192 else { ptgs.push([R.n, R.f(blob, length, opts)]); }
20193 }
20194 return ptgs;
20195}
20196
20197function stringify_array(f) {
20198 var o = [];
20199 for(var i = 0; i < f.length; ++i) {
20200 var x = f[i], r = [];
20201 for(var j = 0; j < x.length; ++j) {
20202 var y = x[j];
20203 if(y) switch(y[0]) {
20204 // TODO: handle embedded quotes
20205 case 0x02:
20206r.push('"' + y[1].replace(/"/g,'""') + '"'); break;
20207 default: r.push(y[1]);
20208 } else r.push("");
20209 }
20210 o.push(r.join(","));
20211 }
20212 return o.join(";");
20213}
20214
20215/* [MS-XLS] 2.2.2 ; [MS-XLSB] 2.2.2 TODO */
20216var PtgBinOp = {
20217 PtgAdd: "+",
20218 PtgConcat: "&",
20219 PtgDiv: "/",
20220 PtgEq: "=",
20221 PtgGe: ">=",
20222 PtgGt: ">",
20223 PtgLe: "<=",
20224 PtgLt: "<",
20225 PtgMul: "*",
20226 PtgNe: "<>",
20227 PtgPower: "^",
20228 PtgSub: "-"
20229};
20230function formula_quote_sheet_name(sname, opts) {
20231 if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name");
20232 if(sname.indexOf(" ") > -1) return "'" + sname + "'";
20233 return sname;
20234}
20235function get_ixti_raw(supbooks, ixti, opts) {
20236 if(!supbooks) return "SH33TJSERR0";
20237 if(opts.biff > 8 && (!supbooks.XTI || !supbooks.XTI[ixti])) return supbooks.SheetNames[ixti];
20238 if(!supbooks.XTI) return "SH33TJSERR6";
20239 var XTI = supbooks.XTI[ixti];
20240 if(opts.biff < 8) {
20241 if(ixti > 10000) ixti-= 65536;
20242 if(ixti < 0) ixti = -ixti;
20243 return ixti == 0 ? "" : supbooks.XTI[ixti - 1];
20244 }
20245 if(!XTI) return "SH33TJSERR1";
20246 var o = "";
20247 if(opts.biff > 8) switch(supbooks[XTI[0]][0]) {
20248 case 0x0165: /* 'BrtSupSelf' */
20249 o = XTI[1] == -1 ? "#REF" : supbooks.SheetNames[XTI[1]];
20250 return XTI[1] == XTI[2] ? o : o + ":" + supbooks.SheetNames[XTI[2]];
20251 case 0x0166: /* 'BrtSupSame' */
20252 if(opts.SID != null) return supbooks.SheetNames[opts.SID];
20253 return "SH33TJSSAME" + supbooks[XTI[0]][0];
20254 case 0x0163: /* 'BrtSupBookSrc' */
20255 /* falls through */
20256 default: return "SH33TJSSRC" + supbooks[XTI[0]][0];
20257 }
20258 switch(supbooks[XTI[0]][0][0]) {
20259 case 0x0401:
20260 o = XTI[1] == -1 ? "#REF" : (supbooks.SheetNames[XTI[1]] || "SH33TJSERR3");
20261 return XTI[1] == XTI[2] ? o : o + ":" + supbooks.SheetNames[XTI[2]];
20262 case 0x3A01: return supbooks[XTI[0]].slice(1).map(function(name) { return name.Name; }).join(";;"); //return "SH33TJSERR8";
20263 default:
20264 if(!supbooks[XTI[0]][0][3]) return "SH33TJSERR2";
20265 o = XTI[1] == -1 ? "#REF" : (supbooks[XTI[0]][0][3][XTI[1]] || "SH33TJSERR4");
20266 return XTI[1] == XTI[2] ? o : o + ":" + supbooks[XTI[0]][0][3][XTI[2]];
20267 }
20268}
20269function get_ixti(supbooks, ixti, opts) {
20270 return formula_quote_sheet_name(get_ixti_raw(supbooks, ixti, opts), opts);
20271}
20272function stringify_formula(formula/*Array<any>*/, range, cell, supbooks, opts) {
20273 var biff = (opts && opts.biff) || 8;
20274 var _range = /*range != null ? range :*/ {s:{c:0, r:0},e:{c:0, r:0}};
20275 var stack = [], e1, e2, c, ixti=0, nameidx=0, r, sname="";
20276 if(!formula[0] || !formula[0][0]) return "";
20277 var last_sp = -1, sp = "";
20278 for(var ff = 0, fflen = formula[0].length; ff < fflen; ++ff) {
20279 var f = formula[0][ff];
20280 switch(f[0]) {
20281 case 'PtgUminus': /* [MS-XLS] 2.5.198.93 */
20282 stack.push("-" + stack.pop()); break;
20283 case 'PtgUplus': /* [MS-XLS] 2.5.198.95 */
20284 stack.push("+" + stack.pop()); break;
20285 case 'PtgPercent': /* [MS-XLS] 2.5.198.81 */
20286 stack.push(stack.pop() + "%"); break;
20287
20288 case 'PtgAdd': /* [MS-XLS] 2.5.198.26 */
20289 case 'PtgConcat': /* [MS-XLS] 2.5.198.43 */
20290 case 'PtgDiv': /* [MS-XLS] 2.5.198.45 */
20291 case 'PtgEq': /* [MS-XLS] 2.5.198.56 */
20292 case 'PtgGe': /* [MS-XLS] 2.5.198.64 */
20293 case 'PtgGt': /* [MS-XLS] 2.5.198.65 */
20294 case 'PtgLe': /* [MS-XLS] 2.5.198.68 */
20295 case 'PtgLt': /* [MS-XLS] 2.5.198.69 */
20296 case 'PtgMul': /* [MS-XLS] 2.5.198.75 */
20297 case 'PtgNe': /* [MS-XLS] 2.5.198.78 */
20298 case 'PtgPower': /* [MS-XLS] 2.5.198.82 */
20299 case 'PtgSub': /* [MS-XLS] 2.5.198.90 */
20300 e1 = stack.pop(); e2 = stack.pop();
20301 if(last_sp >= 0) {
20302 switch(formula[0][last_sp][1][0]) {
20303 case 0:
20304 // $FlowIgnore
20305 sp = fill(" ", formula[0][last_sp][1][1]); break;
20306 case 1:
20307 // $FlowIgnore
20308 sp = fill("\r", formula[0][last_sp][1][1]); break;
20309 default:
20310 sp = "";
20311 // $FlowIgnore
20312 if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + formula[0][last_sp][1][0]);
20313 }
20314 e2 = e2 + sp;
20315 last_sp = -1;
20316 }
20317 stack.push(e2+PtgBinOp[f[0]]+e1);
20318 break;
20319
20320 case 'PtgIsect': /* [MS-XLS] 2.5.198.67 */
20321 e1 = stack.pop(); e2 = stack.pop();
20322 stack.push(e2+" "+e1);
20323 break;
20324 case 'PtgUnion': /* [MS-XLS] 2.5.198.94 */
20325 e1 = stack.pop(); e2 = stack.pop();
20326 stack.push(e2+","+e1);
20327 break;
20328 case 'PtgRange': /* [MS-XLS] 2.5.198.83 */
20329 e1 = stack.pop(); e2 = stack.pop();
20330 stack.push(e2+":"+e1);
20331 break;
20332
20333 case 'PtgAttrChoose': /* [MS-XLS] 2.5.198.34 */
20334 break;
20335 case 'PtgAttrGoto': /* [MS-XLS] 2.5.198.35 */
20336 break;
20337 case 'PtgAttrIf': /* [MS-XLS] 2.5.198.36 */
20338 break;
20339 case 'PtgAttrIfError': /* [MS-XLSB] 2.5.97.28 */
20340 break;
20341
20342
20343 case 'PtgRef': /* [MS-XLS] 2.5.198.84 */
20344c = shift_cell_xls((f[1][1]), _range, opts);
20345 stack.push(encode_cell_xls(c, biff));
20346 break;
20347 case 'PtgRefN': /* [MS-XLS] 2.5.198.88 */
20348c = cell ? shift_cell_xls((f[1][1]), cell, opts) : (f[1][1]);
20349 stack.push(encode_cell_xls(c, biff));
20350 break;
20351 case 'PtgRef3d': /* [MS-XLS] 2.5.198.85 */
20352ixti = f[1][1]; c = shift_cell_xls((f[1][2]), _range, opts);
20353 sname = get_ixti(supbooks, ixti, opts);
20354 var w = sname; /* IE9 fails on defined names */ // eslint-disable-line no-unused-vars
20355 stack.push(sname + "!" + encode_cell_xls(c, biff));
20356 break;
20357
20358 case 'PtgFunc': /* [MS-XLS] 2.5.198.62 */
20359 case 'PtgFuncVar': /* [MS-XLS] 2.5.198.63 */
20360 /* f[1] = [argc, func, type] */
20361 var argc = (f[1][0]), func = (f[1][1]);
20362 if(!argc) argc = 0;
20363 argc &= 0x7F;
20364 var args = argc == 0 ? [] : stack.slice(-argc);
20365 stack.length -= argc;
20366 if(func === 'User') func = args.shift();
20367 stack.push(func + "(" + args.join(",") + ")");
20368 break;
20369
20370 case 'PtgBool': /* [MS-XLS] 2.5.198.42 */
20371 stack.push(f[1] ? "TRUE" : "FALSE"); break;
20372 case 'PtgInt': /* [MS-XLS] 2.5.198.66 */
20373 stack.push(f[1]); break;
20374 case 'PtgNum': /* [MS-XLS] 2.5.198.79 TODO: precision? */
20375 stack.push(String(f[1])); break;
20376 case 'PtgStr': /* [MS-XLS] 2.5.198.89 */
20377 // $FlowIgnore
20378 stack.push('"' + f[1].replace(/"/g, '""') + '"'); break;
20379 case 'PtgErr': /* [MS-XLS] 2.5.198.57 */
20380 stack.push(f[1]); break;
20381 case 'PtgAreaN': /* [MS-XLS] 2.5.198.31 TODO */
20382r = shift_range_xls(f[1][1], cell ? {s:cell} : _range, opts);
20383 stack.push(encode_range_xls((r), opts));
20384 break;
20385 case 'PtgArea': /* [MS-XLS] 2.5.198.27 TODO: fixed points */
20386r = shift_range_xls(f[1][1], _range, opts);
20387 stack.push(encode_range_xls((r), opts));
20388 break;
20389 case 'PtgArea3d': /* [MS-XLS] 2.5.198.28 TODO */
20390ixti = f[1][1]; r = f[1][2];
20391 sname = get_ixti(supbooks, ixti, opts);
20392 stack.push(sname + "!" + encode_range_xls((r), opts));
20393 break;
20394 case 'PtgAttrSum': /* [MS-XLS] 2.5.198.41 */
20395 stack.push("SUM(" + stack.pop() + ")");
20396 break;
20397
20398 case 'PtgAttrBaxcel': /* [MS-XLS] 2.5.198.33 */
20399 case 'PtgAttrSemi': /* [MS-XLS] 2.5.198.37 */
20400 break;
20401
20402 case 'PtgName': /* [MS-XLS] 2.5.198.76 ; [MS-XLSB] 2.5.97.60 TODO: revisions */
20403 /* f[1] = type, 0, nameindex */
20404 nameidx = (f[1][2]);
20405 var lbl = (supbooks.names||[])[nameidx-1] || (supbooks[0]||[])[nameidx];
20406 var name = lbl ? lbl.Name : "SH33TJSNAME" + String(nameidx);
20407 if(name in XLSXFutureFunctions) name = XLSXFutureFunctions[name];
20408 stack.push(name);
20409 break;
20410
20411 case 'PtgNameX': /* [MS-XLS] 2.5.198.77 ; [MS-XLSB] 2.5.97.61 TODO: revisions */
20412 /* f[1] = type, ixti, nameindex */
20413 var bookidx = (f[1][1]); nameidx = (f[1][2]); var externbook;
20414 /* TODO: Properly handle missing values -- this should be using get_ixti_raw primarily */
20415 if(opts.biff <= 5) {
20416 if(bookidx < 0) bookidx = -bookidx;
20417 if(supbooks[bookidx]) externbook = supbooks[bookidx][nameidx];
20418 } else {
20419 var o = "";
20420 if(((supbooks[bookidx]||[])[0]||[])[0] == 0x3A01){/* empty */}
20421 else if(((supbooks[bookidx]||[])[0]||[])[0] == 0x0401){
20422 if(supbooks[bookidx][nameidx] && supbooks[bookidx][nameidx].itab > 0) {
20423 o = supbooks.SheetNames[supbooks[bookidx][nameidx].itab-1] + "!";
20424 }
20425 }
20426 else o = supbooks.SheetNames[nameidx-1]+ "!";
20427 if(supbooks[bookidx] && supbooks[bookidx][nameidx]) o += supbooks[bookidx][nameidx].Name;
20428 else if(supbooks[0] && supbooks[0][nameidx]) o += supbooks[0][nameidx].Name;
20429 else {
20430 var ixtidata = get_ixti_raw(supbooks, bookidx, opts).split(";;");
20431 if(ixtidata[nameidx - 1]) o = ixtidata[nameidx - 1]; // TODO: confirm this is correct
20432 else o += "SH33TJSERRX";
20433 }
20434 stack.push(o);
20435 break;
20436 }
20437 if(!externbook) externbook = {Name: "SH33TJSERRY"};
20438 stack.push(externbook.Name);
20439 break;
20440
20441 case 'PtgParen': /* [MS-XLS] 2.5.198.80 */
20442 var lp = '(', rp = ')';
20443 if(last_sp >= 0) {
20444 sp = "";
20445 switch(formula[0][last_sp][1][0]) {
20446 // $FlowIgnore
20447 case 2: lp = fill(" ", formula[0][last_sp][1][1]) + lp; break;
20448 // $FlowIgnore
20449 case 3: lp = fill("\r", formula[0][last_sp][1][1]) + lp; break;
20450 // $FlowIgnore
20451 case 4: rp = fill(" ", formula[0][last_sp][1][1]) + rp; break;
20452 // $FlowIgnore
20453 case 5: rp = fill("\r", formula[0][last_sp][1][1]) + rp; break;
20454 default:
20455 // $FlowIgnore
20456 if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + formula[0][last_sp][1][0]);
20457 }
20458 last_sp = -1;
20459 }
20460 stack.push(lp + stack.pop() + rp); break;
20461
20462 case 'PtgRefErr': /* [MS-XLS] 2.5.198.86 */
20463 stack.push('#REF!'); break;
20464
20465 case 'PtgRefErr3d': /* [MS-XLS] 2.5.198.87 */
20466 stack.push('#REF!'); break;
20467
20468 case 'PtgExp': /* [MS-XLS] 2.5.198.58 TODO */
20469 c = {c:(f[1][1]),r:(f[1][0])};
20470 var q = ({c: cell.c, r:cell.r});
20471 if(supbooks.sharedf[encode_cell(c)]) {
20472 var parsedf = (supbooks.sharedf[encode_cell(c)]);
20473 stack.push(stringify_formula(parsedf, _range, q, supbooks, opts));
20474 }
20475 else {
20476 var fnd = false;
20477 for(e1=0;e1!=supbooks.arrayf.length; ++e1) {
20478 /* TODO: should be something like range_has */
20479 e2 = supbooks.arrayf[e1];
20480 if(c.c < e2[0].s.c || c.c > e2[0].e.c) continue;
20481 if(c.r < e2[0].s.r || c.r > e2[0].e.r) continue;
20482 stack.push(stringify_formula(e2[1], _range, q, supbooks, opts));
20483 fnd = true;
20484 break;
20485 }
20486 if(!fnd) stack.push(f[1]);
20487 }
20488 break;
20489
20490 case 'PtgArray': /* [MS-XLS] 2.5.198.32 TODO */
20491 stack.push("{" + stringify_array(f[1]) + "}");
20492 break;
20493
20494 case 'PtgMemArea': /* [MS-XLS] 2.5.198.70 TODO: confirm this is a non-display */
20495 //stack.push("(" + f[2].map(encode_range).join(",") + ")");
20496 break;
20497
20498 case 'PtgAttrSpace': /* [MS-XLS] 2.5.198.38 */
20499 case 'PtgAttrSpaceSemi': /* [MS-XLS] 2.5.198.39 */
20500 last_sp = ff;
20501 break;
20502
20503 case 'PtgTbl': /* [MS-XLS] 2.5.198.92 TODO */
20504 break;
20505
20506 case 'PtgMemErr': /* [MS-XLS] 2.5.198.71 */
20507 break;
20508
20509 case 'PtgMissArg': /* [MS-XLS] 2.5.198.74 */
20510 stack.push("");
20511 break;
20512
20513 case 'PtgAreaErr': /* [MS-XLS] 2.5.198.29 */
20514 stack.push("#REF!"); break;
20515
20516 case 'PtgAreaErr3d': /* [MS-XLS] 2.5.198.30 */
20517 stack.push("#REF!"); break;
20518
20519 case 'PtgList': /* [MS-XLSB] 2.5.97.52 */
20520 // $FlowIgnore
20521 stack.push("Table" + f[1].idx + "[#" + f[1].rt + "]");
20522 break;
20523
20524 case 'PtgMemAreaN':
20525 case 'PtgMemNoMemN':
20526 case 'PtgAttrNoop':
20527 case 'PtgSheet':
20528 case 'PtgEndSheet':
20529 break;
20530
20531 case 'PtgMemFunc': /* [MS-XLS] 2.5.198.72 TODO */
20532 break;
20533 case 'PtgMemNoMem': /* [MS-XLS] 2.5.198.73 TODO */
20534 break;
20535
20536 case 'PtgElfCol': /* [MS-XLS] 2.5.198.46 */
20537 case 'PtgElfColS': /* [MS-XLS] 2.5.198.47 */
20538 case 'PtgElfColSV': /* [MS-XLS] 2.5.198.48 */
20539 case 'PtgElfColV': /* [MS-XLS] 2.5.198.49 */
20540 case 'PtgElfLel': /* [MS-XLS] 2.5.198.50 */
20541 case 'PtgElfRadical': /* [MS-XLS] 2.5.198.51 */
20542 case 'PtgElfRadicalLel': /* [MS-XLS] 2.5.198.52 */
20543 case 'PtgElfRadicalS': /* [MS-XLS] 2.5.198.53 */
20544 case 'PtgElfRw': /* [MS-XLS] 2.5.198.54 */
20545 case 'PtgElfRwV': /* [MS-XLS] 2.5.198.55 */
20546 throw new Error("Unsupported ELFs");
20547
20548 case 'PtgSxName': /* [MS-XLS] 2.5.198.91 TODO -- find a test case */
20549 throw new Error('Unrecognized Formula Token: ' + String(f));
20550 default: throw new Error('Unrecognized Formula Token: ' + String(f));
20551 }
20552 var PtgNonDisp = ['PtgAttrSpace', 'PtgAttrSpaceSemi', 'PtgAttrGoto'];
20553 if(opts.biff != 3) if(last_sp >= 0 && PtgNonDisp.indexOf(formula[0][ff][0]) == -1) {
20554 f = formula[0][last_sp];
20555 var _left = true;
20556 switch(f[1][0]) {
20557 /* note: some bad XLSB files omit the PtgParen */
20558 case 4: _left = false;
20559 /* falls through */
20560 case 0:
20561 // $FlowIgnore
20562 sp = fill(" ", f[1][1]); break;
20563 case 5: _left = false;
20564 /* falls through */
20565 case 1:
20566 // $FlowIgnore
20567 sp = fill("\r", f[1][1]); break;
20568 default:
20569 sp = "";
20570 // $FlowIgnore
20571 if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + f[1][0]);
20572 }
20573 stack.push((_left ? sp : "") + stack.pop() + (_left ? "" : sp));
20574 last_sp = -1;
20575 }
20576 }
20577 if(stack.length > 1 && opts.WTF) throw new Error("bad formula stack");
20578 return stack[0];
20579}
20580
20581/* [MS-XLS] 2.5.198.1 TODO */
20582function parse_ArrayParsedFormula(blob, length, opts) {
20583 var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
20584 var rgcb, cce = blob.read_shift(len); // length of rgce
20585 if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
20586 var rgce = parse_Rgce(blob, cce, opts);
20587 if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
20588 blob.l = target;
20589 return [rgce, rgcb];
20590}
20591
20592/* [MS-XLS] 2.5.198.3 TODO */
20593function parse_XLSCellParsedFormula(blob, length, opts) {
20594 var target = blob.l + length, len = opts.biff == 2 ? 1 : 2;
20595 var rgcb, cce = blob.read_shift(len); // length of rgce
20596 if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
20597 var rgce = parse_Rgce(blob, cce, opts);
20598 if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts);
20599 blob.l = target;
20600 return [rgce, rgcb];
20601}
20602
20603/* [MS-XLS] 2.5.198.21 */
20604function parse_NameParsedFormula(blob, length, opts, cce) {
20605 var target = blob.l + length;
20606 var rgce = parse_Rgce(blob, cce, opts);
20607 var rgcb;
20608 if(target !== blob.l) rgcb = parse_RgbExtra(blob, target - blob.l, rgce, opts);
20609 return [rgce, rgcb];
20610}
20611
20612/* [MS-XLS] 2.5.198.118 TODO */
20613function parse_SharedParsedFormula(blob, length, opts) {
20614 var target = blob.l + length;
20615 var rgcb, cce = blob.read_shift(2); // length of rgce
20616 var rgce = parse_Rgce(blob, cce, opts);
20617 if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)];
20618 if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts);
20619 return [rgce, rgcb];
20620}
20621
20622/* [MS-XLS] 2.5.133 TODO: how to emit empty strings? */
20623function parse_FormulaValue(blob) {
20624 var b;
20625 if(__readUInt16LE(blob,blob.l + 6) !== 0xFFFF) return [parse_Xnum(blob),'n'];
20626 switch(blob[blob.l]) {
20627 case 0x00: blob.l += 8; return ["String", 's'];
20628 case 0x01: b = blob[blob.l+2] === 0x1; blob.l += 8; return [b,'b'];
20629 case 0x02: b = blob[blob.l+2]; blob.l += 8; return [b,'e'];
20630 case 0x03: blob.l += 8; return ["",'s'];
20631 }
20632 return [];
20633}
20634function write_FormulaValue(value) {
20635 if(value == null) {
20636 // Blank String Value
20637 var o = new_buf(8);
20638 o.write_shift(1, 0x03);
20639 o.write_shift(1, 0);
20640 o.write_shift(2, 0);
20641 o.write_shift(2, 0);
20642 o.write_shift(2, 0xFFFF);
20643 return o;
20644 } else if(typeof value == "number") return write_Xnum(value);
20645 return write_Xnum(0);
20646}
20647
20648/* [MS-XLS] 2.4.127 TODO */
20649function parse_Formula(blob, length, opts) {
20650 var end = blob.l + length;
20651 var cell = parse_XLSCell(blob, 6);
20652 if(opts.biff == 2) ++blob.l;
20653 var val = parse_FormulaValue(blob,8);
20654 var flags = blob.read_shift(1);
20655 if(opts.biff != 2) {
20656 blob.read_shift(1);
20657 if(opts.biff >= 5) {
20658 /*var chn = */blob.read_shift(4);
20659 }
20660 }
20661 var cbf = parse_XLSCellParsedFormula(blob, end - blob.l, opts);
20662 return {cell:cell, val:val[0], formula:cbf, shared: (flags >> 3) & 1, tt:val[1]};
20663}
20664function write_Formula(cell, R, C, opts, os) {
20665 // Cell
20666 var o1 = write_XLSCell(R, C, os);
20667
20668 // FormulaValue
20669 var o2 = write_FormulaValue(cell.v);
20670
20671 // flags + cache
20672 var o3 = new_buf(6);
20673 var flags = 0x01 | 0x20;
20674 o3.write_shift(2, flags);
20675 o3.write_shift(4, 0);
20676
20677 // CellParsedFormula
20678 var bf = new_buf(cell.bf.length);
20679 for(var i = 0; i < cell.bf.length; ++i) bf[i] = cell.bf[i];
20680
20681 var out = bconcat([o1, o2, o3, bf]);
20682 return out;
20683}
20684
20685
20686/* XLSB Parsed Formula records have the same shape */
20687function parse_XLSBParsedFormula(data, length, opts) {
20688 var cce = data.read_shift(4);
20689 var rgce = parse_Rgce(data, cce, opts);
20690 var cb = data.read_shift(4);
20691 var rgcb = cb > 0 ? parse_RgbExtra(data, cb, rgce, opts) : null;
20692 return [rgce, rgcb];
20693}
20694
20695/* [MS-XLSB] 2.5.97.1 ArrayParsedFormula */
20696var parse_XLSBArrayParsedFormula = parse_XLSBParsedFormula;
20697/* [MS-XLSB] 2.5.97.4 CellParsedFormula */
20698var parse_XLSBCellParsedFormula = parse_XLSBParsedFormula;
20699/* [MS-XLSB] 2.5.97.8 DVParsedFormula */
20700//var parse_XLSBDVParsedFormula = parse_XLSBParsedFormula;
20701/* [MS-XLSB] 2.5.97.9 FRTParsedFormula */
20702//var parse_XLSBFRTParsedFormula = parse_XLSBParsedFormula2;
20703/* [MS-XLSB] 2.5.97.12 NameParsedFormula */
20704var parse_XLSBNameParsedFormula = parse_XLSBParsedFormula;
20705/* [MS-XLSB] 2.5.97.98 SharedParsedFormula */
20706var parse_XLSBSharedParsedFormula = parse_XLSBParsedFormula;
20707/* [MS-XLS] 2.5.198.4 */
20708var Cetab = {
207090x0000: 'BEEP',
207100x0001: 'OPEN',
207110x0002: 'OPEN.LINKS',
207120x0003: 'CLOSE.ALL',
207130x0004: 'SAVE',
207140x0005: 'SAVE.AS',
207150x0006: 'FILE.DELETE',
207160x0007: 'PAGE.SETUP',
207170x0008: 'PRINT',
207180x0009: 'PRINTER.SETUP',
207190x000A: 'QUIT',
207200x000B: 'NEW.WINDOW',
207210x000C: 'ARRANGE.ALL',
207220x000D: 'WINDOW.SIZE',
207230x000E: 'WINDOW.MOVE',
207240x000F: 'FULL',
207250x0010: 'CLOSE',
207260x0011: 'RUN',
207270x0016: 'SET.PRINT.AREA',
207280x0017: 'SET.PRINT.TITLES',
207290x0018: 'SET.PAGE.BREAK',
207300x0019: 'REMOVE.PAGE.BREAK',
207310x001A: 'FONT',
207320x001B: 'DISPLAY',
207330x001C: 'PROTECT.DOCUMENT',
207340x001D: 'PRECISION',
207350x001E: 'A1.R1C1',
207360x001F: 'CALCULATE.NOW',
207370x0020: 'CALCULATION',
207380x0022: 'DATA.FIND',
207390x0023: 'EXTRACT',
207400x0024: 'DATA.DELETE',
207410x0025: 'SET.DATABASE',
207420x0026: 'SET.CRITERIA',
207430x0027: 'SORT',
207440x0028: 'DATA.SERIES',
207450x0029: 'TABLE',
207460x002A: 'FORMAT.NUMBER',
207470x002B: 'ALIGNMENT',
207480x002C: 'STYLE',
207490x002D: 'BORDER',
207500x002E: 'CELL.PROTECTION',
207510x002F: 'COLUMN.WIDTH',
207520x0030: 'UNDO',
207530x0031: 'CUT',
207540x0032: 'COPY',
207550x0033: 'PASTE',
207560x0034: 'CLEAR',
207570x0035: 'PASTE.SPECIAL',
207580x0036: 'EDIT.DELETE',
207590x0037: 'INSERT',
207600x0038: 'FILL.RIGHT',
207610x0039: 'FILL.DOWN',
207620x003D: 'DEFINE.NAME',
207630x003E: 'CREATE.NAMES',
207640x003F: 'FORMULA.GOTO',
207650x0040: 'FORMULA.FIND',
207660x0041: 'SELECT.LAST.CELL',
207670x0042: 'SHOW.ACTIVE.CELL',
207680x0043: 'GALLERY.AREA',
207690x0044: 'GALLERY.BAR',
207700x0045: 'GALLERY.COLUMN',
207710x0046: 'GALLERY.LINE',
207720x0047: 'GALLERY.PIE',
207730x0048: 'GALLERY.SCATTER',
207740x0049: 'COMBINATION',
207750x004A: 'PREFERRED',
207760x004B: 'ADD.OVERLAY',
207770x004C: 'GRIDLINES',
207780x004D: 'SET.PREFERRED',
207790x004E: 'AXES',
207800x004F: 'LEGEND',
207810x0050: 'ATTACH.TEXT',
207820x0051: 'ADD.ARROW',
207830x0052: 'SELECT.CHART',
207840x0053: 'SELECT.PLOT.AREA',
207850x0054: 'PATTERNS',
207860x0055: 'MAIN.CHART',
207870x0056: 'OVERLAY',
207880x0057: 'SCALE',
207890x0058: 'FORMAT.LEGEND',
207900x0059: 'FORMAT.TEXT',
207910x005A: 'EDIT.REPEAT',
207920x005B: 'PARSE',
207930x005C: 'JUSTIFY',
207940x005D: 'HIDE',
207950x005E: 'UNHIDE',
207960x005F: 'WORKSPACE',
207970x0060: 'FORMULA',
207980x0061: 'FORMULA.FILL',
207990x0062: 'FORMULA.ARRAY',
208000x0063: 'DATA.FIND.NEXT',
208010x0064: 'DATA.FIND.PREV',
208020x0065: 'FORMULA.FIND.NEXT',
208030x0066: 'FORMULA.FIND.PREV',
208040x0067: 'ACTIVATE',
208050x0068: 'ACTIVATE.NEXT',
208060x0069: 'ACTIVATE.PREV',
208070x006A: 'UNLOCKED.NEXT',
208080x006B: 'UNLOCKED.PREV',
208090x006C: 'COPY.PICTURE',
208100x006D: 'SELECT',
208110x006E: 'DELETE.NAME',
208120x006F: 'DELETE.FORMAT',
208130x0070: 'VLINE',
208140x0071: 'HLINE',
208150x0072: 'VPAGE',
208160x0073: 'HPAGE',
208170x0074: 'VSCROLL',
208180x0075: 'HSCROLL',
208190x0076: 'ALERT',
208200x0077: 'NEW',
208210x0078: 'CANCEL.COPY',
208220x0079: 'SHOW.CLIPBOARD',
208230x007A: 'MESSAGE',
208240x007C: 'PASTE.LINK',
208250x007D: 'APP.ACTIVATE',
208260x007E: 'DELETE.ARROW',
208270x007F: 'ROW.HEIGHT',
208280x0080: 'FORMAT.MOVE',
208290x0081: 'FORMAT.SIZE',
208300x0082: 'FORMULA.REPLACE',
208310x0083: 'SEND.KEYS',
208320x0084: 'SELECT.SPECIAL',
208330x0085: 'APPLY.NAMES',
208340x0086: 'REPLACE.FONT',
208350x0087: 'FREEZE.PANES',
208360x0088: 'SHOW.INFO',
208370x0089: 'SPLIT',
208380x008A: 'ON.WINDOW',
208390x008B: 'ON.DATA',
208400x008C: 'DISABLE.INPUT',
208410x008E: 'OUTLINE',
208420x008F: 'LIST.NAMES',
208430x0090: 'FILE.CLOSE',
208440x0091: 'SAVE.WORKBOOK',
208450x0092: 'DATA.FORM',
208460x0093: 'COPY.CHART',
208470x0094: 'ON.TIME',
208480x0095: 'WAIT',
208490x0096: 'FORMAT.FONT',
208500x0097: 'FILL.UP',
208510x0098: 'FILL.LEFT',
208520x0099: 'DELETE.OVERLAY',
208530x009B: 'SHORT.MENUS',
208540x009F: 'SET.UPDATE.STATUS',
208550x00A1: 'COLOR.PALETTE',
208560x00A2: 'DELETE.STYLE',
208570x00A3: 'WINDOW.RESTORE',
208580x00A4: 'WINDOW.MAXIMIZE',
208590x00A6: 'CHANGE.LINK',
208600x00A7: 'CALCULATE.DOCUMENT',
208610x00A8: 'ON.KEY',
208620x00A9: 'APP.RESTORE',
208630x00AA: 'APP.MOVE',
208640x00AB: 'APP.SIZE',
208650x00AC: 'APP.MINIMIZE',
208660x00AD: 'APP.MAXIMIZE',
208670x00AE: 'BRING.TO.FRONT',
208680x00AF: 'SEND.TO.BACK',
208690x00B9: 'MAIN.CHART.TYPE',
208700x00BA: 'OVERLAY.CHART.TYPE',
208710x00BB: 'SELECT.END',
208720x00BC: 'OPEN.MAIL',
208730x00BD: 'SEND.MAIL',
208740x00BE: 'STANDARD.FONT',
208750x00BF: 'CONSOLIDATE',
208760x00C0: 'SORT.SPECIAL',
208770x00C1: 'GALLERY.3D.AREA',
208780x00C2: 'GALLERY.3D.COLUMN',
208790x00C3: 'GALLERY.3D.LINE',
208800x00C4: 'GALLERY.3D.PIE',
208810x00C5: 'VIEW.3D',
208820x00C6: 'GOAL.SEEK',
208830x00C7: 'WORKGROUP',
208840x00C8: 'FILL.GROUP',
208850x00C9: 'UPDATE.LINK',
208860x00CA: 'PROMOTE',
208870x00CB: 'DEMOTE',
208880x00CC: 'SHOW.DETAIL',
208890x00CE: 'UNGROUP',
208900x00CF: 'OBJECT.PROPERTIES',
208910x00D0: 'SAVE.NEW.OBJECT',
208920x00D1: 'SHARE',
208930x00D2: 'SHARE.NAME',
208940x00D3: 'DUPLICATE',
208950x00D4: 'APPLY.STYLE',
208960x00D5: 'ASSIGN.TO.OBJECT',
208970x00D6: 'OBJECT.PROTECTION',
208980x00D7: 'HIDE.OBJECT',
208990x00D8: 'SET.EXTRACT',
209000x00D9: 'CREATE.PUBLISHER',
209010x00DA: 'SUBSCRIBE.TO',
209020x00DB: 'ATTRIBUTES',
209030x00DC: 'SHOW.TOOLBAR',
209040x00DE: 'PRINT.PREVIEW',
209050x00DF: 'EDIT.COLOR',
209060x00E0: 'SHOW.LEVELS',
209070x00E1: 'FORMAT.MAIN',
209080x00E2: 'FORMAT.OVERLAY',
209090x00E3: 'ON.RECALC',
209100x00E4: 'EDIT.SERIES',
209110x00E5: 'DEFINE.STYLE',
209120x00F0: 'LINE.PRINT',
209130x00F3: 'ENTER.DATA',
209140x00F9: 'GALLERY.RADAR',
209150x00FA: 'MERGE.STYLES',
209160x00FB: 'EDITION.OPTIONS',
209170x00FC: 'PASTE.PICTURE',
209180x00FD: 'PASTE.PICTURE.LINK',
209190x00FE: 'SPELLING',
209200x0100: 'ZOOM',
209210x0103: 'INSERT.OBJECT',
209220x0104: 'WINDOW.MINIMIZE',
209230x0109: 'SOUND.NOTE',
209240x010A: 'SOUND.PLAY',
209250x010B: 'FORMAT.SHAPE',
209260x010C: 'EXTEND.POLYGON',
209270x010D: 'FORMAT.AUTO',
209280x0110: 'GALLERY.3D.BAR',
209290x0111: 'GALLERY.3D.SURFACE',
209300x0112: 'FILL.AUTO',
209310x0114: 'CUSTOMIZE.TOOLBAR',
209320x0115: 'ADD.TOOL',
209330x0116: 'EDIT.OBJECT',
209340x0117: 'ON.DOUBLECLICK',
209350x0118: 'ON.ENTRY',
209360x0119: 'WORKBOOK.ADD',
209370x011A: 'WORKBOOK.MOVE',
209380x011B: 'WORKBOOK.COPY',
209390x011C: 'WORKBOOK.OPTIONS',
209400x011D: 'SAVE.WORKSPACE',
209410x0120: 'CHART.WIZARD',
209420x0121: 'DELETE.TOOL',
209430x0122: 'MOVE.TOOL',
209440x0123: 'WORKBOOK.SELECT',
209450x0124: 'WORKBOOK.ACTIVATE',
209460x0125: 'ASSIGN.TO.TOOL',
209470x0127: 'COPY.TOOL',
209480x0128: 'RESET.TOOL',
209490x0129: 'CONSTRAIN.NUMERIC',
209500x012A: 'PASTE.TOOL',
209510x012E: 'WORKBOOK.NEW',
209520x0131: 'SCENARIO.CELLS',
209530x0132: 'SCENARIO.DELETE',
209540x0133: 'SCENARIO.ADD',
209550x0134: 'SCENARIO.EDIT',
209560x0135: 'SCENARIO.SHOW',
209570x0136: 'SCENARIO.SHOW.NEXT',
209580x0137: 'SCENARIO.SUMMARY',
209590x0138: 'PIVOT.TABLE.WIZARD',
209600x0139: 'PIVOT.FIELD.PROPERTIES',
209610x013A: 'PIVOT.FIELD',
209620x013B: 'PIVOT.ITEM',
209630x013C: 'PIVOT.ADD.FIELDS',
209640x013E: 'OPTIONS.CALCULATION',
209650x013F: 'OPTIONS.EDIT',
209660x0140: 'OPTIONS.VIEW',
209670x0141: 'ADDIN.MANAGER',
209680x0142: 'MENU.EDITOR',
209690x0143: 'ATTACH.TOOLBARS',
209700x0144: 'VBAActivate',
209710x0145: 'OPTIONS.CHART',
209720x0148: 'VBA.INSERT.FILE',
209730x014A: 'VBA.PROCEDURE.DEFINITION',
209740x0150: 'ROUTING.SLIP',
209750x0152: 'ROUTE.DOCUMENT',
209760x0153: 'MAIL.LOGON',
209770x0156: 'INSERT.PICTURE',
209780x0157: 'EDIT.TOOL',
209790x0158: 'GALLERY.DOUGHNUT',
209800x015E: 'CHART.TREND',
209810x0160: 'PIVOT.ITEM.PROPERTIES',
209820x0162: 'WORKBOOK.INSERT',
209830x0163: 'OPTIONS.TRANSITION',
209840x0164: 'OPTIONS.GENERAL',
209850x0172: 'FILTER.ADVANCED',
209860x0175: 'MAIL.ADD.MAILER',
209870x0176: 'MAIL.DELETE.MAILER',
209880x0177: 'MAIL.REPLY',
209890x0178: 'MAIL.REPLY.ALL',
209900x0179: 'MAIL.FORWARD',
209910x017A: 'MAIL.NEXT.LETTER',
209920x017B: 'DATA.LABEL',
209930x017C: 'INSERT.TITLE',
209940x017D: 'FONT.PROPERTIES',
209950x017E: 'MACRO.OPTIONS',
209960x017F: 'WORKBOOK.HIDE',
209970x0180: 'WORKBOOK.UNHIDE',
209980x0181: 'WORKBOOK.DELETE',
209990x0182: 'WORKBOOK.NAME',
210000x0184: 'GALLERY.CUSTOM',
210010x0186: 'ADD.CHART.AUTOFORMAT',
210020x0187: 'DELETE.CHART.AUTOFORMAT',
210030x0188: 'CHART.ADD.DATA',
210040x0189: 'AUTO.OUTLINE',
210050x018A: 'TAB.ORDER',
210060x018B: 'SHOW.DIALOG',
210070x018C: 'SELECT.ALL',
210080x018D: 'UNGROUP.SHEETS',
210090x018E: 'SUBTOTAL.CREATE',
210100x018F: 'SUBTOTAL.REMOVE',
210110x0190: 'RENAME.OBJECT',
210120x019C: 'WORKBOOK.SCROLL',
210130x019D: 'WORKBOOK.NEXT',
210140x019E: 'WORKBOOK.PREV',
210150x019F: 'WORKBOOK.TAB.SPLIT',
210160x01A0: 'FULL.SCREEN',
210170x01A1: 'WORKBOOK.PROTECT',
210180x01A4: 'SCROLLBAR.PROPERTIES',
210190x01A5: 'PIVOT.SHOW.PAGES',
210200x01A6: 'TEXT.TO.COLUMNS',
210210x01A7: 'FORMAT.CHARTTYPE',
210220x01A8: 'LINK.FORMAT',
210230x01A9: 'TRACER.DISPLAY',
210240x01AE: 'TRACER.NAVIGATE',
210250x01AF: 'TRACER.CLEAR',
210260x01B0: 'TRACER.ERROR',
210270x01B1: 'PIVOT.FIELD.GROUP',
210280x01B2: 'PIVOT.FIELD.UNGROUP',
210290x01B3: 'CHECKBOX.PROPERTIES',
210300x01B4: 'LABEL.PROPERTIES',
210310x01B5: 'LISTBOX.PROPERTIES',
210320x01B6: 'EDITBOX.PROPERTIES',
210330x01B7: 'PIVOT.REFRESH',
210340x01B8: 'LINK.COMBO',
210350x01B9: 'OPEN.TEXT',
210360x01BA: 'HIDE.DIALOG',
210370x01BB: 'SET.DIALOG.FOCUS',
210380x01BC: 'ENABLE.OBJECT',
210390x01BD: 'PUSHBUTTON.PROPERTIES',
210400x01BE: 'SET.DIALOG.DEFAULT',
210410x01BF: 'FILTER',
210420x01C0: 'FILTER.SHOW.ALL',
210430x01C1: 'CLEAR.OUTLINE',
210440x01C2: 'FUNCTION.WIZARD',
210450x01C3: 'ADD.LIST.ITEM',
210460x01C4: 'SET.LIST.ITEM',
210470x01C5: 'REMOVE.LIST.ITEM',
210480x01C6: 'SELECT.LIST.ITEM',
210490x01C7: 'SET.CONTROL.VALUE',
210500x01C8: 'SAVE.COPY.AS',
210510x01CA: 'OPTIONS.LISTS.ADD',
210520x01CB: 'OPTIONS.LISTS.DELETE',
210530x01CC: 'SERIES.AXES',
210540x01CD: 'SERIES.X',
210550x01CE: 'SERIES.Y',
210560x01CF: 'ERRORBAR.X',
210570x01D0: 'ERRORBAR.Y',
210580x01D1: 'FORMAT.CHART',
210590x01D2: 'SERIES.ORDER',
210600x01D3: 'MAIL.LOGOFF',
210610x01D4: 'CLEAR.ROUTING.SLIP',
210620x01D5: 'APP.ACTIVATE.MICROSOFT',
210630x01D6: 'MAIL.EDIT.MAILER',
210640x01D7: 'ON.SHEET',
210650x01D8: 'STANDARD.WIDTH',
210660x01D9: 'SCENARIO.MERGE',
210670x01DA: 'SUMMARY.INFO',
210680x01DB: 'FIND.FILE',
210690x01DC: 'ACTIVE.CELL.FONT',
210700x01DD: 'ENABLE.TIPWIZARD',
210710x01DE: 'VBA.MAKE.ADDIN',
210720x01E0: 'INSERTDATATABLE',
210730x01E1: 'WORKGROUP.OPTIONS',
210740x01E2: 'MAIL.SEND.MAILER',
210750x01E5: 'AUTOCORRECT',
210760x01E9: 'POST.DOCUMENT',
210770x01EB: 'PICKLIST',
210780x01ED: 'VIEW.SHOW',
210790x01EE: 'VIEW.DEFINE',
210800x01EF: 'VIEW.DELETE',
210810x01FD: 'SHEET.BACKGROUND',
210820x01FE: 'INSERT.MAP.OBJECT',
210830x01FF: 'OPTIONS.MENONO',
210840x0205: 'MSOCHECKS',
210850x0206: 'NORMAL',
210860x0207: 'LAYOUT',
210870x0208: 'RM.PRINT.AREA',
210880x0209: 'CLEAR.PRINT.AREA',
210890x020A: 'ADD.PRINT.AREA',
210900x020B: 'MOVE.BRK',
210910x0221: 'HIDECURR.NOTE',
210920x0222: 'HIDEALL.NOTES',
210930x0223: 'DELETE.NOTE',
210940x0224: 'TRAVERSE.NOTES',
210950x0225: 'ACTIVATE.NOTES',
210960x026C: 'PROTECT.REVISIONS',
210970x026D: 'UNPROTECT.REVISIONS',
210980x0287: 'OPTIONS.ME',
210990x028D: 'WEB.PUBLISH',
211000x029B: 'NEWWEBQUERY',
211010x02A1: 'PIVOT.TABLE.CHART',
211020x02F1: 'OPTIONS.SAVE',
211030x02F3: 'OPTIONS.SPELL',
211040x0328: 'HIDEALL.INKANNOTS'
21105};
21106
21107/* [MS-XLS] 2.5.198.17 */
21108/* [MS-XLSB] 2.5.97.10 */
21109var Ftab = {
211100x0000: 'COUNT',
211110x0001: 'IF',
211120x0002: 'ISNA',
211130x0003: 'ISERROR',
211140x0004: 'SUM',
211150x0005: 'AVERAGE',
211160x0006: 'MIN',
211170x0007: 'MAX',
211180x0008: 'ROW',
211190x0009: 'COLUMN',
211200x000A: 'NA',
211210x000B: 'NPV',
211220x000C: 'STDEV',
211230x000D: 'DOLLAR',
211240x000E: 'FIXED',
211250x000F: 'SIN',
211260x0010: 'COS',
211270x0011: 'TAN',
211280x0012: 'ATAN',
211290x0013: 'PI',
211300x0014: 'SQRT',
211310x0015: 'EXP',
211320x0016: 'LN',
211330x0017: 'LOG10',
211340x0018: 'ABS',
211350x0019: 'INT',
211360x001A: 'SIGN',
211370x001B: 'ROUND',
211380x001C: 'LOOKUP',
211390x001D: 'INDEX',
211400x001E: 'REPT',
211410x001F: 'MID',
211420x0020: 'LEN',
211430x0021: 'VALUE',
211440x0022: 'TRUE',
211450x0023: 'FALSE',
211460x0024: 'AND',
211470x0025: 'OR',
211480x0026: 'NOT',
211490x0027: 'MOD',
211500x0028: 'DCOUNT',
211510x0029: 'DSUM',
211520x002A: 'DAVERAGE',
211530x002B: 'DMIN',
211540x002C: 'DMAX',
211550x002D: 'DSTDEV',
211560x002E: 'VAR',
211570x002F: 'DVAR',
211580x0030: 'TEXT',
211590x0031: 'LINEST',
211600x0032: 'TREND',
211610x0033: 'LOGEST',
211620x0034: 'GROWTH',
211630x0035: 'GOTO',
211640x0036: 'HALT',
211650x0037: 'RETURN',
211660x0038: 'PV',
211670x0039: 'FV',
211680x003A: 'NPER',
211690x003B: 'PMT',
211700x003C: 'RATE',
211710x003D: 'MIRR',
211720x003E: 'IRR',
211730x003F: 'RAND',
211740x0040: 'MATCH',
211750x0041: 'DATE',
211760x0042: 'TIME',
211770x0043: 'DAY',
211780x0044: 'MONTH',
211790x0045: 'YEAR',
211800x0046: 'WEEKDAY',
211810x0047: 'HOUR',
211820x0048: 'MINUTE',
211830x0049: 'SECOND',
211840x004A: 'NOW',
211850x004B: 'AREAS',
211860x004C: 'ROWS',
211870x004D: 'COLUMNS',
211880x004E: 'OFFSET',
211890x004F: 'ABSREF',
211900x0050: 'RELREF',
211910x0051: 'ARGUMENT',
211920x0052: 'SEARCH',
211930x0053: 'TRANSPOSE',
211940x0054: 'ERROR',
211950x0055: 'STEP',
211960x0056: 'TYPE',
211970x0057: 'ECHO',
211980x0058: 'SET.NAME',
211990x0059: 'CALLER',
212000x005A: 'DEREF',
212010x005B: 'WINDOWS',
212020x005C: 'SERIES',
212030x005D: 'DOCUMENTS',
212040x005E: 'ACTIVE.CELL',
212050x005F: 'SELECTION',
212060x0060: 'RESULT',
212070x0061: 'ATAN2',
212080x0062: 'ASIN',
212090x0063: 'ACOS',
212100x0064: 'CHOOSE',
212110x0065: 'HLOOKUP',
212120x0066: 'VLOOKUP',
212130x0067: 'LINKS',
212140x0068: 'INPUT',
212150x0069: 'ISREF',
212160x006A: 'GET.FORMULA',
212170x006B: 'GET.NAME',
212180x006C: 'SET.VALUE',
212190x006D: 'LOG',
212200x006E: 'EXEC',
212210x006F: 'CHAR',
212220x0070: 'LOWER',
212230x0071: 'UPPER',
212240x0072: 'PROPER',
212250x0073: 'LEFT',
212260x0074: 'RIGHT',
212270x0075: 'EXACT',
212280x0076: 'TRIM',
212290x0077: 'REPLACE',
212300x0078: 'SUBSTITUTE',
212310x0079: 'CODE',
212320x007A: 'NAMES',
212330x007B: 'DIRECTORY',
212340x007C: 'FIND',
212350x007D: 'CELL',
212360x007E: 'ISERR',
212370x007F: 'ISTEXT',
212380x0080: 'ISNUMBER',
212390x0081: 'ISBLANK',
212400x0082: 'T',
212410x0083: 'N',
212420x0084: 'FOPEN',
212430x0085: 'FCLOSE',
212440x0086: 'FSIZE',
212450x0087: 'FREADLN',
212460x0088: 'FREAD',
212470x0089: 'FWRITELN',
212480x008A: 'FWRITE',
212490x008B: 'FPOS',
212500x008C: 'DATEVALUE',
212510x008D: 'TIMEVALUE',
212520x008E: 'SLN',
212530x008F: 'SYD',
212540x0090: 'DDB',
212550x0091: 'GET.DEF',
212560x0092: 'REFTEXT',
212570x0093: 'TEXTREF',
212580x0094: 'INDIRECT',
212590x0095: 'REGISTER',
212600x0096: 'CALL',
212610x0097: 'ADD.BAR',
212620x0098: 'ADD.MENU',
212630x0099: 'ADD.COMMAND',
212640x009A: 'ENABLE.COMMAND',
212650x009B: 'CHECK.COMMAND',
212660x009C: 'RENAME.COMMAND',
212670x009D: 'SHOW.BAR',
212680x009E: 'DELETE.MENU',
212690x009F: 'DELETE.COMMAND',
212700x00A0: 'GET.CHART.ITEM',
212710x00A1: 'DIALOG.BOX',
212720x00A2: 'CLEAN',
212730x00A3: 'MDETERM',
212740x00A4: 'MINVERSE',
212750x00A5: 'MMULT',
212760x00A6: 'FILES',
212770x00A7: 'IPMT',
212780x00A8: 'PPMT',
212790x00A9: 'COUNTA',
212800x00AA: 'CANCEL.KEY',
212810x00AB: 'FOR',
212820x00AC: 'WHILE',
212830x00AD: 'BREAK',
212840x00AE: 'NEXT',
212850x00AF: 'INITIATE',
212860x00B0: 'REQUEST',
212870x00B1: 'POKE',
212880x00B2: 'EXECUTE',
212890x00B3: 'TERMINATE',
212900x00B4: 'RESTART',
212910x00B5: 'HELP',
212920x00B6: 'GET.BAR',
212930x00B7: 'PRODUCT',
212940x00B8: 'FACT',
212950x00B9: 'GET.CELL',
212960x00BA: 'GET.WORKSPACE',
212970x00BB: 'GET.WINDOW',
212980x00BC: 'GET.DOCUMENT',
212990x00BD: 'DPRODUCT',
213000x00BE: 'ISNONTEXT',
213010x00BF: 'GET.NOTE',
213020x00C0: 'NOTE',
213030x00C1: 'STDEVP',
213040x00C2: 'VARP',
213050x00C3: 'DSTDEVP',
213060x00C4: 'DVARP',
213070x00C5: 'TRUNC',
213080x00C6: 'ISLOGICAL',
213090x00C7: 'DCOUNTA',
213100x00C8: 'DELETE.BAR',
213110x00C9: 'UNREGISTER',
213120x00CC: 'USDOLLAR',
213130x00CD: 'FINDB',
213140x00CE: 'SEARCHB',
213150x00CF: 'REPLACEB',
213160x00D0: 'LEFTB',
213170x00D1: 'RIGHTB',
213180x00D2: 'MIDB',
213190x00D3: 'LENB',
213200x00D4: 'ROUNDUP',
213210x00D5: 'ROUNDDOWN',
213220x00D6: 'ASC',
213230x00D7: 'DBCS',
213240x00D8: 'RANK',
213250x00DB: 'ADDRESS',
213260x00DC: 'DAYS360',
213270x00DD: 'TODAY',
213280x00DE: 'VDB',
213290x00DF: 'ELSE',
213300x00E0: 'ELSE.IF',
213310x00E1: 'END.IF',
213320x00E2: 'FOR.CELL',
213330x00E3: 'MEDIAN',
213340x00E4: 'SUMPRODUCT',
213350x00E5: 'SINH',
213360x00E6: 'COSH',
213370x00E7: 'TANH',
213380x00E8: 'ASINH',
213390x00E9: 'ACOSH',
213400x00EA: 'ATANH',
213410x00EB: 'DGET',
213420x00EC: 'CREATE.OBJECT',
213430x00ED: 'VOLATILE',
213440x00EE: 'LAST.ERROR',
213450x00EF: 'CUSTOM.UNDO',
213460x00F0: 'CUSTOM.REPEAT',
213470x00F1: 'FORMULA.CONVERT',
213480x00F2: 'GET.LINK.INFO',
213490x00F3: 'TEXT.BOX',
213500x00F4: 'INFO',
213510x00F5: 'GROUP',
213520x00F6: 'GET.OBJECT',
213530x00F7: 'DB',
213540x00F8: 'PAUSE',
213550x00FB: 'RESUME',
213560x00FC: 'FREQUENCY',
213570x00FD: 'ADD.TOOLBAR',
213580x00FE: 'DELETE.TOOLBAR',
213590x00FF: 'User',
213600x0100: 'RESET.TOOLBAR',
213610x0101: 'EVALUATE',
213620x0102: 'GET.TOOLBAR',
213630x0103: 'GET.TOOL',
213640x0104: 'SPELLING.CHECK',
213650x0105: 'ERROR.TYPE',
213660x0106: 'APP.TITLE',
213670x0107: 'WINDOW.TITLE',
213680x0108: 'SAVE.TOOLBAR',
213690x0109: 'ENABLE.TOOL',
213700x010A: 'PRESS.TOOL',
213710x010B: 'REGISTER.ID',
213720x010C: 'GET.WORKBOOK',
213730x010D: 'AVEDEV',
213740x010E: 'BETADIST',
213750x010F: 'GAMMALN',
213760x0110: 'BETAINV',
213770x0111: 'BINOMDIST',
213780x0112: 'CHIDIST',
213790x0113: 'CHIINV',
213800x0114: 'COMBIN',
213810x0115: 'CONFIDENCE',
213820x0116: 'CRITBINOM',
213830x0117: 'EVEN',
213840x0118: 'EXPONDIST',
213850x0119: 'FDIST',
213860x011A: 'FINV',
213870x011B: 'FISHER',
213880x011C: 'FISHERINV',
213890x011D: 'FLOOR',
213900x011E: 'GAMMADIST',
213910x011F: 'GAMMAINV',
213920x0120: 'CEILING',
213930x0121: 'HYPGEOMDIST',
213940x0122: 'LOGNORMDIST',
213950x0123: 'LOGINV',
213960x0124: 'NEGBINOMDIST',
213970x0125: 'NORMDIST',
213980x0126: 'NORMSDIST',
213990x0127: 'NORMINV',
214000x0128: 'NORMSINV',
214010x0129: 'STANDARDIZE',
214020x012A: 'ODD',
214030x012B: 'PERMUT',
214040x012C: 'POISSON',
214050x012D: 'TDIST',
214060x012E: 'WEIBULL',
214070x012F: 'SUMXMY2',
214080x0130: 'SUMX2MY2',
214090x0131: 'SUMX2PY2',
214100x0132: 'CHITEST',
214110x0133: 'CORREL',
214120x0134: 'COVAR',
214130x0135: 'FORECAST',
214140x0136: 'FTEST',
214150x0137: 'INTERCEPT',
214160x0138: 'PEARSON',
214170x0139: 'RSQ',
214180x013A: 'STEYX',
214190x013B: 'SLOPE',
214200x013C: 'TTEST',
214210x013D: 'PROB',
214220x013E: 'DEVSQ',
214230x013F: 'GEOMEAN',
214240x0140: 'HARMEAN',
214250x0141: 'SUMSQ',
214260x0142: 'KURT',
214270x0143: 'SKEW',
214280x0144: 'ZTEST',
214290x0145: 'LARGE',
214300x0146: 'SMALL',
214310x0147: 'QUARTILE',
214320x0148: 'PERCENTILE',
214330x0149: 'PERCENTRANK',
214340x014A: 'MODE',
214350x014B: 'TRIMMEAN',
214360x014C: 'TINV',
214370x014E: 'MOVIE.COMMAND',
214380x014F: 'GET.MOVIE',
214390x0150: 'CONCATENATE',
214400x0151: 'POWER',
214410x0152: 'PIVOT.ADD.DATA',
214420x0153: 'GET.PIVOT.TABLE',
214430x0154: 'GET.PIVOT.FIELD',
214440x0155: 'GET.PIVOT.ITEM',
214450x0156: 'RADIANS',
214460x0157: 'DEGREES',
214470x0158: 'SUBTOTAL',
214480x0159: 'SUMIF',
214490x015A: 'COUNTIF',
214500x015B: 'COUNTBLANK',
214510x015C: 'SCENARIO.GET',
214520x015D: 'OPTIONS.LISTS.GET',
214530x015E: 'ISPMT',
214540x015F: 'DATEDIF',
214550x0160: 'DATESTRING',
214560x0161: 'NUMBERSTRING',
214570x0162: 'ROMAN',
214580x0163: 'OPEN.DIALOG',
214590x0164: 'SAVE.DIALOG',
214600x0165: 'VIEW.GET',
214610x0166: 'GETPIVOTDATA',
214620x0167: 'HYPERLINK',
214630x0168: 'PHONETIC',
214640x0169: 'AVERAGEA',
214650x016A: 'MAXA',
214660x016B: 'MINA',
214670x016C: 'STDEVPA',
214680x016D: 'VARPA',
214690x016E: 'STDEVA',
214700x016F: 'VARA',
214710x0170: 'BAHTTEXT',
214720x0171: 'THAIDAYOFWEEK',
214730x0172: 'THAIDIGIT',
214740x0173: 'THAIMONTHOFYEAR',
214750x0174: 'THAINUMSOUND',
214760x0175: 'THAINUMSTRING',
214770x0176: 'THAISTRINGLENGTH',
214780x0177: 'ISTHAIDIGIT',
214790x0178: 'ROUNDBAHTDOWN',
214800x0179: 'ROUNDBAHTUP',
214810x017A: 'THAIYEAR',
214820x017B: 'RTD',
21483
214840x017C: 'CUBEVALUE',
214850x017D: 'CUBEMEMBER',
214860x017E: 'CUBEMEMBERPROPERTY',
214870x017F: 'CUBERANKEDMEMBER',
214880x0180: 'HEX2BIN',
214890x0181: 'HEX2DEC',
214900x0182: 'HEX2OCT',
214910x0183: 'DEC2BIN',
214920x0184: 'DEC2HEX',
214930x0185: 'DEC2OCT',
214940x0186: 'OCT2BIN',
214950x0187: 'OCT2HEX',
214960x0188: 'OCT2DEC',
214970x0189: 'BIN2DEC',
214980x018A: 'BIN2OCT',
214990x018B: 'BIN2HEX',
215000x018C: 'IMSUB',
215010x018D: 'IMDIV',
215020x018E: 'IMPOWER',
215030x018F: 'IMABS',
215040x0190: 'IMSQRT',
215050x0191: 'IMLN',
215060x0192: 'IMLOG2',
215070x0193: 'IMLOG10',
215080x0194: 'IMSIN',
215090x0195: 'IMCOS',
215100x0196: 'IMEXP',
215110x0197: 'IMARGUMENT',
215120x0198: 'IMCONJUGATE',
215130x0199: 'IMAGINARY',
215140x019A: 'IMREAL',
215150x019B: 'COMPLEX',
215160x019C: 'IMSUM',
215170x019D: 'IMPRODUCT',
215180x019E: 'SERIESSUM',
215190x019F: 'FACTDOUBLE',
215200x01A0: 'SQRTPI',
215210x01A1: 'QUOTIENT',
215220x01A2: 'DELTA',
215230x01A3: 'GESTEP',
215240x01A4: 'ISEVEN',
215250x01A5: 'ISODD',
215260x01A6: 'MROUND',
215270x01A7: 'ERF',
215280x01A8: 'ERFC',
215290x01A9: 'BESSELJ',
215300x01AA: 'BESSELK',
215310x01AB: 'BESSELY',
215320x01AC: 'BESSELI',
215330x01AD: 'XIRR',
215340x01AE: 'XNPV',
215350x01AF: 'PRICEMAT',
215360x01B0: 'YIELDMAT',
215370x01B1: 'INTRATE',
215380x01B2: 'RECEIVED',
215390x01B3: 'DISC',
215400x01B4: 'PRICEDISC',
215410x01B5: 'YIELDDISC',
215420x01B6: 'TBILLEQ',
215430x01B7: 'TBILLPRICE',
215440x01B8: 'TBILLYIELD',
215450x01B9: 'PRICE',
215460x01BA: 'YIELD',
215470x01BB: 'DOLLARDE',
215480x01BC: 'DOLLARFR',
215490x01BD: 'NOMINAL',
215500x01BE: 'EFFECT',
215510x01BF: 'CUMPRINC',
215520x01C0: 'CUMIPMT',
215530x01C1: 'EDATE',
215540x01C2: 'EOMONTH',
215550x01C3: 'YEARFRAC',
215560x01C4: 'COUPDAYBS',
215570x01C5: 'COUPDAYS',
215580x01C6: 'COUPDAYSNC',
215590x01C7: 'COUPNCD',
215600x01C8: 'COUPNUM',
215610x01C9: 'COUPPCD',
215620x01CA: 'DURATION',
215630x01CB: 'MDURATION',
215640x01CC: 'ODDLPRICE',
215650x01CD: 'ODDLYIELD',
215660x01CE: 'ODDFPRICE',
215670x01CF: 'ODDFYIELD',
215680x01D0: 'RANDBETWEEN',
215690x01D1: 'WEEKNUM',
215700x01D2: 'AMORDEGRC',
215710x01D3: 'AMORLINC',
215720x01D4: 'CONVERT',
215730x02D4: 'SHEETJS',
215740x01D5: 'ACCRINT',
215750x01D6: 'ACCRINTM',
215760x01D7: 'WORKDAY',
215770x01D8: 'NETWORKDAYS',
215780x01D9: 'GCD',
215790x01DA: 'MULTINOMIAL',
215800x01DB: 'LCM',
215810x01DC: 'FVSCHEDULE',
215820x01DD: 'CUBEKPIMEMBER',
215830x01DE: 'CUBESET',
215840x01DF: 'CUBESETCOUNT',
215850x01E0: 'IFERROR',
215860x01E1: 'COUNTIFS',
215870x01E2: 'SUMIFS',
215880x01E3: 'AVERAGEIF',
215890x01E4: 'AVERAGEIFS'
21590};
21591var FtabArgc = {
215920x0002: 1, /* ISNA */
215930x0003: 1, /* ISERROR */
215940x000A: 0, /* NA */
215950x000F: 1, /* SIN */
215960x0010: 1, /* COS */
215970x0011: 1, /* TAN */
215980x0012: 1, /* ATAN */
215990x0013: 0, /* PI */
216000x0014: 1, /* SQRT */
216010x0015: 1, /* EXP */
216020x0016: 1, /* LN */
216030x0017: 1, /* LOG10 */
216040x0018: 1, /* ABS */
216050x0019: 1, /* INT */
216060x001A: 1, /* SIGN */
216070x001B: 2, /* ROUND */
216080x001E: 2, /* REPT */
216090x001F: 3, /* MID */
216100x0020: 1, /* LEN */
216110x0021: 1, /* VALUE */
216120x0022: 0, /* TRUE */
216130x0023: 0, /* FALSE */
216140x0026: 1, /* NOT */
216150x0027: 2, /* MOD */
216160x0028: 3, /* DCOUNT */
216170x0029: 3, /* DSUM */
216180x002A: 3, /* DAVERAGE */
216190x002B: 3, /* DMIN */
216200x002C: 3, /* DMAX */
216210x002D: 3, /* DSTDEV */
216220x002F: 3, /* DVAR */
216230x0030: 2, /* TEXT */
216240x0035: 1, /* GOTO */
216250x003D: 3, /* MIRR */
216260x003F: 0, /* RAND */
216270x0041: 3, /* DATE */
216280x0042: 3, /* TIME */
216290x0043: 1, /* DAY */
216300x0044: 1, /* MONTH */
216310x0045: 1, /* YEAR */
216320x0046: 1, /* WEEKDAY */
216330x0047: 1, /* HOUR */
216340x0048: 1, /* MINUTE */
216350x0049: 1, /* SECOND */
216360x004A: 0, /* NOW */
216370x004B: 1, /* AREAS */
216380x004C: 1, /* ROWS */
216390x004D: 1, /* COLUMNS */
216400x004F: 2, /* ABSREF */
216410x0050: 2, /* RELREF */
216420x0053: 1, /* TRANSPOSE */
216430x0055: 0, /* STEP */
216440x0056: 1, /* TYPE */
216450x0059: 0, /* CALLER */
216460x005A: 1, /* DEREF */
216470x005E: 0, /* ACTIVE.CELL */
216480x005F: 0, /* SELECTION */
216490x0061: 2, /* ATAN2 */
216500x0062: 1, /* ASIN */
216510x0063: 1, /* ACOS */
216520x0065: 3, /* HLOOKUP */
216530x0066: 3, /* VLOOKUP */
216540x0069: 1, /* ISREF */
216550x006A: 1, /* GET.FORMULA */
216560x006C: 2, /* SET.VALUE */
216570x006F: 1, /* CHAR */
216580x0070: 1, /* LOWER */
216590x0071: 1, /* UPPER */
216600x0072: 1, /* PROPER */
216610x0075: 2, /* EXACT */
216620x0076: 1, /* TRIM */
216630x0077: 4, /* REPLACE */
216640x0079: 1, /* CODE */
216650x007E: 1, /* ISERR */
216660x007F: 1, /* ISTEXT */
216670x0080: 1, /* ISNUMBER */
216680x0081: 1, /* ISBLANK */
216690x0082: 1, /* T */
216700x0083: 1, /* N */
216710x0085: 1, /* FCLOSE */
216720x0086: 1, /* FSIZE */
216730x0087: 1, /* FREADLN */
216740x0088: 2, /* FREAD */
216750x0089: 2, /* FWRITELN */
216760x008A: 2, /* FWRITE */
216770x008C: 1, /* DATEVALUE */
216780x008D: 1, /* TIMEVALUE */
216790x008E: 3, /* SLN */
216800x008F: 4, /* SYD */
216810x0090: 4, /* DDB */
216820x00A1: 1, /* DIALOG.BOX */
216830x00A2: 1, /* CLEAN */
216840x00A3: 1, /* MDETERM */
216850x00A4: 1, /* MINVERSE */
216860x00A5: 2, /* MMULT */
216870x00AC: 1, /* WHILE */
216880x00AF: 2, /* INITIATE */
216890x00B0: 2, /* REQUEST */
216900x00B1: 3, /* POKE */
216910x00B2: 2, /* EXECUTE */
216920x00B3: 1, /* TERMINATE */
216930x00B8: 1, /* FACT */
216940x00BA: 1, /* GET.WORKSPACE */
216950x00BD: 3, /* DPRODUCT */
216960x00BE: 1, /* ISNONTEXT */
216970x00C3: 3, /* DSTDEVP */
216980x00C4: 3, /* DVARP */
216990x00C5: 1, /* TRUNC */
217000x00C6: 1, /* ISLOGICAL */
217010x00C7: 3, /* DCOUNTA */
217020x00C9: 1, /* UNREGISTER */
217030x00CF: 4, /* REPLACEB */
217040x00D2: 3, /* MIDB */
217050x00D3: 1, /* LENB */
217060x00D4: 2, /* ROUNDUP */
217070x00D5: 2, /* ROUNDDOWN */
217080x00D6: 1, /* ASC */
217090x00D7: 1, /* DBCS */
217100x00E1: 0, /* END.IF */
217110x00E5: 1, /* SINH */
217120x00E6: 1, /* COSH */
217130x00E7: 1, /* TANH */
217140x00E8: 1, /* ASINH */
217150x00E9: 1, /* ACOSH */
217160x00EA: 1, /* ATANH */
217170x00EB: 3, /* DGET */
217180x00F4: 1, /* INFO */
217190x00F7: 4, /* DB */
217200x00FC: 2, /* FREQUENCY */
217210x0101: 1, /* EVALUATE */
217220x0105: 1, /* ERROR.TYPE */
217230x010F: 1, /* GAMMALN */
217240x0111: 4, /* BINOMDIST */
217250x0112: 2, /* CHIDIST */
217260x0113: 2, /* CHIINV */
217270x0114: 2, /* COMBIN */
217280x0115: 3, /* CONFIDENCE */
217290x0116: 3, /* CRITBINOM */
217300x0117: 1, /* EVEN */
217310x0118: 3, /* EXPONDIST */
217320x0119: 3, /* FDIST */
217330x011A: 3, /* FINV */
217340x011B: 1, /* FISHER */
217350x011C: 1, /* FISHERINV */
217360x011D: 2, /* FLOOR */
217370x011E: 4, /* GAMMADIST */
217380x011F: 3, /* GAMMAINV */
217390x0120: 2, /* CEILING */
217400x0121: 4, /* HYPGEOMDIST */
217410x0122: 3, /* LOGNORMDIST */
217420x0123: 3, /* LOGINV */
217430x0124: 3, /* NEGBINOMDIST */
217440x0125: 4, /* NORMDIST */
217450x0126: 1, /* NORMSDIST */
217460x0127: 3, /* NORMINV */
217470x0128: 1, /* NORMSINV */
217480x0129: 3, /* STANDARDIZE */
217490x012A: 1, /* ODD */
217500x012B: 2, /* PERMUT */
217510x012C: 3, /* POISSON */
217520x012D: 3, /* TDIST */
217530x012E: 4, /* WEIBULL */
217540x012F: 2, /* SUMXMY2 */
217550x0130: 2, /* SUMX2MY2 */
217560x0131: 2, /* SUMX2PY2 */
217570x0132: 2, /* CHITEST */
217580x0133: 2, /* CORREL */
217590x0134: 2, /* COVAR */
217600x0135: 3, /* FORECAST */
217610x0136: 2, /* FTEST */
217620x0137: 2, /* INTERCEPT */
217630x0138: 2, /* PEARSON */
217640x0139: 2, /* RSQ */
217650x013A: 2, /* STEYX */
217660x013B: 2, /* SLOPE */
217670x013C: 4, /* TTEST */
217680x0145: 2, /* LARGE */
217690x0146: 2, /* SMALL */
217700x0147: 2, /* QUARTILE */
217710x0148: 2, /* PERCENTILE */
217720x014B: 2, /* TRIMMEAN */
217730x014C: 2, /* TINV */
217740x0151: 2, /* POWER */
217750x0156: 1, /* RADIANS */
217760x0157: 1, /* DEGREES */
217770x015A: 2, /* COUNTIF */
217780x015B: 1, /* COUNTBLANK */
217790x015E: 4, /* ISPMT */
217800x015F: 3, /* DATEDIF */
217810x0160: 1, /* DATESTRING */
217820x0161: 2, /* NUMBERSTRING */
217830x0168: 1, /* PHONETIC */
217840x0170: 1, /* BAHTTEXT */
217850x0171: 1, /* THAIDAYOFWEEK */
217860x0172: 1, /* THAIDIGIT */
217870x0173: 1, /* THAIMONTHOFYEAR */
217880x0174: 1, /* THAINUMSOUND */
217890x0175: 1, /* THAINUMSTRING */
217900x0176: 1, /* THAISTRINGLENGTH */
217910x0177: 1, /* ISTHAIDIGIT */
217920x0178: 1, /* ROUNDBAHTDOWN */
217930x0179: 1, /* ROUNDBAHTUP */
217940x017A: 1, /* THAIYEAR */
217950x017E: 3, /* CUBEMEMBERPROPERTY */
217960x0181: 1, /* HEX2DEC */
217970x0188: 1, /* OCT2DEC */
217980x0189: 1, /* BIN2DEC */
217990x018C: 2, /* IMSUB */
218000x018D: 2, /* IMDIV */
218010x018E: 2, /* IMPOWER */
218020x018F: 1, /* IMABS */
218030x0190: 1, /* IMSQRT */
218040x0191: 1, /* IMLN */
218050x0192: 1, /* IMLOG2 */
218060x0193: 1, /* IMLOG10 */
218070x0194: 1, /* IMSIN */
218080x0195: 1, /* IMCOS */
218090x0196: 1, /* IMEXP */
218100x0197: 1, /* IMARGUMENT */
218110x0198: 1, /* IMCONJUGATE */
218120x0199: 1, /* IMAGINARY */
218130x019A: 1, /* IMREAL */
218140x019E: 4, /* SERIESSUM */
218150x019F: 1, /* FACTDOUBLE */
218160x01A0: 1, /* SQRTPI */
218170x01A1: 2, /* QUOTIENT */
218180x01A4: 1, /* ISEVEN */
218190x01A5: 1, /* ISODD */
218200x01A6: 2, /* MROUND */
218210x01A8: 1, /* ERFC */
218220x01A9: 2, /* BESSELJ */
218230x01AA: 2, /* BESSELK */
218240x01AB: 2, /* BESSELY */
218250x01AC: 2, /* BESSELI */
218260x01AE: 3, /* XNPV */
218270x01B6: 3, /* TBILLEQ */
218280x01B7: 3, /* TBILLPRICE */
218290x01B8: 3, /* TBILLYIELD */
218300x01BB: 2, /* DOLLARDE */
218310x01BC: 2, /* DOLLARFR */
218320x01BD: 2, /* NOMINAL */
218330x01BE: 2, /* EFFECT */
218340x01BF: 6, /* CUMPRINC */
218350x01C0: 6, /* CUMIPMT */
218360x01C1: 2, /* EDATE */
218370x01C2: 2, /* EOMONTH */
218380x01D0: 2, /* RANDBETWEEN */
218390x01D4: 3, /* CONVERT */
218400x01DC: 2, /* FVSCHEDULE */
218410x01DF: 1, /* CUBESETCOUNT */
218420x01E0: 2, /* IFERROR */
218430xFFFF: 0
21844};
21845/* [MS-XLSX] 2.2.3 Functions */
21846/* [MS-XLSB] 2.5.97.10 Ftab */
21847var XLSXFutureFunctions = {
21848 "_xlfn.ACOT": "ACOT",
21849 "_xlfn.ACOTH": "ACOTH",
21850 "_xlfn.AGGREGATE": "AGGREGATE",
21851 "_xlfn.ARABIC": "ARABIC",
21852 "_xlfn.AVERAGEIF": "AVERAGEIF",
21853 "_xlfn.AVERAGEIFS": "AVERAGEIFS",
21854 "_xlfn.BASE": "BASE",
21855 "_xlfn.BETA.DIST": "BETA.DIST",
21856 "_xlfn.BETA.INV": "BETA.INV",
21857 "_xlfn.BINOM.DIST": "BINOM.DIST",
21858 "_xlfn.BINOM.DIST.RANGE": "BINOM.DIST.RANGE",
21859 "_xlfn.BINOM.INV": "BINOM.INV",
21860 "_xlfn.BITAND": "BITAND",
21861 "_xlfn.BITLSHIFT": "BITLSHIFT",
21862 "_xlfn.BITOR": "BITOR",
21863 "_xlfn.BITRSHIFT": "BITRSHIFT",
21864 "_xlfn.BITXOR": "BITXOR",
21865 "_xlfn.CEILING.MATH": "CEILING.MATH",
21866 "_xlfn.CEILING.PRECISE": "CEILING.PRECISE",
21867 "_xlfn.CHISQ.DIST": "CHISQ.DIST",
21868 "_xlfn.CHISQ.DIST.RT": "CHISQ.DIST.RT",
21869 "_xlfn.CHISQ.INV": "CHISQ.INV",
21870 "_xlfn.CHISQ.INV.RT": "CHISQ.INV.RT",
21871 "_xlfn.CHISQ.TEST": "CHISQ.TEST",
21872 "_xlfn.COMBINA": "COMBINA",
21873 "_xlfn.CONCAT": "CONCAT",
21874 "_xlfn.CONFIDENCE.NORM": "CONFIDENCE.NORM",
21875 "_xlfn.CONFIDENCE.T": "CONFIDENCE.T",
21876 "_xlfn.COT": "COT",
21877 "_xlfn.COTH": "COTH",
21878 "_xlfn.COUNTIFS": "COUNTIFS",
21879 "_xlfn.COVARIANCE.P": "COVARIANCE.P",
21880 "_xlfn.COVARIANCE.S": "COVARIANCE.S",
21881 "_xlfn.CSC": "CSC",
21882 "_xlfn.CSCH": "CSCH",
21883 "_xlfn.DAYS": "DAYS",
21884 "_xlfn.DECIMAL": "DECIMAL",
21885 "_xlfn.ECMA.CEILING": "ECMA.CEILING",
21886 "_xlfn.ERF.PRECISE": "ERF.PRECISE",
21887 "_xlfn.ERFC.PRECISE": "ERFC.PRECISE",
21888 "_xlfn.EXPON.DIST": "EXPON.DIST",
21889 "_xlfn.F.DIST": "F.DIST",
21890 "_xlfn.F.DIST.RT": "F.DIST.RT",
21891 "_xlfn.F.INV": "F.INV",
21892 "_xlfn.F.INV.RT": "F.INV.RT",
21893 "_xlfn.F.TEST": "F.TEST",
21894 "_xlfn.FILTERXML": "FILTERXML",
21895 "_xlfn.FLOOR.MATH": "FLOOR.MATH",
21896 "_xlfn.FLOOR.PRECISE": "FLOOR.PRECISE",
21897 "_xlfn.FORECAST.ETS": "FORECAST.ETS",
21898 "_xlfn.FORECAST.ETS.CONFINT": "FORECAST.ETS.CONFINT",
21899 "_xlfn.FORECAST.ETS.SEASONALITY": "FORECAST.ETS.SEASONALITY",
21900 "_xlfn.FORECAST.ETS.STAT": "FORECAST.ETS.STAT",
21901 "_xlfn.FORECAST.LINEAR": "FORECAST.LINEAR",
21902 "_xlfn.FORMULATEXT": "FORMULATEXT",
21903 "_xlfn.GAMMA": "GAMMA",
21904 "_xlfn.GAMMA.DIST": "GAMMA.DIST",
21905 "_xlfn.GAMMA.INV": "GAMMA.INV",
21906 "_xlfn.GAMMALN.PRECISE": "GAMMALN.PRECISE",
21907 "_xlfn.GAUSS": "GAUSS",
21908 "_xlfn.HYPGEOM.DIST": "HYPGEOM.DIST",
21909 "_xlfn.IFERROR": "IFERROR",
21910 "_xlfn.IFNA": "IFNA",
21911 "_xlfn.IFS": "IFS",
21912 "_xlfn.IMCOSH": "IMCOSH",
21913 "_xlfn.IMCOT": "IMCOT",
21914 "_xlfn.IMCSC": "IMCSC",
21915 "_xlfn.IMCSCH": "IMCSCH",
21916 "_xlfn.IMSEC": "IMSEC",
21917 "_xlfn.IMSECH": "IMSECH",
21918 "_xlfn.IMSINH": "IMSINH",
21919 "_xlfn.IMTAN": "IMTAN",
21920 "_xlfn.ISFORMULA": "ISFORMULA",
21921 "_xlfn.ISO.CEILING": "ISO.CEILING",
21922 "_xlfn.ISOWEEKNUM": "ISOWEEKNUM",
21923 "_xlfn.LOGNORM.DIST": "LOGNORM.DIST",
21924 "_xlfn.LOGNORM.INV": "LOGNORM.INV",
21925 "_xlfn.MAXIFS": "MAXIFS",
21926 "_xlfn.MINIFS": "MINIFS",
21927 "_xlfn.MODE.MULT": "MODE.MULT",
21928 "_xlfn.MODE.SNGL": "MODE.SNGL",
21929 "_xlfn.MUNIT": "MUNIT",
21930 "_xlfn.NEGBINOM.DIST": "NEGBINOM.DIST",
21931 "_xlfn.NETWORKDAYS.INTL": "NETWORKDAYS.INTL",
21932 "_xlfn.NIGBINOM": "NIGBINOM",
21933 "_xlfn.NORM.DIST": "NORM.DIST",
21934 "_xlfn.NORM.INV": "NORM.INV",
21935 "_xlfn.NORM.S.DIST": "NORM.S.DIST",
21936 "_xlfn.NORM.S.INV": "NORM.S.INV",
21937 "_xlfn.NUMBERVALUE": "NUMBERVALUE",
21938 "_xlfn.PDURATION": "PDURATION",
21939 "_xlfn.PERCENTILE.EXC": "PERCENTILE.EXC",
21940 "_xlfn.PERCENTILE.INC": "PERCENTILE.INC",
21941 "_xlfn.PERCENTRANK.EXC": "PERCENTRANK.EXC",
21942 "_xlfn.PERCENTRANK.INC": "PERCENTRANK.INC",
21943 "_xlfn.PERMUTATIONA": "PERMUTATIONA",
21944 "_xlfn.PHI": "PHI",
21945 "_xlfn.POISSON.DIST": "POISSON.DIST",
21946 "_xlfn.QUARTILE.EXC": "QUARTILE.EXC",
21947 "_xlfn.QUARTILE.INC": "QUARTILE.INC",
21948 "_xlfn.QUERYSTRING": "QUERYSTRING",
21949 "_xlfn.RANK.AVG": "RANK.AVG",
21950 "_xlfn.RANK.EQ": "RANK.EQ",
21951 "_xlfn.RRI": "RRI",
21952 "_xlfn.SEC": "SEC",
21953 "_xlfn.SECH": "SECH",
21954 "_xlfn.SHEET": "SHEET",
21955 "_xlfn.SHEETS": "SHEETS",
21956 "_xlfn.SKEW.P": "SKEW.P",
21957 "_xlfn.STDEV.P": "STDEV.P",
21958 "_xlfn.STDEV.S": "STDEV.S",
21959 "_xlfn.SUMIFS": "SUMIFS",
21960 "_xlfn.SWITCH": "SWITCH",
21961 "_xlfn.T.DIST": "T.DIST",
21962 "_xlfn.T.DIST.2T": "T.DIST.2T",
21963 "_xlfn.T.DIST.RT": "T.DIST.RT",
21964 "_xlfn.T.INV": "T.INV",
21965 "_xlfn.T.INV.2T": "T.INV.2T",
21966 "_xlfn.T.TEST": "T.TEST",
21967 "_xlfn.TEXTJOIN": "TEXTJOIN",
21968 "_xlfn.UNICHAR": "UNICHAR",
21969 "_xlfn.UNICODE": "UNICODE",
21970 "_xlfn.VAR.P": "VAR.P",
21971 "_xlfn.VAR.S": "VAR.S",
21972 "_xlfn.WEBSERVICE": "WEBSERVICE",
21973 "_xlfn.WEIBULL.DIST": "WEIBULL.DIST",
21974 "_xlfn.WORKDAY.INTL": "WORKDAY.INTL",
21975 "_xlfn.XOR": "XOR",
21976 "_xlfn.Z.TEST": "Z.TEST"
21977};
21978
21979/* Part 3 TODO: actually parse formulae */
21980function ods_to_csf_formula(f) {
21981 if(f.slice(0,3) == "of:") f = f.slice(3);
21982 /* 5.2 Basic Expressions */
21983 if(f.charCodeAt(0) == 61) {
21984 f = f.slice(1);
21985 if(f.charCodeAt(0) == 61) f = f.slice(1);
21986 }
21987 f = f.replace(/COM\.MICROSOFT\./g, "");
21988 /* Part 3 Section 5.8 References */
21989 f = f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, function($$, $1) { return $1.replace(/\./g,""); });
21990 /* TODO: something other than this */
21991 f = f.replace(/\[.(#[A-Z]*[?!])\]/g, "$1");
21992 return f.replace(/[;~]/g,",").replace(/\|/g,";");
21993}
21994
21995function csf_to_ods_formula(f) {
21996 var o = "of:=" + f.replace(crefregex, "$1[.$2$3$4$5]").replace(/\]:\[/g,":");
21997 /* TODO: something other than this */
21998 return o.replace(/;/g, "|").replace(/,/g,";");
21999}
22000
22001function ods_to_csf_3D(r) {
22002 var a = r.split(":");
22003 var s = a[0].split(".")[0];
22004 return [s, a[0].split(".")[1] + (a.length > 1 ? (":" + (a[1].split(".")[1] || a[1].split(".")[0])) : "")];
22005}
22006
22007function csf_to_ods_3D(r) {
22008 return r.replace(/\./,"!");
22009}
22010
22011var strs = {}; // shared strings
22012var _ssfopts = {}; // spreadsheet formatting options
22013
22014RELS.WS = [
22015 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
22016 "http://purl.oclc.org/ooxml/officeDocument/relationships/worksheet"
22017];
22018
22019/*global Map */
22020var browser_has_Map = typeof Map !== 'undefined';
22021
22022function get_sst_id(sst, str, rev) {
22023 var i = 0, len = sst.length;
22024 if(rev) {
22025 if(browser_has_Map ? rev.has(str) : rev.hasOwnProperty(str)) {
22026 var revarr = browser_has_Map ? rev.get(str) : rev[str];
22027 for(; i < revarr.length; ++i) {
22028 if(sst[revarr[i]].t === str) { sst.Count ++; return revarr[i]; }
22029 }
22030 }
22031 } else for(; i < len; ++i) {
22032 if(sst[i].t === str) { sst.Count ++; return i; }
22033 }
22034 sst[len] = ({t:str}); sst.Count ++; sst.Unique ++;
22035 if(rev) {
22036 if(browser_has_Map) {
22037 if(!rev.has(str)) rev.set(str, []);
22038 rev.get(str).push(len);
22039 } else {
22040 if(!rev.hasOwnProperty(str)) rev[str] = [];
22041 rev[str].push(len);
22042 }
22043 }
22044 return len;
22045}
22046
22047function col_obj_w(C, col) {
22048 var p = ({min:C+1,max:C+1});
22049 /* wch (chars), wpx (pixels) */
22050 var wch = -1;
22051 if(col.MDW) MDW = col.MDW;
22052 if(col.width != null) p.customWidth = 1;
22053 else if(col.wpx != null) wch = px2char(col.wpx);
22054 else if(col.wch != null) wch = col.wch;
22055 if(wch > -1) { p.width = char2width(wch); p.customWidth = 1; }
22056 else if(col.width != null) p.width = col.width;
22057 if(col.hidden) p.hidden = true;
22058 return p;
22059}
22060
22061function default_margins(margins, mode) {
22062 if(!margins) return;
22063 var defs = [0.7, 0.7, 0.75, 0.75, 0.3, 0.3];
22064 if(mode == 'xlml') defs = [1, 1, 1, 1, 0.5, 0.5];
22065 if(margins.left == null) margins.left = defs[0];
22066 if(margins.right == null) margins.right = defs[1];
22067 if(margins.top == null) margins.top = defs[2];
22068 if(margins.bottom == null) margins.bottom = defs[3];
22069 if(margins.header == null) margins.header = defs[4];
22070 if(margins.footer == null) margins.footer = defs[5];
22071}
22072
22073function get_cell_style(styles, cell, opts) {
22074 var z = opts.revssf[cell.z != null ? cell.z : "General"];
22075 var i = 0x3c, len = styles.length;
22076 if(z == null && opts.ssf) {
22077 for(; i < 0x188; ++i) if(opts.ssf[i] == null) {
22078 SSF.load(cell.z, i);
22079 // $FlowIgnore
22080 opts.ssf[i] = cell.z;
22081 opts.revssf[cell.z] = z = i;
22082 break;
22083 }
22084 }
22085 for(i = 0; i != len; ++i) if(styles[i].numFmtId === z) return i;
22086 styles[len] = {
22087 numFmtId:z,
22088 fontId:0,
22089 fillId:0,
22090 borderId:0,
22091 xfId:0,
22092 applyNumberFormat:1
22093 };
22094 return len;
22095}
22096
22097function safe_format(p, fmtid, fillid, opts, themes, styles) {
22098 if(p.t === 'z') return;
22099 if(p.t === 'd' && typeof p.v === 'string') p.v = parseDate(p.v);
22100 try {
22101 if(opts.cellNF) p.z = SSF._table[fmtid];
22102 } catch(e) { if(opts.WTF) throw e; }
22103 if(!opts || opts.cellText !== false) try {
22104 if(SSF._table[fmtid] == null) SSF.load(SSFImplicit[fmtid] || "General", fmtid);
22105 if(p.t === 'e') p.w = p.w || BErr[p.v];
22106 else if(fmtid === 0) {
22107 if(p.t === 'n') {
22108 if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
22109 else p.w = SSF._general_num(p.v);
22110 }
22111 else if(p.t === 'd') {
22112 var dd = datenum(p.v);
22113 if((dd|0) === dd) p.w = SSF._general_int(dd);
22114 else p.w = SSF._general_num(dd);
22115 }
22116 else if(p.v === undefined) return "";
22117 else p.w = SSF._general(p.v,_ssfopts);
22118 }
22119 else if(p.t === 'd') p.w = SSF.format(fmtid,datenum(p.v),_ssfopts);
22120 else p.w = SSF.format(fmtid,p.v,_ssfopts);
22121 } catch(e) { if(opts.WTF) throw e; }
22122 if(!opts.cellStyles) return;
22123 if(fillid != null) try {
22124 p.s = styles.Fills[fillid];
22125 if (p.s.fgColor && p.s.fgColor.theme && !p.s.fgColor.rgb) {
22126 p.s.fgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.fgColor.theme].rgb, p.s.fgColor.tint || 0);
22127 if(opts.WTF) p.s.fgColor.raw_rgb = themes.themeElements.clrScheme[p.s.fgColor.theme].rgb;
22128 }
22129 if (p.s.bgColor && p.s.bgColor.theme) {
22130 p.s.bgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.bgColor.theme].rgb, p.s.bgColor.tint || 0);
22131 if(opts.WTF) p.s.bgColor.raw_rgb = themes.themeElements.clrScheme[p.s.bgColor.theme].rgb;
22132 }
22133 } catch(e) { if(opts.WTF && styles.Fills) throw e; }
22134}
22135
22136function check_ws(ws, sname, i) {
22137 if(ws && ws['!ref']) {
22138 var range = safe_decode_range(ws['!ref']);
22139 if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']);
22140 }
22141}
22142function parse_ws_xml_dim(ws, s) {
22143 var d = safe_decode_range(s);
22144 if(d.s.r<=d.e.r && d.s.c<=d.e.c && d.s.r>=0 && d.s.c>=0) ws["!ref"] = encode_range(d);
22145}
22146var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*[\/]?>/g;
22147var sheetdataregex = /<(?:\w+:)?sheetData[^>]*>([\s\S]*)<\/(?:\w+:)?sheetData>/;
22148var hlinkregex = /<(?:\w:)?hyperlink [^>]*>/mg;
22149var dimregex = /"(\w*:\w*)"/;
22150var colregex = /<(?:\w:)?col\b[^>]*[\/]?>/g;
22151var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g;
22152var marginregex= /<(?:\w:)?pageMargins[^>]*\/>/g;
22153var sheetprregex = /<(?:\w:)?sheetPr\b(?:[^>a-z][^>]*)?\/>/;
22154var svsregex = /<(?:\w:)?sheetViews[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetViews)>/;
22155
22156/* 18.3 Worksheets */
22157function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) {
22158 if(!data) return data;
22159 if(!rels) rels = {'!id':{}};
22160 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
22161
22162 /* 18.3.1.99 worksheet CT_Worksheet */
22163 var s = opts.dense ? ([]) : ({});
22164 var refguess = ({s: {r:2000000, c:2000000}, e: {r:0, c:0} });
22165
22166 var data1 = "", data2 = "";
22167 var mtch = data.match(sheetdataregex);
22168 if(mtch) {
22169 data1 = data.slice(0, mtch.index);
22170 data2 = data.slice(mtch.index + mtch[0].length);
22171 } else data1 = data2 = data;
22172
22173 /* 18.3.1.82 sheetPr CT_SheetPr */
22174 var sheetPr = data1.match(sheetprregex);
22175 if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
22176
22177 /* 18.3.1.35 dimension CT_SheetDimension */
22178 var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index;
22179 if(ridx > 0) {
22180 var ref = data1.slice(ridx,ridx+50).match(dimregex);
22181 if(ref) parse_ws_xml_dim(s, ref[1]);
22182 }
22183
22184 /* 18.3.1.88 sheetViews CT_SheetViews */
22185 var svs = data1.match(svsregex);
22186 if(svs && svs[1]) parse_ws_xml_sheetviews(svs[1], wb);
22187
22188 /* 18.3.1.17 cols CT_Cols */
22189 var columns = [];
22190 if(opts.cellStyles) {
22191 /* 18.3.1.13 col CT_Col */
22192 var cols = data1.match(colregex);
22193 if(cols) parse_ws_xml_cols(columns, cols);
22194 }
22195
22196 /* 18.3.1.80 sheetData CT_SheetData ? */
22197 if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
22198
22199 /* 18.3.1.2 autoFilter CT_AutoFilter */
22200 var afilter = data2.match(afregex);
22201 if(afilter) s['!autofilter'] = parse_ws_xml_autofilter(afilter[0]);
22202
22203 /* 18.3.1.55 mergeCells CT_MergeCells */
22204 var merges = [];
22205 var _merge = data2.match(mergecregex);
22206 if(_merge) for(ridx = 0; ridx != _merge.length; ++ridx)
22207 merges[ridx] = safe_decode_range(_merge[ridx].slice(_merge[ridx].indexOf("\"")+1));
22208
22209 /* 18.3.1.48 hyperlinks CT_Hyperlinks */
22210 var hlink = data2.match(hlinkregex);
22211 if(hlink) parse_ws_xml_hlinks(s, hlink, rels);
22212
22213 /* 18.3.1.62 pageMargins CT_PageMargins */
22214 var margins = data2.match(marginregex);
22215 if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0]));
22216
22217 if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
22218 if(opts.sheetRows > 0 && s["!ref"]) {
22219 var tmpref = safe_decode_range(s["!ref"]);
22220 if(opts.sheetRows <= +tmpref.e.r) {
22221 tmpref.e.r = opts.sheetRows - 1;
22222 if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
22223 if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
22224 if(tmpref.e.c > refguess.e.c) tmpref.e.c = refguess.e.c;
22225 if(tmpref.e.c < tmpref.s.c) tmpref.s.c = tmpref.e.c;
22226 s["!fullref"] = s["!ref"];
22227 s["!ref"] = encode_range(tmpref);
22228 }
22229 }
22230 if(columns.length > 0) s["!cols"] = columns;
22231 if(merges.length > 0) s["!merges"] = merges;
22232 return s;
22233}
22234
22235function write_ws_xml_merges(merges) {
22236 if(merges.length === 0) return "";
22237 var o = '<mergeCells count="' + merges.length + '">';
22238 for(var i = 0; i != merges.length; ++i) o += '<mergeCell ref="' + encode_range(merges[i]) + '"/>';
22239 return o + '</mergeCells>';
22240}
22241
22242/* 18.3.1.82-3 sheetPr CT_ChartsheetPr / CT_SheetPr */
22243function parse_ws_xml_sheetpr(sheetPr, s, wb, idx) {
22244 var data = parsexmltag(sheetPr);
22245 if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
22246 if(data.codeName) wb.Sheets[idx].CodeName = data.codeName;
22247}
22248function write_ws_xml_sheetpr(ws, wb, idx, opts, o) {
22249 var needed = false;
22250 var props = {}, payload = null;
22251 if(opts.bookType !== 'xlsx' && wb.vbaraw) {
22252 var cname = wb.SheetNames[idx];
22253 try { if(wb.Workbook) cname = wb.Workbook.Sheets[idx].CodeName || cname; } catch(e) {}
22254 needed = true;
22255 props.codeName = escapexml(cname);
22256 }
22257
22258 if(!needed && !payload) return;
22259 o[o.length] = (writextag('sheetPr', payload, props));
22260}
22261
22262/* 18.3.1.85 sheetProtection CT_SheetProtection */
22263var sheetprot_deffalse = ["objects", "scenarios", "selectLockedCells", "selectUnlockedCells"];
22264var sheetprot_deftrue = [
22265 "formatColumns", "formatRows", "formatCells",
22266 "insertColumns", "insertRows", "insertHyperlinks",
22267 "deleteColumns", "deleteRows",
22268 "sort", "autoFilter", "pivotTables"
22269];
22270function write_ws_xml_protection(sp) {
22271 // algorithmName, hashValue, saltValue, spinCountpassword
22272 var o = ({sheet:1});
22273 sheetprot_deffalse.forEach(function(n) { if(sp[n] != null && sp[n]) o[n] = "1"; });
22274 sheetprot_deftrue.forEach(function(n) { if(sp[n] != null && !sp[n]) o[n] = "0"; });
22275 /* TODO: algorithm */
22276 if(sp.password) o.password = crypto_CreatePasswordVerifier_Method1(sp.password).toString(16).toUpperCase();
22277 return writextag('sheetProtection', null, o);
22278}
22279
22280function parse_ws_xml_hlinks(s, data, rels) {
22281 var dense = Array.isArray(s);
22282 for(var i = 0; i != data.length; ++i) {
22283 var val = parsexmltag(utf8read(data[i]), true);
22284 if(!val.ref) return;
22285 var rel = ((rels || {})['!id']||[])[val.id];
22286 if(rel) {
22287 val.Target = rel.Target;
22288 if(val.location) val.Target += "#"+val.location;
22289 } else {
22290 val.Target = "#" + val.location;
22291 rel = {Target: val.Target, TargetMode: 'Internal'};
22292 }
22293 val.Rel = rel;
22294 if(val.tooltip) { val.Tooltip = val.tooltip; delete val.tooltip; }
22295 var rng = safe_decode_range(val.ref);
22296 for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) {
22297 var addr = encode_cell({c:C,r:R});
22298 if(dense) {
22299 if(!s[R]) s[R] = [];
22300 if(!s[R][C]) s[R][C] = {t:"z",v:undefined};
22301 s[R][C].l = val;
22302 } else {
22303 if(!s[addr]) s[addr] = {t:"z",v:undefined};
22304 s[addr].l = val;
22305 }
22306 }
22307 }
22308}
22309
22310function parse_ws_xml_margins(margin) {
22311 var o = {};
22312 ["left", "right", "top", "bottom", "header", "footer"].forEach(function(k) {
22313 if(margin[k]) o[k] = parseFloat(margin[k]);
22314 });
22315 return o;
22316}
22317function write_ws_xml_margins(margin) {
22318 default_margins(margin);
22319 return writextag('pageMargins', null, margin);
22320}
22321
22322function parse_ws_xml_cols(columns, cols) {
22323 var seencol = false;
22324 for(var coli = 0; coli != cols.length; ++coli) {
22325 var coll = parsexmltag(cols[coli], true);
22326 if(coll.hidden) coll.hidden = parsexmlbool(coll.hidden);
22327 var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1;
22328 delete coll.min; delete coll.max; coll.width = +coll.width;
22329 if(!seencol && coll.width) { seencol = true; find_mdw_colw(coll.width); }
22330 process_col(coll);
22331 while(colm <= colM) columns[colm++] = dup(coll);
22332 }
22333}
22334function write_ws_xml_cols(ws, cols) {
22335 var o = ["<cols>"], col;
22336 for(var i = 0; i != cols.length; ++i) {
22337 if(!(col = cols[i])) continue;
22338 o[o.length] = (writextag('col', null, col_obj_w(i, col)));
22339 }
22340 o[o.length] = "</cols>";
22341 return o.join("");
22342}
22343
22344function parse_ws_xml_autofilter(data) {
22345 var o = { ref: (data.match(/ref="([^"]*)"/)||[])[1]};
22346 return o;
22347}
22348function write_ws_xml_autofilter(data, ws, wb, idx) {
22349 var ref = typeof data.ref == "string" ? data.ref : encode_range(data.ref);
22350 if(!wb.Workbook) wb.Workbook = ({Sheets:[]});
22351 if(!wb.Workbook.Names) wb.Workbook.Names = [];
22352 var names = wb.Workbook.Names;
22353 var range = decode_range(ref);
22354 if(range.s.r == range.e.r) { range.e.r = decode_range(ws["!ref"]).e.r; ref = encode_range(range); }
22355 for(var i = 0; i < names.length; ++i) {
22356 var name = names[i];
22357 if(name.Name != '_xlnm._FilterDatabase') continue;
22358 if(name.Sheet != idx) continue;
22359 name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break;
22360 }
22361 if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref });
22362 return writextag("autoFilter", null, {ref:ref});
22363}
22364
22365/* 18.3.1.88 sheetViews CT_SheetViews */
22366/* 18.3.1.87 sheetView CT_SheetView */
22367var sviewregex = /<(?:\w:)?sheetView(?:[^>a-z][^>]*)?\/?>/;
22368function parse_ws_xml_sheetviews(data, wb) {
22369 if(!wb.Views) wb.Views = [{}];
22370 (data.match(sviewregex)||[]).forEach(function(r, i) {
22371 var tag = parsexmltag(r);
22372 // $FlowIgnore
22373 if(!wb.Views[i]) wb.Views[i] = {};
22374 // $FlowIgnore
22375 if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
22376 });
22377}
22378function write_ws_xml_sheetviews(ws, opts, idx, wb) {
22379 var sview = ({workbookViewId:"0"});
22380 // $FlowIgnore
22381 if((((wb||{}).Workbook||{}).Views||[])[0]) sview.rightToLeft = wb.Workbook.Views[0].RTL ? "1" : "0";
22382 return writextag("sheetViews", writextag("sheetView", null, sview), {});
22383}
22384
22385function write_ws_xml_cell(cell, ref, ws, opts) {
22386 if(cell.v === undefined && cell.f === undefined || cell.t === 'z') return "";
22387 var vv = "";
22388 var oldt = cell.t, oldv = cell.v;
22389 if(cell.t !== "z") switch(cell.t) {
22390 case 'b': vv = cell.v ? "1" : "0"; break;
22391 case 'n': vv = ''+cell.v; break;
22392 case 'e': vv = BErr[cell.v]; break;
22393 case 'd':
22394 if(opts && opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
22395 else {
22396 cell = dup(cell);
22397 cell.t = 'n';
22398 vv = ''+(cell.v = datenum(parseDate(cell.v)));
22399 }
22400 if(typeof cell.z === 'undefined') cell.z = SSF._table[14];
22401 break;
22402 default: vv = cell.v; break;
22403 }
22404 var v = writetag('v', escapexml(vv)), o = ({r:ref});
22405 /* TODO: cell style */
22406 var os = get_cell_style(opts.cellXfs, cell, opts);
22407 if(os !== 0) o.s = os;
22408 switch(cell.t) {
22409 case 'n': break;
22410 case 'd': o.t = "d"; break;
22411 case 'b': o.t = "b"; break;
22412 case 'e': o.t = "e"; break;
22413 case 'z': break;
22414 default: if(cell.v == null) { delete cell.t; break; }
22415 if(opts && opts.bookSST) {
22416 v = writetag('v', ''+get_sst_id(opts.Strings, cell.v, opts.revStrings));
22417 o.t = "s"; break;
22418 }
22419 o.t = "str"; break;
22420 }
22421 if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; }
22422 if(cell.f) {
22423 var ff = cell.F && cell.F.slice(0, ref.length) == ref ? {t:"array", ref:cell.F} : null;
22424 v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : "");
22425 }
22426 if(cell.l) ws['!links'].push([ref, cell.l]);
22427 if(cell.c) ws['!comments'].push([ref, cell.c]);
22428 return writextag('c', v, o);
22429}
22430
22431var parse_ws_xml_data = (function() {
22432 var cellregex = /<(?:\w+:)?c[ >]/, rowregex = /<\/(?:\w+:)?row>/;
22433 var rregex = /r=["']([^"']*)["']/, isregex = /<(?:\w+:)?is>([\S\s]*?)<\/(?:\w+:)?is>/;
22434 var refregex = /ref=["']([^"']*)["']/;
22435 var match_v = matchtag("v"), match_f = matchtag("f");
22436
22437return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
22438 var ri = 0, x = "", cells = [], cref = [], idx=0, i=0, cc=0, d="", p;
22439 var tag, tagr = 0, tagc = 0;
22440 var sstr, ftag;
22441 var fmtid = 0, fillid = 0;
22442 var do_format = Array.isArray(styles.CellXf), cf;
22443 var arrayf = [];
22444 var sharedf = [];
22445 var dense = Array.isArray(s);
22446 var rows = [], rowobj = {}, rowrite = false;
22447 for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
22448 x = marr[mt].trim();
22449 var xlen = x.length;
22450 if(xlen === 0) continue;
22451
22452 /* 18.3.1.73 row CT_Row */
22453 for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri;
22454 tag = parsexmltag(x.slice(0,ri), true);
22455 tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1;
22456 if(opts.sheetRows && opts.sheetRows < tagr) continue;
22457 if(guess.s.r > tagr - 1) guess.s.r = tagr - 1;
22458 if(guess.e.r < tagr - 1) guess.e.r = tagr - 1;
22459
22460 if(opts && opts.cellStyles) {
22461 rowobj = {}; rowrite = false;
22462 if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
22463 if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; }
22464 if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
22465 if(rowrite) rows[tagr-1] = rowobj;
22466 }
22467
22468 /* 18.3.1.4 c CT_Cell */
22469 cells = x.slice(ri).split(cellregex);
22470 for(var rslice = 0; rslice != cells.length; ++rslice) if(cells[rslice].trim().charAt(0) != "<") break;
22471 cells = cells.slice(rslice);
22472 for(ri = 0; ri != cells.length; ++ri) {
22473 x = cells[ri].trim();
22474 if(x.length === 0) continue;
22475 cref = x.match(rregex); idx = ri; i=0; cc=0;
22476 x = "<c " + (x.slice(0,1)=="<"?">":"") + x;
22477 if(cref != null && cref.length === 2) {
22478 idx = 0; d=cref[1];
22479 for(i=0; i != d.length; ++i) {
22480 if((cc=d.charCodeAt(i)-64) < 1 || cc > 26) break;
22481 idx = 26*idx + cc;
22482 }
22483 --idx;
22484 tagc = idx;
22485 } else ++tagc;
22486 for(i = 0; i != x.length; ++i) if(x.charCodeAt(i) === 62) break; ++i;
22487 tag = parsexmltag(x.slice(0,i), true);
22488 if(!tag.r) tag.r = encode_cell({r:tagr-1, c:tagc});
22489 d = x.slice(i);
22490 p = ({t:""});
22491
22492 if((cref=d.match(match_v))!= null && cref[1] !== '') p.v=unescapexml(cref[1]);
22493 if(opts.cellFormula) {
22494 if((cref=d.match(match_f))!= null && cref[1] !== '') {
22495 /* TODO: match against XLSXFutureFunctions */
22496 p.f=_xlfn(unescapexml(utf8read(cref[1])));
22497 if(cref[0].indexOf('t="array"') > -1) {
22498 p.F = (d.match(refregex)||[])[1];
22499 if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
22500 } else if(cref[0].indexOf('t="shared"') > -1) {
22501 // TODO: parse formula
22502 ftag = parsexmltag(cref[0]);
22503 sharedf[parseInt(ftag.si, 10)] = [ftag, _xlfn(unescapexml(utf8read(cref[1]))), tag.r];
22504 }
22505 } else if((cref=d.match(/<f[^>]*\/>/))) {
22506 ftag = parsexmltag(cref[0]);
22507 if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
22508 }
22509 /* TODO: factor out contains logic */
22510 var _tag = decode_cell(tag.r);
22511 for(i = 0; i < arrayf.length; ++i)
22512 if(_tag.r >= arrayf[i][0].s.r && _tag.r <= arrayf[i][0].e.r)
22513 if(_tag.c >= arrayf[i][0].s.c && _tag.c <= arrayf[i][0].e.c)
22514 p.F = arrayf[i][1];
22515 }
22516
22517 if(tag.t == null && p.v === undefined) {
22518 if(p.f || p.F) {
22519 p.v = 0; p.t = "n";
22520 } else if(!opts.sheetStubs) continue;
22521 else p.t = "z";
22522 }
22523 else p.t = tag.t || "n";
22524 if(guess.s.c > tagc) guess.s.c = tagc;
22525 if(guess.e.c < tagc) guess.e.c = tagc;
22526 /* 18.18.11 t ST_CellType */
22527 switch(p.t) {
22528 case 'n':
22529 if(p.v == "" || p.v == null) {
22530 if(!opts.sheetStubs) continue;
22531 p.t = 'z';
22532 } else p.v = parseFloat(p.v);
22533 break;
22534 case 's':
22535 if(typeof p.v == 'undefined') {
22536 if(!opts.sheetStubs) continue;
22537 p.t = 'z';
22538 } else {
22539 sstr = strs[parseInt(p.v, 10)];
22540 p.v = sstr.t;
22541 p.r = sstr.r;
22542 if(opts.cellHTML) p.h = sstr.h;
22543 }
22544 break;
22545 case 'str':
22546 p.t = "s";
22547 p.v = (p.v!=null) ? utf8read(p.v) : '';
22548 if(opts.cellHTML) p.h = escapehtml(p.v);
22549 break;
22550 case 'inlineStr':
22551 cref = d.match(isregex);
22552 p.t = 's';
22553 if(cref != null && (sstr = parse_si(cref[1]))) {
22554 p.v = sstr.t;
22555 if(opts.cellHTML) p.h = sstr.h;
22556 } else p.v = "";
22557 break;
22558 case 'b': p.v = parsexmlbool(p.v); break;
22559 case 'd':
22560 if(opts.cellDates) p.v = parseDate(p.v, 1);
22561 else { p.v = datenum(parseDate(p.v, 1)); p.t = 'n'; }
22562 break;
22563 /* error string in .w, number in .v */
22564 case 'e':
22565 if(!opts || opts.cellText !== false) p.w = p.v;
22566 p.v = RBErr[p.v]; break;
22567 }
22568 /* formatting */
22569 fmtid = fillid = 0;
22570 cf = null;
22571 if(do_format && tag.s !== undefined) {
22572 cf = styles.CellXf[tag.s];
22573 if(cf != null) {
22574 if(cf.numFmtId != null) fmtid = cf.numFmtId;
22575 if(opts.cellStyles) {
22576 if(cf.fillId != null) fillid = cf.fillId;
22577 }
22578 }
22579 }
22580 safe_format(p, fmtid, fillid, opts, themes, styles);
22581 if(opts.cellDates && do_format && p.t == 'n' && SSF.is_date(SSF._table[fmtid])) { p.t = 'd'; p.v = numdate(p.v); }
22582 if(dense) {
22583 var _r = decode_cell(tag.r);
22584 if(!s[_r.r]) s[_r.r] = [];
22585 s[_r.r][_r.c] = p;
22586 } else s[tag.r] = p;
22587 }
22588 }
22589 if(rows.length > 0) s['!rows'] = rows;
22590}; })();
22591
22592function write_ws_xml_data(ws, opts, idx, wb) {
22593 var o = [], r = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols = [], R=0, C=0, rows = ws['!rows'];
22594 var dense = Array.isArray(ws);
22595 var params = ({r:rr}), row, height = -1;
22596 for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
22597 for(R = range.s.r; R <= range.e.r; ++R) {
22598 r = [];
22599 rr = encode_row(R);
22600 for(C = range.s.c; C <= range.e.c; ++C) {
22601 ref = cols[C] + rr;
22602 var _cell = dense ? (ws[R]||[])[C]: ws[ref];
22603 if(_cell === undefined) continue;
22604 if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell);
22605 }
22606 if(r.length > 0 || (rows && rows[R])) {
22607 params = ({r:rr});
22608 if(rows && rows[R]) {
22609 row = rows[R];
22610 if(row.hidden) params.hidden = 1;
22611 height = -1;
22612 if(row.hpx) height = px2pt(row.hpx);
22613 else if(row.hpt) height = row.hpt;
22614 if(height > -1) { params.ht = height; params.customHeight = 1; }
22615 if(row.level) { params.outlineLevel = row.level; }
22616 }
22617 o[o.length] = (writextag('row', r.join(""), params));
22618 }
22619 }
22620 if(rows) for(; R < rows.length; ++R) {
22621 if(rows && rows[R]) {
22622 params = ({r:R+1});
22623 row = rows[R];
22624 if(row.hidden) params.hidden = 1;
22625 height = -1;
22626 if (row.hpx) height = px2pt(row.hpx);
22627 else if (row.hpt) height = row.hpt;
22628 if (height > -1) { params.ht = height; params.customHeight = 1; }
22629 if (row.level) { params.outlineLevel = row.level; }
22630 o[o.length] = (writextag('row', "", params));
22631 }
22632 }
22633 return o.join("");
22634}
22635
22636var WS_XML_ROOT = writextag('worksheet', null, {
22637 'xmlns': XMLNS.main[0],
22638 'xmlns:r': XMLNS.r
22639});
22640
22641function write_ws_xml(idx, opts, wb, rels) {
22642 var o = [XML_HEADER, WS_XML_ROOT];
22643 var s = wb.SheetNames[idx], sidx = 0, rdata = "";
22644 var ws = wb.Sheets[s];
22645 if(ws == null) ws = {};
22646 var ref = ws['!ref'] || 'A1';
22647 var range = safe_decode_range(ref);
22648 if(range.e.c > 0x3FFF || range.e.r > 0xFFFFF) {
22649 if(opts.WTF) throw new Error("Range " + ref + " exceeds format limit A1:XFD1048576");
22650 range.e.c = Math.min(range.e.c, 0x3FFF);
22651 range.e.r = Math.min(range.e.c, 0xFFFFF);
22652 ref = encode_range(range);
22653 }
22654 if(!rels) rels = {};
22655 ws['!comments'] = [];
22656 var _drawing = [];
22657
22658 write_ws_xml_sheetpr(ws, wb, idx, opts, o);
22659
22660 o[o.length] = (writextag('dimension', null, {'ref': ref}));
22661
22662 o[o.length] = write_ws_xml_sheetviews(ws, opts, idx, wb);
22663
22664 /* TODO: store in WB, process styles */
22665 if(opts.sheetFormat) o[o.length] = (writextag('sheetFormatPr', null, {
22666 defaultRowHeight:opts.sheetFormat.defaultRowHeight||'16',
22667 baseColWidth:opts.sheetFormat.baseColWidth||'10',
22668 outlineLevelRow:opts.sheetFormat.outlineLevelRow||'7'
22669 }));
22670
22671 if(ws['!cols'] != null && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols']));
22672
22673 o[sidx = o.length] = '<sheetData/>';
22674 ws['!links'] = [];
22675 if(ws['!ref'] != null) {
22676 rdata = write_ws_xml_data(ws, opts, idx, wb, rels);
22677 if(rdata.length > 0) o[o.length] = (rdata);
22678 }
22679 if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
22680
22681 /* sheetCalcPr */
22682
22683 if(ws['!protect'] != null) o[o.length] = write_ws_xml_protection(ws['!protect']);
22684
22685 /* protectedRanges */
22686 /* scenarios */
22687
22688 if(ws['!autofilter'] != null) o[o.length] = write_ws_xml_autofilter(ws['!autofilter'], ws, wb, idx);
22689
22690 /* sortState */
22691 /* dataConsolidate */
22692 /* customSheetViews */
22693
22694 if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));
22695
22696 /* phoneticPr */
22697 /* conditionalFormatting */
22698 /* dataValidations */
22699
22700 var relc = -1, rel, rId = -1;
22701 if(ws['!links'].length > 0) {
22702 o[o.length] = "<hyperlinks>";
22703ws['!links'].forEach(function(l) {
22704 if(!l[1].Target) return;
22705 rel = ({"ref":l[0]});
22706 if(l[1].Target.charAt(0) != "#") {
22707 rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#.*$/, ""), RELS.HLINK);
22708 rel["r:id"] = "rId"+rId;
22709 }
22710 if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1));
22711 if(l[1].Tooltip) rel.tooltip = escapexml(l[1].Tooltip);
22712 o[o.length] = writextag("hyperlink",null,rel);
22713 });
22714 o[o.length] = "</hyperlinks>";
22715 }
22716 delete ws['!links'];
22717
22718 /* printOptions */
22719
22720 if(ws['!margins'] != null) o[o.length] = write_ws_xml_margins(ws['!margins']);
22721
22722 /* pageSetup */
22723 /* headerFooter */
22724 /* rowBreaks */
22725 /* colBreaks */
22726 /* customProperties */
22727 /* cellWatches */
22728
22729 if(!opts || opts.ignoreEC || (opts.ignoreEC == (void 0))) o[o.length] = writetag("ignoredErrors", writextag("ignoredError", null, {numberStoredAsText:1, sqref:ref}));
22730
22731 /* smartTags */
22732
22733 if(_drawing.length > 0) {
22734 rId = add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW);
22735 o[o.length] = writextag("drawing", null, {"r:id":"rId" + rId});
22736 ws['!drawing'] = _drawing;
22737 }
22738
22739 if(ws['!comments'].length > 0) {
22740 rId = add_rels(rels, -1, "../drawings/vmlDrawing" + (idx+1) + ".vml", RELS.VML);
22741 o[o.length] = writextag("legacyDrawing", null, {"r:id":"rId" + rId});
22742 ws['!legacy'] = rId;
22743 }
22744
22745 /* legacyDrawingHF */
22746 /* picture */
22747 /* oleObjects */
22748 /* controls */
22749 /* webPublishItems */
22750 /* tableParts */
22751 /* extLst */
22752
22753 if(o.length>1) { o[o.length] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
22754 return o.join("");
22755}
22756
22757/* [MS-XLSB] 2.4.726 BrtRowHdr */
22758function parse_BrtRowHdr(data, length) {
22759 var z = ({});
22760 var tgt = data.l + length;
22761 z.r = data.read_shift(4);
22762 data.l += 4; // TODO: ixfe
22763 var miyRw = data.read_shift(2);
22764 data.l += 1; // TODO: top/bot padding
22765 var flags = data.read_shift(1);
22766 data.l = tgt;
22767 if(flags & 0x07) z.level = flags & 0x07;
22768 if(flags & 0x10) z.hidden = true;
22769 if(flags & 0x20) z.hpt = miyRw / 20;
22770 return z;
22771}
22772function write_BrtRowHdr(R, range, ws) {
22773 var o = new_buf(17+8*16);
22774 var row = (ws['!rows']||[])[R]||{};
22775 o.write_shift(4, R);
22776
22777 o.write_shift(4, 0); /* TODO: ixfe */
22778
22779 var miyRw = 0x0140;
22780 if(row.hpx) miyRw = px2pt(row.hpx) * 20;
22781 else if(row.hpt) miyRw = row.hpt * 20;
22782 o.write_shift(2, miyRw);
22783
22784 o.write_shift(1, 0); /* top/bot padding */
22785
22786 var flags = 0x0;
22787 if(row.level) flags |= row.level;
22788 if(row.hidden) flags |= 0x10;
22789 if(row.hpx || row.hpt) flags |= 0x20;
22790 o.write_shift(1, flags);
22791
22792 o.write_shift(1, 0); /* phonetic guide */
22793
22794 /* [MS-XLSB] 2.5.8 BrtColSpan explains the mechanism */
22795 var ncolspan = 0, lcs = o.l;
22796 o.l += 4;
22797
22798 var caddr = {r:R, c:0};
22799 for(var i = 0; i < 16; ++i) {
22800 if((range.s.c > ((i+1) << 10)) || (range.e.c < (i << 10))) continue;
22801 var first = -1, last = -1;
22802 for(var j = (i<<10); j < ((i+1)<<10); ++j) {
22803 caddr.c = j;
22804 var cell = Array.isArray(ws) ? (ws[caddr.r]||[])[caddr.c] : ws[encode_cell(caddr)];
22805 if(cell) { if(first < 0) first = j; last = j; }
22806 }
22807 if(first < 0) continue;
22808 ++ncolspan;
22809 o.write_shift(4, first);
22810 o.write_shift(4, last);
22811 }
22812
22813 var l = o.l;
22814 o.l = lcs;
22815 o.write_shift(4, ncolspan);
22816 o.l = l;
22817
22818 return o.length > o.l ? o.slice(0, o.l) : o;
22819}
22820function write_row_header(ba, ws, range, R) {
22821 var o = write_BrtRowHdr(R, range, ws);
22822 if((o.length > 17) || (ws['!rows']||[])[R]) write_record(ba, 'BrtRowHdr', o);
22823}
22824
22825/* [MS-XLSB] 2.4.820 BrtWsDim */
22826var parse_BrtWsDim = parse_UncheckedRfX;
22827var write_BrtWsDim = write_UncheckedRfX;
22828
22829/* [MS-XLSB] 2.4.821 BrtWsFmtInfo */
22830function parse_BrtWsFmtInfo() {
22831}
22832//function write_BrtWsFmtInfo(ws, o) { }
22833
22834/* [MS-XLSB] 2.4.823 BrtWsProp */
22835function parse_BrtWsProp(data, length) {
22836 var z = {};
22837 /* TODO: pull flags */
22838 data.l += 19;
22839 z.name = parse_XLSBCodeName(data, length - 19);
22840 return z;
22841}
22842function write_BrtWsProp(str, o) {
22843 if(o == null) o = new_buf(84+4*str.length);
22844 for(var i = 0; i < 3; ++i) o.write_shift(1,0);
22845 write_BrtColor({auto:1}, o);
22846 o.write_shift(-4,-1);
22847 o.write_shift(-4,-1);
22848 write_XLSBCodeName(str, o);
22849 return o.slice(0, o.l);
22850}
22851
22852/* [MS-XLSB] 2.4.306 BrtCellBlank */
22853function parse_BrtCellBlank(data) {
22854 var cell = parse_XLSBCell(data);
22855 return [cell];
22856}
22857function write_BrtCellBlank(cell, ncell, o) {
22858 if(o == null) o = new_buf(8);
22859 return write_XLSBCell(ncell, o);
22860}
22861
22862
22863/* [MS-XLSB] 2.4.307 BrtCellBool */
22864function parse_BrtCellBool(data) {
22865 var cell = parse_XLSBCell(data);
22866 var fBool = data.read_shift(1);
22867 return [cell, fBool, 'b'];
22868}
22869function write_BrtCellBool(cell, ncell, o) {
22870 if(o == null) o = new_buf(9);
22871 write_XLSBCell(ncell, o);
22872 o.write_shift(1, cell.v ? 1 : 0);
22873 return o;
22874}
22875
22876/* [MS-XLSB] 2.4.308 BrtCellError */
22877function parse_BrtCellError(data) {
22878 var cell = parse_XLSBCell(data);
22879 var bError = data.read_shift(1);
22880 return [cell, bError, 'e'];
22881}
22882
22883/* [MS-XLSB] 2.4.311 BrtCellIsst */
22884function parse_BrtCellIsst(data) {
22885 var cell = parse_XLSBCell(data);
22886 var isst = data.read_shift(4);
22887 return [cell, isst, 's'];
22888}
22889function write_BrtCellIsst(cell, ncell, o) {
22890 if(o == null) o = new_buf(12);
22891 write_XLSBCell(ncell, o);
22892 o.write_shift(4, ncell.v);
22893 return o;
22894}
22895
22896/* [MS-XLSB] 2.4.313 BrtCellReal */
22897function parse_BrtCellReal(data) {
22898 var cell = parse_XLSBCell(data);
22899 var value = parse_Xnum(data);
22900 return [cell, value, 'n'];
22901}
22902function write_BrtCellReal(cell, ncell, o) {
22903 if(o == null) o = new_buf(16);
22904 write_XLSBCell(ncell, o);
22905 write_Xnum(cell.v, o);
22906 return o;
22907}
22908
22909/* [MS-XLSB] 2.4.314 BrtCellRk */
22910function parse_BrtCellRk(data) {
22911 var cell = parse_XLSBCell(data);
22912 var value = parse_RkNumber(data);
22913 return [cell, value, 'n'];
22914}
22915function write_BrtCellRk(cell, ncell, o) {
22916 if(o == null) o = new_buf(12);
22917 write_XLSBCell(ncell, o);
22918 write_RkNumber(cell.v, o);
22919 return o;
22920}
22921
22922
22923/* [MS-XLSB] 2.4.317 BrtCellSt */
22924function parse_BrtCellSt(data) {
22925 var cell = parse_XLSBCell(data);
22926 var value = parse_XLWideString(data);
22927 return [cell, value, 'str'];
22928}
22929function write_BrtCellSt(cell, ncell, o) {
22930 if(o == null) o = new_buf(12 + 4 * cell.v.length);
22931 write_XLSBCell(ncell, o);
22932 write_XLWideString(cell.v, o);
22933 return o.length > o.l ? o.slice(0, o.l) : o;
22934}
22935
22936/* [MS-XLSB] 2.4.653 BrtFmlaBool */
22937function parse_BrtFmlaBool(data, length, opts) {
22938 var end = data.l + length;
22939 var cell = parse_XLSBCell(data);
22940 cell.r = opts['!row'];
22941 var value = data.read_shift(1);
22942 var o = [cell, value, 'b'];
22943 if(opts.cellFormula) {
22944 data.l += 2;
22945 var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
22946 o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
22947 }
22948 else data.l = end;
22949 return o;
22950}
22951
22952/* [MS-XLSB] 2.4.654 BrtFmlaError */
22953function parse_BrtFmlaError(data, length, opts) {
22954 var end = data.l + length;
22955 var cell = parse_XLSBCell(data);
22956 cell.r = opts['!row'];
22957 var value = data.read_shift(1);
22958 var o = [cell, value, 'e'];
22959 if(opts.cellFormula) {
22960 data.l += 2;
22961 var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
22962 o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
22963 }
22964 else data.l = end;
22965 return o;
22966}
22967
22968/* [MS-XLSB] 2.4.655 BrtFmlaNum */
22969function parse_BrtFmlaNum(data, length, opts) {
22970 var end = data.l + length;
22971 var cell = parse_XLSBCell(data);
22972 cell.r = opts['!row'];
22973 var value = parse_Xnum(data);
22974 var o = [cell, value, 'n'];
22975 if(opts.cellFormula) {
22976 data.l += 2;
22977 var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
22978 o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
22979 }
22980 else data.l = end;
22981 return o;
22982}
22983
22984/* [MS-XLSB] 2.4.656 BrtFmlaString */
22985function parse_BrtFmlaString(data, length, opts) {
22986 var end = data.l + length;
22987 var cell = parse_XLSBCell(data);
22988 cell.r = opts['!row'];
22989 var value = parse_XLWideString(data);
22990 var o = [cell, value, 'str'];
22991 if(opts.cellFormula) {
22992 data.l += 2;
22993 var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts);
22994 o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */
22995 }
22996 else data.l = end;
22997 return o;
22998}
22999
23000/* [MS-XLSB] 2.4.682 BrtMergeCell */
23001var parse_BrtMergeCell = parse_UncheckedRfX;
23002var write_BrtMergeCell = write_UncheckedRfX;
23003/* [MS-XLSB] 2.4.107 BrtBeginMergeCells */
23004function write_BrtBeginMergeCells(cnt, o) {
23005 if(o == null) o = new_buf(4);
23006 o.write_shift(4, cnt);
23007 return o;
23008}
23009
23010/* [MS-XLSB] 2.4.662 BrtHLink */
23011function parse_BrtHLink(data, length) {
23012 var end = data.l + length;
23013 var rfx = parse_UncheckedRfX(data, 16);
23014 var relId = parse_XLNullableWideString(data);
23015 var loc = parse_XLWideString(data);
23016 var tooltip = parse_XLWideString(data);
23017 var display = parse_XLWideString(data);
23018 data.l = end;
23019 var o = ({rfx:rfx, relId:relId, loc:loc, display:display});
23020 if(tooltip) o.Tooltip = tooltip;
23021 return o;
23022}
23023function write_BrtHLink(l, rId) {
23024 var o = new_buf(50+4*(l[1].Target.length + (l[1].Tooltip || "").length));
23025 write_UncheckedRfX({s:decode_cell(l[0]), e:decode_cell(l[0])}, o);
23026 write_RelID("rId" + rId, o);
23027 var locidx = l[1].Target.indexOf("#");
23028 var loc = locidx == -1 ? "" : l[1].Target.slice(locidx+1);
23029 write_XLWideString(loc || "", o);
23030 write_XLWideString(l[1].Tooltip || "", o);
23031 write_XLWideString("", o);
23032 return o.slice(0, o.l);
23033}
23034
23035/* [MS-XLSB] 2.4.692 BrtPane */
23036function parse_BrtPane(/*data, length, opts*/) {
23037}
23038
23039/* [MS-XLSB] 2.4.6 BrtArrFmla */
23040function parse_BrtArrFmla(data, length, opts) {
23041 var end = data.l + length;
23042 var rfx = parse_RfX(data, 16);
23043 var fAlwaysCalc = data.read_shift(1);
23044 var o = [rfx]; o[2] = fAlwaysCalc;
23045 if(opts.cellFormula) {
23046 var formula = parse_XLSBArrayParsedFormula(data, end - data.l, opts);
23047 o[1] = formula;
23048 } else data.l = end;
23049 return o;
23050}
23051
23052/* [MS-XLSB] 2.4.750 BrtShrFmla */
23053function parse_BrtShrFmla(data, length, opts) {
23054 var end = data.l + length;
23055 var rfx = parse_UncheckedRfX(data, 16);
23056 var o = [rfx];
23057 if(opts.cellFormula) {
23058 var formula = parse_XLSBSharedParsedFormula(data, end - data.l, opts);
23059 o[1] = formula;
23060 data.l = end;
23061 } else data.l = end;
23062 return o;
23063}
23064
23065/* [MS-XLSB] 2.4.323 BrtColInfo */
23066/* TODO: once XLS ColInfo is set, combine the functions */
23067function write_BrtColInfo(C, col, o) {
23068 if(o == null) o = new_buf(18);
23069 var p = col_obj_w(C, col);
23070 o.write_shift(-4, C);
23071 o.write_shift(-4, C);
23072 o.write_shift(4, (p.width || 10) * 256);
23073 o.write_shift(4, 0/*ixfe*/); // style
23074 var flags = 0;
23075 if(col.hidden) flags |= 0x01;
23076 if(typeof p.width == 'number') flags |= 0x02;
23077 if(col.level) flags |= (col.level << 8);
23078 o.write_shift(2, flags); // bit flag
23079 return o;
23080}
23081
23082/* [MS-XLSB] 2.4.678 BrtMargins */
23083var BrtMarginKeys = ["left","right","top","bottom","header","footer"];
23084function parse_BrtMargins(data) {
23085 var margins = ({});
23086 BrtMarginKeys.forEach(function(k) { margins[k] = parse_Xnum(data, 8); });
23087 return margins;
23088}
23089function write_BrtMargins(margins, o) {
23090 if(o == null) o = new_buf(6*8);
23091 default_margins(margins);
23092 BrtMarginKeys.forEach(function(k) { write_Xnum((margins)[k], o); });
23093 return o;
23094}
23095
23096/* [MS-XLSB] 2.4.299 BrtBeginWsView */
23097function parse_BrtBeginWsView(data) {
23098 var f = data.read_shift(2);
23099 data.l += 28;
23100 return { RTL: f & 0x20 };
23101}
23102function write_BrtBeginWsView(ws, Workbook, o) {
23103 if(o == null) o = new_buf(30);
23104 var f = 0x39c;
23105 if((((Workbook||{}).Views||[])[0]||{}).RTL) f |= 0x20;
23106 o.write_shift(2, f); // bit flag
23107 o.write_shift(4, 0);
23108 o.write_shift(4, 0); // view first row
23109 o.write_shift(4, 0); // view first col
23110 o.write_shift(1, 0); // gridline color ICV
23111 o.write_shift(1, 0);
23112 o.write_shift(2, 0);
23113 o.write_shift(2, 100); // zoom scale
23114 o.write_shift(2, 0);
23115 o.write_shift(2, 0);
23116 o.write_shift(2, 0);
23117 o.write_shift(4, 0); // workbook view id
23118 return o;
23119}
23120
23121/* [MS-XLSB] 2.4.309 BrtCellIgnoreEC */
23122function write_BrtCellIgnoreEC(ref) {
23123 var o = new_buf(24);
23124 o.write_shift(4, 4);
23125 o.write_shift(4, 1);
23126 write_UncheckedRfX(ref, o);
23127 return o;
23128}
23129
23130/* [MS-XLSB] 2.4.748 BrtSheetProtection */
23131function write_BrtSheetProtection(sp, o) {
23132 if(o == null) o = new_buf(16*4+2);
23133 o.write_shift(2, sp.password ? crypto_CreatePasswordVerifier_Method1(sp.password) : 0);
23134 o.write_shift(4, 1); // this record should not be written if no protection
23135 [
23136 ["objects", false], // fObjects
23137 ["scenarios", false], // fScenarios
23138 ["formatCells", true], // fFormatCells
23139 ["formatColumns", true], // fFormatColumns
23140 ["formatRows", true], // fFormatRows
23141 ["insertColumns", true], // fInsertColumns
23142 ["insertRows", true], // fInsertRows
23143 ["insertHyperlinks", true], // fInsertHyperlinks
23144 ["deleteColumns", true], // fDeleteColumns
23145 ["deleteRows", true], // fDeleteRows
23146 ["selectLockedCells", false], // fSelLockedCells
23147 ["sort", true], // fSort
23148 ["autoFilter", true], // fAutoFilter
23149 ["pivotTables", true], // fPivotTables
23150 ["selectUnlockedCells", false] // fSelUnlockedCells
23151 ].forEach(function(n) {
23152if(n[1]) o.write_shift(4, sp[n[0]] != null && !sp[n[0]] ? 1 : 0);
23153 else o.write_shift(4, sp[n[0]] != null && sp[n[0]] ? 0 : 1);
23154 });
23155 return o;
23156}
23157
23158function parse_BrtDVal(/*data, length, opts*/) {
23159}
23160function parse_BrtDVal14(/*data, length, opts*/) {
23161}
23162/* [MS-XLSB] 2.1.7.61 Worksheet */
23163function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles) {
23164 if(!data) return data;
23165 var opts = _opts || {};
23166 if(!rels) rels = {'!id':{}};
23167 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
23168 var s = (opts.dense ? [] : {});
23169
23170 var ref;
23171 var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
23172
23173 var state = [];
23174 var pass = false, end = false;
23175 var row, p, cf, R, C, addr, sstr, rr, cell;
23176 var merges = [];
23177 opts.biff = 12;
23178 opts['!row'] = 0;
23179
23180 var ai = 0, af = false;
23181
23182 var arrayf = [];
23183 var sharedf = {};
23184 var supbooks = opts.supbooks || wb.supbooks || ([[]]);
23185 supbooks.sharedf = sharedf;
23186 supbooks.arrayf = arrayf;
23187 supbooks.SheetNames = wb.SheetNames || wb.Sheets.map(function(x) { return x.name; });
23188 if(!opts.supbooks) {
23189 opts.supbooks = supbooks;
23190 if(wb.Names) for(var i = 0; i < wb.Names.length; ++i) supbooks[0][i+1] = wb.Names[i];
23191 }
23192
23193 var colinfo = [], rowinfo = [];
23194 var seencol = false;
23195
23196 recordhopper(data, function ws_parse(val, R_n, RT) {
23197 if(end) return;
23198 switch(RT) {
23199 case 0x0094: /* 'BrtWsDim' */
23200 ref = val; break;
23201 case 0x0000: /* 'BrtRowHdr' */
23202 row = val;
23203 if(opts.sheetRows && opts.sheetRows <= row.r) end=true;
23204 rr = encode_row(R = row.r);
23205 opts['!row'] = row.r;
23206 if(val.hidden || val.hpt || val.level != null) {
23207 if(val.hpt) val.hpx = pt2px(val.hpt);
23208 rowinfo[val.r] = val;
23209 }
23210 break;
23211
23212 case 0x0002: /* 'BrtCellRk' */
23213 case 0x0003: /* 'BrtCellError' */
23214 case 0x0004: /* 'BrtCellBool' */
23215 case 0x0005: /* 'BrtCellReal' */
23216 case 0x0006: /* 'BrtCellSt' */
23217 case 0x0007: /* 'BrtCellIsst' */
23218 case 0x0008: /* 'BrtFmlaString' */
23219 case 0x0009: /* 'BrtFmlaNum' */
23220 case 0x000A: /* 'BrtFmlaBool' */
23221 case 0x000B: /* 'BrtFmlaError' */
23222 p = ({t:val[2]});
23223 switch(val[2]) {
23224 case 'n': p.v = val[1]; break;
23225 case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break;
23226 case 'b': p.v = val[1] ? true : false; break;
23227 case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break;
23228 case 'str': p.t = 's'; p.v = val[1]; break;
23229 }
23230 if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles);
23231 C = val[0].c;
23232 if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
23233 else s[encode_col(C) + rr] = p;
23234 if(opts.cellFormula) {
23235 af = false;
23236 for(ai = 0; ai < arrayf.length; ++ai) {
23237 var aii = arrayf[ai];
23238 if(row.r >= aii[0].s.r && row.r <= aii[0].e.r)
23239 if(C >= aii[0].s.c && C <= aii[0].e.c) {
23240 p.F = encode_range(aii[0]); af = true;
23241 }
23242 }
23243 if(!af && val.length > 3) p.f = val[3];
23244 }
23245 if(refguess.s.r > row.r) refguess.s.r = row.r;
23246 if(refguess.s.c > C) refguess.s.c = C;
23247 if(refguess.e.r < row.r) refguess.e.r = row.r;
23248 if(refguess.e.c < C) refguess.e.c = C;
23249 if(opts.cellDates && cf && p.t == 'n' && SSF.is_date(SSF._table[cf.numFmtId])) {
23250 var _d = SSF.parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
23251 }
23252 break;
23253
23254 case 0x0001: /* 'BrtCellBlank' */
23255 if(!opts.sheetStubs || pass) break;
23256 p = ({t:'z',v:undefined});
23257 C = val[0].c;
23258 if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; }
23259 else s[encode_col(C) + rr] = p;
23260 if(refguess.s.r > row.r) refguess.s.r = row.r;
23261 if(refguess.s.c > C) refguess.s.c = C;
23262 if(refguess.e.r < row.r) refguess.e.r = row.r;
23263 if(refguess.e.c < C) refguess.e.c = C;
23264 break;
23265
23266 case 0x00B0: /* 'BrtMergeCell' */
23267 merges.push(val); break;
23268
23269 case 0x01EE: /* 'BrtHLink' */
23270 var rel = rels['!id'][val.relId];
23271 if(rel) {
23272 val.Target = rel.Target;
23273 if(val.loc) val.Target += "#"+val.loc;
23274 val.Rel = rel;
23275 } else if(val.relId == '') {
23276 val.Target = "#" + val.loc;
23277 }
23278 for(R=val.rfx.s.r;R<=val.rfx.e.r;++R) for(C=val.rfx.s.c;C<=val.rfx.e.c;++C) {
23279 if(opts.dense) {
23280 if(!s[R]) s[R] = [];
23281 if(!s[R][C]) s[R][C] = {t:'z',v:undefined};
23282 s[R][C].l = val;
23283 } else {
23284 addr = encode_cell({c:C,r:R});
23285 if(!s[addr]) s[addr] = {t:'z',v:undefined};
23286 s[addr].l = val;
23287 }
23288 }
23289 break;
23290
23291 case 0x01AA: /* 'BrtArrFmla' */
23292 if(!opts.cellFormula) break;
23293 arrayf.push(val);
23294 cell = ((opts.dense ? s[R][C] : s[encode_col(C) + rr]));
23295 cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
23296 cell.F = encode_range(val[0]);
23297 break;
23298 case 0x01AB: /* 'BrtShrFmla' */
23299 if(!opts.cellFormula) break;
23300 sharedf[encode_cell(val[0].s)] = val[1];
23301 cell = (opts.dense ? s[R][C] : s[encode_col(C) + rr]);
23302 cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts);
23303 break;
23304
23305 /* identical to 'ColInfo' in XLS */
23306 case 0x003C: /* 'BrtColInfo' */
23307 if(!opts.cellStyles) break;
23308 while(val.e >= val.s) {
23309 colinfo[val.e--] = { width: val.w/256, hidden: !!(val.flags & 0x01), level: val.level };
23310 if(!seencol) { seencol = true; find_mdw_colw(val.w/256); }
23311 process_col(colinfo[val.e+1]);
23312 }
23313 break;
23314
23315 case 0x00A1: /* 'BrtBeginAFilter' */
23316 s['!autofilter'] = { ref:encode_range(val) };
23317 break;
23318
23319 case 0x01DC: /* 'BrtMargins' */
23320 s['!margins'] = val;
23321 break;
23322
23323 case 0x0093: /* 'BrtWsProp' */
23324 if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
23325 if(val.name) wb.Sheets[idx].CodeName = val.name;
23326 break;
23327
23328 case 0x0089: /* 'BrtBeginWsView' */
23329 if(!wb.Views) wb.Views = [{}];
23330 if(!wb.Views[0]) wb.Views[0] = {};
23331 if(val.RTL) wb.Views[0].RTL = true;
23332 break;
23333
23334 case 0x01E5: /* 'BrtWsFmtInfo' */
23335 break;
23336
23337 case 0x0040: /* 'BrtDVal' */
23338 case 0x041D: /* 'BrtDVal14' */
23339 break;
23340
23341 case 0x0097: /* 'BrtPane' */
23342 break;
23343 case 0x00AF: /* 'BrtAFilterDateGroupItem' */
23344 case 0x0284: /* 'BrtActiveX' */
23345 case 0x0271: /* 'BrtBigName' */
23346 case 0x0232: /* 'BrtBkHim' */
23347 case 0x018C: /* 'BrtBrk' */
23348 case 0x0458: /* 'BrtCFIcon' */
23349 case 0x047A: /* 'BrtCFRuleExt' */
23350 case 0x01D7: /* 'BrtCFVO' */
23351 case 0x041A: /* 'BrtCFVO14' */
23352 case 0x0289: /* 'BrtCellIgnoreEC' */
23353 case 0x0451: /* 'BrtCellIgnoreEC14' */
23354 case 0x0031: /* 'BrtCellMeta' */
23355 case 0x024D: /* 'BrtCellSmartTagProperty' */
23356 case 0x025F: /* 'BrtCellWatch' */
23357 case 0x0234: /* 'BrtColor' */
23358 case 0x041F: /* 'BrtColor14' */
23359 case 0x00A8: /* 'BrtColorFilter' */
23360 case 0x00AE: /* 'BrtCustomFilter' */
23361 case 0x049C: /* 'BrtCustomFilter14' */
23362 case 0x01F3: /* 'BrtDRef' */
23363 case 0x0226: /* 'BrtDrawing' */
23364 case 0x00AB: /* 'BrtDynamicFilter' */
23365 case 0x00A7: /* 'BrtFilter' */
23366 case 0x0499: /* 'BrtFilter14' */
23367 case 0x00A9: /* 'BrtIconFilter' */
23368 case 0x049D: /* 'BrtIconFilter14' */
23369 case 0x0227: /* 'BrtLegacyDrawing' */
23370 case 0x0228: /* 'BrtLegacyDrawingHF' */
23371 case 0x0295: /* 'BrtListPart' */
23372 case 0x027F: /* 'BrtOleObject' */
23373 case 0x01DE: /* 'BrtPageSetup' */
23374 case 0x0219: /* 'BrtPhoneticInfo' */
23375 case 0x01DD: /* 'BrtPrintOptions' */
23376 case 0x0218: /* 'BrtRangeProtection' */
23377 case 0x044F: /* 'BrtRangeProtection14' */
23378 case 0x02A8: /* 'BrtRangeProtectionIso' */
23379 case 0x0450: /* 'BrtRangeProtectionIso14' */
23380 case 0x0400: /* 'BrtRwDescent' */
23381 case 0x0098: /* 'BrtSel' */
23382 case 0x0297: /* 'BrtSheetCalcProp' */
23383 case 0x0217: /* 'BrtSheetProtection' */
23384 case 0x02A6: /* 'BrtSheetProtectionIso' */
23385 case 0x01F8: /* 'BrtSlc' */
23386 case 0x0413: /* 'BrtSparkline' */
23387 case 0x01AC: /* 'BrtTable' */
23388 case 0x00AA: /* 'BrtTop10Filter' */
23389 case 0x0C00: /* 'BrtUid' */
23390 case 0x0032: /* 'BrtValueMeta' */
23391 case 0x0816: /* 'BrtWebExtension' */
23392 case 0x0415: /* 'BrtWsFmtInfoEx14' */
23393 break;
23394
23395 case 0x0023: /* 'BrtFRTBegin' */
23396 pass = true; break;
23397 case 0x0024: /* 'BrtFRTEnd' */
23398 pass = false; break;
23399 case 0x0025: /* 'BrtACBegin' */
23400 state.push(R_n); pass = true; break;
23401 case 0x0026: /* 'BrtACEnd' */
23402 state.pop(); pass = false; break;
23403
23404 default:
23405 if((R_n||"").indexOf("Begin") > 0){/* empty */}
23406 else if((R_n||"").indexOf("End") > 0){/* empty */}
23407 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
23408 }
23409 }, opts);
23410
23411 delete opts.supbooks;
23412 delete opts['!row'];
23413
23414 if(!s["!ref"] && (refguess.s.r < 2000000 || ref && (ref.e.r > 0 || ref.e.c > 0 || ref.s.r > 0 || ref.s.c > 0))) s["!ref"] = encode_range(ref || refguess);
23415 if(opts.sheetRows && s["!ref"]) {
23416 var tmpref = safe_decode_range(s["!ref"]);
23417 if(opts.sheetRows <= +tmpref.e.r) {
23418 tmpref.e.r = opts.sheetRows - 1;
23419 if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r;
23420 if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r;
23421 if(tmpref.e.c > refguess.e.c) tmpref.e.c = refguess.e.c;
23422 if(tmpref.e.c < tmpref.s.c) tmpref.s.c = tmpref.e.c;
23423 s["!fullref"] = s["!ref"];
23424 s["!ref"] = encode_range(tmpref);
23425 }
23426 }
23427 if(merges.length > 0) s["!merges"] = merges;
23428 if(colinfo.length > 0) s["!cols"] = colinfo;
23429 if(rowinfo.length > 0) s["!rows"] = rowinfo;
23430 return s;
23431}
23432
23433/* TODO: something useful -- this is a stub */
23434function write_ws_bin_cell(ba, cell, R, C, opts, ws) {
23435 if(cell.v === undefined) return;
23436 var vv = "";
23437 switch(cell.t) {
23438 case 'b': vv = cell.v ? "1" : "0"; break;
23439 case 'd': // no BrtCellDate :(
23440 cell = dup(cell);
23441 cell.z = cell.z || SSF._table[14];
23442 cell.v = datenum(parseDate(cell.v)); cell.t = 'n';
23443 break;
23444 /* falls through */
23445 case 'n': case 'e': vv = ''+cell.v; break;
23446 default: vv = cell.v; break;
23447 }
23448 var o = ({r:R, c:C});
23449 /* TODO: cell style */
23450 o.s = get_cell_style(opts.cellXfs, cell, opts);
23451 if(cell.l) ws['!links'].push([encode_cell(o), cell.l]);
23452 if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
23453 switch(cell.t) {
23454 case 's': case 'str':
23455 if(opts.bookSST) {
23456 vv = get_sst_id(opts.Strings, (cell.v), opts.revStrings);
23457 o.t = "s"; o.v = vv;
23458 write_record(ba, "BrtCellIsst", write_BrtCellIsst(cell, o));
23459 } else {
23460 o.t = "str";
23461 write_record(ba, "BrtCellSt", write_BrtCellSt(cell, o));
23462 }
23463 return;
23464 case 'n':
23465 /* TODO: determine threshold for Real vs RK */
23466 if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) write_record(ba, "BrtCellRk", write_BrtCellRk(cell, o));
23467 else write_record(ba, "BrtCellReal", write_BrtCellReal(cell, o));
23468 return;
23469 case 'b':
23470 o.t = "b";
23471 write_record(ba, "BrtCellBool", write_BrtCellBool(cell, o));
23472 return;
23473 case 'e': /* TODO: error */ o.t = "e"; break;
23474 }
23475 write_record(ba, "BrtCellBlank", write_BrtCellBlank(cell, o));
23476}
23477
23478function write_CELLTABLE(ba, ws, idx, opts) {
23479 var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = [];
23480 write_record(ba, 'BrtBeginSheetData');
23481 var dense = Array.isArray(ws);
23482 var cap = range.e.r;
23483 if(ws['!rows']) cap = Math.max(range.e.r, ws['!rows'].length - 1);
23484 for(var R = range.s.r; R <= cap; ++R) {
23485 rr = encode_row(R);
23486 /* [ACCELLTABLE] */
23487 /* BrtRowHdr */
23488 write_row_header(ba, ws, range, R);
23489 if(R <= range.e.r) for(var C = range.s.c; C <= range.e.c; ++C) {
23490 /* *16384CELL */
23491 if(R === range.s.r) cols[C] = encode_col(C);
23492 ref = cols[C] + rr;
23493 var cell = dense ? (ws[R]||[])[C] : ws[ref];
23494 if(!cell) continue;
23495 /* write cell */
23496 write_ws_bin_cell(ba, cell, R, C, opts, ws);
23497 }
23498 }
23499 write_record(ba, 'BrtEndSheetData');
23500}
23501
23502function write_MERGECELLS(ba, ws) {
23503 if(!ws || !ws['!merges']) return;
23504 write_record(ba, 'BrtBeginMergeCells', write_BrtBeginMergeCells(ws['!merges'].length));
23505 ws['!merges'].forEach(function(m) { write_record(ba, 'BrtMergeCell', write_BrtMergeCell(m)); });
23506 write_record(ba, 'BrtEndMergeCells');
23507}
23508
23509function write_COLINFOS(ba, ws) {
23510 if(!ws || !ws['!cols']) return;
23511 write_record(ba, 'BrtBeginColInfos');
23512 ws['!cols'].forEach(function(m, i) { if(m) write_record(ba, 'BrtColInfo', write_BrtColInfo(i, m)); });
23513 write_record(ba, 'BrtEndColInfos');
23514}
23515
23516function write_IGNOREECS(ba, ws) {
23517 if(!ws || !ws['!ref']) return;
23518 write_record(ba, 'BrtBeginCellIgnoreECs');
23519 write_record(ba, 'BrtCellIgnoreEC', write_BrtCellIgnoreEC(safe_decode_range(ws['!ref'])));
23520 write_record(ba, 'BrtEndCellIgnoreECs');
23521}
23522
23523function write_HLINKS(ba, ws, rels) {
23524 /* *BrtHLink */
23525 ws['!links'].forEach(function(l) {
23526 if(!l[1].Target) return;
23527 var rId = add_rels(rels, -1, l[1].Target.replace(/#.*$/, ""), RELS.HLINK);
23528 write_record(ba, "BrtHLink", write_BrtHLink(l, rId));
23529 });
23530 delete ws['!links'];
23531}
23532function write_LEGACYDRAWING(ba, ws, idx, rels) {
23533 /* [BrtLegacyDrawing] */
23534 if(ws['!comments'].length > 0) {
23535 var rId = add_rels(rels, -1, "../drawings/vmlDrawing" + (idx+1) + ".vml", RELS.VML);
23536 write_record(ba, "BrtLegacyDrawing", write_RelID("rId" + rId));
23537 ws['!legacy'] = rId;
23538 }
23539}
23540
23541function write_AUTOFILTER(ba, ws, wb, idx) {
23542 if(!ws['!autofilter']) return;
23543 var data = ws['!autofilter'];
23544 var ref = typeof data.ref === "string" ? data.ref : encode_range(data.ref);
23545
23546 /* Update FilterDatabase defined name for the worksheet */
23547 if(!wb.Workbook) wb.Workbook = ({Sheets:[]});
23548 if(!wb.Workbook.Names) wb.Workbook.Names = [];
23549 var names = wb.Workbook.Names;
23550 var range = decode_range(ref);
23551 if(range.s.r == range.e.r) { range.e.r = decode_range(ws["!ref"]).e.r; ref = encode_range(range); }
23552 for(var i = 0; i < names.length; ++i) {
23553 var name = names[i];
23554 if(name.Name != '_xlnm._FilterDatabase') continue;
23555 if(name.Sheet != idx) continue;
23556 name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break;
23557 }
23558 if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref });
23559
23560 write_record(ba, "BrtBeginAFilter", write_UncheckedRfX(safe_decode_range(ref)));
23561 /* *FILTERCOLUMN */
23562 /* [SORTSTATE] */
23563 /* BrtEndAFilter */
23564 write_record(ba, "BrtEndAFilter");
23565}
23566
23567function write_WSVIEWS2(ba, ws, Workbook) {
23568 write_record(ba, "BrtBeginWsViews");
23569 { /* 1*WSVIEW2 */
23570 /* [ACUID] */
23571 write_record(ba, "BrtBeginWsView", write_BrtBeginWsView(ws, Workbook));
23572 /* [BrtPane] */
23573 /* *4BrtSel */
23574 /* *4SXSELECT */
23575 /* *FRT */
23576 write_record(ba, "BrtEndWsView");
23577 }
23578 /* *FRT */
23579 write_record(ba, "BrtEndWsViews");
23580}
23581
23582function write_WSFMTINFO() {
23583 /* [ACWSFMTINFO] */
23584 //write_record(ba, "BrtWsFmtInfo", write_BrtWsFmtInfo(ws));
23585}
23586
23587function write_SHEETPROTECT(ba, ws) {
23588 if(!ws['!protect']) return;
23589 /* [BrtSheetProtectionIso] */
23590 write_record(ba, "BrtSheetProtection", write_BrtSheetProtection(ws['!protect']));
23591}
23592
23593function write_ws_bin(idx, opts, wb, rels) {
23594 var ba = buf_array();
23595 var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
23596 var c = s; try { if(wb && wb.Workbook) c = wb.Workbook.Sheets[idx].CodeName || c; } catch(e) {}
23597 var r = safe_decode_range(ws['!ref'] || "A1");
23598 if(r.e.c > 0x3FFF || r.e.r > 0xFFFFF) {
23599 if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:XFD1048576");
23600 r.e.c = Math.min(r.e.c, 0x3FFF);
23601 r.e.r = Math.min(r.e.c, 0xFFFFF);
23602 }
23603 ws['!links'] = [];
23604 /* passed back to write_zip and removed there */
23605 ws['!comments'] = [];
23606 write_record(ba, "BrtBeginSheet");
23607 if(wb.vbaraw) write_record(ba, "BrtWsProp", write_BrtWsProp(c));
23608 write_record(ba, "BrtWsDim", write_BrtWsDim(r));
23609 write_WSVIEWS2(ba, ws, wb.Workbook);
23610 write_WSFMTINFO(ba, ws);
23611 write_COLINFOS(ba, ws, idx, opts, wb);
23612 write_CELLTABLE(ba, ws, idx, opts, wb);
23613 /* [BrtSheetCalcProp] */
23614 write_SHEETPROTECT(ba, ws);
23615 /* *([BrtRangeProtectionIso] BrtRangeProtection) */
23616 /* [SCENMAN] */
23617 write_AUTOFILTER(ba, ws, wb, idx);
23618 /* [SORTSTATE] */
23619 /* [DCON] */
23620 /* [USERSHVIEWS] */
23621 write_MERGECELLS(ba, ws);
23622 /* [BrtPhoneticInfo] */
23623 /* *CONDITIONALFORMATTING */
23624 /* [DVALS] */
23625 write_HLINKS(ba, ws, rels);
23626 /* [BrtPrintOptions] */
23627 if(ws['!margins']) write_record(ba, "BrtMargins", write_BrtMargins(ws['!margins']));
23628 /* [BrtPageSetup] */
23629 /* [HEADERFOOTER] */
23630 /* [RWBRK] */
23631 /* [COLBRK] */
23632 /* *BrtBigName */
23633 /* [CELLWATCHES] */
23634 if(!opts || opts.ignoreEC || (opts.ignoreEC == (void 0))) write_IGNOREECS(ba, ws);
23635 /* [SMARTTAGS] */
23636 /* [BrtDrawing] */
23637 write_LEGACYDRAWING(ba, ws, idx, rels);
23638 /* [BrtLegacyDrawingHF] */
23639 /* [BrtBkHim] */
23640 /* [OLEOBJECTS] */
23641 /* [ACTIVEXCONTROLS] */
23642 /* [WEBPUBITEMS] */
23643 /* [LISTPARTS] */
23644 /* FRTWORKSHEET */
23645 write_record(ba, "BrtEndSheet");
23646 return ba.end();
23647}
23648RELS.CHART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart";
23649RELS.CHARTEX = "http://schemas.microsoft.com/office/2014/relationships/chartEx";
23650
23651function parse_Cache(data) {
23652 var col = [];
23653 var num = data.match(/^<c:numCache>/);
23654 var f;
23655
23656 /* 21.2.2.150 pt CT_NumVal */
23657 (data.match(/<c:pt idx="(\d*)">(.*?)<\/c:pt>/mg)||[]).forEach(function(pt) {
23658 var q = pt.match(/<c:pt idx="(\d*?)"><c:v>(.*)<\/c:v><\/c:pt>/);
23659 if(!q) return;
23660 col[+q[1]] = num ? +q[2] : q[2];
23661 });
23662
23663 /* 21.2.2.71 formatCode CT_Xstring */
23664 var nf = unescapexml((data.match(/<c:formatCode>([\s\S]*?)<\/c:formatCode>/) || ["","General"])[1]);
23665
23666 (data.match(/<c:f>(.*?)<\/c:f>/mg)||[]).forEach(function(F) { f = F.replace(/<.*?>/g,""); });
23667
23668 return [col, nf, f];
23669}
23670
23671/* 21.2 DrawingML - Charts */
23672function parse_chart(data, name, opts, rels, wb, csheet) {
23673 var cs = ((csheet || {"!type":"chart"}));
23674 if(!data) return csheet;
23675 /* 21.2.2.27 chart CT_Chart */
23676
23677 var C = 0, R = 0, col = "A";
23678 var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
23679
23680 /* 21.2.2.120 numCache CT_NumData */
23681 (data.match(/<c:numCache>[\s\S]*?<\/c:numCache>/gm)||[]).forEach(function(nc) {
23682 var cache = parse_Cache(nc);
23683 refguess.s.r = refguess.s.c = 0;
23684 refguess.e.c = C;
23685 col = encode_col(C);
23686 cache[0].forEach(function(n,i) {
23687 cs[col + encode_row(i)] = {t:'n', v:n, z:cache[1] };
23688 R = i;
23689 });
23690 if(refguess.e.r < R) refguess.e.r = R;
23691 ++C;
23692 });
23693 if(C > 0) cs["!ref"] = encode_range(refguess);
23694 return cs;
23695}
23696RELS.CS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet";
23697
23698var CS_XML_ROOT = writextag('chartsheet', null, {
23699 'xmlns': XMLNS.main[0],
23700 'xmlns:r': XMLNS.r
23701});
23702
23703/* 18.3 Worksheets also covers Chartsheets */
23704function parse_cs_xml(data, opts, idx, rels, wb) {
23705 if(!data) return data;
23706 /* 18.3.1.12 chartsheet CT_ChartSheet */
23707 if(!rels) rels = {'!id':{}};
23708 var s = ({'!type':"chart", '!drawel':null, '!rel':""});
23709 var m;
23710
23711 /* 18.3.1.83 sheetPr CT_ChartsheetPr */
23712 var sheetPr = data.match(sheetprregex);
23713 if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);
23714
23715 /* 18.3.1.36 drawing CT_Drawing */
23716 if((m = data.match(/drawing r:id="(.*?)"/))) s['!rel'] = m[1];
23717
23718 if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
23719 return s;
23720}
23721function write_cs_xml(idx, opts, wb, rels) {
23722 var o = [XML_HEADER, CS_XML_ROOT];
23723 o[o.length] = writextag("drawing", null, {"r:id": "rId1"});
23724 add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW);
23725 if(o.length>2) { o[o.length] = ('</chartsheet>'); o[1]=o[1].replace("/>",">"); }
23726 return o.join("");
23727}
23728
23729/* [MS-XLSB] 2.4.331 BrtCsProp */
23730function parse_BrtCsProp(data, length) {
23731 data.l += 10;
23732 var name = parse_XLWideString(data, length - 10);
23733 return { name: name };
23734}
23735
23736/* [MS-XLSB] 2.1.7.7 Chart Sheet */
23737function parse_cs_bin(data, opts, idx, rels, wb) {
23738 if(!data) return data;
23739 if(!rels) rels = {'!id':{}};
23740 var s = {'!type':"chart", '!drawel':null, '!rel':""};
23741 var state = [];
23742 var pass = false;
23743 recordhopper(data, function cs_parse(val, R_n, RT) {
23744 switch(RT) {
23745
23746 case 0x0226: /* 'BrtDrawing' */
23747 s['!rel'] = val; break;
23748
23749 case 0x028B: /* 'BrtCsProp' */
23750 if(!wb.Sheets[idx]) wb.Sheets[idx] = {};
23751 if(val.name) wb.Sheets[idx].CodeName = val.name;
23752 break;
23753
23754 case 0x0232: /* 'BrtBkHim' */
23755 case 0x028C: /* 'BrtCsPageSetup' */
23756 case 0x029D: /* 'BrtCsProtection' */
23757 case 0x02A7: /* 'BrtCsProtectionIso' */
23758 case 0x0227: /* 'BrtLegacyDrawing' */
23759 case 0x0228: /* 'BrtLegacyDrawingHF' */
23760 case 0x01DC: /* 'BrtMargins' */
23761 case 0x0C00: /* 'BrtUid' */
23762 break;
23763
23764 case 0x0023: /* 'BrtFRTBegin' */
23765 pass = true; break;
23766 case 0x0024: /* 'BrtFRTEnd' */
23767 pass = false; break;
23768 case 0x0025: /* 'BrtACBegin' */
23769 state.push(R_n); break;
23770 case 0x0026: /* 'BrtACEnd' */
23771 state.pop(); break;
23772
23773 default:
23774 if((R_n||"").indexOf("Begin") > 0) state.push(R_n);
23775 else if((R_n||"").indexOf("End") > 0) state.pop();
23776 else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n);
23777 }
23778 }, opts);
23779
23780 if(rels['!id'][s['!rel']]) s['!drawel'] = rels['!id'][s['!rel']];
23781 return s;
23782}
23783function write_cs_bin() {
23784 var ba = buf_array();
23785 write_record(ba, "BrtBeginSheet");
23786 /* [BrtCsProp] */
23787 /* CSVIEWS */
23788 /* [[BrtCsProtectionIso] BrtCsProtection] */
23789 /* [USERCSVIEWS] */
23790 /* [BrtMargins] */
23791 /* [BrtCsPageSetup] */
23792 /* [HEADERFOOTER] */
23793 /* BrtDrawing */
23794 /* [BrtLegacyDrawing] */
23795 /* [BrtLegacyDrawingHF] */
23796 /* [BrtBkHim] */
23797 /* [WEBPUBITEMS] */
23798 /* FRTCHARTSHEET */
23799 write_record(ba, "BrtEndSheet");
23800 return ba.end();
23801}
23802/* 18.2.28 (CT_WorkbookProtection) Defaults */
23803var WBPropsDef = [
23804 ['allowRefreshQuery', false, "bool"],
23805 ['autoCompressPictures', true, "bool"],
23806 ['backupFile', false, "bool"],
23807 ['checkCompatibility', false, "bool"],
23808 ['CodeName', ''],
23809 ['date1904', false, "bool"],
23810 ['defaultThemeVersion', 0, "int"],
23811 ['filterPrivacy', false, "bool"],
23812 ['hidePivotFieldList', false, "bool"],
23813 ['promptedSolutions', false, "bool"],
23814 ['publishItems', false, "bool"],
23815 ['refreshAllConnections', false, "bool"],
23816 ['saveExternalLinkValues', true, "bool"],
23817 ['showBorderUnselectedTables', true, "bool"],
23818 ['showInkAnnotation', true, "bool"],
23819 ['showObjects', 'all'],
23820 ['showPivotChartFilter', false, "bool"],
23821 ['updateLinks', 'userSet']
23822];
23823
23824/* 18.2.30 (CT_BookView) Defaults */
23825var WBViewDef = [
23826 ['activeTab', 0, "int"],
23827 ['autoFilterDateGrouping', true, "bool"],
23828 ['firstSheet', 0, "int"],
23829 ['minimized', false, "bool"],
23830 ['showHorizontalScroll', true, "bool"],
23831 ['showSheetTabs', true, "bool"],
23832 ['showVerticalScroll', true, "bool"],
23833 ['tabRatio', 600, "int"],
23834 ['visibility', 'visible']
23835 //window{Height,Width}, {x,y}Window
23836];
23837
23838/* 18.2.19 (CT_Sheet) Defaults */
23839var SheetDef = [
23840 //['state', 'visible']
23841];
23842
23843/* 18.2.2 (CT_CalcPr) Defaults */
23844var CalcPrDef = [
23845 ['calcCompleted', 'true'],
23846 ['calcMode', 'auto'],
23847 ['calcOnSave', 'true'],
23848 ['concurrentCalc', 'true'],
23849 ['fullCalcOnLoad', 'false'],
23850 ['fullPrecision', 'true'],
23851 ['iterate', 'false'],
23852 ['iterateCount', '100'],
23853 ['iterateDelta', '0.001'],
23854 ['refMode', 'A1']
23855];
23856
23857/* 18.2.3 (CT_CustomWorkbookView) Defaults */
23858/*var CustomWBViewDef = [
23859 ['autoUpdate', 'false'],
23860 ['changesSavedWin', 'false'],
23861 ['includeHiddenRowCol', 'true'],
23862 ['includePrintSettings', 'true'],
23863 ['maximized', 'false'],
23864 ['minimized', 'false'],
23865 ['onlySync', 'false'],
23866 ['personalView', 'false'],
23867 ['showComments', 'commIndicator'],
23868 ['showFormulaBar', 'true'],
23869 ['showHorizontalScroll', 'true'],
23870 ['showObjects', 'all'],
23871 ['showSheetTabs', 'true'],
23872 ['showStatusbar', 'true'],
23873 ['showVerticalScroll', 'true'],
23874 ['tabRatio', '600'],
23875 ['xWindow', '0'],
23876 ['yWindow', '0']
23877];*/
23878
23879function push_defaults_array(target, defaults) {
23880 for(var j = 0; j != target.length; ++j) { var w = target[j];
23881 for(var i=0; i != defaults.length; ++i) { var z = defaults[i];
23882 if(w[z[0]] == null) w[z[0]] = z[1];
23883 else switch(z[2]) {
23884 case "bool": if(typeof w[z[0]] == "string") w[z[0]] = parsexmlbool(w[z[0]]); break;
23885 case "int": if(typeof w[z[0]] == "string") w[z[0]] = parseInt(w[z[0]], 10); break;
23886 }
23887 }
23888 }
23889}
23890function push_defaults(target, defaults) {
23891 for(var i = 0; i != defaults.length; ++i) { var z = defaults[i];
23892 if(target[z[0]] == null) target[z[0]] = z[1];
23893 else switch(z[2]) {
23894 case "bool": if(typeof target[z[0]] == "string") target[z[0]] = parsexmlbool(target[z[0]]); break;
23895 case "int": if(typeof target[z[0]] == "string") target[z[0]] = parseInt(target[z[0]], 10); break;
23896 }
23897 }
23898}
23899
23900function parse_wb_defaults(wb) {
23901 push_defaults(wb.WBProps, WBPropsDef);
23902 push_defaults(wb.CalcPr, CalcPrDef);
23903
23904 push_defaults_array(wb.WBView, WBViewDef);
23905 push_defaults_array(wb.Sheets, SheetDef);
23906
23907 _ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904);
23908}
23909
23910function safe1904(wb) {
23911 /* TODO: store date1904 somewhere else */
23912 if(!wb.Workbook) return "false";
23913 if(!wb.Workbook.WBProps) return "false";
23914 return parsexmlbool(wb.Workbook.WBProps.date1904) ? "true" : "false";
23915}
23916
23917var badchars = "][*?\/\\".split("");
23918function check_ws_name(n, safe) {
23919 if(n.length > 31) { if(safe) return false; throw new Error("Sheet names cannot exceed 31 chars"); }
23920 var _good = true;
23921 badchars.forEach(function(c) {
23922 if(n.indexOf(c) == -1) return;
23923 if(!safe) throw new Error("Sheet name cannot contain : \\ / ? * [ ]");
23924 _good = false;
23925 });
23926 return _good;
23927}
23928function check_wb_names(N, S, codes) {
23929 N.forEach(function(n,i) {
23930 check_ws_name(n);
23931 for(var j = 0; j < i; ++j) if(n == N[j]) throw new Error("Duplicate Sheet Name: " + n);
23932 if(codes) {
23933 var cn = (S && S[i] && S[i].CodeName) || n;
23934 if(cn.charCodeAt(0) == 95 && cn.length > 22) throw new Error("Bad Code Name: Worksheet" + cn);
23935 }
23936 });
23937}
23938function check_wb(wb) {
23939 if(!wb || !wb.SheetNames || !wb.Sheets) throw new Error("Invalid Workbook");
23940 if(!wb.SheetNames.length) throw new Error("Workbook is empty");
23941 var Sheets = (wb.Workbook && wb.Workbook.Sheets) || [];
23942 check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw);
23943 for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i);
23944 /* TODO: validate workbook */
23945}
23946/* 18.2 Workbook */
23947var wbnsregex = /<\w+:workbook/;
23948function parse_wb_xml(data, opts) {
23949 if(!data) throw new Error("Could not find file");
23950 var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, Names:[], xmlns: "" };
23951 var pass = false, xmlns = "xmlns";
23952 var dname = {}, dnstart = 0;
23953 data.replace(tagregex, function xml_wb(x, idx) {
23954 var y = parsexmltag(x);
23955 switch(strip_ns(y[0])) {
23956 case '<?xml': break;
23957
23958 /* 18.2.27 workbook CT_Workbook 1 */
23959 case '<workbook':
23960 if(x.match(wbnsregex)) xmlns = "xmlns" + x.match(/<(\w+):/)[1];
23961 wb.xmlns = y[xmlns];
23962 break;
23963 case '</workbook>': break;
23964
23965 /* 18.2.13 fileVersion CT_FileVersion ? */
23966 case '<fileVersion': delete y[0]; wb.AppVersion = y; break;
23967 case '<fileVersion/>': case '</fileVersion>': break;
23968
23969 /* 18.2.12 fileSharing CT_FileSharing ? */
23970 case '<fileSharing':
23971 break;
23972 case '<fileSharing/>': break;
23973
23974 /* 18.2.28 workbookPr CT_WorkbookPr ? */
23975 case '<workbookPr':
23976 case '<workbookPr/>':
23977 WBPropsDef.forEach(function(w) {
23978 if(y[w[0]] == null) return;
23979 switch(w[2]) {
23980 case "bool": wb.WBProps[w[0]] = parsexmlbool(y[w[0]]); break;
23981 case "int": wb.WBProps[w[0]] = parseInt(y[w[0]], 10); break;
23982 default: wb.WBProps[w[0]] = y[w[0]];
23983 }
23984 });
23985 if(y.codeName) wb.WBProps.CodeName = y.codeName;
23986 break;
23987 case '</workbookPr>': break;
23988
23989 /* 18.2.29 workbookProtection CT_WorkbookProtection ? */
23990 case '<workbookProtection':
23991 break;
23992 case '<workbookProtection/>': break;
23993
23994 /* 18.2.1 bookViews CT_BookViews ? */
23995 case '<bookViews': case '<bookViews>': case '</bookViews>': break;
23996 /* 18.2.30 workbookView CT_BookView + */
23997 case '<workbookView': case '<workbookView/>': delete y[0]; wb.WBView.push(y); break;
23998 case '</workbookView>': break;
23999
24000 /* 18.2.20 sheets CT_Sheets 1 */
24001 case '<sheets': case '<sheets>': case '</sheets>': break; // aggregate sheet
24002 /* 18.2.19 sheet CT_Sheet + */
24003 case '<sheet':
24004 switch(y.state) {
24005 case "hidden": y.Hidden = 1; break;
24006 case "veryHidden": y.Hidden = 2; break;
24007 default: y.Hidden = 0;
24008 }
24009 delete y.state;
24010 y.name = unescapexml(utf8read(y.name));
24011 delete y[0]; wb.Sheets.push(y); break;
24012 case '</sheet>': break;
24013
24014 /* 18.2.15 functionGroups CT_FunctionGroups ? */
24015 case '<functionGroups': case '<functionGroups/>': break;
24016 /* 18.2.14 functionGroup CT_FunctionGroup + */
24017 case '<functionGroup': break;
24018
24019 /* 18.2.9 externalReferences CT_ExternalReferences ? */
24020 case '<externalReferences': case '</externalReferences>': case '<externalReferences>': break;
24021 /* 18.2.8 externalReference CT_ExternalReference + */
24022 case '<externalReference': break;
24023
24024 /* 18.2.6 definedNames CT_DefinedNames ? */
24025 case '<definedNames/>': break;
24026 case '<definedNames>': case '<definedNames': pass=true; break;
24027 case '</definedNames>': pass=false; break;
24028 /* 18.2.5 definedName CT_DefinedName + */
24029 case '<definedName': {
24030 dname = {};
24031 dname.Name = utf8read(y.name);
24032 if(y.comment) dname.Comment = y.comment;
24033 if(y.localSheetId) dname.Sheet = +y.localSheetId;
24034 if(parsexmlbool(y.hidden||"0")) dname.Hidden = true;
24035 dnstart = idx + x.length;
24036 } break;
24037 case '</definedName>': {
24038 dname.Ref = unescapexml(utf8read(data.slice(dnstart, idx)));
24039 wb.Names.push(dname);
24040 } break;
24041 case '<definedName/>': break;
24042
24043 /* 18.2.2 calcPr CT_CalcPr ? */
24044 case '<calcPr': delete y[0]; wb.CalcPr = y; break;
24045 case '<calcPr/>': delete y[0]; wb.CalcPr = y; break;
24046 case '</calcPr>': break;
24047
24048 /* 18.2.16 oleSize CT_OleSize ? (ref required) */
24049 case '<oleSize': break;
24050
24051 /* 18.2.4 customWorkbookViews CT_CustomWorkbookViews ? */
24052 case '<customWorkbookViews>': case '</customWorkbookViews>': case '<customWorkbookViews': break;
24053 /* 18.2.3 customWorkbookView CT_CustomWorkbookView + */
24054 case '<customWorkbookView': case '</customWorkbookView>': break;
24055
24056 /* 18.2.18 pivotCaches CT_PivotCaches ? */
24057 case '<pivotCaches>': case '</pivotCaches>': case '<pivotCaches': break;
24058 /* 18.2.17 pivotCache CT_PivotCache ? */
24059 case '<pivotCache': break;
24060
24061 /* 18.2.21 smartTagPr CT_SmartTagPr ? */
24062 case '<smartTagPr': case '<smartTagPr/>': break;
24063
24064 /* 18.2.23 smartTagTypes CT_SmartTagTypes ? */
24065 case '<smartTagTypes': case '<smartTagTypes>': case '</smartTagTypes>': break;
24066 /* 18.2.22 smartTagType CT_SmartTagType ? */
24067 case '<smartTagType': break;
24068
24069 /* 18.2.24 webPublishing CT_WebPublishing ? */
24070 case '<webPublishing': case '<webPublishing/>': break;
24071
24072 /* 18.2.11 fileRecoveryPr CT_FileRecoveryPr ? */
24073 case '<fileRecoveryPr': case '<fileRecoveryPr/>': break;
24074
24075 /* 18.2.26 webPublishObjects CT_WebPublishObjects ? */
24076 case '<webPublishObjects>': case '<webPublishObjects': case '</webPublishObjects>': break;
24077 /* 18.2.25 webPublishObject CT_WebPublishObject ? */
24078 case '<webPublishObject': break;
24079
24080 /* 18.2.10 extLst CT_ExtensionList ? */
24081 case '<extLst': case '<extLst>': case '</extLst>': case '<extLst/>': break;
24082 /* 18.2.7 ext CT_Extension + */
24083 case '<ext': pass=true; break; //TODO: check with versions of excel
24084 case '</ext>': pass=false; break;
24085
24086 /* Others */
24087 case '<ArchID': break;
24088 case '<AlternateContent':
24089 case '<AlternateContent>': pass=true; break;
24090 case '</AlternateContent>': pass=false; break;
24091
24092 /* TODO */
24093 case '<revisionPtr': break;
24094
24095 default: if(!pass && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in workbook');
24096 }
24097 return x;
24098 });
24099 if(XMLNS.main.indexOf(wb.xmlns) === -1) throw new Error("Unknown Namespace: " + wb.xmlns);
24100
24101 parse_wb_defaults(wb);
24102
24103 return wb;
24104}
24105
24106var WB_XML_ROOT = writextag('workbook', null, {
24107 'xmlns': XMLNS.main[0],
24108 //'xmlns:mx': XMLNS.mx,
24109 //'xmlns:s': XMLNS.main[0],
24110 'xmlns:r': XMLNS.r
24111});
24112
24113function write_wb_xml(wb) {
24114 var o = [XML_HEADER];
24115 o[o.length] = WB_XML_ROOT;
24116
24117 var write_names = (wb.Workbook && (wb.Workbook.Names||[]).length > 0);
24118
24119 /* fileVersion */
24120 /* fileSharing */
24121
24122 var workbookPr = ({codeName:"ThisWorkbook"});
24123 if(wb.Workbook && wb.Workbook.WBProps) {
24124 WBPropsDef.forEach(function(x) {
24125if((wb.Workbook.WBProps[x[0]]) == null) return;
24126 if((wb.Workbook.WBProps[x[0]]) == x[1]) return;
24127 workbookPr[x[0]] = (wb.Workbook.WBProps[x[0]]);
24128 });
24129if(wb.Workbook.WBProps.CodeName) { workbookPr.codeName = wb.Workbook.WBProps.CodeName; delete workbookPr.CodeName; }
24130 }
24131 o[o.length] = (writextag('workbookPr', null, workbookPr));
24132
24133 /* workbookProtection */
24134
24135 var sheets = wb.Workbook && wb.Workbook.Sheets || [];
24136 var i = 0;
24137
24138 /* bookViews */
24139
24140 o[o.length] = "<sheets>";
24141 for(i = 0; i != wb.SheetNames.length; ++i) {
24142 var sht = ({name:escapexml(wb.SheetNames[i].slice(0,31))});
24143 sht.sheetId = ""+(i+1);
24144 sht["r:id"] = "rId"+(i+1);
24145 if(sheets[i]) switch(sheets[i].Hidden) {
24146 case 1: sht.state = "hidden"; break;
24147 case 2: sht.state = "veryHidden"; break;
24148 }
24149 o[o.length] = (writextag('sheet',null,sht));
24150 }
24151 o[o.length] = "</sheets>";
24152
24153 /* functionGroups */
24154 /* externalReferences */
24155
24156 if(write_names) {
24157 o[o.length] = "<definedNames>";
24158 if(wb.Workbook && wb.Workbook.Names) wb.Workbook.Names.forEach(function(n) {
24159 var d = {name:n.Name};
24160 if(n.Comment) d.comment = n.Comment;
24161 if(n.Sheet != null) d.localSheetId = ""+n.Sheet;
24162 if(n.Hidden) d.hidden = "1";
24163 if(!n.Ref) return;
24164 o[o.length] = writextag('definedName', String(n.Ref).replace(/</g, "&lt;").replace(/>/g, "&gt;"), d);
24165 });
24166 o[o.length] = "</definedNames>";
24167 }
24168
24169 /* calcPr */
24170 /* oleSize */
24171 /* customWorkbookViews */
24172 /* pivotCaches */
24173 /* smartTagPr */
24174 /* smartTagTypes */
24175 /* webPublishing */
24176 /* fileRecoveryPr */
24177 /* webPublishObjects */
24178 /* extLst */
24179
24180 if(o.length>2){ o[o.length] = '</workbook>'; o[1]=o[1].replace("/>",">"); }
24181 return o.join("");
24182}
24183/* [MS-XLSB] 2.4.304 BrtBundleSh */
24184function parse_BrtBundleSh(data, length) {
24185 var z = {};
24186 z.Hidden = data.read_shift(4); //hsState ST_SheetState
24187 z.iTabID = data.read_shift(4);
24188 z.strRelID = parse_RelID(data,length-8);
24189 z.name = parse_XLWideString(data);
24190 return z;
24191}
24192function write_BrtBundleSh(data, o) {
24193 if(!o) o = new_buf(127);
24194 o.write_shift(4, data.Hidden);
24195 o.write_shift(4, data.iTabID);
24196 write_RelID(data.strRelID, o);
24197 write_XLWideString(data.name.slice(0,31), o);
24198 return o.length > o.l ? o.slice(0, o.l) : o;
24199}
24200
24201/* [MS-XLSB] 2.4.815 BrtWbProp */
24202function parse_BrtWbProp(data, length) {
24203 var o = ({});
24204 var flags = data.read_shift(4);
24205 o.defaultThemeVersion = data.read_shift(4);
24206 var strName = (length > 8) ? parse_XLWideString(data) : "";
24207 if(strName.length > 0) o.CodeName = strName;
24208 o.autoCompressPictures = !!(flags & 0x10000);
24209 o.backupFile = !!(flags & 0x40);
24210 o.checkCompatibility = !!(flags & 0x1000);
24211 o.date1904 = !!(flags & 0x01);
24212 o.filterPrivacy = !!(flags & 0x08);
24213 o.hidePivotFieldList = !!(flags & 0x400);
24214 o.promptedSolutions = !!(flags & 0x10);
24215 o.publishItems = !!(flags & 0x800);
24216 o.refreshAllConnections = !!(flags & 0x40000);
24217 o.saveExternalLinkValues = !!(flags & 0x80);
24218 o.showBorderUnselectedTables = !!(flags & 0x04);
24219 o.showInkAnnotation = !!(flags & 0x20);
24220 o.showObjects = ["all", "placeholders", "none"][(flags >> 13) & 0x03];
24221 o.showPivotChartFilter = !!(flags & 0x8000);
24222 o.updateLinks = ["userSet", "never", "always"][(flags >> 8) & 0x03];
24223 return o;
24224}
24225function write_BrtWbProp(data, o) {
24226 if(!o) o = new_buf(72);
24227 var flags = 0;
24228 if(data) {
24229 /* TODO: mirror parse_BrtWbProp fields */
24230 if(data.filterPrivacy) flags |= 0x08;
24231 }
24232 o.write_shift(4, flags);
24233 o.write_shift(4, 0);
24234 write_XLSBCodeName(data && data.CodeName || "ThisWorkbook", o);
24235 return o.slice(0, o.l);
24236}
24237
24238function parse_BrtFRTArchID$(data, length) {
24239 var o = {};
24240 data.read_shift(4);
24241 o.ArchID = data.read_shift(4);
24242 data.l += length - 8;
24243 return o;
24244}
24245
24246/* [MS-XLSB] 2.4.687 BrtName */
24247function parse_BrtName(data, length, opts) {
24248 var end = data.l + length;
24249 data.l += 4; //var flags = data.read_shift(4);
24250 data.l += 1; //var chKey = data.read_shift(1);
24251 var itab = data.read_shift(4);
24252 var name = parse_XLNameWideString(data);
24253 var formula = parse_XLSBNameParsedFormula(data, 0, opts);
24254 var comment = parse_XLNullableWideString(data);
24255 //if(0 /* fProc */) {
24256 // unusedstring1: XLNullableWideString
24257 // description: XLNullableWideString
24258 // helpTopic: XLNullableWideString
24259 // unusedstring2: XLNullableWideString
24260 //}
24261 data.l = end;
24262 var out = ({Name:name, Ptg:formula});
24263 if(itab < 0xFFFFFFF) out.Sheet = itab;
24264 if(comment) out.Comment = comment;
24265 return out;
24266}
24267
24268/* [MS-XLSB] 2.1.7.61 Workbook */
24269function parse_wb_bin(data, opts) {
24270 var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" };
24271 var state = [];
24272 var pass = false;
24273
24274 if(!opts) opts = {};
24275 opts.biff = 12;
24276
24277 var Names = [];
24278 var supbooks = ([[]]);
24279 supbooks.SheetNames = [];
24280 supbooks.XTI = [];
24281
24282 recordhopper(data, function hopper_wb(val, R_n, RT) {
24283 switch(RT) {
24284 case 0x009C: /* 'BrtBundleSh' */
24285 supbooks.SheetNames.push(val.name);
24286 wb.Sheets.push(val); break;
24287
24288 case 0x0099: /* 'BrtWbProp' */
24289 wb.WBProps = val; break;
24290
24291 case 0x0027: /* 'BrtName' */
24292 if(val.Sheet != null) opts.SID = val.Sheet;
24293 val.Ref = stringify_formula(val.Ptg, null, null, supbooks, opts);
24294 delete opts.SID;
24295 delete val.Ptg;
24296 Names.push(val);
24297 break;
24298 case 0x040C: /* 'BrtNameExt' */ break;
24299
24300 case 0x0165: /* 'BrtSupSelf' */
24301 case 0x0166: /* 'BrtSupSame' */
24302 case 0x0163: /* 'BrtSupBookSrc' */
24303 case 0x029B: /* 'BrtSupAddin' */
24304 if(!supbooks[0].length) supbooks[0] = [RT, val];
24305 else supbooks.push([RT, val]);
24306 supbooks[supbooks.length - 1].XTI = [];
24307 break;
24308 case 0x016A: /* 'BrtExternSheet' */
24309 if(supbooks.length === 0) { supbooks[0] = []; supbooks[0].XTI = []; }
24310 supbooks[supbooks.length - 1].XTI = supbooks[supbooks.length - 1].XTI.concat(val);
24311 supbooks.XTI = supbooks.XTI.concat(val);
24312 break;
24313 case 0x0169: /* 'BrtPlaceholderName' */
24314 break;
24315
24316 /* case 'BrtModelTimeGroupingCalcCol' */
24317 case 0x0C00: /* 'BrtUid' */
24318 case 0x0C01: /* 'BrtRevisionPtr' */
24319 case 0x0817: /* 'BrtAbsPath15' */
24320 case 0x0216: /* 'BrtBookProtection' */
24321 case 0x02A5: /* 'BrtBookProtectionIso' */
24322 case 0x009E: /* 'BrtBookView' */
24323 case 0x009D: /* 'BrtCalcProp' */
24324 case 0x0262: /* 'BrtCrashRecErr' */
24325 case 0x0802: /* 'BrtDecoupledPivotCacheID' */
24326 case 0x009B: /* 'BrtFileRecover' */
24327 case 0x0224: /* 'BrtFileSharing' */
24328 case 0x02A4: /* 'BrtFileSharingIso' */
24329 case 0x0080: /* 'BrtFileVersion' */
24330 case 0x0299: /* 'BrtFnGroup' */
24331 case 0x0850: /* 'BrtModelRelationship' */
24332 case 0x084D: /* 'BrtModelTable' */
24333 case 0x0225: /* 'BrtOleSize' */
24334 case 0x0805: /* 'BrtPivotTableRef' */
24335 case 0x0254: /* 'BrtSmartTagType' */
24336 case 0x081C: /* 'BrtTableSlicerCacheID' */
24337 case 0x081B: /* 'BrtTableSlicerCacheIDs' */
24338 case 0x0822: /* 'BrtTimelineCachePivotCacheID' */
24339 case 0x018D: /* 'BrtUserBookView' */
24340 case 0x009A: /* 'BrtWbFactoid' */
24341 case 0x045D: /* 'BrtWbProp14' */
24342 case 0x0229: /* 'BrtWebOpt' */
24343 case 0x082B: /* 'BrtWorkBookPr15' */
24344 break;
24345
24346 case 0x0023: /* 'BrtFRTBegin' */
24347 state.push(R_n); pass = true; break;
24348 case 0x0024: /* 'BrtFRTEnd' */
24349 state.pop(); pass = false; break;
24350 case 0x0025: /* 'BrtACBegin' */
24351 state.push(R_n); pass = true; break;
24352 case 0x0026: /* 'BrtACEnd' */
24353 state.pop(); pass = false; break;
24354
24355 case 0x0010: /* 'BrtFRTArchID$' */ break;
24356
24357 default:
24358 if((R_n||"").indexOf("Begin") > 0){/* empty */}
24359 else if((R_n||"").indexOf("End") > 0){/* empty */}
24360 else if(!pass || (opts.WTF && state[state.length-1] != "BrtACBegin" && state[state.length-1] != "BrtFRTBegin")) throw new Error("Unexpected record " + RT + " " + R_n);
24361 }
24362 }, opts);
24363
24364 parse_wb_defaults(wb);
24365
24366 // $FlowIgnore
24367 wb.Names = Names;
24368
24369 (wb).supbooks = supbooks;
24370 return wb;
24371}
24372
24373function write_BUNDLESHS(ba, wb) {
24374 write_record(ba, "BrtBeginBundleShs");
24375 for(var idx = 0; idx != wb.SheetNames.length; ++idx) {
24376 var viz = wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx] && wb.Workbook.Sheets[idx].Hidden || 0;
24377 var d = { Hidden: viz, iTabID: idx+1, strRelID: 'rId' + (idx+1), name: wb.SheetNames[idx] };
24378 write_record(ba, "BrtBundleSh", write_BrtBundleSh(d));
24379 }
24380 write_record(ba, "BrtEndBundleShs");
24381}
24382
24383/* [MS-XLSB] 2.4.649 BrtFileVersion */
24384function write_BrtFileVersion(data, o) {
24385 if(!o) o = new_buf(127);
24386 for(var i = 0; i != 4; ++i) o.write_shift(4, 0);
24387 write_XLWideString("SheetJS", o);
24388 write_XLWideString(XLSX.version, o);
24389 write_XLWideString(XLSX.version, o);
24390 write_XLWideString("7262", o);
24391 o.length = o.l;
24392 return o.length > o.l ? o.slice(0, o.l) : o;
24393}
24394
24395/* [MS-XLSB] 2.4.301 BrtBookView */
24396function write_BrtBookView(idx, o) {
24397 if(!o) o = new_buf(29);
24398 o.write_shift(-4, 0);
24399 o.write_shift(-4, 460);
24400 o.write_shift(4, 28800);
24401 o.write_shift(4, 17600);
24402 o.write_shift(4, 500);
24403 o.write_shift(4, idx);
24404 o.write_shift(4, idx);
24405 var flags = 0x78;
24406 o.write_shift(1, flags);
24407 return o.length > o.l ? o.slice(0, o.l) : o;
24408}
24409
24410function write_BOOKVIEWS(ba, wb) {
24411 /* required if hidden tab appears before visible tab */
24412 if(!wb.Workbook || !wb.Workbook.Sheets) return;
24413 var sheets = wb.Workbook.Sheets;
24414 var i = 0, vistab = -1, hidden = -1;
24415 for(; i < sheets.length; ++i) {
24416 if(!sheets[i] || !sheets[i].Hidden && vistab == -1) vistab = i;
24417 else if(sheets[i].Hidden == 1 && hidden == -1) hidden = i;
24418 }
24419 if(hidden > vistab) return;
24420 write_record(ba, "BrtBeginBookViews");
24421 write_record(ba, "BrtBookView", write_BrtBookView(vistab));
24422 /* 1*(BrtBookView *FRT) */
24423 write_record(ba, "BrtEndBookViews");
24424}
24425
24426/* [MS-XLSB] 2.4.305 BrtCalcProp */
24427/*function write_BrtCalcProp(data, o) {
24428 if(!o) o = new_buf(26);
24429 o.write_shift(4,0); // force recalc
24430 o.write_shift(4,1);
24431 o.write_shift(4,0);
24432 write_Xnum(0, o);
24433 o.write_shift(-4, 1023);
24434 o.write_shift(1, 0x33);
24435 o.write_shift(1, 0x00);
24436 return o;
24437}*/
24438
24439/* [MS-XLSB] 2.4.646 BrtFileRecover */
24440/*function write_BrtFileRecover(data, o) {
24441 if(!o) o = new_buf(1);
24442 o.write_shift(1,0);
24443 return o;
24444}*/
24445
24446/* [MS-XLSB] 2.1.7.61 Workbook */
24447function write_wb_bin(wb, opts) {
24448 var ba = buf_array();
24449 write_record(ba, "BrtBeginBook");
24450 write_record(ba, "BrtFileVersion", write_BrtFileVersion());
24451 /* [[BrtFileSharingIso] BrtFileSharing] */
24452 write_record(ba, "BrtWbProp", write_BrtWbProp(wb.Workbook && wb.Workbook.WBProps || null));
24453 /* [ACABSPATH] */
24454 /* [[BrtBookProtectionIso] BrtBookProtection] */
24455 write_BOOKVIEWS(ba, wb, opts);
24456 write_BUNDLESHS(ba, wb, opts);
24457 /* [FNGROUP] */
24458 /* [EXTERNALS] */
24459 /* *BrtName */
24460 /* write_record(ba, "BrtCalcProp", write_BrtCalcProp()); */
24461 /* [BrtOleSize] */
24462 /* *(BrtUserBookView *FRT) */
24463 /* [PIVOTCACHEIDS] */
24464 /* [BrtWbFactoid] */
24465 /* [SMARTTAGTYPES] */
24466 /* [BrtWebOpt] */
24467 /* write_record(ba, "BrtFileRecover", write_BrtFileRecover()); */
24468 /* [WEBPUBITEMS] */
24469 /* [CRERRS] */
24470 /* FRTWORKBOOK */
24471 write_record(ba, "BrtEndBook");
24472
24473 return ba.end();
24474}
24475function parse_wb(data, name, opts) {
24476 if(name.slice(-4)===".bin") return parse_wb_bin((data), opts);
24477 return parse_wb_xml((data), opts);
24478}
24479
24480function parse_ws(data, name, idx, opts, rels, wb, themes, styles) {
24481 if(name.slice(-4)===".bin") return parse_ws_bin((data), opts, idx, rels, wb, themes, styles);
24482 return parse_ws_xml((data), opts, idx, rels, wb, themes, styles);
24483}
24484
24485function parse_cs(data, name, idx, opts, rels, wb, themes, styles) {
24486 if(name.slice(-4)===".bin") return parse_cs_bin((data), opts, idx, rels, wb, themes, styles);
24487 return parse_cs_xml((data), opts, idx, rels, wb, themes, styles);
24488}
24489
24490function parse_ms(data, name, idx, opts, rels, wb, themes, styles) {
24491 if(name.slice(-4)===".bin") return parse_ms_bin((data), opts, idx, rels, wb, themes, styles);
24492 return parse_ms_xml((data), opts, idx, rels, wb, themes, styles);
24493}
24494
24495function parse_ds(data, name, idx, opts, rels, wb, themes, styles) {
24496 if(name.slice(-4)===".bin") return parse_ds_bin((data), opts, idx, rels, wb, themes, styles);
24497 return parse_ds_xml((data), opts, idx, rels, wb, themes, styles);
24498}
24499
24500function parse_sty(data, name, themes, opts) {
24501 if(name.slice(-4)===".bin") return parse_sty_bin((data), themes, opts);
24502 return parse_sty_xml((data), themes, opts);
24503}
24504
24505function parse_theme(data, name, opts) {
24506 return parse_theme_xml(data, opts);
24507}
24508
24509function parse_sst(data, name, opts) {
24510 if(name.slice(-4)===".bin") return parse_sst_bin((data), opts);
24511 return parse_sst_xml((data), opts);
24512}
24513
24514function parse_cmnt(data, name, opts) {
24515 if(name.slice(-4)===".bin") return parse_comments_bin((data), opts);
24516 return parse_comments_xml((data), opts);
24517}
24518
24519function parse_cc(data, name, opts) {
24520 if(name.slice(-4)===".bin") return parse_cc_bin((data), name, opts);
24521 return parse_cc_xml((data), name, opts);
24522}
24523
24524function parse_xlink(data, rel, name, opts) {
24525 if(name.slice(-4)===".bin") return parse_xlink_bin((data), rel, name, opts);
24526 return parse_xlink_xml((data), rel, name, opts);
24527}
24528
24529function write_wb(wb, name, opts) {
24530 return (name.slice(-4)===".bin" ? write_wb_bin : write_wb_xml)(wb, opts);
24531}
24532
24533function write_ws(data, name, opts, wb, rels) {
24534 return (name.slice(-4)===".bin" ? write_ws_bin : write_ws_xml)(data, opts, wb, rels);
24535}
24536
24537// eslint-disable-next-line no-unused-vars
24538function write_cs(data, name, opts, wb, rels) {
24539 return (name.slice(-4)===".bin" ? write_cs_bin : write_cs_xml)(data, opts, wb, rels);
24540}
24541
24542function write_sty(data, name, opts) {
24543 return (name.slice(-4)===".bin" ? write_sty_bin : write_sty_xml)(data, opts);
24544}
24545
24546function write_sst(data, name, opts) {
24547 return (name.slice(-4)===".bin" ? write_sst_bin : write_sst_xml)(data, opts);
24548}
24549
24550function write_cmnt(data, name, opts) {
24551 return (name.slice(-4)===".bin" ? write_comments_bin : write_comments_xml)(data, opts);
24552}
24553/*
24554function write_cc(data, name:string, opts) {
24555 return (name.slice(-4)===".bin" ? write_cc_bin : write_cc_xml)(data, opts);
24556}
24557*/
24558var attregexg2=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g;
24559var attregex2=/([\w:]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/;
24560function xlml_parsexmltag(tag, skip_root) {
24561 var words = tag.split(/\s+/);
24562 var z = ([]); if(!skip_root) z[0] = words[0];
24563 if(words.length === 1) return z;
24564 var m = tag.match(attregexg2), y, j, w, i;
24565 if(m) for(i = 0; i != m.length; ++i) {
24566 y = m[i].match(attregex2);
24567if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].slice(1,y[2].length-1);
24568 else {
24569 if(y[1].slice(0,6) === "xmlns:") w = "xmlns"+y[1].slice(6);
24570 else w = y[1].slice(j+1);
24571 z[w] = y[2].slice(1,y[2].length-1);
24572 }
24573 }
24574 return z;
24575}
24576function xlml_parsexmltagobj(tag) {
24577 var words = tag.split(/\s+/);
24578 var z = {};
24579 if(words.length === 1) return z;
24580 var m = tag.match(attregexg2), y, j, w, i;
24581 if(m) for(i = 0; i != m.length; ++i) {
24582 y = m[i].match(attregex2);
24583if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].slice(1,y[2].length-1);
24584 else {
24585 if(y[1].slice(0,6) === "xmlns:") w = "xmlns"+y[1].slice(6);
24586 else w = y[1].slice(j+1);
24587 z[w] = y[2].slice(1,y[2].length-1);
24588 }
24589 }
24590 return z;
24591}
24592
24593// ----
24594
24595function xlml_format(format, value) {
24596 var fmt = XLMLFormatMap[format] || unescapexml(format);
24597 if(fmt === "General") return SSF._general(value);
24598 return SSF.format(fmt, value);
24599}
24600
24601function xlml_set_custprop(Custprops, key, cp, val) {
24602 var oval = val;
24603 switch((cp[0].match(/dt:dt="([\w.]+)"/)||["",""])[1]) {
24604 case "boolean": oval = parsexmlbool(val); break;
24605 case "i2": case "int": oval = parseInt(val, 10); break;
24606 case "r4": case "float": oval = parseFloat(val); break;
24607 case "date": case "dateTime.tz": oval = parseDate(val); break;
24608 case "i8": case "string": case "fixed": case "uuid": case "bin.base64": break;
24609 default: throw new Error("bad custprop:" + cp[0]);
24610 }
24611 Custprops[unescapexml(key)] = oval;
24612}
24613
24614function safe_format_xlml(cell, nf, o) {
24615 if(cell.t === 'z') return;
24616 if(!o || o.cellText !== false) try {
24617 if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; }
24618 else if(nf === "General") {
24619 if(cell.t === 'n') {
24620 if((cell.v|0) === cell.v) cell.w = SSF._general_int(cell.v);
24621 else cell.w = SSF._general_num(cell.v);
24622 }
24623 else cell.w = SSF._general(cell.v);
24624 }
24625 else cell.w = xlml_format(nf||"General", cell.v);
24626 } catch(e) { if(o.WTF) throw e; }
24627 try {
24628 var z = XLMLFormatMap[nf]||nf||"General";
24629 if(o.cellNF) cell.z = z;
24630 if(o.cellDates && cell.t == 'n' && SSF.is_date(z)) {
24631 var _d = SSF.parse_date_code(cell.v); if(_d) { cell.t = 'd'; cell.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
24632 }
24633 } catch(e) { if(o.WTF) throw e; }
24634}
24635
24636function process_style_xlml(styles, stag, opts) {
24637 if(opts.cellStyles) {
24638 if(stag.Interior) {
24639 var I = stag.Interior;
24640 if(I.Pattern) I.patternType = XLMLPatternTypeMap[I.Pattern] || I.Pattern;
24641 }
24642 }
24643 styles[stag.ID] = stag;
24644}
24645
24646/* TODO: there must exist some form of OSP-blessed spec */
24647function parse_xlml_data(xml, ss, data, cell, base, styles, csty, row, arrayf, o) {
24648 var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
24649 var interiors = [];
24650 var i = 0;
24651 if(sid === undefined && row) sid = row.StyleID;
24652 if(sid === undefined && csty) sid = csty.StyleID;
24653 while(styles[sid] !== undefined) {
24654 if(styles[sid].nf) nf = styles[sid].nf;
24655 if(styles[sid].Interior) interiors.push(styles[sid].Interior);
24656 if(!styles[sid].Parent) break;
24657 sid = styles[sid].Parent;
24658 }
24659 switch(data.Type) {
24660 case 'Boolean':
24661 cell.t = 'b';
24662 cell.v = parsexmlbool(xml);
24663 break;
24664 case 'String':
24665 cell.t = 's'; cell.r = xlml_fixstr(unescapexml(xml));
24666 cell.v = xml.indexOf("<") > -1 ? unescapexml(ss||xml) : cell.r;
24667 break;
24668 case 'DateTime':
24669 if(xml.slice(-1) != "Z") xml += "Z";
24670 cell.v = (parseDate(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
24671 if(cell.v !== cell.v) cell.v = unescapexml(xml);
24672 else if(cell.v<60) cell.v = cell.v -1;
24673 if(!nf || nf == "General") nf = "yyyy-mm-dd";
24674 /* falls through */
24675 case 'Number':
24676 if(cell.v === undefined) cell.v=+xml;
24677 if(!cell.t) cell.t = 'n';
24678 break;
24679 case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; if(o.cellText !== false) cell.w = xml; break;
24680 default: cell.t = 's'; cell.v = xlml_fixstr(ss||xml); break;
24681 }
24682 safe_format_xlml(cell, nf, o);
24683 if(o.cellFormula !== false) {
24684 if(cell.Formula) {
24685 var fstr = unescapexml(cell.Formula);
24686 /* strictly speaking, the leading = is required but some writers omit */
24687 if(fstr.charCodeAt(0) == 61 /* = */) fstr = fstr.slice(1);
24688 cell.f = rc_to_a1(fstr, base);
24689 delete cell.Formula;
24690 if(cell.ArrayRange == "RC") cell.F = rc_to_a1("RC:RC", base);
24691 else if(cell.ArrayRange) {
24692 cell.F = rc_to_a1(cell.ArrayRange, base);
24693 arrayf.push([safe_decode_range(cell.F), cell.F]);
24694 }
24695 } else {
24696 for(i = 0; i < arrayf.length; ++i)
24697 if(base.r >= arrayf[i][0].s.r && base.r <= arrayf[i][0].e.r)
24698 if(base.c >= arrayf[i][0].s.c && base.c <= arrayf[i][0].e.c)
24699 cell.F = arrayf[i][1];
24700 }
24701 }
24702 if(o.cellStyles) {
24703 interiors.forEach(function(x) {
24704 if(!S.patternType && x.patternType) S.patternType = x.patternType;
24705 });
24706 cell.s = S;
24707 }
24708 if(cell.StyleID !== undefined) cell.ixfe = cell.StyleID;
24709}
24710
24711function xlml_clean_comment(comment) {
24712 comment.t = comment.v || "";
24713 comment.t = comment.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n");
24714 comment.v = comment.w = comment.ixfe = undefined;
24715}
24716
24717function xlml_normalize(d) {
24718 if(has_buf && Buffer.isBuffer(d)) return d.toString('utf8');
24719 if(typeof d === 'string') return d;
24720 /* duktape */
24721 if(typeof Uint8Array !== 'undefined' && d instanceof Uint8Array) return utf8read(a2s(ab2a(d)));
24722 throw new Error("Bad input format: expected Buffer or string");
24723}
24724
24725/* TODO: Everything */
24726/* UOS uses CJK in tags */
24727var xlmlregex = /<(\/?)([^\s?>!\/:]*:|)([^\s?>:\/]+)[^>]*>/mg;
24728//var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg;
24729function parse_xlml_xml(d, _opts) {
24730 var opts = _opts || {};
24731 make_ssf(SSF);
24732 var str = debom(xlml_normalize(d));
24733 if(opts.type == 'binary' || opts.type == 'array' || opts.type == 'base64') {
24734 if(typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str));
24735 else str = utf8read(str);
24736 }
24737 var opening = str.slice(0, 1024).toLowerCase(), ishtml = false;
24738 if(opening.indexOf("<?xml") == -1) ["html", "table", "head", "meta", "script", "style", "div"].forEach(function(tag) { if(opening.indexOf("<" + tag) >= 0) ishtml = true; });
24739 if(ishtml) return HTML_.to_workbook(str, opts);
24740 var Rn;
24741 var state = [], tmp;
24742 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
24743 var sheets = {}, sheetnames = [], cursheet = (opts.dense ? [] : {}), sheetname = "";
24744 var table = {}, cell = ({}), row = {};// eslint-disable-line no-unused-vars
24745 var dtag = xlml_parsexmltag('<Data ss:Type="String">'), didx = 0;
24746 var c = 0, r = 0;
24747 var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
24748 var styles = {}, stag = {};
24749 var ss = "", fidx = 0;
24750 var merges = [];
24751 var Props = {}, Custprops = {}, pidx = 0, cp = [];
24752 var comments = [], comment = ({});
24753 var cstys = [], csty, seencol = false;
24754 var arrayf = [];
24755 var rowinfo = [], rowobj = {}, cc = 0, rr = 0;
24756 var Workbook = ({ Sheets:[], WBProps:{date1904:false} }), wsprops = {};
24757 xlmlregex.lastIndex = 0;
24758 str = str.replace(/<!--([\s\S]*?)-->/mg,"");
24759 while((Rn = xlmlregex.exec(str))) switch(Rn[3]) {
24760 case 'Data':
24761 if(state[state.length-1][1]) break;
24762 if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]=="Comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts);
24763 else { ss = ""; dtag = xlml_parsexmltag(Rn[0]); didx = Rn.index + Rn[0].length; }
24764 break;
24765 case 'Cell':
24766 if(Rn[1]==='/'){
24767 if(comments.length > 0) cell.c = comments;
24768 if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== undefined) {
24769 if(opts.dense) {
24770 if(!cursheet[r]) cursheet[r] = [];
24771 cursheet[r][c] = cell;
24772 } else cursheet[encode_col(c) + encode_row(r)] = cell;
24773 }
24774 if(cell.HRef) {
24775 cell.l = ({Target:cell.HRef});
24776 if(cell.HRefScreenTip) cell.l.Tooltip = cell.HRefScreenTip;
24777 delete cell.HRef; delete cell.HRefScreenTip;
24778 }
24779 if(cell.MergeAcross || cell.MergeDown) {
24780 cc = c + (parseInt(cell.MergeAcross,10)|0);
24781 rr = r + (parseInt(cell.MergeDown,10)|0);
24782 merges.push({s:{c:c,r:r},e:{c:cc,r:rr}});
24783 }
24784 if(!opts.sheetStubs) { if(cell.MergeAcross) c = cc + 1; else ++c; }
24785 else if(cell.MergeAcross || cell.MergeDown) {
24786for(var cma = c; cma <= cc; ++cma) {
24787 for(var cmd = r; cmd <= rr; ++cmd) {
24788 if(cma > c || cmd > r) {
24789 if(opts.dense) {
24790 if(!cursheet[cmd]) cursheet[cmd] = [];
24791 cursheet[cmd][cma] = {t:'z'};
24792 } else cursheet[encode_col(cma) + encode_row(cmd)] = {t:'z'};
24793 }
24794 }
24795 }
24796 c = cc + 1;
24797 }
24798 else ++c;
24799 } else {
24800 cell = xlml_parsexmltagobj(Rn[0]);
24801 if(cell.Index) c = +cell.Index - 1;
24802 if(c < refguess.s.c) refguess.s.c = c;
24803 if(c > refguess.e.c) refguess.e.c = c;
24804 if(Rn[0].slice(-2) === "/>") ++c;
24805 comments = [];
24806 }
24807 break;
24808 case 'Row':
24809 if(Rn[1]==='/' || Rn[0].slice(-2) === "/>") {
24810 if(r < refguess.s.r) refguess.s.r = r;
24811 if(r > refguess.e.r) refguess.e.r = r;
24812 if(Rn[0].slice(-2) === "/>") {
24813 row = xlml_parsexmltag(Rn[0]);
24814 if(row.Index) r = +row.Index - 1;
24815 }
24816 c = 0; ++r;
24817 } else {
24818 row = xlml_parsexmltag(Rn[0]);
24819 if(row.Index) r = +row.Index - 1;
24820 rowobj = {};
24821 if(row.AutoFitHeight == "0" || row.Height) {
24822 rowobj.hpx = parseInt(row.Height, 10); rowobj.hpt = px2pt(rowobj.hpx);
24823 rowinfo[r] = rowobj;
24824 }
24825 if(row.Hidden == "1") { rowobj.hidden = true; rowinfo[r] = rowobj; }
24826 }
24827 break;
24828 case 'Worksheet': /* TODO: read range from FullRows/FullColumns */
24829 if(Rn[1]==='/'){
24830 if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
24831 sheetnames.push(sheetname);
24832 if(refguess.s.r <= refguess.e.r && refguess.s.c <= refguess.e.c) {
24833 cursheet["!ref"] = encode_range(refguess);
24834 if(opts.sheetRows && opts.sheetRows <= refguess.e.r) {
24835 cursheet["!fullref"] = cursheet["!ref"];
24836 refguess.e.r = opts.sheetRows - 1;
24837 cursheet["!ref"] = encode_range(refguess);
24838 }
24839 }
24840 if(merges.length) cursheet["!merges"] = merges;
24841 if(cstys.length > 0) cursheet["!cols"] = cstys;
24842 if(rowinfo.length > 0) cursheet["!rows"] = rowinfo;
24843 sheets[sheetname] = cursheet;
24844 } else {
24845 refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} };
24846 r = c = 0;
24847 state.push([Rn[3], false]);
24848 tmp = xlml_parsexmltag(Rn[0]);
24849 sheetname = unescapexml(tmp.Name);
24850 cursheet = (opts.dense ? [] : {});
24851 merges = [];
24852 arrayf = [];
24853 rowinfo = [];
24854 wsprops = {name:sheetname, Hidden:0};
24855 Workbook.Sheets.push(wsprops);
24856 }
24857 break;
24858 case 'Table':
24859 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
24860 else if(Rn[0].slice(-2) == "/>") break;
24861 else {
24862 table = xlml_parsexmltag(Rn[0]);
24863 state.push([Rn[3], false]);
24864 cstys = []; seencol = false;
24865 }
24866 break;
24867
24868 case 'Style':
24869 if(Rn[1]==='/') process_style_xlml(styles, stag, opts);
24870 else stag = xlml_parsexmltag(Rn[0]);
24871 break;
24872
24873 case 'NumberFormat':
24874 stag.nf = unescapexml(xlml_parsexmltag(Rn[0]).Format || "General");
24875 if(XLMLFormatMap[stag.nf]) stag.nf = XLMLFormatMap[stag.nf];
24876 for(var ssfidx = 0; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == stag.nf) break;
24877 if(ssfidx == 0x188) for(ssfidx = 0x39; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == null) { SSF.load(stag.nf, ssfidx); break; }
24878 break;
24879
24880 case 'Column':
24881 if(state[state.length-1][0] !== 'Table') break;
24882 csty = xlml_parsexmltag(Rn[0]);
24883 if(csty.Hidden) { csty.hidden = true; delete csty.Hidden; }
24884 if(csty.Width) csty.wpx = parseInt(csty.Width, 10);
24885 if(!seencol && csty.wpx > 10) {
24886 seencol = true; MDW = DEF_MDW; //find_mdw_wpx(csty.wpx);
24887 for(var _col = 0; _col < cstys.length; ++_col) if(cstys[_col]) process_col(cstys[_col]);
24888 }
24889 if(seencol) process_col(csty);
24890 cstys[(csty.Index-1||cstys.length)] = csty;
24891 for(var i = 0; i < +csty.Span; ++i) cstys[cstys.length] = dup(csty);
24892 break;
24893
24894 case 'NamedRange':
24895 if(!Workbook.Names) Workbook.Names = [];
24896 var _NamedRange = parsexmltag(Rn[0]);
24897 var _DefinedName = ({
24898 Name: _NamedRange.Name,
24899 Ref: rc_to_a1(_NamedRange.RefersTo.slice(1), {r:0, c:0})
24900 });
24901 if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1;
24902Workbook.Names.push(_DefinedName);
24903 break;
24904
24905 case 'NamedCell': break;
24906 case 'B': break;
24907 case 'I': break;
24908 case 'U': break;
24909 case 'S': break;
24910 case 'Sub': break;
24911 case 'Sup': break;
24912 case 'Span': break;
24913 case 'Alignment':
24914 break;
24915 case 'Borders': break;
24916 case 'Border': break;
24917 case 'Font':
24918 if(Rn[0].slice(-2) === "/>") break;
24919 else if(Rn[1]==="/") ss += str.slice(fidx, Rn.index);
24920 else fidx = Rn.index + Rn[0].length;
24921 break;
24922 case 'Interior':
24923 if(!opts.cellStyles) break;
24924 stag.Interior = xlml_parsexmltag(Rn[0]);
24925 break;
24926 case 'Protection': break;
24927
24928 case 'Author':
24929 case 'Title':
24930 case 'Description':
24931 case 'Created':
24932 case 'Keywords':
24933 case 'Subject':
24934 case 'Category':
24935 case 'Company':
24936 case 'LastAuthor':
24937 case 'LastSaved':
24938 case 'LastPrinted':
24939 case 'Version':
24940 case 'Revision':
24941 case 'TotalTime':
24942 case 'HyperlinkBase':
24943 case 'Manager':
24944 case 'ContentStatus':
24945 case 'Identifier':
24946 case 'Language':
24947 case 'AppName':
24948 if(Rn[0].slice(-2) === "/>") break;
24949 else if(Rn[1]==="/") xlml_set_prop(Props, Rn[3], str.slice(pidx, Rn.index));
24950 else pidx = Rn.index + Rn[0].length;
24951 break;
24952 case 'Paragraphs': break;
24953
24954 case 'Styles':
24955 case 'Workbook':
24956 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
24957 else state.push([Rn[3], false]);
24958 break;
24959
24960 case 'Comment':
24961 if(Rn[1]==='/'){
24962 if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
24963 xlml_clean_comment(comment);
24964 comments.push(comment);
24965 } else {
24966 state.push([Rn[3], false]);
24967 tmp = xlml_parsexmltag(Rn[0]);
24968 comment = ({a:tmp.Author});
24969 }
24970 break;
24971
24972 case 'AutoFilter':
24973 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
24974 else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
24975 var AutoFilter = xlml_parsexmltag(Rn[0]);
24976 cursheet['!autofilter'] = { ref:rc_to_a1(AutoFilter.Range).replace(/\$/g,"") };
24977 state.push([Rn[3], true]);
24978 }
24979 break;
24980
24981 case 'Name': break;
24982
24983 case 'DataValidation':
24984 if(Rn[1]==='/'){
24985 if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));
24986 } else {
24987 if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
24988 }
24989 break;
24990
24991 case 'ComponentOptions':
24992 case 'DocumentProperties':
24993 case 'CustomDocumentProperties':
24994 case 'OfficeDocumentSettings':
24995 case 'PivotTable':
24996 case 'PivotCache':
24997 case 'Names':
24998 case 'MapInfo':
24999 case 'PageBreaks':
25000 case 'QueryTable':
25001 case 'Sorting':
25002 case 'Schema':
25003 case 'data':
25004 case 'ConditionalFormatting':
25005 case 'SmartTagType':
25006 case 'SmartTags':
25007 case 'ExcelWorkbook':
25008 case 'WorkbookOptions':
25009 case 'WorksheetOptions':
25010 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));}
25011 else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
25012 break;
25013
25014 default:
25015 /* FODS file root is <office:document> */
25016 if(state.length == 0 && Rn[3] == "document") return parse_fods(str, opts);
25017 /* UOS file root is <uof:UOF> */
25018 if(state.length == 0 && Rn[3] == "UOF") return parse_fods(str, opts);
25019
25020 var seen = true;
25021 switch(state[state.length-1][0]) {
25022 /* OfficeDocumentSettings */
25023 case 'OfficeDocumentSettings': switch(Rn[3]) {
25024 case 'AllowPNG': break;
25025 case 'RemovePersonalInformation': break;
25026 case 'DownloadComponents': break;
25027 case 'LocationOfComponents': break;
25028 case 'Colors': break;
25029 case 'Color': break;
25030 case 'Index': break;
25031 case 'RGB': break;
25032 case 'PixelsPerInch': break; // TODO: set PPI
25033 case 'TargetScreenSize': break;
25034 case 'ReadOnlyRecommended': break;
25035 default: seen = false;
25036 } break;
25037
25038 /* ComponentOptions */
25039 case 'ComponentOptions': switch(Rn[3]) {
25040 case 'Toolbar': break;
25041 case 'HideOfficeLogo': break;
25042 case 'SpreadsheetAutoFit': break;
25043 case 'Label': break;
25044 case 'Caption': break;
25045 case 'MaxHeight': break;
25046 case 'MaxWidth': break;
25047 case 'NextSheetNumber': break;
25048 default: seen = false;
25049 } break;
25050
25051 /* ExcelWorkbook */
25052 case 'ExcelWorkbook': switch(Rn[3]) {
25053 case 'Date1904':
25054Workbook.WBProps.date1904 = true;
25055 break;
25056 case 'WindowHeight': break;
25057 case 'WindowWidth': break;
25058 case 'WindowTopX': break;
25059 case 'WindowTopY': break;
25060 case 'TabRatio': break;
25061 case 'ProtectStructure': break;
25062 case 'ProtectWindow': break;
25063 case 'ProtectWindows': break;
25064 case 'ActiveSheet': break;
25065 case 'DisplayInkNotes': break;
25066 case 'FirstVisibleSheet': break;
25067 case 'SupBook': break;
25068 case 'SheetName': break;
25069 case 'SheetIndex': break;
25070 case 'SheetIndexFirst': break;
25071 case 'SheetIndexLast': break;
25072 case 'Dll': break;
25073 case 'AcceptLabelsInFormulas': break;
25074 case 'DoNotSaveLinkValues': break;
25075 case 'Iteration': break;
25076 case 'MaxIterations': break;
25077 case 'MaxChange': break;
25078 case 'Path': break;
25079 case 'Xct': break;
25080 case 'Count': break;
25081 case 'SelectedSheets': break;
25082 case 'Calculation': break;
25083 case 'Uncalced': break;
25084 case 'StartupPrompt': break;
25085 case 'Crn': break;
25086 case 'ExternName': break;
25087 case 'Formula': break;
25088 case 'ColFirst': break;
25089 case 'ColLast': break;
25090 case 'WantAdvise': break;
25091 case 'Boolean': break;
25092 case 'Error': break;
25093 case 'Text': break;
25094 case 'OLE': break;
25095 case 'NoAutoRecover': break;
25096 case 'PublishObjects': break;
25097 case 'DoNotCalculateBeforeSave': break;
25098 case 'Number': break;
25099 case 'RefModeR1C1': break;
25100 case 'EmbedSaveSmartTags': break;
25101 default: seen = false;
25102 } break;
25103
25104 /* WorkbookOptions */
25105 case 'WorkbookOptions': switch(Rn[3]) {
25106 case 'OWCVersion': break;
25107 case 'Height': break;
25108 case 'Width': break;
25109 default: seen = false;
25110 } break;
25111
25112 /* WorksheetOptions */
25113 case 'WorksheetOptions': switch(Rn[3]) {
25114 case 'Visible':
25115 if(Rn[0].slice(-2) === "/>"){/* empty */}
25116 else if(Rn[1]==="/") switch(str.slice(pidx, Rn.index)) {
25117 case "SheetHidden": wsprops.Hidden = 1; break;
25118 case "SheetVeryHidden": wsprops.Hidden = 2; break;
25119 }
25120 else pidx = Rn.index + Rn[0].length;
25121 break;
25122 case 'Header':
25123 if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
25124 cursheet['!margins'].header = parsexmltag(Rn[0]).Margin;
25125 break;
25126 case 'Footer':
25127 if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml');
25128 cursheet['!margins'].footer = parsexmltag(Rn[0]).Margin;
25129 break;
25130 case 'PageMargins':
25131 var pagemargins = parsexmltag(Rn[0]);
25132 if(!cursheet['!margins']) default_margins(cursheet['!margins']={},'xlml');
25133 if(pagemargins.Top) cursheet['!margins'].top = pagemargins.Top;
25134 if(pagemargins.Left) cursheet['!margins'].left = pagemargins.Left;
25135 if(pagemargins.Right) cursheet['!margins'].right = pagemargins.Right;
25136 if(pagemargins.Bottom) cursheet['!margins'].bottom = pagemargins.Bottom;
25137 break;
25138 case 'DisplayRightToLeft':
25139 if(!Workbook.Views) Workbook.Views = [];
25140 if(!Workbook.Views[0]) Workbook.Views[0] = {};
25141 Workbook.Views[0].RTL = true;
25142 break;
25143
25144 case 'FreezePanes': break;
25145 case 'FrozenNoSplit': break;
25146
25147 case 'SplitHorizontal':
25148 case 'SplitVertical':
25149 break;
25150
25151 case 'DoNotDisplayGridlines':
25152 break;
25153
25154 case 'TopRowBottomPane': break;
25155 case 'LeftColumnRightPane': break;
25156
25157 case 'Unsynced': break;
25158 case 'Print': break;
25159 case 'Panes': break;
25160 case 'Scale': break;
25161 case 'Pane': break;
25162 case 'Number': break;
25163 case 'Layout': break;
25164 case 'PageSetup': break;
25165 case 'Selected': break;
25166 case 'ProtectObjects': break;
25167 case 'EnableSelection': break;
25168 case 'ProtectScenarios': break;
25169 case 'ValidPrinterInfo': break;
25170 case 'HorizontalResolution': break;
25171 case 'VerticalResolution': break;
25172 case 'NumberofCopies': break;
25173 case 'ActiveRow': break;
25174 case 'ActiveCol': break;
25175 case 'ActivePane': break;
25176 case 'TopRowVisible': break;
25177 case 'LeftColumnVisible': break;
25178 case 'FitToPage': break;
25179 case 'RangeSelection': break;
25180 case 'PaperSizeIndex': break;
25181 case 'PageLayoutZoom': break;
25182 case 'PageBreakZoom': break;
25183 case 'FilterOn': break;
25184 case 'FitWidth': break;
25185 case 'FitHeight': break;
25186 case 'CommentsLayout': break;
25187 case 'Zoom': break;
25188 case 'LeftToRight': break;
25189 case 'Gridlines': break;
25190 case 'AllowSort': break;
25191 case 'AllowFilter': break;
25192 case 'AllowInsertRows': break;
25193 case 'AllowDeleteRows': break;
25194 case 'AllowInsertCols': break;
25195 case 'AllowDeleteCols': break;
25196 case 'AllowInsertHyperlinks': break;
25197 case 'AllowFormatCells': break;
25198 case 'AllowSizeCols': break;
25199 case 'AllowSizeRows': break;
25200 case 'NoSummaryRowsBelowDetail': break;
25201 case 'TabColorIndex': break;
25202 case 'DoNotDisplayHeadings': break;
25203 case 'ShowPageLayoutZoom': break;
25204 case 'NoSummaryColumnsRightDetail': break;
25205 case 'BlackAndWhite': break;
25206 case 'DoNotDisplayZeros': break;
25207 case 'DisplayPageBreak': break;
25208 case 'RowColHeadings': break;
25209 case 'DoNotDisplayOutline': break;
25210 case 'NoOrientation': break;
25211 case 'AllowUsePivotTables': break;
25212 case 'ZeroHeight': break;
25213 case 'ViewableRange': break;
25214 case 'Selection': break;
25215 case 'ProtectContents': break;
25216 default: seen = false;
25217 } break;
25218
25219 /* PivotTable */
25220 case 'PivotTable': case 'PivotCache': switch(Rn[3]) {
25221 case 'ImmediateItemsOnDrop': break;
25222 case 'ShowPageMultipleItemLabel': break;
25223 case 'CompactRowIndent': break;
25224 case 'Location': break;
25225 case 'PivotField': break;
25226 case 'Orientation': break;
25227 case 'LayoutForm': break;
25228 case 'LayoutSubtotalLocation': break;
25229 case 'LayoutCompactRow': break;
25230 case 'Position': break;
25231 case 'PivotItem': break;
25232 case 'DataType': break;
25233 case 'DataField': break;
25234 case 'SourceName': break;
25235 case 'ParentField': break;
25236 case 'PTLineItems': break;
25237 case 'PTLineItem': break;
25238 case 'CountOfSameItems': break;
25239 case 'Item': break;
25240 case 'ItemType': break;
25241 case 'PTSource': break;
25242 case 'CacheIndex': break;
25243 case 'ConsolidationReference': break;
25244 case 'FileName': break;
25245 case 'Reference': break;
25246 case 'NoColumnGrand': break;
25247 case 'NoRowGrand': break;
25248 case 'BlankLineAfterItems': break;
25249 case 'Hidden': break;
25250 case 'Subtotal': break;
25251 case 'BaseField': break;
25252 case 'MapChildItems': break;
25253 case 'Function': break;
25254 case 'RefreshOnFileOpen': break;
25255 case 'PrintSetTitles': break;
25256 case 'MergeLabels': break;
25257 case 'DefaultVersion': break;
25258 case 'RefreshName': break;
25259 case 'RefreshDate': break;
25260 case 'RefreshDateCopy': break;
25261 case 'VersionLastRefresh': break;
25262 case 'VersionLastUpdate': break;
25263 case 'VersionUpdateableMin': break;
25264 case 'VersionRefreshableMin': break;
25265 case 'Calculation': break;
25266 default: seen = false;
25267 } break;
25268
25269 /* PageBreaks */
25270 case 'PageBreaks': switch(Rn[3]) {
25271 case 'ColBreaks': break;
25272 case 'ColBreak': break;
25273 case 'RowBreaks': break;
25274 case 'RowBreak': break;
25275 case 'ColStart': break;
25276 case 'ColEnd': break;
25277 case 'RowEnd': break;
25278 default: seen = false;
25279 } break;
25280
25281 /* AutoFilter */
25282 case 'AutoFilter': switch(Rn[3]) {
25283 case 'AutoFilterColumn': break;
25284 case 'AutoFilterCondition': break;
25285 case 'AutoFilterAnd': break;
25286 case 'AutoFilterOr': break;
25287 default: seen = false;
25288 } break;
25289
25290 /* QueryTable */
25291 case 'QueryTable': switch(Rn[3]) {
25292 case 'Id': break;
25293 case 'AutoFormatFont': break;
25294 case 'AutoFormatPattern': break;
25295 case 'QuerySource': break;
25296 case 'QueryType': break;
25297 case 'EnableRedirections': break;
25298 case 'RefreshedInXl9': break;
25299 case 'URLString': break;
25300 case 'HTMLTables': break;
25301 case 'Connection': break;
25302 case 'CommandText': break;
25303 case 'RefreshInfo': break;
25304 case 'NoTitles': break;
25305 case 'NextId': break;
25306 case 'ColumnInfo': break;
25307 case 'OverwriteCells': break;
25308 case 'DoNotPromptForFile': break;
25309 case 'TextWizardSettings': break;
25310 case 'Source': break;
25311 case 'Number': break;
25312 case 'Decimal': break;
25313 case 'ThousandSeparator': break;
25314 case 'TrailingMinusNumbers': break;
25315 case 'FormatSettings': break;
25316 case 'FieldType': break;
25317 case 'Delimiters': break;
25318 case 'Tab': break;
25319 case 'Comma': break;
25320 case 'AutoFormatName': break;
25321 case 'VersionLastEdit': break;
25322 case 'VersionLastRefresh': break;
25323 default: seen = false;
25324 } break;
25325
25326 case 'DataValidation':
25327 switch(Rn[3]) {
25328 case 'Range': break;
25329
25330 case 'Type': break;
25331 case 'Min': break;
25332 case 'Max': break;
25333 case 'Sort': break;
25334 case 'Descending': break;
25335 case 'Order': break;
25336 case 'CaseSensitive': break;
25337 case 'Value': break;
25338 case 'ErrorStyle': break;
25339 case 'ErrorMessage': break;
25340 case 'ErrorTitle': break;
25341 case 'InputMessage': break;
25342 case 'InputTitle': break;
25343 case 'ComboHide': break;
25344 case 'InputHide': break;
25345 case 'Condition': break;
25346 case 'Qualifier': break;
25347 case 'UseBlank': break;
25348 case 'Value1': break;
25349 case 'Value2': break;
25350 case 'Format': break;
25351
25352 case 'CellRangeList': break;
25353 default: seen = false;
25354 } break;
25355
25356 case 'Sorting':
25357 case 'ConditionalFormatting':
25358 switch(Rn[3]) {
25359 case 'Range': break;
25360 case 'Type': break;
25361 case 'Min': break;
25362 case 'Max': break;
25363 case 'Sort': break;
25364 case 'Descending': break;
25365 case 'Order': break;
25366 case 'CaseSensitive': break;
25367 case 'Value': break;
25368 case 'ErrorStyle': break;
25369 case 'ErrorMessage': break;
25370 case 'ErrorTitle': break;
25371 case 'CellRangeList': break;
25372 case 'InputMessage': break;
25373 case 'InputTitle': break;
25374 case 'ComboHide': break;
25375 case 'InputHide': break;
25376 case 'Condition': break;
25377 case 'Qualifier': break;
25378 case 'UseBlank': break;
25379 case 'Value1': break;
25380 case 'Value2': break;
25381 case 'Format': break;
25382 default: seen = false;
25383 } break;
25384
25385 /* MapInfo (schema) */
25386 case 'MapInfo': case 'Schema': case 'data': switch(Rn[3]) {
25387 case 'Map': break;
25388 case 'Entry': break;
25389 case 'Range': break;
25390 case 'XPath': break;
25391 case 'Field': break;
25392 case 'XSDType': break;
25393 case 'FilterOn': break;
25394 case 'Aggregate': break;
25395 case 'ElementType': break;
25396 case 'AttributeType': break;
25397 /* These are from xsd (XML Schema Definition) */
25398 case 'schema':
25399 case 'element':
25400 case 'complexType':
25401 case 'datatype':
25402 case 'all':
25403 case 'attribute':
25404 case 'extends': break;
25405
25406 case 'row': break;
25407 default: seen = false;
25408 } break;
25409
25410 /* SmartTags (can be anything) */
25411 case 'SmartTags': break;
25412
25413 default: seen = false; break;
25414 }
25415 if(seen) break;
25416 /* CustomDocumentProperties */
25417 if(Rn[3].match(/!\[CDATA/)) break;
25418 if(!state[state.length-1][1]) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|");
25419 if(state[state.length-1][0]==='CustomDocumentProperties') {
25420 if(Rn[0].slice(-2) === "/>") break;
25421 else if(Rn[1]==="/") xlml_set_custprop(Custprops, Rn[3], cp, str.slice(pidx, Rn.index));
25422 else { cp = Rn; pidx = Rn.index + Rn[0].length; }
25423 break;
25424 }
25425 if(opts.WTF) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|");
25426 }
25427 var out = ({});
25428 if(!opts.bookSheets && !opts.bookProps) out.Sheets = sheets;
25429 out.SheetNames = sheetnames;
25430 out.Workbook = Workbook;
25431 out.SSF = SSF.get_table();
25432 out.Props = Props;
25433 out.Custprops = Custprops;
25434 return out;
25435}
25436
25437function parse_xlml(data, opts) {
25438 fix_read_opts(opts=opts||{});
25439 switch(opts.type||"base64") {
25440 case "base64": return parse_xlml_xml(Base64.decode(data), opts);
25441 case "binary": case "buffer": case "file": return parse_xlml_xml(data, opts);
25442 case "array": return parse_xlml_xml(a2s(data), opts);
25443 }
25444}
25445
25446/* TODO */
25447function write_props_xlml(wb, opts) {
25448 var o = [];
25449 /* DocumentProperties */
25450 if(wb.Props) o.push(xlml_write_docprops(wb.Props, opts));
25451 /* CustomDocumentProperties */
25452 if(wb.Custprops) o.push(xlml_write_custprops(wb.Props, wb.Custprops, opts));
25453 return o.join("");
25454}
25455/* TODO */
25456function write_wb_xlml() {
25457 /* OfficeDocumentSettings */
25458 /* ExcelWorkbook */
25459 return "";
25460}
25461/* TODO */
25462function write_sty_xlml(wb, opts) {
25463 /* Styles */
25464 var styles = ['<Style ss:ID="Default" ss:Name="Normal"><NumberFormat/></Style>'];
25465 opts.cellXfs.forEach(function(xf, id) {
25466 var payload = [];
25467 payload.push(writextag('NumberFormat', null, {"ss:Format": escapexml(SSF._table[xf.numFmtId])}));
25468 styles.push(writextag('Style', payload.join(""), {"ss:ID": "s" + (21+id)}));
25469 });
25470 return writextag("Styles", styles.join(""));
25471}
25472function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); }
25473function write_names_xlml(wb) {
25474 if(!((wb||{}).Workbook||{}).Names) return "";
25475var names = wb.Workbook.Names;
25476 var out = [];
25477 for(var i = 0; i < names.length; ++i) {
25478 var n = names[i];
25479 if(n.Sheet != null) continue;
25480 if(n.Name.match(/^_xlfn\./)) continue;
25481 out.push(write_name_xlml(n));
25482 }
25483 return writextag("Names", out.join(""));
25484}
25485function write_ws_xlml_names(ws, opts, idx, wb) {
25486 if(!ws) return "";
25487 if(!((wb||{}).Workbook||{}).Names) return "";
25488var names = wb.Workbook.Names;
25489 var out = [];
25490 for(var i = 0; i < names.length; ++i) {
25491 var n = names[i];
25492 if(n.Sheet != idx) continue;
25493 /*switch(n.Name) {
25494 case "_": continue;
25495 }*/
25496 if(n.Name.match(/^_xlfn\./)) continue;
25497 out.push(write_name_xlml(n));
25498 }
25499 return out.join("");
25500}
25501/* WorksheetOptions */
25502function write_ws_xlml_wsopts(ws, opts, idx, wb) {
25503 if(!ws) return "";
25504 var o = [];
25505 /* NOTE: spec technically allows any order, but stick with implied order */
25506
25507 /* FitToPage */
25508 /* DoNotDisplayColHeaders */
25509 /* DoNotDisplayRowHeaders */
25510 /* ViewableRange */
25511 /* Selection */
25512 /* GridlineColor */
25513 /* Name */
25514 /* ExcelWorksheetType */
25515 /* IntlMacro */
25516 /* Unsynced */
25517 /* Selected */
25518 /* CodeName */
25519
25520 if(ws['!margins']) {
25521 o.push("<PageSetup>");
25522 if(ws['!margins'].header) o.push(writextag("Header", null, {'x:Margin':ws['!margins'].header}));
25523 if(ws['!margins'].footer) o.push(writextag("Footer", null, {'x:Margin':ws['!margins'].footer}));
25524 o.push(writextag("PageMargins", null, {
25525 'x:Bottom': ws['!margins'].bottom || "0.75",
25526 'x:Left': ws['!margins'].left || "0.7",
25527 'x:Right': ws['!margins'].right || "0.7",
25528 'x:Top': ws['!margins'].top || "0.75"
25529 }));
25530 o.push("</PageSetup>");
25531 }
25532
25533 /* PageSetup */
25534 /* DisplayPageBreak */
25535 /* TransitionExpressionEvaluation */
25536 /* TransitionFormulaEntry */
25537 /* Print */
25538 /* Zoom */
25539 /* PageLayoutZoom */
25540 /* PageBreakZoom */
25541 /* ShowPageBreakZoom */
25542 /* DefaultRowHeight */
25543 /* DefaultColumnWidth */
25544 /* StandardWidth */
25545
25546 if(wb && wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx]) {
25547 /* Visible */
25548 if(wb.Workbook.Sheets[idx].Hidden) o.push(writextag("Visible", (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden"), {}));
25549 else {
25550 /* Selected */
25551 for(var i = 0; i < idx; ++i) if(wb.Workbook.Sheets[i] && !wb.Workbook.Sheets[i].Hidden) break;
25552 if(i == idx) o.push("<Selected/>");
25553 }
25554 }
25555
25556 /* LeftColumnVisible */
25557
25558 if(((((wb||{}).Workbook||{}).Views||[])[0]||{}).RTL) o.push("<DisplayRightToLeft/>");
25559
25560 /* GridlineColorIndex */
25561 /* DisplayFormulas */
25562 /* DoNotDisplayGridlines */
25563 /* DoNotDisplayHeadings */
25564 /* DoNotDisplayOutline */
25565 /* ApplyAutomaticOutlineStyles */
25566 /* NoSummaryRowsBelowDetail */
25567 /* NoSummaryColumnsRightDetail */
25568 /* DoNotDisplayZeros */
25569 /* ActiveRow */
25570 /* ActiveColumn */
25571 /* FilterOn */
25572 /* RangeSelection */
25573 /* TopRowVisible */
25574 /* TopRowBottomPane */
25575 /* LeftColumnRightPane */
25576 /* ActivePane */
25577 /* SplitHorizontal */
25578 /* SplitVertical */
25579 /* FreezePanes */
25580 /* FrozenNoSplit */
25581 /* TabColorIndex */
25582 /* Panes */
25583
25584 /* NOTE: Password not supported in XLML Format */
25585 if(ws['!protect']) {
25586 o.push(writetag("ProtectContents", "True"));
25587 if(ws['!protect'].objects) o.push(writetag("ProtectObjects", "True"));
25588 if(ws['!protect'].scenarios) o.push(writetag("ProtectScenarios", "True"));
25589 if(ws['!protect'].selectLockedCells != null && !ws['!protect'].selectLockedCells) o.push(writetag("EnableSelection", "NoSelection"));
25590 else if(ws['!protect'].selectUnlockedCells != null && !ws['!protect'].selectUnlockedCells) o.push(writetag("EnableSelection", "UnlockedCells"));
25591 [
25592 [ "formatCells", "AllowFormatCells" ],
25593 [ "formatColumns", "AllowSizeCols" ],
25594 [ "formatRows", "AllowSizeRows" ],
25595 [ "insertColumns", "AllowInsertCols" ],
25596 [ "insertRows", "AllowInsertRows" ],
25597 [ "insertHyperlinks", "AllowInsertHyperlinks" ],
25598 [ "deleteColumns", "AllowDeleteCols" ],
25599 [ "deleteRows", "AllowDeleteRows" ],
25600 [ "sort", "AllowSort" ],
25601 [ "autoFilter", "AllowFilter" ],
25602 [ "pivotTables", "AllowUsePivotTables" ]
25603 ].forEach(function(x) { if(ws['!protect'][x[0]]) o.push("<"+x[1]+"/>"); });
25604 }
25605
25606 if(o.length == 0) return "";
25607 return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x});
25608}
25609function write_ws_xlml_comment(comments) {
25610 return comments.map(function(c) {
25611 // TODO: formatted text
25612 var t = xlml_unfixstr(c.t||"");
25613 var d =writextag("ss:Data", t, {"xmlns":"http://www.w3.org/TR/REC-html40"});
25614 return writextag("Comment", d, {"ss:Author":c.a});
25615 }).join("");
25616}
25617function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){
25618 if(!cell || (cell.v == undefined && cell.f == undefined)) return "";
25619
25620 var attr = {};
25621 if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr));
25622 if(cell.F && cell.F.slice(0, ref.length) == ref) {
25623 var end = decode_cell(cell.F.slice(ref.length + 1));
25624 attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]");
25625 }
25626
25627 if(cell.l && cell.l.Target) {
25628 attr["ss:HRef"] = escapexml(cell.l.Target);
25629 if(cell.l.Tooltip) attr["x:HRefScreenTip"] = escapexml(cell.l.Tooltip);
25630 }
25631
25632 if(ws['!merges']) {
25633 var marr = ws['!merges'];
25634 for(var mi = 0; mi != marr.length; ++mi) {
25635 if(marr[mi].s.c != addr.c || marr[mi].s.r != addr.r) continue;
25636 if(marr[mi].e.c > marr[mi].s.c) attr['ss:MergeAcross'] = marr[mi].e.c - marr[mi].s.c;
25637 if(marr[mi].e.r > marr[mi].s.r) attr['ss:MergeDown'] = marr[mi].e.r - marr[mi].s.r;
25638 }
25639 }
25640
25641 var t = "", p = "";
25642 switch(cell.t) {
25643 case 'z': if(!opts.sheetStubs) return ""; break;
25644 case 'n': t = 'Number'; p = String(cell.v); break;
25645 case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break;
25646 case 'e': t = 'Error'; p = BErr[cell.v]; break;
25647 case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break;
25648 case 's': t = 'String'; p = escapexlml(cell.v||""); break;
25649 }
25650 /* TODO: cell style */
25651 var os = get_cell_style(opts.cellXfs, cell, opts);
25652 attr["ss:StyleID"] = "s" + (21+os);
25653 attr["ss:Index"] = addr.c + 1;
25654 var _v = (cell.v != null ? p : "");
25655 var m = cell.t == 'z' ? "" : ('<Data ss:Type="' + t + '">' + _v + '</Data>');
25656
25657 if((cell.c||[]).length > 0) m += write_ws_xlml_comment(cell.c);
25658
25659 return writextag("Cell", m, attr);
25660}
25661function write_ws_xlml_row(R, row) {
25662 var o = '<Row ss:Index="' + (R+1) + '"';
25663 if(row) {
25664 if(row.hpt && !row.hpx) row.hpx = pt2px(row.hpt);
25665 if(row.hpx) o += ' ss:AutoFitHeight="0" ss:Height="' + row.hpx + '"';
25666 if(row.hidden) o += ' ss:Hidden="1"';
25667 }
25668 return o + '>';
25669}
25670/* TODO */
25671function write_ws_xlml_table(ws, opts, idx, wb) {
25672 if(!ws['!ref']) return "";
25673 var range = safe_decode_range(ws['!ref']);
25674 var marr = ws['!merges'] || [], mi = 0;
25675 var o = [];
25676 if(ws['!cols']) ws['!cols'].forEach(function(n, i) {
25677 process_col(n);
25678 var w = !!n.width;
25679 var p = col_obj_w(i, n);
25680 var k = {"ss:Index":i+1};
25681 if(w) k['ss:Width'] = width2px(p.width);
25682 if(n.hidden) k['ss:Hidden']="1";
25683 o.push(writextag("Column",null,k));
25684 });
25685 var dense = Array.isArray(ws);
25686 for(var R = range.s.r; R <= range.e.r; ++R) {
25687 var row = [write_ws_xlml_row(R, (ws['!rows']||[])[R])];
25688 for(var C = range.s.c; C <= range.e.c; ++C) {
25689 var skip = false;
25690 for(mi = 0; mi != marr.length; ++mi) {
25691 if(marr[mi].s.c > C) continue;
25692 if(marr[mi].s.r > R) continue;
25693 if(marr[mi].e.c < C) continue;
25694 if(marr[mi].e.r < R) continue;
25695 if(marr[mi].s.c != C || marr[mi].s.r != R) skip = true;
25696 break;
25697 }
25698 if(skip) continue;
25699 var addr = {r:R,c:C};
25700 var ref = encode_cell(addr), cell = dense ? (ws[R]||[])[C] : ws[ref];
25701 row.push(write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr));
25702 }
25703 row.push("</Row>");
25704 if(row.length > 2) o.push(row.join(""));
25705 }
25706 return o.join("");
25707}
25708function write_ws_xlml(idx, opts, wb) {
25709 var o = [];
25710 var s = wb.SheetNames[idx];
25711 var ws = wb.Sheets[s];
25712
25713 var t = ws ? write_ws_xlml_names(ws, opts, idx, wb) : "";
25714 if(t.length > 0) o.push("<Names>" + t + "</Names>");
25715
25716 /* Table */
25717 t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : "";
25718 if(t.length > 0) o.push("<Table>" + t + "</Table>");
25719
25720 /* WorksheetOptions */
25721 o.push(write_ws_xlml_wsopts(ws, opts, idx, wb));
25722
25723 return o.join("");
25724}
25725function write_xlml(wb, opts) {
25726 if(!opts) opts = {};
25727 if(!wb.SSF) wb.SSF = SSF.get_table();
25728 if(wb.SSF) {
25729 make_ssf(SSF); SSF.load_table(wb.SSF);
25730 // $FlowIgnore
25731 opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
25732 opts.ssf = wb.SSF;
25733 opts.cellXfs = [];
25734 get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}});
25735 }
25736 var d = [];
25737 d.push(write_props_xlml(wb, opts));
25738 d.push(write_wb_xlml(wb, opts));
25739 d.push("");
25740 d.push("");
25741 for(var i = 0; i < wb.SheetNames.length; ++i)
25742 d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])}));
25743 d[2] = write_sty_xlml(wb, opts);
25744 d[3] = write_names_xlml(wb, opts);
25745 return XML_HEADER + writextag("Workbook", d.join(""), {
25746 'xmlns': XLMLNS.ss,
25747 'xmlns:o': XLMLNS.o,
25748 'xmlns:x': XLMLNS.x,
25749 'xmlns:ss': XLMLNS.ss,
25750 'xmlns:dt': XLMLNS.dt,
25751 'xmlns:html': XLMLNS.html
25752 });
25753}
25754/* [MS-OLEDS] 2.3.8 CompObjStream */
25755function parse_compobj(obj) {
25756 var v = {};
25757 var o = obj.content;
25758/* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */
25759 o.l = 28;
25760
25761 v.AnsiUserType = o.read_shift(0, "lpstr-ansi");
25762 v.AnsiClipboardFormat = parse_ClipboardFormatOrAnsiString(o);
25763
25764 if(o.length - o.l <= 4) return v;
25765
25766 var m = o.read_shift(4);
25767 if(m == 0 || m > 40) return v;
25768 o.l-=4; v.Reserved1 = o.read_shift(0, "lpstr-ansi");
25769
25770 if(o.length - o.l <= 4) return v;
25771 m = o.read_shift(4);
25772 if(m !== 0x71b239f4) return v;
25773 v.UnicodeClipboardFormat = parse_ClipboardFormatOrUnicodeString(o);
25774
25775 m = o.read_shift(4);
25776 if(m == 0 || m > 40) return v;
25777 o.l-=4; v.Reserved2 = o.read_shift(0, "lpwstr");
25778}
25779
25780/*
25781 Continue logic for:
25782 - 2.4.58 Continue
25783 - 2.4.59 ContinueBigName
25784 - 2.4.60 ContinueFrt
25785 - 2.4.61 ContinueFrt11
25786 - 2.4.62 ContinueFrt12
25787*/
25788function slurp(R, blob, length, opts) {
25789 var l = length;
25790 var bufs = [];
25791 var d = blob.slice(blob.l,blob.l+l);
25792 if(opts && opts.enc && opts.enc.insitu) switch(R.n) {
25793 case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': break;
25794 default:
25795 if(d.length === 0) break;
25796 opts.enc.insitu(d);
25797 }
25798 bufs.push(d);
25799 blob.l += l;
25800 var next = (XLSRecordEnum[__readUInt16LE(blob,blob.l)]);
25801 var start = 0;
25802 while(next != null && next.n.slice(0,8) === 'Continue') {
25803 l = __readUInt16LE(blob,blob.l+2);
25804 start = blob.l + 4;
25805 if(next.n == 'ContinueFrt') start += 4;
25806 else if(next.n.slice(0,11) == 'ContinueFrt') start += 12;
25807 bufs.push(blob.slice(start,blob.l+4+l));
25808 blob.l += 4+l;
25809 next = (XLSRecordEnum[__readUInt16LE(blob, blob.l)]);
25810 }
25811 var b = (bconcat(bufs));
25812 prep_blob(b, 0);
25813 var ll = 0; b.lens = [];
25814 for(var j = 0; j < bufs.length; ++j) { b.lens.push(ll); ll += bufs[j].length; }
25815 return R.f(b, b.length, opts);
25816}
25817
25818function safe_format_xf(p, opts, date1904) {
25819 if(p.t === 'z') return;
25820 if(!p.XF) return;
25821 var fmtid = 0;
25822 try {
25823 fmtid = p.z || p.XF.numFmtId || 0;
25824 if(opts.cellNF) p.z = SSF._table[fmtid];
25825 } catch(e) { if(opts.WTF) throw e; }
25826 if(!opts || opts.cellText !== false) try {
25827 if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
25828 else if(fmtid === 0 || fmtid == "General") {
25829 if(p.t === 'n') {
25830 if((p.v|0) === p.v) p.w = SSF._general_int(p.v);
25831 else p.w = SSF._general_num(p.v);
25832 }
25833 else p.w = SSF._general(p.v);
25834 }
25835 else p.w = SSF.format(fmtid,p.v, {date1904:!!date1904});
25836 } catch(e) { if(opts.WTF) throw e; }
25837 if(opts.cellDates && fmtid && p.t == 'n' && SSF.is_date(SSF._table[fmtid] || String(fmtid))) {
25838 var _d = SSF.parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
25839 }
25840}
25841
25842function make_cell(val, ixfe, t) {
25843 return ({v:val, ixfe:ixfe, t:t});
25844}
25845
25846// 2.3.2
25847function parse_workbook(blob, options) {
25848 var wb = ({opts:{}});
25849 var Sheets = {};
25850 if(DENSE != null && options.dense == null) options.dense = DENSE;
25851 var out = ((options.dense ? [] : {}));
25852 var Directory = {};
25853 var range = ({});
25854 var last_formula = null;
25855 var sst = ([]);
25856 var cur_sheet = "";
25857 var Preamble = {};
25858 var lastcell, last_cell = "", cc, cmnt, rngC, rngR;
25859 var sharedf = {};
25860 var arrayf = [];
25861 var temp_val;
25862 var country;
25863 var cell_valid = true;
25864 var XFs = []; /* XF records */
25865 var palette = [];
25866 var Workbook = ({ Sheets:[], WBProps:{date1904:false}, Views:[{}] }), wsprops = {};
25867 var get_rgb = function getrgb(icv) {
25868 if(icv < 8) return XLSIcv[icv];
25869 if(icv < 64) return palette[icv-8] || XLSIcv[icv];
25870 return XLSIcv[icv];
25871 };
25872 var process_cell_style = function pcs(cell, line, options) {
25873 var xfd = line.XF.data;
25874 if(!xfd || !xfd.patternType || !options || !options.cellStyles) return;
25875 line.s = ({});
25876 line.s.patternType = xfd.patternType;
25877 var t;
25878 if((t = rgb2Hex(get_rgb(xfd.icvFore)))) { line.s.fgColor = {rgb:t}; }
25879 if((t = rgb2Hex(get_rgb(xfd.icvBack)))) { line.s.bgColor = {rgb:t}; }
25880 };
25881 var addcell = function addcell(cell, line, options) {
25882 if(file_depth > 1) return;
25883 if(options.sheetRows && cell.r >= options.sheetRows) cell_valid = false;
25884 if(!cell_valid) return;
25885 if(options.cellStyles && line.XF && line.XF.data) process_cell_style(cell, line, options);
25886 delete line.ixfe; delete line.XF;
25887 lastcell = cell;
25888 last_cell = encode_cell(cell);
25889 if(!range || !range.s || !range.e) range = {s:{r:0,c:0},e:{r:0,c:0}};
25890 if(cell.r < range.s.r) range.s.r = cell.r;
25891 if(cell.c < range.s.c) range.s.c = cell.c;
25892 if(cell.r + 1 > range.e.r) range.e.r = cell.r + 1;
25893 if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1;
25894 if(options.cellFormula && line.f) {
25895 for(var afi = 0; afi < arrayf.length; ++afi) {
25896 if(arrayf[afi][0].s.c > cell.c || arrayf[afi][0].s.r > cell.r) continue;
25897 if(arrayf[afi][0].e.c < cell.c || arrayf[afi][0].e.r < cell.r) continue;
25898 line.F = encode_range(arrayf[afi][0]);
25899 if(arrayf[afi][0].s.c != cell.c || arrayf[afi][0].s.r != cell.r) delete line.f;
25900 if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts);
25901 break;
25902 }
25903 }
25904 {
25905 if(options.dense) {
25906 if(!out[cell.r]) out[cell.r] = [];
25907 out[cell.r][cell.c] = line;
25908 } else out[last_cell] = line;
25909 }
25910 };
25911 var opts = ({
25912 enc: false, // encrypted
25913 sbcch: 0, // cch in the preceding SupBook
25914 snames: [], // sheetnames
25915 sharedf: sharedf, // shared formulae by address
25916 arrayf: arrayf, // array formulae array
25917 rrtabid: [], // RRTabId
25918 lastuser: "", // Last User from WriteAccess
25919 biff: 8, // BIFF version
25920 codepage: 0, // CP from CodePage record
25921 winlocked: 0, // fLockWn from WinProtect
25922 cellStyles: !!options && !!options.cellStyles,
25923 WTF: !!options && !!options.wtf
25924 });
25925 if(options.password) opts.password = options.password;
25926 var themes;
25927 var merges = [];
25928 var objects = [];
25929 var colinfo = [], rowinfo = [];
25930 // eslint-disable-next-line no-unused-vars
25931 var defwidth = 0, defheight = 0; // twips / MDW respectively
25932 var seencol = false;
25933 var supbooks = ([]); // 1-indexed, will hold extern names
25934 supbooks.SheetNames = opts.snames;
25935 supbooks.sharedf = opts.sharedf;
25936 supbooks.arrayf = opts.arrayf;
25937 supbooks.names = [];
25938 supbooks.XTI = [];
25939 var last_Rn = '';
25940 var file_depth = 0; /* TODO: make a real stack */
25941 var BIFF2Fmt = 0, BIFF2FmtTable = [];
25942 var FilterDatabases = []; /* TODO: sort out supbooks and process elsewhere */
25943 var last_lbl;
25944
25945 /* explicit override for some broken writers */
25946 opts.codepage = 1200;
25947 set_cp(1200);
25948 var seen_codepage = false;
25949 while(blob.l < blob.length - 1) {
25950 var s = blob.l;
25951 var RecordType = blob.read_shift(2);
25952 if(RecordType === 0 && last_Rn === 'EOF') break;
25953 var length = (blob.l === blob.length ? 0 : blob.read_shift(2));
25954 var R = XLSRecordEnum[RecordType];
25955 //console.log(RecordType.toString(16), RecordType, R, blob.l, length, blob.length);
25956 //if(!R) console.log(blob.slice(blob.l, blob.l + length));
25957 if(R && R.f) {
25958 if(options.bookSheets) {
25959 if(last_Rn === 'BoundSheet8' && R.n !== 'BoundSheet8') break;
25960 }
25961 last_Rn = R.n;
25962 if(R.r === 2 || R.r == 12) {
25963 var rt = blob.read_shift(2); length -= 2;
25964 if(!opts.enc && rt !== RecordType && (((rt&0xFF)<<8)|(rt>>8)) !== RecordType) throw new Error("rt mismatch: " + rt + "!=" + RecordType);
25965 if(R.r == 12){ blob.l += 10; length -= 10; } // skip FRT
25966 }
25967 //console.error(R,blob.l,length,blob.length);
25968 var val = ({});
25969 if(R.n === 'EOF') val = R.f(blob, length, opts);
25970 else val = slurp(R, blob, length, opts);
25971 var Rn = R.n;
25972if(file_depth == 0 && Rn != 'BOF') continue;
25973 /* nested switch statements to workaround V8 128 limit */
25974 switch(Rn) {
25975 /* Workbook Options */
25976 case 'Date1904':
25977wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
25978 case 'WriteProtect': wb.opts.WriteProtect = true; break;
25979 case 'FilePass':
25980 if(!opts.enc) blob.l = 0;
25981 opts.enc = val;
25982 if(!options.password) throw new Error("File is password-protected");
25983 if(val.valid == null) throw new Error("Encryption scheme unsupported");
25984 if(!val.valid) throw new Error("Password is incorrect");
25985 break;
25986 case 'WriteAccess': opts.lastuser = val; break;
25987 case 'FileSharing': break; //TODO
25988 case 'CodePage':
25989 var cpval = Number(val);
25990 /* overrides based on test cases */
25991 switch(cpval) {
25992 case 0x5212: cpval = 1200; break;
25993 case 0x8000: cpval = 10000; break;
25994 case 0x8001: cpval = 1252; break;
25995 }
25996 set_cp(opts.codepage = cpval);
25997 seen_codepage = true;
25998 break;
25999 case 'RRTabId': opts.rrtabid = val; break;
26000 case 'WinProtect': opts.winlocked = val; break;
26001 case 'Template': break; // TODO
26002 case 'BookBool': break; // TODO
26003 case 'UsesELFs': break;
26004 case 'MTRSettings': break;
26005 case 'RefreshAll':
26006 case 'CalcCount':
26007 case 'CalcDelta':
26008 case 'CalcIter':
26009 case 'CalcMode':
26010 case 'CalcPrecision':
26011 case 'CalcSaveRecalc':
26012 wb.opts[Rn] = val; break;
26013 case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1
26014 case 'Uncalced': break;
26015 case 'ForceFullCalculation': wb.opts.FullCalc = val; break;
26016 case 'WsBool':
26017 if(val.fDialog) out["!type"] = "dialog";
26018 break; // TODO
26019 case 'XF':
26020 XFs.push(val); break;
26021 case 'ExtSST': break; // TODO
26022 case 'BookExt': break; // TODO
26023 case 'RichTextStream': break;
26024 case 'BkHim': break;
26025
26026 case 'SupBook':
26027 supbooks.push([val]);
26028 supbooks[supbooks.length-1].XTI = [];
26029 break;
26030 case 'ExternName':
26031 supbooks[supbooks.length-1].push(val);
26032 break;
26033 case 'Index': break; // TODO
26034 case 'Lbl':
26035 last_lbl = ({
26036 Name: val.Name,
26037 Ref: stringify_formula(val.rgce,range,null,supbooks,opts)
26038 });
26039 if(val.itab > 0) last_lbl.Sheet = val.itab - 1;
26040 supbooks.names.push(last_lbl);
26041 if(!supbooks[0]) { supbooks[0] = []; supbooks[0].XTI = []; }
26042 supbooks[supbooks.length-1].push(val);
26043 if(val.Name == "_xlnm._FilterDatabase" && val.itab > 0)
26044 if(val.rgce && val.rgce[0] && val.rgce[0][0] && val.rgce[0][0][0] == 'PtgArea3d')
26045 FilterDatabases[val.itab - 1] = { ref: encode_range(val.rgce[0][0][1][2]) };
26046 break;
26047 case 'ExternCount': opts.ExternCount = val; break;
26048 case 'ExternSheet':
26049 if(supbooks.length == 0) { supbooks[0] = []; supbooks[0].XTI = []; }
26050 supbooks[supbooks.length - 1].XTI = supbooks[supbooks.length - 1].XTI.concat(val); supbooks.XTI = supbooks.XTI.concat(val); break;
26051 case 'NameCmt':
26052 /* TODO: search for correct name */
26053 if(opts.biff < 8) break;
26054 if(last_lbl != null) last_lbl.Comment = val[1];
26055 break;
26056
26057 case 'Protect': out["!protect"] = val; break; /* for sheet or book */
26058 case 'Password': if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break;
26059 case 'Prot4Rev': case 'Prot4RevPass': break; /*TODO: Revision Control*/
26060
26061 case 'BoundSheet8': {
26062 Directory[val.pos] = val;
26063 opts.snames.push(val.name);
26064 } break;
26065 case 'EOF': {
26066 if(--file_depth) break;
26067 if(range.e) {
26068 if(range.e.r > 0 && range.e.c > 0) {
26069 range.e.r--; range.e.c--;
26070 out["!ref"] = encode_range(range);
26071 if(options.sheetRows && options.sheetRows <= range.e.r) {
26072 var tmpri = range.e.r;
26073 range.e.r = options.sheetRows - 1;
26074 out["!fullref"] = out["!ref"];
26075 out["!ref"] = encode_range(range);
26076 range.e.r = tmpri;
26077 }
26078 range.e.r++; range.e.c++;
26079 }
26080 if(merges.length > 0) out["!merges"] = merges;
26081 if(objects.length > 0) out["!objects"] = objects;
26082 if(colinfo.length > 0) out["!cols"] = colinfo;
26083 if(rowinfo.length > 0) out["!rows"] = rowinfo;
26084 Workbook.Sheets.push(wsprops);
26085 }
26086 if(cur_sheet === "") Preamble = out; else Sheets[cur_sheet] = out;
26087 out = ((options.dense ? [] : {}));
26088 } break;
26089 case 'BOF': {
26090 if(opts.biff === 8) opts.biff = {
260910x0009:2,
260920x0209:3,
260930x0409:4
26094 }[RecordType] || {
260950x0200:2,
260960x0300:3,
260970x0400:4,
260980x0500:5,
260990x0600:8,
261000x0002:2,
261010x0007:2
26102 }[val.BIFFVer] || 8;
26103 if(opts.biff == 8 && val.BIFFVer == 0 && val.dt == 16) opts.biff = 2;
26104 if(file_depth++) break;
26105 cell_valid = true;
26106 out = ((options.dense ? [] : {}));
26107
26108 if(opts.biff < 8 && !seen_codepage) { seen_codepage = true; set_cp(opts.codepage = options.codepage || 1252); }
26109 if(opts.biff < 5) {
26110 if(cur_sheet === "") cur_sheet = "Sheet1";
26111 range = {s:{r:0,c:0},e:{r:0,c:0}};
26112 /* fake BoundSheet8 */
26113 var fakebs8 = {pos: blob.l - length, name:cur_sheet};
26114 Directory[fakebs8.pos] = fakebs8;
26115 opts.snames.push(cur_sheet);
26116 }
26117 else cur_sheet = (Directory[s] || {name:""}).name;
26118 if(val.dt == 0x20) out["!type"] = "chart";
26119 if(val.dt == 0x40) out["!type"] = "macro";
26120 merges = [];
26121 objects = [];
26122 opts.arrayf = arrayf = [];
26123 colinfo = []; rowinfo = [];
26124 defwidth = defheight = 0;
26125 seencol = false;
26126 wsprops = {Hidden:(Directory[s]||{hs:0}).hs, name:cur_sheet };
26127 } break;
26128
26129 case 'Number': case 'BIFF2NUM': case 'BIFF2INT': {
26130 if(out["!type"] == "chart") if(options.dense ? (out[val.r]||[])[val.c]: out[encode_cell({c:val.c, r:val.r})]) ++val.c;
26131 temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe]||{}, v:val.val, t:'n'});
26132 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
26133 safe_format_xf(temp_val, options, wb.opts.Date1904);
26134 addcell({c:val.c, r:val.r}, temp_val, options);
26135 } break;
26136 case 'BoolErr': {
26137 temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t});
26138 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
26139 safe_format_xf(temp_val, options, wb.opts.Date1904);
26140 addcell({c:val.c, r:val.r}, temp_val, options);
26141 } break;
26142 case 'RK': {
26143 temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'});
26144 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
26145 safe_format_xf(temp_val, options, wb.opts.Date1904);
26146 addcell({c:val.c, r:val.r}, temp_val, options);
26147 } break;
26148 case 'MulRk': {
26149 for(var j = val.c; j <= val.C; ++j) {
26150 var ixfe = val.rkrec[j-val.c][0];
26151 temp_val= ({ixfe:ixfe, XF:XFs[ixfe], v:val.rkrec[j-val.c][1], t:'n'});
26152 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
26153 safe_format_xf(temp_val, options, wb.opts.Date1904);
26154 addcell({c:j, r:val.r}, temp_val, options);
26155 }
26156 } break;
26157 case 'Formula': {
26158 if(val.val == 'String') { last_formula = val; break; }
26159 temp_val = make_cell(val.val, val.cell.ixfe, val.tt);
26160 temp_val.XF = XFs[temp_val.ixfe];
26161 if(options.cellFormula) {
26162 var _f = val.formula;
26163 if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') {
26164 var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1];
26165 var _fe = encode_cell({r:_fr, c:_fc});
26166 if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
26167 else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F;
26168 } else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
26169 }
26170 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
26171 safe_format_xf(temp_val, options, wb.opts.Date1904);
26172 addcell(val.cell, temp_val, options);
26173 last_formula = val;
26174 } break;
26175 case 'String': {
26176 if(last_formula) { /* technically always true */
26177 last_formula.val = val;
26178 temp_val = make_cell(val, last_formula.cell.ixfe, 's');
26179 temp_val.XF = XFs[temp_val.ixfe];
26180 if(options.cellFormula) {
26181 temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
26182 }
26183 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
26184 safe_format_xf(temp_val, options, wb.opts.Date1904);
26185 addcell(last_formula.cell, temp_val, options);
26186 last_formula = null;
26187 } else throw new Error("String record expects Formula");
26188 } break;
26189 case 'Array': {
26190 arrayf.push(val);
26191 var _arraystart = encode_cell(val[0].s);
26192 cc = options.dense ? (out[val[0].s.r]||[])[val[0].s.c] : out[_arraystart];
26193 if(options.cellFormula && cc) {
26194 if(!last_formula) break; /* technically unreachable */
26195 if(!_arraystart || !cc) break;
26196 cc.f = ""+stringify_formula(val[1], range, val[0], supbooks, opts);
26197 cc.F = encode_range(val[0]);
26198 }
26199 } break;
26200 case 'ShrFmla': {
26201 if(!cell_valid) break;
26202 if(!options.cellFormula) break;
26203 if(last_cell) {
26204 /* TODO: capture range */
26205 if(!last_formula) break; /* technically unreachable */
26206 sharedf[encode_cell(last_formula.cell)]= val[0];
26207 cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)];
26208 (cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts);
26209 }
26210 } break;
26211 case 'LabelSst':
26212 temp_val=make_cell(sst[val.isst].t, val.ixfe, 's');
26213 if(sst[val.isst].h) temp_val.h = sst[val.isst].h;
26214 temp_val.XF = XFs[temp_val.ixfe];
26215 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
26216 safe_format_xf(temp_val, options, wb.opts.Date1904);
26217 addcell({c:val.c, r:val.r}, temp_val, options);
26218 break;
26219 case 'Blank': if(options.sheetStubs) {
26220 temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'});
26221 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
26222 safe_format_xf(temp_val, options, wb.opts.Date1904);
26223 addcell({c:val.c, r:val.r}, temp_val, options);
26224 } break;
26225 case 'MulBlank': if(options.sheetStubs) {
26226 for(var _j = val.c; _j <= val.C; ++_j) {
26227 var _ixfe = val.ixfe[_j-val.c];
26228 temp_val= ({ixfe:_ixfe, XF:XFs[_ixfe], t:'z'});
26229 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
26230 safe_format_xf(temp_val, options, wb.opts.Date1904);
26231 addcell({c:_j, r:val.r}, temp_val, options);
26232 }
26233 } break;
26234 case 'RString':
26235 case 'Label': case 'BIFF2STR':
26236 temp_val=make_cell(val.val, val.ixfe, 's');
26237 temp_val.XF = XFs[temp_val.ixfe];
26238 if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F];
26239 safe_format_xf(temp_val, options, wb.opts.Date1904);
26240 addcell({c:val.c, r:val.r}, temp_val, options);
26241 break;
26242
26243 case 'Dimensions': {
26244 if(file_depth === 1) range = val; /* TODO: stack */
26245 } break;
26246 case 'SST': {
26247 sst = val;
26248 } break;
26249 case 'Format': { /* val = [id, fmt] */
26250 if(opts.biff == 4) {
26251 BIFF2FmtTable[BIFF2Fmt++] = val[1];
26252 for(var b4idx = 0; b4idx < BIFF2Fmt + 163; ++b4idx) if(SSF._table[b4idx] == val[1]) break;
26253 if(b4idx >= 163) SSF.load(val[1], BIFF2Fmt + 163);
26254 }
26255 else SSF.load(val[1], val[0]);
26256 } break;
26257 case 'BIFF2FORMAT': {
26258 BIFF2FmtTable[BIFF2Fmt++] = val;
26259 for(var b2idx = 0; b2idx < BIFF2Fmt + 163; ++b2idx) if(SSF._table[b2idx] == val) break;
26260 if(b2idx >= 163) SSF.load(val, BIFF2Fmt + 163);
26261 } break;
26262
26263 case 'MergeCells': merges = merges.concat(val); break;
26264
26265 case 'Obj': objects[val.cmo[0]] = opts.lastobj = val; break;
26266 case 'TxO': opts.lastobj.TxO = val; break;
26267 case 'ImData': opts.lastobj.ImData = val; break;
26268
26269 case 'HLink': {
26270 for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
26271 for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
26272 cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
26273 if(cc) cc.l = val[1];
26274 }
26275 } break;
26276 case 'HLinkTooltip': {
26277 for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR)
26278 for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) {
26279 cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})];
26280 if(cc && cc.l) cc.l.Tooltip = val[1];
26281 }
26282 } break;
26283
26284 /* Comments */
26285 case 'Note': {
26286 if(opts.biff <= 5 && opts.biff >= 2) break; /* TODO: BIFF5 */
26287 cc = options.dense ? (out[val[0].r]||[])[val[0].c] : out[encode_cell(val[0])];
26288 var noteobj = objects[val[2]];
26289 if(!cc) {
26290 if(options.dense) {
26291 if(!out[val[0].r]) out[val[0].r] = [];
26292 cc = out[val[0].r][val[0].c] = ({t:"z"});
26293 } else {
26294 cc = out[encode_cell(val[0])] = ({t:"z"});
26295 }
26296 range.e.r = Math.max(range.e.r, val[0].r);
26297 range.s.r = Math.min(range.s.r, val[0].r);
26298 range.e.c = Math.max(range.e.c, val[0].c);
26299 range.s.c = Math.min(range.s.c, val[0].c);
26300 }
26301 if(!cc.c) cc.c = [];
26302 cmnt = {a:val[1],t:noteobj.TxO.t};
26303 cc.c.push(cmnt);
26304 } break;
26305
26306 default: switch(R.n) { /* nested */
26307 case 'ClrtClient': break;
26308 case 'XFExt': update_xfext(XFs[val.ixfe], val.ext); break;
26309
26310 case 'DefColWidth': defwidth = val; break;
26311 case 'DefaultRowHeight': defheight = val[1]; break; // TODO: flags
26312
26313 case 'ColInfo': {
26314 if(!opts.cellStyles) break;
26315 while(val.e >= val.s) {
26316 colinfo[val.e--] = { width: val.w/256 };
26317 if(!seencol) { seencol = true; find_mdw_colw(val.w/256); }
26318 process_col(colinfo[val.e+1]);
26319 }
26320 } break;
26321 case 'Row': {
26322 var rowobj = {};
26323 if(val.level != null) { rowinfo[val.r] = rowobj; rowobj.level = val.level; }
26324 if(val.hidden) { rowinfo[val.r] = rowobj; rowobj.hidden = true; }
26325 if(val.hpt) {
26326 rowinfo[val.r] = rowobj;
26327 rowobj.hpt = val.hpt; rowobj.hpx = pt2px(val.hpt);
26328 }
26329 } break;
26330
26331 case 'LeftMargin':
26332 case 'RightMargin':
26333 case 'TopMargin':
26334 case 'BottomMargin':
26335 if(!out['!margins']) default_margins(out['!margins'] = {});
26336 out['!margins'][Rn.slice(0,-6).toLowerCase()] = val;
26337 break;
26338
26339 case 'Setup': // TODO
26340 if(!out['!margins']) default_margins(out['!margins'] = {});
26341 out['!margins'].header = val.header;
26342 out['!margins'].footer = val.footer;
26343 break;
26344
26345 case 'Window2': // TODO
26346 // $FlowIgnore
26347 if(val.RTL) Workbook.Views[0].RTL = true;
26348 break;
26349
26350 case 'Header': break; // TODO
26351 case 'Footer': break; // TODO
26352 case 'HCenter': break; // TODO
26353 case 'VCenter': break; // TODO
26354 case 'Pls': break; // TODO
26355 case 'GCW': break;
26356 case 'LHRecord': break;
26357 case 'DBCell': break; // TODO
26358 case 'EntExU2': break; // TODO
26359 case 'SxView': break; // TODO
26360 case 'Sxvd': break; // TODO
26361 case 'SXVI': break; // TODO
26362 case 'SXVDEx': break; // TODO
26363 case 'SxIvd': break; // TODO
26364 case 'SXString': break; // TODO
26365 case 'Sync': break;
26366 case 'Addin': break;
26367 case 'SXDI': break; // TODO
26368 case 'SXLI': break; // TODO
26369 case 'SXEx': break; // TODO
26370 case 'QsiSXTag': break; // TODO
26371 case 'Selection': break;
26372 case 'Feat': break;
26373 case 'FeatHdr': case 'FeatHdr11': break;
26374 case 'Feature11': case 'Feature12': case 'List12': break;
26375 case 'Country': country = val; break;
26376 case 'RecalcId': break;
26377 case 'DxGCol': break; // TODO: htmlify
26378 case 'Fbi': case 'Fbi2': case 'GelFrame': break;
26379 case 'Font': break; // TODO
26380 case 'XFCRC': break; // TODO
26381 case 'Style': break; // TODO
26382 case 'StyleExt': break; // TODO
26383 case 'Palette': palette = val; break;
26384 case 'Theme': themes = val; break;
26385 /* Protection */
26386 case 'ScenarioProtect': break;
26387 case 'ObjProtect': break;
26388
26389 /* Conditional Formatting */
26390 case 'CondFmt12': break;
26391
26392 /* Table */
26393 case 'Table': break; // TODO
26394 case 'TableStyles': break; // TODO
26395 case 'TableStyle': break; // TODO
26396 case 'TableStyleElement': break; // TODO
26397
26398 /* PivotTable */
26399 case 'SXStreamID': break; // TODO
26400 case 'SXVS': break; // TODO
26401 case 'DConRef': break; // TODO
26402 case 'SXAddl': break; // TODO
26403 case 'DConBin': break; // TODO
26404 case 'DConName': break; // TODO
26405 case 'SXPI': break; // TODO
26406 case 'SxFormat': break; // TODO
26407 case 'SxSelect': break; // TODO
26408 case 'SxRule': break; // TODO
26409 case 'SxFilt': break; // TODO
26410 case 'SxItm': break; // TODO
26411 case 'SxDXF': break; // TODO
26412
26413 /* Scenario Manager */
26414 case 'ScenMan': break;
26415
26416 /* Data Consolidation */
26417 case 'DCon': break;
26418
26419 /* Watched Cell */
26420 case 'CellWatch': break;
26421
26422 /* Print Settings */
26423 case 'PrintRowCol': break;
26424 case 'PrintGrid': break;
26425 case 'PrintSize': break;
26426
26427 case 'XCT': break;
26428 case 'CRN': break;
26429
26430 case 'Scl': {
26431 //console.log("Zoom Level:", val[0]/val[1],val);
26432 } break;
26433 case 'SheetExt': {
26434 /* empty */
26435 } break;
26436 case 'SheetExtOptional': {
26437 /* empty */
26438 } break;
26439
26440 /* VBA */
26441 case 'ObNoMacros': {
26442 /* empty */
26443 } break;
26444 case 'ObProj': {
26445 /* empty */
26446 } break;
26447 case 'CodeName': {
26448if(!cur_sheet) Workbook.WBProps.CodeName = val || "ThisWorkbook";
26449 else wsprops.CodeName = val || wsprops.name;
26450 } break;
26451 case 'GUIDTypeLib': {
26452 /* empty */
26453 } break;
26454
26455 case 'WOpt': break; // TODO: WTF?
26456 case 'PhoneticInfo': break;
26457
26458 case 'OleObjectSize': break;
26459
26460 /* Differential Formatting */
26461 case 'DXF': case 'DXFN': case 'DXFN12': case 'DXFN12List': case 'DXFN12NoCB': break;
26462
26463 /* Data Validation */
26464 case 'Dv': case 'DVal': break;
26465
26466 /* Data Series */
26467 case 'BRAI': case 'Series': case 'SeriesText': break;
26468
26469 /* Data Connection */
26470 case 'DConn': break;
26471 case 'DbOrParamQry': break;
26472 case 'DBQueryExt': break;
26473
26474 case 'OleDbConn': break;
26475 case 'ExtString': break;
26476
26477 /* Formatting */
26478 case 'IFmtRecord': break;
26479 case 'CondFmt': case 'CF': case 'CF12': case 'CFEx': break;
26480
26481 /* Explicitly Ignored */
26482 case 'Excel9File': break;
26483 case 'Units': break;
26484 case 'InterfaceHdr': case 'Mms': case 'InterfaceEnd': case 'DSF': break;
26485 case 'BuiltInFnGroupCount': /* 2.4.30 0x0E or 0x10 but excel 2011 generates 0x11? */ break;
26486 /* View Stuff */
26487 case 'Window1': case 'HideObj': case 'GridSet': case 'Guts':
26488 case 'UserBView': case 'UserSViewBegin': case 'UserSViewEnd': break;
26489 case 'Pane': break;
26490 default: switch(R.n) { /* nested */
26491 /* Chart */
26492 case 'Dat':
26493 case 'Begin': case 'End':
26494 case 'StartBlock': case 'EndBlock':
26495 case 'Frame': case 'Area':
26496 case 'Axis': case 'AxisLine': case 'Tick': break;
26497 case 'AxesUsed':
26498 case 'CrtLayout12': case 'CrtLayout12A': case 'CrtLink': case 'CrtLine': case 'CrtMlFrt': case 'CrtMlFrtContinue': break;
26499 case 'LineFormat': case 'AreaFormat':
26500 case 'Chart': case 'Chart3d': case 'Chart3DBarShape': case 'ChartFormat': case 'ChartFrtInfo': break;
26501 case 'PlotArea': case 'PlotGrowth': break;
26502 case 'SeriesList': case 'SerParent': case 'SerAuxTrend': break;
26503 case 'DataFormat': case 'SerToCrt': case 'FontX': break;
26504 case 'CatSerRange': case 'AxcExt': case 'SerFmt': break;
26505 case 'ShtProps': break;
26506 case 'DefaultText': case 'Text': case 'CatLab': break;
26507 case 'DataLabExtContents': break;
26508 case 'Legend': case 'LegendException': break;
26509 case 'Pie': case 'Scatter': break;
26510 case 'PieFormat': case 'MarkerFormat': break;
26511 case 'StartObject': case 'EndObject': break;
26512 case 'AlRuns': case 'ObjectLink': break;
26513 case 'SIIndex': break;
26514 case 'AttachedLabel': case 'YMult': break;
26515
26516 /* Chart Group */
26517 case 'Line': case 'Bar': break;
26518 case 'Surf': break;
26519
26520 /* Axis Group */
26521 case 'AxisParent': break;
26522 case 'Pos': break;
26523 case 'ValueRange': break;
26524
26525 /* Pivot Chart */
26526 case 'SXViewEx9': break; // TODO
26527 case 'SXViewLink': break;
26528 case 'PivotChartBits': break;
26529 case 'SBaseRef': break;
26530 case 'TextPropsStream': break;
26531
26532 /* Chart Misc */
26533 case 'LnExt': break;
26534 case 'MkrExt': break;
26535 case 'CrtCoopt': break;
26536
26537 /* Query Table */
26538 case 'Qsi': case 'Qsif': case 'Qsir': case 'QsiSXTag': break;
26539 case 'TxtQry': break;
26540
26541 /* Filter */
26542 case 'FilterMode': break;
26543 case 'AutoFilter': case 'AutoFilterInfo': break;
26544 case 'AutoFilter12': break;
26545 case 'DropDownObjIds': break;
26546 case 'Sort': break;
26547 case 'SortData': break;
26548
26549 /* Drawing */
26550 case 'ShapePropsStream': break;
26551 case 'MsoDrawing': case 'MsoDrawingGroup': case 'MsoDrawingSelection': break;
26552 /* Pub Stuff */
26553 case 'WebPub': case 'AutoWebPub': break;
26554
26555 /* Print Stuff */
26556 case 'HeaderFooter': case 'HFPicture': case 'PLV':
26557 case 'HorizontalPageBreaks': case 'VerticalPageBreaks': break;
26558 /* Behavioral */
26559 case 'Backup': case 'CompressPictures': case 'Compat12': break;
26560
26561 /* Should not Happen */
26562 case 'Continue': case 'ContinueFrt12': break;
26563
26564 /* Future Records */
26565 case 'FrtFontList': case 'FrtWrapper': break;
26566
26567 default: switch(R.n) { /* nested */
26568 /* BIFF5 records */
26569 case 'TabIdConf': case 'Radar': case 'RadarArea': case 'DropBar': case 'Intl': case 'CoordList': case 'SerAuxErrBar': break;
26570
26571 /* BIFF2-4 records */
26572 case 'BIFF2FONTCLR': case 'BIFF2FMTCNT': case 'BIFF2FONTXTRA': break;
26573 case 'BIFF2XF': case 'BIFF3XF': case 'BIFF4XF': break;
26574 case 'BIFF4FMTCNT': case 'BIFF2ROW': case 'BIFF2WINDOW2': break;
26575
26576 /* Miscellaneous */
26577 case 'SCENARIO': case 'DConBin': case 'PicF': case 'DataLabExt':
26578 case 'Lel': case 'BopPop': case 'BopPopCustom': case 'RealTimeData':
26579 case 'Name': break;
26580 case 'LHNGraph': case 'FnGroupName': case 'AddMenu': case 'LPr': break;
26581 case 'ListObj': case 'ListField': break;
26582 case 'RRSort': break;
26583 case 'BigName': break;
26584 case 'ToolbarHdr': case 'ToolbarEnd': break;
26585 case 'DDEObjName': break;
26586 case 'FRTArchId$': break;
26587 default: if(options.WTF) throw 'Unrecognized Record ' + R.n;
26588 }}}}
26589 } else blob.l += length;
26590 }
26591 wb.SheetNames=keys(Directory).sort(function(a,b) { return Number(a) - Number(b); }).map(function(x){return Directory[x].name;});
26592 if(!options.bookSheets) wb.Sheets=Sheets;
26593 if(wb.Sheets) FilterDatabases.forEach(function(r,i) { wb.Sheets[wb.SheetNames[i]]['!autofilter'] = r; });
26594 wb.Preamble=Preamble;
26595 wb.Strings = sst;
26596 wb.SSF = SSF.get_table();
26597 if(opts.enc) wb.Encryption = opts.enc;
26598 if(themes) wb.Themes = themes;
26599 wb.Metadata = {};
26600 if(country !== undefined) wb.Metadata.Country = country;
26601 if(supbooks.names.length > 0) Workbook.Names = supbooks.names;
26602 wb.Workbook = Workbook;
26603 return wb;
26604}
26605
26606/* TODO: split props*/
26607var PSCLSID = {
26608 SI: "e0859ff2f94f6810ab9108002b27b3d9",
26609 DSI: "02d5cdd59c2e1b10939708002b2cf9ae",
26610 UDI: "05d5cdd59c2e1b10939708002b2cf9ae"
26611};
26612function parse_xls_props(cfb, props, o) {
26613 /* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */
26614 var DSI = CFB.find(cfb, '!DocumentSummaryInformation');
26615 if(DSI && DSI.size > 0) try {
26616 var DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI, PSCLSID.DSI);
26617 for(var d in DocSummary) props[d] = DocSummary[d];
26618 } catch(e) {if(o.WTF) throw e;/* empty */}
26619
26620 /* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/
26621 var SI = CFB.find(cfb, '!SummaryInformation');
26622 if(SI && SI.size > 0) try {
26623 var Summary = parse_PropertySetStream(SI, SummaryPIDSI, PSCLSID.SI);
26624 for(var s in Summary) if(props[s] == null) props[s] = Summary[s];
26625 } catch(e) {if(o.WTF) throw e;/* empty */}
26626
26627 if(props.HeadingPairs && props.TitlesOfParts) {
26628 load_props_pairs(props.HeadingPairs, props.TitlesOfParts, props, o);
26629 delete props.HeadingPairs; delete props.TitlesOfParts;
26630 }
26631}
26632function write_xls_props(wb, cfb) {
26633 var DSEntries = [], SEntries = [], CEntries = [];
26634 var i = 0, Keys;
26635 if(wb.Props) {
26636 Keys = keys(wb.Props);
26637 // $FlowIgnore
26638 for(i = 0; i < Keys.length; ++i) (DocSummaryRE.hasOwnProperty(Keys[i]) ? DSEntries : SummaryRE.hasOwnProperty(Keys[i]) ? SEntries : CEntries).push([Keys[i], wb.Props[Keys[i]]]);
26639 }
26640 if(wb.Custprops) {
26641 Keys = keys(wb.Custprops);
26642 // $FlowIgnore
26643 for(i = 0; i < Keys.length; ++i) if(!(wb.Props||{}).hasOwnProperty(Keys[i])) (DocSummaryRE.hasOwnProperty(Keys[i]) ? DSEntries : SummaryRE.hasOwnProperty(Keys[i]) ? SEntries : CEntries).push([Keys[i], wb.Custprops[Keys[i]]]);
26644 }
26645 var CEntries2 = [];
26646 for(i = 0; i < CEntries.length; ++i) {
26647 if(XLSPSSkip.indexOf(CEntries[i][0]) > -1) continue;
26648 if(CEntries[i][1] == null) continue;
26649 CEntries2.push(CEntries[i]);
26650 }
26651 if(SEntries.length) CFB.utils.cfb_add(cfb, "/\u0005SummaryInformation", write_PropertySetStream(SEntries, PSCLSID.SI, SummaryRE, SummaryPIDSI));
26652 if(DSEntries.length || CEntries2.length) CFB.utils.cfb_add(cfb, "/\u0005DocumentSummaryInformation", write_PropertySetStream(DSEntries, PSCLSID.DSI, DocSummaryRE, DocSummaryPIDDSI, CEntries2.length ? CEntries2 : null, PSCLSID.UDI));
26653}
26654
26655function parse_xlscfb(cfb, options) {
26656if(!options) options = {};
26657fix_read_opts(options);
26658reset_cp();
26659if(options.codepage) set_ansi(options.codepage);
26660var CompObj, WB;
26661if(cfb.FullPaths) {
26662 if(CFB.find(cfb, '/encryption')) throw new Error("File is password-protected");
26663 CompObj = CFB.find(cfb, '!CompObj');
26664 WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book');
26665} else {
26666 switch(options.type) {
26667 case 'base64': cfb = s2a(Base64.decode(cfb)); break;
26668 case 'binary': cfb = s2a(cfb); break;
26669 case 'buffer': break;
26670 case 'array': if(!Array.isArray(cfb)) cfb = Array.prototype.slice.call(cfb); break;
26671 }
26672 prep_blob(cfb, 0);
26673 WB = ({content: cfb});
26674}
26675var WorkbookP;
26676
26677var _data;
26678if(CompObj) parse_compobj(CompObj);
26679if(options.bookProps && !options.bookSheets) WorkbookP = ({});
26680else {
26681 var T = has_buf ? 'buffer' : 'array';
26682 if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options);
26683 /* Quattro Pro 7-8 */
26684 else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
26685 /* Quattro Pro 9 */
26686 else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options));
26687 else throw new Error("Cannot find Workbook stream");
26688 if(options.bookVBA && cfb.FullPaths && CFB.find(cfb, '/_VBA_PROJECT_CUR/VBA/dir')) WorkbookP.vbaraw = make_vba_xls(cfb);
26689}
26690
26691var props = {};
26692if(cfb.FullPaths) parse_xls_props(cfb, props, options);
26693
26694WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */
26695if(options.bookFiles) WorkbookP.cfb = cfb;
26696/*WorkbookP.CompObjP = CompObjP; // TODO: storage? */
26697return WorkbookP;
26698}
26699
26700
26701function write_xlscfb(wb, opts) {
26702 var o = opts || {};
26703 var cfb = CFB.utils.cfb_new({root:"R"});
26704 var wbpath = "/Workbook";
26705 switch(o.bookType || "xls") {
26706 case "xls": o.bookType = "biff8";
26707 /* falls through */
26708 case "xla": if(!o.bookType) o.bookType = "xla";
26709 /* falls through */
26710 case "biff8": wbpath = "/Workbook"; o.biff = 8; break;
26711 case "biff5": wbpath = "/Book"; o.biff = 5; break;
26712 default: throw new Error("invalid type " + o.bookType + " for XLS CFB");
26713 }
26714 CFB.utils.cfb_add(cfb, wbpath, write_biff_buf(wb, o));
26715 if(o.biff == 8 && (wb.Props || wb.Custprops)) write_xls_props(wb, cfb);
26716 // TODO: SI, DSI, CO
26717 if(o.biff == 8 && wb.vbaraw) fill_vba_xls(cfb, CFB.read(wb.vbaraw, {type: typeof wb.vbaraw == "string" ? "binary" : "buffer"}));
26718 return cfb;
26719}
26720/* [MS-XLSB] 2.3 Record Enumeration */
26721var XLSBRecordEnum = {
267220x0000: { n:"BrtRowHdr", f:parse_BrtRowHdr },
267230x0001: { n:"BrtCellBlank", f:parse_BrtCellBlank },
267240x0002: { n:"BrtCellRk", f:parse_BrtCellRk },
267250x0003: { n:"BrtCellError", f:parse_BrtCellError },
267260x0004: { n:"BrtCellBool", f:parse_BrtCellBool },
267270x0005: { n:"BrtCellReal", f:parse_BrtCellReal },
267280x0006: { n:"BrtCellSt", f:parse_BrtCellSt },
267290x0007: { n:"BrtCellIsst", f:parse_BrtCellIsst },
267300x0008: { n:"BrtFmlaString", f:parse_BrtFmlaString },
267310x0009: { n:"BrtFmlaNum", f:parse_BrtFmlaNum },
267320x000A: { n:"BrtFmlaBool", f:parse_BrtFmlaBool },
267330x000B: { n:"BrtFmlaError", f:parse_BrtFmlaError },
267340x0010: { n:"BrtFRTArchID$", f:parse_BrtFRTArchID$ },
267350x0013: { n:"BrtSSTItem", f:parse_RichStr },
267360x0014: { n:"BrtPCDIMissing" },
267370x0015: { n:"BrtPCDINumber" },
267380x0016: { n:"BrtPCDIBoolean" },
267390x0017: { n:"BrtPCDIError" },
267400x0018: { n:"BrtPCDIString" },
267410x0019: { n:"BrtPCDIDatetime" },
267420x001A: { n:"BrtPCDIIndex" },
267430x001B: { n:"BrtPCDIAMissing" },
267440x001C: { n:"BrtPCDIANumber" },
267450x001D: { n:"BrtPCDIABoolean" },
267460x001E: { n:"BrtPCDIAError" },
267470x001F: { n:"BrtPCDIAString" },
267480x0020: { n:"BrtPCDIADatetime" },
267490x0021: { n:"BrtPCRRecord" },
267500x0022: { n:"BrtPCRRecordDt" },
267510x0023: { n:"BrtFRTBegin" },
267520x0024: { n:"BrtFRTEnd" },
267530x0025: { n:"BrtACBegin" },
267540x0026: { n:"BrtACEnd" },
267550x0027: { n:"BrtName", f:parse_BrtName },
267560x0028: { n:"BrtIndexRowBlock" },
267570x002A: { n:"BrtIndexBlock" },
267580x002B: { n:"BrtFont", f:parse_BrtFont },
267590x002C: { n:"BrtFmt", f:parse_BrtFmt },
267600x002D: { n:"BrtFill", f:parse_BrtFill },
267610x002E: { n:"BrtBorder", f:parse_BrtBorder },
267620x002F: { n:"BrtXF", f:parse_BrtXF },
267630x0030: { n:"BrtStyle" },
267640x0031: { n:"BrtCellMeta" },
267650x0032: { n:"BrtValueMeta" },
267660x0033: { n:"BrtMdb" },
267670x0034: { n:"BrtBeginFmd" },
267680x0035: { n:"BrtEndFmd" },
267690x0036: { n:"BrtBeginMdx" },
267700x0037: { n:"BrtEndMdx" },
267710x0038: { n:"BrtBeginMdxTuple" },
267720x0039: { n:"BrtEndMdxTuple" },
267730x003A: { n:"BrtMdxMbrIstr" },
267740x003B: { n:"BrtStr" },
267750x003C: { n:"BrtColInfo", f:parse_ColInfo },
267760x003E: { n:"BrtCellRString" },
267770x003F: { n:"BrtCalcChainItem$", f:parse_BrtCalcChainItem$ },
267780x0040: { n:"BrtDVal", f:parse_BrtDVal },
267790x0041: { n:"BrtSxvcellNum" },
267800x0042: { n:"BrtSxvcellStr" },
267810x0043: { n:"BrtSxvcellBool" },
267820x0044: { n:"BrtSxvcellErr" },
267830x0045: { n:"BrtSxvcellDate" },
267840x0046: { n:"BrtSxvcellNil" },
267850x0080: { n:"BrtFileVersion" },
267860x0081: { n:"BrtBeginSheet" },
267870x0082: { n:"BrtEndSheet" },
267880x0083: { n:"BrtBeginBook", f:parsenoop, p:0 },
267890x0084: { n:"BrtEndBook" },
267900x0085: { n:"BrtBeginWsViews" },
267910x0086: { n:"BrtEndWsViews" },
267920x0087: { n:"BrtBeginBookViews" },
267930x0088: { n:"BrtEndBookViews" },
267940x0089: { n:"BrtBeginWsView", f:parse_BrtBeginWsView },
267950x008A: { n:"BrtEndWsView" },
267960x008B: { n:"BrtBeginCsViews" },
267970x008C: { n:"BrtEndCsViews" },
267980x008D: { n:"BrtBeginCsView" },
267990x008E: { n:"BrtEndCsView" },
268000x008F: { n:"BrtBeginBundleShs" },
268010x0090: { n:"BrtEndBundleShs" },
268020x0091: { n:"BrtBeginSheetData" },
268030x0092: { n:"BrtEndSheetData" },
268040x0093: { n:"BrtWsProp", f:parse_BrtWsProp },
268050x0094: { n:"BrtWsDim", f:parse_BrtWsDim, p:16 },
268060x0097: { n:"BrtPane", f:parse_BrtPane },
268070x0098: { n:"BrtSel" },
268080x0099: { n:"BrtWbProp", f:parse_BrtWbProp },
268090x009A: { n:"BrtWbFactoid" },
268100x009B: { n:"BrtFileRecover" },
268110x009C: { n:"BrtBundleSh", f:parse_BrtBundleSh },
268120x009D: { n:"BrtCalcProp" },
268130x009E: { n:"BrtBookView" },
268140x009F: { n:"BrtBeginSst", f:parse_BrtBeginSst },
268150x00A0: { n:"BrtEndSst" },
268160x00A1: { n:"BrtBeginAFilter", f:parse_UncheckedRfX },
268170x00A2: { n:"BrtEndAFilter" },
268180x00A3: { n:"BrtBeginFilterColumn" },
268190x00A4: { n:"BrtEndFilterColumn" },
268200x00A5: { n:"BrtBeginFilters" },
268210x00A6: { n:"BrtEndFilters" },
268220x00A7: { n:"BrtFilter" },
268230x00A8: { n:"BrtColorFilter" },
268240x00A9: { n:"BrtIconFilter" },
268250x00AA: { n:"BrtTop10Filter" },
268260x00AB: { n:"BrtDynamicFilter" },
268270x00AC: { n:"BrtBeginCustomFilters" },
268280x00AD: { n:"BrtEndCustomFilters" },
268290x00AE: { n:"BrtCustomFilter" },
268300x00AF: { n:"BrtAFilterDateGroupItem" },
268310x00B0: { n:"BrtMergeCell", f:parse_BrtMergeCell },
268320x00B1: { n:"BrtBeginMergeCells" },
268330x00B2: { n:"BrtEndMergeCells" },
268340x00B3: { n:"BrtBeginPivotCacheDef" },
268350x00B4: { n:"BrtEndPivotCacheDef" },
268360x00B5: { n:"BrtBeginPCDFields" },
268370x00B6: { n:"BrtEndPCDFields" },
268380x00B7: { n:"BrtBeginPCDField" },
268390x00B8: { n:"BrtEndPCDField" },
268400x00B9: { n:"BrtBeginPCDSource" },
268410x00BA: { n:"BrtEndPCDSource" },
268420x00BB: { n:"BrtBeginPCDSRange" },
268430x00BC: { n:"BrtEndPCDSRange" },
268440x00BD: { n:"BrtBeginPCDFAtbl" },
268450x00BE: { n:"BrtEndPCDFAtbl" },
268460x00BF: { n:"BrtBeginPCDIRun" },
268470x00C0: { n:"BrtEndPCDIRun" },
268480x00C1: { n:"BrtBeginPivotCacheRecords" },
268490x00C2: { n:"BrtEndPivotCacheRecords" },
268500x00C3: { n:"BrtBeginPCDHierarchies" },
268510x00C4: { n:"BrtEndPCDHierarchies" },
268520x00C5: { n:"BrtBeginPCDHierarchy" },
268530x00C6: { n:"BrtEndPCDHierarchy" },
268540x00C7: { n:"BrtBeginPCDHFieldsUsage" },
268550x00C8: { n:"BrtEndPCDHFieldsUsage" },
268560x00C9: { n:"BrtBeginExtConnection" },
268570x00CA: { n:"BrtEndExtConnection" },
268580x00CB: { n:"BrtBeginECDbProps" },
268590x00CC: { n:"BrtEndECDbProps" },
268600x00CD: { n:"BrtBeginECOlapProps" },
268610x00CE: { n:"BrtEndECOlapProps" },
268620x00CF: { n:"BrtBeginPCDSConsol" },
268630x00D0: { n:"BrtEndPCDSConsol" },
268640x00D1: { n:"BrtBeginPCDSCPages" },
268650x00D2: { n:"BrtEndPCDSCPages" },
268660x00D3: { n:"BrtBeginPCDSCPage" },
268670x00D4: { n:"BrtEndPCDSCPage" },
268680x00D5: { n:"BrtBeginPCDSCPItem" },
268690x00D6: { n:"BrtEndPCDSCPItem" },
268700x00D7: { n:"BrtBeginPCDSCSets" },
268710x00D8: { n:"BrtEndPCDSCSets" },
268720x00D9: { n:"BrtBeginPCDSCSet" },
268730x00DA: { n:"BrtEndPCDSCSet" },
268740x00DB: { n:"BrtBeginPCDFGroup" },
268750x00DC: { n:"BrtEndPCDFGroup" },
268760x00DD: { n:"BrtBeginPCDFGItems" },
268770x00DE: { n:"BrtEndPCDFGItems" },
268780x00DF: { n:"BrtBeginPCDFGRange" },
268790x00E0: { n:"BrtEndPCDFGRange" },
268800x00E1: { n:"BrtBeginPCDFGDiscrete" },
268810x00E2: { n:"BrtEndPCDFGDiscrete" },
268820x00E3: { n:"BrtBeginPCDSDTupleCache" },
268830x00E4: { n:"BrtEndPCDSDTupleCache" },
268840x00E5: { n:"BrtBeginPCDSDTCEntries" },
268850x00E6: { n:"BrtEndPCDSDTCEntries" },
268860x00E7: { n:"BrtBeginPCDSDTCEMembers" },
268870x00E8: { n:"BrtEndPCDSDTCEMembers" },
268880x00E9: { n:"BrtBeginPCDSDTCEMember" },
268890x00EA: { n:"BrtEndPCDSDTCEMember" },
268900x00EB: { n:"BrtBeginPCDSDTCQueries" },
268910x00EC: { n:"BrtEndPCDSDTCQueries" },
268920x00ED: { n:"BrtBeginPCDSDTCQuery" },
268930x00EE: { n:"BrtEndPCDSDTCQuery" },
268940x00EF: { n:"BrtBeginPCDSDTCSets" },
268950x00F0: { n:"BrtEndPCDSDTCSets" },
268960x00F1: { n:"BrtBeginPCDSDTCSet" },
268970x00F2: { n:"BrtEndPCDSDTCSet" },
268980x00F3: { n:"BrtBeginPCDCalcItems" },
268990x00F4: { n:"BrtEndPCDCalcItems" },
269000x00F5: { n:"BrtBeginPCDCalcItem" },
269010x00F6: { n:"BrtEndPCDCalcItem" },
269020x00F7: { n:"BrtBeginPRule" },
269030x00F8: { n:"BrtEndPRule" },
269040x00F9: { n:"BrtBeginPRFilters" },
269050x00FA: { n:"BrtEndPRFilters" },
269060x00FB: { n:"BrtBeginPRFilter" },
269070x00FC: { n:"BrtEndPRFilter" },
269080x00FD: { n:"BrtBeginPNames" },
269090x00FE: { n:"BrtEndPNames" },
269100x00FF: { n:"BrtBeginPName" },
269110x0100: { n:"BrtEndPName" },
269120x0101: { n:"BrtBeginPNPairs" },
269130x0102: { n:"BrtEndPNPairs" },
269140x0103: { n:"BrtBeginPNPair" },
269150x0104: { n:"BrtEndPNPair" },
269160x0105: { n:"BrtBeginECWebProps" },
269170x0106: { n:"BrtEndECWebProps" },
269180x0107: { n:"BrtBeginEcWpTables" },
269190x0108: { n:"BrtEndECWPTables" },
269200x0109: { n:"BrtBeginECParams" },
269210x010A: { n:"BrtEndECParams" },
269220x010B: { n:"BrtBeginECParam" },
269230x010C: { n:"BrtEndECParam" },
269240x010D: { n:"BrtBeginPCDKPIs" },
269250x010E: { n:"BrtEndPCDKPIs" },
269260x010F: { n:"BrtBeginPCDKPI" },
269270x0110: { n:"BrtEndPCDKPI" },
269280x0111: { n:"BrtBeginDims" },
269290x0112: { n:"BrtEndDims" },
269300x0113: { n:"BrtBeginDim" },
269310x0114: { n:"BrtEndDim" },
269320x0115: { n:"BrtIndexPartEnd" },
269330x0116: { n:"BrtBeginStyleSheet" },
269340x0117: { n:"BrtEndStyleSheet" },
269350x0118: { n:"BrtBeginSXView" },
269360x0119: { n:"BrtEndSXVI" },
269370x011A: { n:"BrtBeginSXVI" },
269380x011B: { n:"BrtBeginSXVIs" },
269390x011C: { n:"BrtEndSXVIs" },
269400x011D: { n:"BrtBeginSXVD" },
269410x011E: { n:"BrtEndSXVD" },
269420x011F: { n:"BrtBeginSXVDs" },
269430x0120: { n:"BrtEndSXVDs" },
269440x0121: { n:"BrtBeginSXPI" },
269450x0122: { n:"BrtEndSXPI" },
269460x0123: { n:"BrtBeginSXPIs" },
269470x0124: { n:"BrtEndSXPIs" },
269480x0125: { n:"BrtBeginSXDI" },
269490x0126: { n:"BrtEndSXDI" },
269500x0127: { n:"BrtBeginSXDIs" },
269510x0128: { n:"BrtEndSXDIs" },
269520x0129: { n:"BrtBeginSXLI" },
269530x012A: { n:"BrtEndSXLI" },
269540x012B: { n:"BrtBeginSXLIRws" },
269550x012C: { n:"BrtEndSXLIRws" },
269560x012D: { n:"BrtBeginSXLICols" },
269570x012E: { n:"BrtEndSXLICols" },
269580x012F: { n:"BrtBeginSXFormat" },
269590x0130: { n:"BrtEndSXFormat" },
269600x0131: { n:"BrtBeginSXFormats" },
269610x0132: { n:"BrtEndSxFormats" },
269620x0133: { n:"BrtBeginSxSelect" },
269630x0134: { n:"BrtEndSxSelect" },
269640x0135: { n:"BrtBeginISXVDRws" },
269650x0136: { n:"BrtEndISXVDRws" },
269660x0137: { n:"BrtBeginISXVDCols" },
269670x0138: { n:"BrtEndISXVDCols" },
269680x0139: { n:"BrtEndSXLocation" },
269690x013A: { n:"BrtBeginSXLocation" },
269700x013B: { n:"BrtEndSXView" },
269710x013C: { n:"BrtBeginSXTHs" },
269720x013D: { n:"BrtEndSXTHs" },
269730x013E: { n:"BrtBeginSXTH" },
269740x013F: { n:"BrtEndSXTH" },
269750x0140: { n:"BrtBeginISXTHRws" },
269760x0141: { n:"BrtEndISXTHRws" },
269770x0142: { n:"BrtBeginISXTHCols" },
269780x0143: { n:"BrtEndISXTHCols" },
269790x0144: { n:"BrtBeginSXTDMPS" },
269800x0145: { n:"BrtEndSXTDMPs" },
269810x0146: { n:"BrtBeginSXTDMP" },
269820x0147: { n:"BrtEndSXTDMP" },
269830x0148: { n:"BrtBeginSXTHItems" },
269840x0149: { n:"BrtEndSXTHItems" },
269850x014A: { n:"BrtBeginSXTHItem" },
269860x014B: { n:"BrtEndSXTHItem" },
269870x014C: { n:"BrtBeginMetadata" },
269880x014D: { n:"BrtEndMetadata" },
269890x014E: { n:"BrtBeginEsmdtinfo" },
269900x014F: { n:"BrtMdtinfo" },
269910x0150: { n:"BrtEndEsmdtinfo" },
269920x0151: { n:"BrtBeginEsmdb" },
269930x0152: { n:"BrtEndEsmdb" },
269940x0153: { n:"BrtBeginEsfmd" },
269950x0154: { n:"BrtEndEsfmd" },
269960x0155: { n:"BrtBeginSingleCells" },
269970x0156: { n:"BrtEndSingleCells" },
269980x0157: { n:"BrtBeginList" },
269990x0158: { n:"BrtEndList" },
270000x0159: { n:"BrtBeginListCols" },
270010x015A: { n:"BrtEndListCols" },
270020x015B: { n:"BrtBeginListCol" },
270030x015C: { n:"BrtEndListCol" },
270040x015D: { n:"BrtBeginListXmlCPr" },
270050x015E: { n:"BrtEndListXmlCPr" },
270060x015F: { n:"BrtListCCFmla" },
270070x0160: { n:"BrtListTrFmla" },
270080x0161: { n:"BrtBeginExternals" },
270090x0162: { n:"BrtEndExternals" },
270100x0163: { n:"BrtSupBookSrc", f:parse_RelID},
270110x0165: { n:"BrtSupSelf" },
270120x0166: { n:"BrtSupSame" },
270130x0167: { n:"BrtSupTabs" },
270140x0168: { n:"BrtBeginSupBook" },
270150x0169: { n:"BrtPlaceholderName" },
270160x016A: { n:"BrtExternSheet", f:parse_ExternSheet },
270170x016B: { n:"BrtExternTableStart" },
270180x016C: { n:"BrtExternTableEnd" },
270190x016E: { n:"BrtExternRowHdr" },
270200x016F: { n:"BrtExternCellBlank" },
270210x0170: { n:"BrtExternCellReal" },
270220x0171: { n:"BrtExternCellBool" },
270230x0172: { n:"BrtExternCellError" },
270240x0173: { n:"BrtExternCellString" },
270250x0174: { n:"BrtBeginEsmdx" },
270260x0175: { n:"BrtEndEsmdx" },
270270x0176: { n:"BrtBeginMdxSet" },
270280x0177: { n:"BrtEndMdxSet" },
270290x0178: { n:"BrtBeginMdxMbrProp" },
270300x0179: { n:"BrtEndMdxMbrProp" },
270310x017A: { n:"BrtBeginMdxKPI" },
270320x017B: { n:"BrtEndMdxKPI" },
270330x017C: { n:"BrtBeginEsstr" },
270340x017D: { n:"BrtEndEsstr" },
270350x017E: { n:"BrtBeginPRFItem" },
270360x017F: { n:"BrtEndPRFItem" },
270370x0180: { n:"BrtBeginPivotCacheIDs" },
270380x0181: { n:"BrtEndPivotCacheIDs" },
270390x0182: { n:"BrtBeginPivotCacheID" },
270400x0183: { n:"BrtEndPivotCacheID" },
270410x0184: { n:"BrtBeginISXVIs" },
270420x0185: { n:"BrtEndISXVIs" },
270430x0186: { n:"BrtBeginColInfos" },
270440x0187: { n:"BrtEndColInfos" },
270450x0188: { n:"BrtBeginRwBrk" },
270460x0189: { n:"BrtEndRwBrk" },
270470x018A: { n:"BrtBeginColBrk" },
270480x018B: { n:"BrtEndColBrk" },
270490x018C: { n:"BrtBrk" },
270500x018D: { n:"BrtUserBookView" },
270510x018E: { n:"BrtInfo" },
270520x018F: { n:"BrtCUsr" },
270530x0190: { n:"BrtUsr" },
270540x0191: { n:"BrtBeginUsers" },
270550x0193: { n:"BrtEOF" },
270560x0194: { n:"BrtUCR" },
270570x0195: { n:"BrtRRInsDel" },
270580x0196: { n:"BrtRREndInsDel" },
270590x0197: { n:"BrtRRMove" },
270600x0198: { n:"BrtRREndMove" },
270610x0199: { n:"BrtRRChgCell" },
270620x019A: { n:"BrtRREndChgCell" },
270630x019B: { n:"BrtRRHeader" },
270640x019C: { n:"BrtRRUserView" },
270650x019D: { n:"BrtRRRenSheet" },
270660x019E: { n:"BrtRRInsertSh" },
270670x019F: { n:"BrtRRDefName" },
270680x01A0: { n:"BrtRRNote" },
270690x01A1: { n:"BrtRRConflict" },
270700x01A2: { n:"BrtRRTQSIF" },
270710x01A3: { n:"BrtRRFormat" },
270720x01A4: { n:"BrtRREndFormat" },
270730x01A5: { n:"BrtRRAutoFmt" },
270740x01A6: { n:"BrtBeginUserShViews" },
270750x01A7: { n:"BrtBeginUserShView" },
270760x01A8: { n:"BrtEndUserShView" },
270770x01A9: { n:"BrtEndUserShViews" },
270780x01AA: { n:"BrtArrFmla", f:parse_BrtArrFmla },
270790x01AB: { n:"BrtShrFmla", f:parse_BrtShrFmla },
270800x01AC: { n:"BrtTable" },
270810x01AD: { n:"BrtBeginExtConnections" },
270820x01AE: { n:"BrtEndExtConnections" },
270830x01AF: { n:"BrtBeginPCDCalcMems" },
270840x01B0: { n:"BrtEndPCDCalcMems" },
270850x01B1: { n:"BrtBeginPCDCalcMem" },
270860x01B2: { n:"BrtEndPCDCalcMem" },
270870x01B3: { n:"BrtBeginPCDHGLevels" },
270880x01B4: { n:"BrtEndPCDHGLevels" },
270890x01B5: { n:"BrtBeginPCDHGLevel" },
270900x01B6: { n:"BrtEndPCDHGLevel" },
270910x01B7: { n:"BrtBeginPCDHGLGroups" },
270920x01B8: { n:"BrtEndPCDHGLGroups" },
270930x01B9: { n:"BrtBeginPCDHGLGroup" },
270940x01BA: { n:"BrtEndPCDHGLGroup" },
270950x01BB: { n:"BrtBeginPCDHGLGMembers" },
270960x01BC: { n:"BrtEndPCDHGLGMembers" },
270970x01BD: { n:"BrtBeginPCDHGLGMember" },
270980x01BE: { n:"BrtEndPCDHGLGMember" },
270990x01BF: { n:"BrtBeginQSI" },
271000x01C0: { n:"BrtEndQSI" },
271010x01C1: { n:"BrtBeginQSIR" },
271020x01C2: { n:"BrtEndQSIR" },
271030x01C3: { n:"BrtBeginDeletedNames" },
271040x01C4: { n:"BrtEndDeletedNames" },
271050x01C5: { n:"BrtBeginDeletedName" },
271060x01C6: { n:"BrtEndDeletedName" },
271070x01C7: { n:"BrtBeginQSIFs" },
271080x01C8: { n:"BrtEndQSIFs" },
271090x01C9: { n:"BrtBeginQSIF" },
271100x01CA: { n:"BrtEndQSIF" },
271110x01CB: { n:"BrtBeginAutoSortScope" },
271120x01CC: { n:"BrtEndAutoSortScope" },
271130x01CD: { n:"BrtBeginConditionalFormatting" },
271140x01CE: { n:"BrtEndConditionalFormatting" },
271150x01CF: { n:"BrtBeginCFRule" },
271160x01D0: { n:"BrtEndCFRule" },
271170x01D1: { n:"BrtBeginIconSet" },
271180x01D2: { n:"BrtEndIconSet" },
271190x01D3: { n:"BrtBeginDatabar" },
271200x01D4: { n:"BrtEndDatabar" },
271210x01D5: { n:"BrtBeginColorScale" },
271220x01D6: { n:"BrtEndColorScale" },
271230x01D7: { n:"BrtCFVO" },
271240x01D8: { n:"BrtExternValueMeta" },
271250x01D9: { n:"BrtBeginColorPalette" },
271260x01DA: { n:"BrtEndColorPalette" },
271270x01DB: { n:"BrtIndexedColor" },
271280x01DC: { n:"BrtMargins", f:parse_BrtMargins },
271290x01DD: { n:"BrtPrintOptions" },
271300x01DE: { n:"BrtPageSetup" },
271310x01DF: { n:"BrtBeginHeaderFooter" },
271320x01E0: { n:"BrtEndHeaderFooter" },
271330x01E1: { n:"BrtBeginSXCrtFormat" },
271340x01E2: { n:"BrtEndSXCrtFormat" },
271350x01E3: { n:"BrtBeginSXCrtFormats" },
271360x01E4: { n:"BrtEndSXCrtFormats" },
271370x01E5: { n:"BrtWsFmtInfo", f:parse_BrtWsFmtInfo },
271380x01E6: { n:"BrtBeginMgs" },
271390x01E7: { n:"BrtEndMGs" },
271400x01E8: { n:"BrtBeginMGMaps" },
271410x01E9: { n:"BrtEndMGMaps" },
271420x01EA: { n:"BrtBeginMG" },
271430x01EB: { n:"BrtEndMG" },
271440x01EC: { n:"BrtBeginMap" },
271450x01ED: { n:"BrtEndMap" },
271460x01EE: { n:"BrtHLink", f:parse_BrtHLink },
271470x01EF: { n:"BrtBeginDCon" },
271480x01F0: { n:"BrtEndDCon" },
271490x01F1: { n:"BrtBeginDRefs" },
271500x01F2: { n:"BrtEndDRefs" },
271510x01F3: { n:"BrtDRef" },
271520x01F4: { n:"BrtBeginScenMan" },
271530x01F5: { n:"BrtEndScenMan" },
271540x01F6: { n:"BrtBeginSct" },
271550x01F7: { n:"BrtEndSct" },
271560x01F8: { n:"BrtSlc" },
271570x01F9: { n:"BrtBeginDXFs" },
271580x01FA: { n:"BrtEndDXFs" },
271590x01FB: { n:"BrtDXF" },
271600x01FC: { n:"BrtBeginTableStyles" },
271610x01FD: { n:"BrtEndTableStyles" },
271620x01FE: { n:"BrtBeginTableStyle" },
271630x01FF: { n:"BrtEndTableStyle" },
271640x0200: { n:"BrtTableStyleElement" },
271650x0201: { n:"BrtTableStyleClient" },
271660x0202: { n:"BrtBeginVolDeps" },
271670x0203: { n:"BrtEndVolDeps" },
271680x0204: { n:"BrtBeginVolType" },
271690x0205: { n:"BrtEndVolType" },
271700x0206: { n:"BrtBeginVolMain" },
271710x0207: { n:"BrtEndVolMain" },
271720x0208: { n:"BrtBeginVolTopic" },
271730x0209: { n:"BrtEndVolTopic" },
271740x020A: { n:"BrtVolSubtopic" },
271750x020B: { n:"BrtVolRef" },
271760x020C: { n:"BrtVolNum" },
271770x020D: { n:"BrtVolErr" },
271780x020E: { n:"BrtVolStr" },
271790x020F: { n:"BrtVolBool" },
271800x0210: { n:"BrtBeginCalcChain$" },
271810x0211: { n:"BrtEndCalcChain$" },
271820x0212: { n:"BrtBeginSortState" },
271830x0213: { n:"BrtEndSortState" },
271840x0214: { n:"BrtBeginSortCond" },
271850x0215: { n:"BrtEndSortCond" },
271860x0216: { n:"BrtBookProtection" },
271870x0217: { n:"BrtSheetProtection" },
271880x0218: { n:"BrtRangeProtection" },
271890x0219: { n:"BrtPhoneticInfo" },
271900x021A: { n:"BrtBeginECTxtWiz" },
271910x021B: { n:"BrtEndECTxtWiz" },
271920x021C: { n:"BrtBeginECTWFldInfoLst" },
271930x021D: { n:"BrtEndECTWFldInfoLst" },
271940x021E: { n:"BrtBeginECTwFldInfo" },
271950x0224: { n:"BrtFileSharing" },
271960x0225: { n:"BrtOleSize" },
271970x0226: { n:"BrtDrawing", f:parse_RelID },
271980x0227: { n:"BrtLegacyDrawing" },
271990x0228: { n:"BrtLegacyDrawingHF" },
272000x0229: { n:"BrtWebOpt" },
272010x022A: { n:"BrtBeginWebPubItems" },
272020x022B: { n:"BrtEndWebPubItems" },
272030x022C: { n:"BrtBeginWebPubItem" },
272040x022D: { n:"BrtEndWebPubItem" },
272050x022E: { n:"BrtBeginSXCondFmt" },
272060x022F: { n:"BrtEndSXCondFmt" },
272070x0230: { n:"BrtBeginSXCondFmts" },
272080x0231: { n:"BrtEndSXCondFmts" },
272090x0232: { n:"BrtBkHim" },
272100x0234: { n:"BrtColor" },
272110x0235: { n:"BrtBeginIndexedColors" },
272120x0236: { n:"BrtEndIndexedColors" },
272130x0239: { n:"BrtBeginMRUColors" },
272140x023A: { n:"BrtEndMRUColors" },
272150x023C: { n:"BrtMRUColor" },
272160x023D: { n:"BrtBeginDVals" },
272170x023E: { n:"BrtEndDVals" },
272180x0241: { n:"BrtSupNameStart" },
272190x0242: { n:"BrtSupNameValueStart" },
272200x0243: { n:"BrtSupNameValueEnd" },
272210x0244: { n:"BrtSupNameNum" },
272220x0245: { n:"BrtSupNameErr" },
272230x0246: { n:"BrtSupNameSt" },
272240x0247: { n:"BrtSupNameNil" },
272250x0248: { n:"BrtSupNameBool" },
272260x0249: { n:"BrtSupNameFmla" },
272270x024A: { n:"BrtSupNameBits" },
272280x024B: { n:"BrtSupNameEnd" },
272290x024C: { n:"BrtEndSupBook" },
272300x024D: { n:"BrtCellSmartTagProperty" },
272310x024E: { n:"BrtBeginCellSmartTag" },
272320x024F: { n:"BrtEndCellSmartTag" },
272330x0250: { n:"BrtBeginCellSmartTags" },
272340x0251: { n:"BrtEndCellSmartTags" },
272350x0252: { n:"BrtBeginSmartTags" },
272360x0253: { n:"BrtEndSmartTags" },
272370x0254: { n:"BrtSmartTagType" },
272380x0255: { n:"BrtBeginSmartTagTypes" },
272390x0256: { n:"BrtEndSmartTagTypes" },
272400x0257: { n:"BrtBeginSXFilters" },
272410x0258: { n:"BrtEndSXFilters" },
272420x0259: { n:"BrtBeginSXFILTER" },
272430x025A: { n:"BrtEndSXFilter" },
272440x025B: { n:"BrtBeginFills" },
272450x025C: { n:"BrtEndFills" },
272460x025D: { n:"BrtBeginCellWatches" },
272470x025E: { n:"BrtEndCellWatches" },
272480x025F: { n:"BrtCellWatch" },
272490x0260: { n:"BrtBeginCRErrs" },
272500x0261: { n:"BrtEndCRErrs" },
272510x0262: { n:"BrtCrashRecErr" },
272520x0263: { n:"BrtBeginFonts" },
272530x0264: { n:"BrtEndFonts" },
272540x0265: { n:"BrtBeginBorders" },
272550x0266: { n:"BrtEndBorders" },
272560x0267: { n:"BrtBeginFmts" },
272570x0268: { n:"BrtEndFmts" },
272580x0269: { n:"BrtBeginCellXFs" },
272590x026A: { n:"BrtEndCellXFs" },
272600x026B: { n:"BrtBeginStyles" },
272610x026C: { n:"BrtEndStyles" },
272620x0271: { n:"BrtBigName" },
272630x0272: { n:"BrtBeginCellStyleXFs" },
272640x0273: { n:"BrtEndCellStyleXFs" },
272650x0274: { n:"BrtBeginComments" },
272660x0275: { n:"BrtEndComments" },
272670x0276: { n:"BrtBeginCommentAuthors" },
272680x0277: { n:"BrtEndCommentAuthors" },
272690x0278: { n:"BrtCommentAuthor", f:parse_BrtCommentAuthor },
272700x0279: { n:"BrtBeginCommentList" },
272710x027A: { n:"BrtEndCommentList" },
272720x027B: { n:"BrtBeginComment", f:parse_BrtBeginComment},
272730x027C: { n:"BrtEndComment" },
272740x027D: { n:"BrtCommentText", f:parse_BrtCommentText },
272750x027E: { n:"BrtBeginOleObjects" },
272760x027F: { n:"BrtOleObject" },
272770x0280: { n:"BrtEndOleObjects" },
272780x0281: { n:"BrtBeginSxrules" },
272790x0282: { n:"BrtEndSxRules" },
272800x0283: { n:"BrtBeginActiveXControls" },
272810x0284: { n:"BrtActiveX" },
272820x0285: { n:"BrtEndActiveXControls" },
272830x0286: { n:"BrtBeginPCDSDTCEMembersSortBy" },
272840x0288: { n:"BrtBeginCellIgnoreECs" },
272850x0289: { n:"BrtCellIgnoreEC" },
272860x028A: { n:"BrtEndCellIgnoreECs" },
272870x028B: { n:"BrtCsProp", f:parse_BrtCsProp },
272880x028C: { n:"BrtCsPageSetup" },
272890x028D: { n:"BrtBeginUserCsViews" },
272900x028E: { n:"BrtEndUserCsViews" },
272910x028F: { n:"BrtBeginUserCsView" },
272920x0290: { n:"BrtEndUserCsView" },
272930x0291: { n:"BrtBeginPcdSFCIEntries" },
272940x0292: { n:"BrtEndPCDSFCIEntries" },
272950x0293: { n:"BrtPCDSFCIEntry" },
272960x0294: { n:"BrtBeginListParts" },
272970x0295: { n:"BrtListPart" },
272980x0296: { n:"BrtEndListParts" },
272990x0297: { n:"BrtSheetCalcProp" },
273000x0298: { n:"BrtBeginFnGroup" },
273010x0299: { n:"BrtFnGroup" },
273020x029A: { n:"BrtEndFnGroup" },
273030x029B: { n:"BrtSupAddin" },
273040x029C: { n:"BrtSXTDMPOrder" },
273050x029D: { n:"BrtCsProtection" },
273060x029F: { n:"BrtBeginWsSortMap" },
273070x02A0: { n:"BrtEndWsSortMap" },
273080x02A1: { n:"BrtBeginRRSort" },
273090x02A2: { n:"BrtEndRRSort" },
273100x02A3: { n:"BrtRRSortItem" },
273110x02A4: { n:"BrtFileSharingIso" },
273120x02A5: { n:"BrtBookProtectionIso" },
273130x02A6: { n:"BrtSheetProtectionIso" },
273140x02A7: { n:"BrtCsProtectionIso" },
273150x02A8: { n:"BrtRangeProtectionIso" },
273160x02A9: { n:"BrtDValList" },
273170x0400: { n:"BrtRwDescent" },
273180x0401: { n:"BrtKnownFonts" },
273190x0402: { n:"BrtBeginSXTupleSet" },
273200x0403: { n:"BrtEndSXTupleSet" },
273210x0404: { n:"BrtBeginSXTupleSetHeader" },
273220x0405: { n:"BrtEndSXTupleSetHeader" },
273230x0406: { n:"BrtSXTupleSetHeaderItem" },
273240x0407: { n:"BrtBeginSXTupleSetData" },
273250x0408: { n:"BrtEndSXTupleSetData" },
273260x0409: { n:"BrtBeginSXTupleSetRow" },
273270x040A: { n:"BrtEndSXTupleSetRow" },
273280x040B: { n:"BrtSXTupleSetRowItem" },
273290x040C: { n:"BrtNameExt" },
273300x040D: { n:"BrtPCDH14" },
273310x040E: { n:"BrtBeginPCDCalcMem14" },
273320x040F: { n:"BrtEndPCDCalcMem14" },
273330x0410: { n:"BrtSXTH14" },
273340x0411: { n:"BrtBeginSparklineGroup" },
273350x0412: { n:"BrtEndSparklineGroup" },
273360x0413: { n:"BrtSparkline" },
273370x0414: { n:"BrtSXDI14" },
273380x0415: { n:"BrtWsFmtInfoEx14" },
273390x0416: { n:"BrtBeginConditionalFormatting14" },
273400x0417: { n:"BrtEndConditionalFormatting14" },
273410x0418: { n:"BrtBeginCFRule14" },
273420x0419: { n:"BrtEndCFRule14" },
273430x041A: { n:"BrtCFVO14" },
273440x041B: { n:"BrtBeginDatabar14" },
273450x041C: { n:"BrtBeginIconSet14" },
273460x041D: { n:"BrtDVal14", f: parse_BrtDVal14 },
273470x041E: { n:"BrtBeginDVals14" },
273480x041F: { n:"BrtColor14" },
273490x0420: { n:"BrtBeginSparklines" },
273500x0421: { n:"BrtEndSparklines" },
273510x0422: { n:"BrtBeginSparklineGroups" },
273520x0423: { n:"BrtEndSparklineGroups" },
273530x0425: { n:"BrtSXVD14" },
273540x0426: { n:"BrtBeginSXView14" },
273550x0427: { n:"BrtEndSXView14" },
273560x0428: { n:"BrtBeginSXView16" },
273570x0429: { n:"BrtEndSXView16" },
273580x042A: { n:"BrtBeginPCD14" },
273590x042B: { n:"BrtEndPCD14" },
273600x042C: { n:"BrtBeginExtConn14" },
273610x042D: { n:"BrtEndExtConn14" },
273620x042E: { n:"BrtBeginSlicerCacheIDs" },
273630x042F: { n:"BrtEndSlicerCacheIDs" },
273640x0430: { n:"BrtBeginSlicerCacheID" },
273650x0431: { n:"BrtEndSlicerCacheID" },
273660x0433: { n:"BrtBeginSlicerCache" },
273670x0434: { n:"BrtEndSlicerCache" },
273680x0435: { n:"BrtBeginSlicerCacheDef" },
273690x0436: { n:"BrtEndSlicerCacheDef" },
273700x0437: { n:"BrtBeginSlicersEx" },
273710x0438: { n:"BrtEndSlicersEx" },
273720x0439: { n:"BrtBeginSlicerEx" },
273730x043A: { n:"BrtEndSlicerEx" },
273740x043B: { n:"BrtBeginSlicer" },
273750x043C: { n:"BrtEndSlicer" },
273760x043D: { n:"BrtSlicerCachePivotTables" },
273770x043E: { n:"BrtBeginSlicerCacheOlapImpl" },
273780x043F: { n:"BrtEndSlicerCacheOlapImpl" },
273790x0440: { n:"BrtBeginSlicerCacheLevelsData" },
273800x0441: { n:"BrtEndSlicerCacheLevelsData" },
273810x0442: { n:"BrtBeginSlicerCacheLevelData" },
273820x0443: { n:"BrtEndSlicerCacheLevelData" },
273830x0444: { n:"BrtBeginSlicerCacheSiRanges" },
273840x0445: { n:"BrtEndSlicerCacheSiRanges" },
273850x0446: { n:"BrtBeginSlicerCacheSiRange" },
273860x0447: { n:"BrtEndSlicerCacheSiRange" },
273870x0448: { n:"BrtSlicerCacheOlapItem" },
273880x0449: { n:"BrtBeginSlicerCacheSelections" },
273890x044A: { n:"BrtSlicerCacheSelection" },
273900x044B: { n:"BrtEndSlicerCacheSelections" },
273910x044C: { n:"BrtBeginSlicerCacheNative" },
273920x044D: { n:"BrtEndSlicerCacheNative" },
273930x044E: { n:"BrtSlicerCacheNativeItem" },
273940x044F: { n:"BrtRangeProtection14" },
273950x0450: { n:"BrtRangeProtectionIso14" },
273960x0451: { n:"BrtCellIgnoreEC14" },
273970x0457: { n:"BrtList14" },
273980x0458: { n:"BrtCFIcon" },
273990x0459: { n:"BrtBeginSlicerCachesPivotCacheIDs" },
274000x045A: { n:"BrtEndSlicerCachesPivotCacheIDs" },
274010x045B: { n:"BrtBeginSlicers" },
274020x045C: { n:"BrtEndSlicers" },
274030x045D: { n:"BrtWbProp14" },
274040x045E: { n:"BrtBeginSXEdit" },
274050x045F: { n:"BrtEndSXEdit" },
274060x0460: { n:"BrtBeginSXEdits" },
274070x0461: { n:"BrtEndSXEdits" },
274080x0462: { n:"BrtBeginSXChange" },
274090x0463: { n:"BrtEndSXChange" },
274100x0464: { n:"BrtBeginSXChanges" },
274110x0465: { n:"BrtEndSXChanges" },
274120x0466: { n:"BrtSXTupleItems" },
274130x0468: { n:"BrtBeginSlicerStyle" },
274140x0469: { n:"BrtEndSlicerStyle" },
274150x046A: { n:"BrtSlicerStyleElement" },
274160x046B: { n:"BrtBeginStyleSheetExt14" },
274170x046C: { n:"BrtEndStyleSheetExt14" },
274180x046D: { n:"BrtBeginSlicerCachesPivotCacheID" },
274190x046E: { n:"BrtEndSlicerCachesPivotCacheID" },
274200x046F: { n:"BrtBeginConditionalFormattings" },
274210x0470: { n:"BrtEndConditionalFormattings" },
274220x0471: { n:"BrtBeginPCDCalcMemExt" },
274230x0472: { n:"BrtEndPCDCalcMemExt" },
274240x0473: { n:"BrtBeginPCDCalcMemsExt" },
274250x0474: { n:"BrtEndPCDCalcMemsExt" },
274260x0475: { n:"BrtPCDField14" },
274270x0476: { n:"BrtBeginSlicerStyles" },
274280x0477: { n:"BrtEndSlicerStyles" },
274290x0478: { n:"BrtBeginSlicerStyleElements" },
274300x0479: { n:"BrtEndSlicerStyleElements" },
274310x047A: { n:"BrtCFRuleExt" },
274320x047B: { n:"BrtBeginSXCondFmt14" },
274330x047C: { n:"BrtEndSXCondFmt14" },
274340x047D: { n:"BrtBeginSXCondFmts14" },
274350x047E: { n:"BrtEndSXCondFmts14" },
274360x0480: { n:"BrtBeginSortCond14" },
274370x0481: { n:"BrtEndSortCond14" },
274380x0482: { n:"BrtEndDVals14" },
274390x0483: { n:"BrtEndIconSet14" },
274400x0484: { n:"BrtEndDatabar14" },
274410x0485: { n:"BrtBeginColorScale14" },
274420x0486: { n:"BrtEndColorScale14" },
274430x0487: { n:"BrtBeginSxrules14" },
274440x0488: { n:"BrtEndSxrules14" },
274450x0489: { n:"BrtBeginPRule14" },
274460x048A: { n:"BrtEndPRule14" },
274470x048B: { n:"BrtBeginPRFilters14" },
274480x048C: { n:"BrtEndPRFilters14" },
274490x048D: { n:"BrtBeginPRFilter14" },
274500x048E: { n:"BrtEndPRFilter14" },
274510x048F: { n:"BrtBeginPRFItem14" },
274520x0490: { n:"BrtEndPRFItem14" },
274530x0491: { n:"BrtBeginCellIgnoreECs14" },
274540x0492: { n:"BrtEndCellIgnoreECs14" },
274550x0493: { n:"BrtDxf14" },
274560x0494: { n:"BrtBeginDxF14s" },
274570x0495: { n:"BrtEndDxf14s" },
274580x0499: { n:"BrtFilter14" },
274590x049A: { n:"BrtBeginCustomFilters14" },
274600x049C: { n:"BrtCustomFilter14" },
274610x049D: { n:"BrtIconFilter14" },
274620x049E: { n:"BrtPivotCacheConnectionName" },
274630x0800: { n:"BrtBeginDecoupledPivotCacheIDs" },
274640x0801: { n:"BrtEndDecoupledPivotCacheIDs" },
274650x0802: { n:"BrtDecoupledPivotCacheID" },
274660x0803: { n:"BrtBeginPivotTableRefs" },
274670x0804: { n:"BrtEndPivotTableRefs" },
274680x0805: { n:"BrtPivotTableRef" },
274690x0806: { n:"BrtSlicerCacheBookPivotTables" },
274700x0807: { n:"BrtBeginSxvcells" },
274710x0808: { n:"BrtEndSxvcells" },
274720x0809: { n:"BrtBeginSxRow" },
274730x080A: { n:"BrtEndSxRow" },
274740x080C: { n:"BrtPcdCalcMem15" },
274750x0813: { n:"BrtQsi15" },
274760x0814: { n:"BrtBeginWebExtensions" },
274770x0815: { n:"BrtEndWebExtensions" },
274780x0816: { n:"BrtWebExtension" },
274790x0817: { n:"BrtAbsPath15" },
274800x0818: { n:"BrtBeginPivotTableUISettings" },
274810x0819: { n:"BrtEndPivotTableUISettings" },
274820x081B: { n:"BrtTableSlicerCacheIDs" },
274830x081C: { n:"BrtTableSlicerCacheID" },
274840x081D: { n:"BrtBeginTableSlicerCache" },
274850x081E: { n:"BrtEndTableSlicerCache" },
274860x081F: { n:"BrtSxFilter15" },
274870x0820: { n:"BrtBeginTimelineCachePivotCacheIDs" },
274880x0821: { n:"BrtEndTimelineCachePivotCacheIDs" },
274890x0822: { n:"BrtTimelineCachePivotCacheID" },
274900x0823: { n:"BrtBeginTimelineCacheIDs" },
274910x0824: { n:"BrtEndTimelineCacheIDs" },
274920x0825: { n:"BrtBeginTimelineCacheID" },
274930x0826: { n:"BrtEndTimelineCacheID" },
274940x0827: { n:"BrtBeginTimelinesEx" },
274950x0828: { n:"BrtEndTimelinesEx" },
274960x0829: { n:"BrtBeginTimelineEx" },
274970x082A: { n:"BrtEndTimelineEx" },
274980x082B: { n:"BrtWorkBookPr15" },
274990x082C: { n:"BrtPCDH15" },
275000x082D: { n:"BrtBeginTimelineStyle" },
275010x082E: { n:"BrtEndTimelineStyle" },
275020x082F: { n:"BrtTimelineStyleElement" },
275030x0830: { n:"BrtBeginTimelineStylesheetExt15" },
275040x0831: { n:"BrtEndTimelineStylesheetExt15" },
275050x0832: { n:"BrtBeginTimelineStyles" },
275060x0833: { n:"BrtEndTimelineStyles" },
275070x0834: { n:"BrtBeginTimelineStyleElements" },
275080x0835: { n:"BrtEndTimelineStyleElements" },
275090x0836: { n:"BrtDxf15" },
275100x0837: { n:"BrtBeginDxfs15" },
275110x0838: { n:"brtEndDxfs15" },
275120x0839: { n:"BrtSlicerCacheHideItemsWithNoData" },
275130x083A: { n:"BrtBeginItemUniqueNames" },
275140x083B: { n:"BrtEndItemUniqueNames" },
275150x083C: { n:"BrtItemUniqueName" },
275160x083D: { n:"BrtBeginExtConn15" },
275170x083E: { n:"BrtEndExtConn15" },
275180x083F: { n:"BrtBeginOledbPr15" },
275190x0840: { n:"BrtEndOledbPr15" },
275200x0841: { n:"BrtBeginDataFeedPr15" },
275210x0842: { n:"BrtEndDataFeedPr15" },
275220x0843: { n:"BrtTextPr15" },
275230x0844: { n:"BrtRangePr15" },
275240x0845: { n:"BrtDbCommand15" },
275250x0846: { n:"BrtBeginDbTables15" },
275260x0847: { n:"BrtEndDbTables15" },
275270x0848: { n:"BrtDbTable15" },
275280x0849: { n:"BrtBeginDataModel" },
275290x084A: { n:"BrtEndDataModel" },
275300x084B: { n:"BrtBeginModelTables" },
275310x084C: { n:"BrtEndModelTables" },
275320x084D: { n:"BrtModelTable" },
275330x084E: { n:"BrtBeginModelRelationships" },
275340x084F: { n:"BrtEndModelRelationships" },
275350x0850: { n:"BrtModelRelationship" },
275360x0851: { n:"BrtBeginECTxtWiz15" },
275370x0852: { n:"BrtEndECTxtWiz15" },
275380x0853: { n:"BrtBeginECTWFldInfoLst15" },
275390x0854: { n:"BrtEndECTWFldInfoLst15" },
275400x0855: { n:"BrtBeginECTWFldInfo15" },
275410x0856: { n:"BrtFieldListActiveItem" },
275420x0857: { n:"BrtPivotCacheIdVersion" },
275430x0858: { n:"BrtSXDI15" },
275440x0859: { n:"BrtBeginModelTimeGroupings" },
275450x085A: { n:"BrtEndModelTimeGroupings" },
275460x085B: { n:"BrtBeginModelTimeGrouping" },
275470x085C: { n:"BrtEndModelTimeGrouping" },
275480x085D: { n:"BrtModelTimeGroupingCalcCol" },
275490x0C00: { n:"BrtUid" },
275500x0C01: { n:"BrtRevisionPtr" },
275510x13e7: { n:"BrtBeginCalcFeatures" },
275520x13e8: { n:"BrtEndCalcFeatures" },
275530x13e9: { n:"BrtCalcFeature" },
275540xFFFF: { n:"" }
27555};
27556
27557var XLSBRE = evert_key(XLSBRecordEnum, 'n');
27558
27559/* [MS-XLS] 2.3 Record Enumeration */
27560var XLSRecordEnum = {
275610x0003: { n:"BIFF2NUM", f:parse_BIFF2NUM },
275620x0004: { n:"BIFF2STR", f:parse_BIFF2STR },
275630x0006: { n:"Formula", f:parse_Formula },
275640x0009: { n:'BOF', f:parse_BOF },
275650x000a: { n:'EOF', f:parsenoop2 },
275660x000c: { n:"CalcCount", f:parseuint16 },
275670x000d: { n:"CalcMode", f:parseuint16 },
275680x000e: { n:"CalcPrecision", f:parsebool },
275690x000f: { n:"CalcRefMode", f:parsebool },
275700x0010: { n:"CalcDelta", f:parse_Xnum },
275710x0011: { n:"CalcIter", f:parsebool },
275720x0012: { n:"Protect", f:parsebool },
275730x0013: { n:"Password", f:parseuint16 },
275740x0014: { n:"Header", f:parse_XLHeaderFooter },
275750x0015: { n:"Footer", f:parse_XLHeaderFooter },
275760x0017: { n:"ExternSheet", f:parse_ExternSheet },
275770x0018: { n:"Lbl", f:parse_Lbl },
275780x0019: { n:"WinProtect", f:parsebool },
275790x001a: { n:"VerticalPageBreaks" },
275800x001b: { n:"HorizontalPageBreaks" },
275810x001c: { n:"Note", f:parse_Note },
275820x001d: { n:"Selection" },
275830x0022: { n:"Date1904", f:parsebool },
275840x0023: { n:"ExternName", f:parse_ExternName },
275850x0026: { n:"LeftMargin", f:parse_Xnum },
275860x0027: { n:"RightMargin", f:parse_Xnum },
275870x0028: { n:"TopMargin", f:parse_Xnum },
275880x0029: { n:"BottomMargin", f:parse_Xnum },
275890x002a: { n:"PrintRowCol", f:parsebool },
275900x002b: { n:"PrintGrid", f:parsebool },
275910x002f: { n:"FilePass", f:parse_FilePass },
275920x0031: { n:"Font", f:parse_Font },
275930x0033: { n:"PrintSize", f:parseuint16 },
275940x003c: { n:"Continue" },
275950x003d: { n:"Window1", f:parse_Window1 },
275960x0040: { n:"Backup", f:parsebool },
275970x0041: { n:"Pane", f:parse_Pane },
275980x0042: { n:'CodePage', f:parseuint16 },
275990x004d: { n:"Pls" },
276000x0050: { n:"DCon" },
276010x0051: { n:"DConRef" },
276020x0052: { n:"DConName" },
276030x0055: { n:"DefColWidth", f:parseuint16 },
276040x0059: { n:"XCT" },
276050x005a: { n:"CRN" },
276060x005b: { n:"FileSharing" },
276070x005c: { n:'WriteAccess', f:parse_WriteAccess },
276080x005d: { n:"Obj", f:parse_Obj },
276090x005e: { n:"Uncalced" },
276100x005f: { n:"CalcSaveRecalc", f:parsebool },
276110x0060: { n:"Template" },
276120x0061: { n:"Intl" },
276130x0063: { n:"ObjProtect", f:parsebool },
276140x007d: { n:"ColInfo", f:parse_ColInfo },
276150x0080: { n:"Guts", f:parse_Guts },
276160x0081: { n:"WsBool", f:parse_WsBool },
276170x0082: { n:"GridSet", f:parseuint16 },
276180x0083: { n:"HCenter", f:parsebool },
276190x0084: { n:"VCenter", f:parsebool },
276200x0085: { n:'BoundSheet8', f:parse_BoundSheet8 },
276210x0086: { n:"WriteProtect" },
276220x008c: { n:"Country", f:parse_Country },
276230x008d: { n:"HideObj", f:parseuint16 },
276240x0090: { n:"Sort" },
276250x0092: { n:"Palette", f:parse_Palette },
276260x0097: { n:"Sync" },
276270x0098: { n:"LPr" },
276280x0099: { n:"DxGCol" },
276290x009a: { n:"FnGroupName" },
276300x009b: { n:"FilterMode" },
276310x009c: { n:"BuiltInFnGroupCount", f:parseuint16 },
276320x009d: { n:"AutoFilterInfo" },
276330x009e: { n:"AutoFilter" },
276340x00a0: { n:"Scl", f:parse_Scl },
276350x00a1: { n:"Setup", f:parse_Setup },
276360x00ae: { n:"ScenMan" },
276370x00af: { n:"SCENARIO" },
276380x00b0: { n:"SxView" },
276390x00b1: { n:"Sxvd" },
276400x00b2: { n:"SXVI" },
276410x00b4: { n:"SxIvd" },
276420x00b5: { n:"SXLI" },
276430x00b6: { n:"SXPI" },
276440x00b8: { n:"DocRoute" },
276450x00b9: { n:"RecipName" },
276460x00bd: { n:"MulRk", f:parse_MulRk },
276470x00be: { n:"MulBlank", f:parse_MulBlank },
276480x00c1: { n:'Mms', f:parsenoop2 },
276490x00c5: { n:"SXDI" },
276500x00c6: { n:"SXDB" },
276510x00c7: { n:"SXFDB" },
276520x00c8: { n:"SXDBB" },
276530x00c9: { n:"SXNum" },
276540x00ca: { n:"SxBool", f:parsebool },
276550x00cb: { n:"SxErr" },
276560x00cc: { n:"SXInt" },
276570x00cd: { n:"SXString" },
276580x00ce: { n:"SXDtr" },
276590x00cf: { n:"SxNil" },
276600x00d0: { n:"SXTbl" },
276610x00d1: { n:"SXTBRGIITM" },
276620x00d2: { n:"SxTbpg" },
276630x00d3: { n:"ObProj" },
276640x00d5: { n:"SXStreamID" },
276650x00d7: { n:"DBCell" },
276660x00d8: { n:"SXRng" },
276670x00d9: { n:"SxIsxoper" },
276680x00da: { n:"BookBool", f:parseuint16 },
276690x00dc: { n:"DbOrParamQry" },
276700x00dd: { n:"ScenarioProtect", f:parsebool },
276710x00de: { n:"OleObjectSize" },
276720x00e0: { n:"XF", f:parse_XF },
276730x00e1: { n:'InterfaceHdr', f:parse_InterfaceHdr },
276740x00e2: { n:'InterfaceEnd', f:parsenoop2 },
276750x00e3: { n:"SXVS" },
276760x00e5: { n:"MergeCells", f:parse_MergeCells },
276770x00e9: { n:"BkHim" },
276780x00eb: { n:"MsoDrawingGroup" },
276790x00ec: { n:"MsoDrawing" },
276800x00ed: { n:"MsoDrawingSelection" },
276810x00ef: { n:"PhoneticInfo" },
276820x00f0: { n:"SxRule" },
276830x00f1: { n:"SXEx" },
276840x00f2: { n:"SxFilt" },
276850x00f4: { n:"SxDXF" },
276860x00f5: { n:"SxItm" },
276870x00f6: { n:"SxName" },
276880x00f7: { n:"SxSelect" },
276890x00f8: { n:"SXPair" },
276900x00f9: { n:"SxFmla" },
276910x00fb: { n:"SxFormat" },
276920x00fc: { n:"SST", f:parse_SST },
276930x00fd: { n:"LabelSst", f:parse_LabelSst },
276940x00ff: { n:"ExtSST", f:parse_ExtSST },
276950x0100: { n:"SXVDEx" },
276960x0103: { n:"SXFormula" },
276970x0122: { n:"SXDBEx" },
276980x0137: { n:"RRDInsDel" },
276990x0138: { n:"RRDHead" },
277000x013b: { n:"RRDChgCell" },
277010x013d: { n:"RRTabId", f:parseuint16a },
277020x013e: { n:"RRDRenSheet" },
277030x013f: { n:"RRSort" },
277040x0140: { n:"RRDMove" },
277050x014a: { n:"RRFormat" },
277060x014b: { n:"RRAutoFmt" },
277070x014d: { n:"RRInsertSh" },
277080x014e: { n:"RRDMoveBegin" },
277090x014f: { n:"RRDMoveEnd" },
277100x0150: { n:"RRDInsDelBegin" },
277110x0151: { n:"RRDInsDelEnd" },
277120x0152: { n:"RRDConflict" },
277130x0153: { n:"RRDDefName" },
277140x0154: { n:"RRDRstEtxp" },
277150x015f: { n:"LRng" },
277160x0160: { n:"UsesELFs", f:parsebool },
277170x0161: { n:"DSF", f:parsenoop2 },
277180x0191: { n:"CUsr" },
277190x0192: { n:"CbUsr" },
277200x0193: { n:"UsrInfo" },
277210x0194: { n:"UsrExcl" },
277220x0195: { n:"FileLock" },
277230x0196: { n:"RRDInfo" },
277240x0197: { n:"BCUsrs" },
277250x0198: { n:"UsrChk" },
277260x01a9: { n:"UserBView" },
277270x01aa: { n:"UserSViewBegin" },
277280x01ab: { n:"UserSViewEnd" },
277290x01ac: { n:"RRDUserView" },
277300x01ad: { n:"Qsi" },
277310x01ae: { n:"SupBook", f:parse_SupBook },
277320x01af: { n:"Prot4Rev", f:parsebool },
277330x01b0: { n:"CondFmt" },
277340x01b1: { n:"CF" },
277350x01b2: { n:"DVal" },
277360x01b5: { n:"DConBin" },
277370x01b6: { n:"TxO", f:parse_TxO },
277380x01b7: { n:"RefreshAll", f:parsebool },
277390x01b8: { n:"HLink", f:parse_HLink },
277400x01b9: { n:"Lel" },
277410x01ba: { n:"CodeName", f:parse_XLUnicodeString },
277420x01bb: { n:"SXFDBType" },
277430x01bc: { n:"Prot4RevPass", f:parseuint16 },
277440x01bd: { n:"ObNoMacros" },
277450x01be: { n:"Dv" },
277460x01c0: { n:"Excel9File", f:parsenoop2 },
277470x01c1: { n:"RecalcId", f:parse_RecalcId, r:2},
277480x01c2: { n:"EntExU2", f:parsenoop2 },
277490x0200: { n:"Dimensions", f:parse_Dimensions },
277500x0201: { n:"Blank", f:parse_Blank },
277510x0203: { n:"Number", f:parse_Number },
277520x0204: { n:"Label", f:parse_Label },
277530x0205: { n:"BoolErr", f:parse_BoolErr },
277540x0206: { n:"Formula", f:parse_Formula },
277550x0207: { n:"String", f:parse_String },
277560x0208: { n:'Row', f:parse_Row },
277570x020b: { n:"Index" },
277580x0221: { n:"Array", f:parse_Array },
277590x0225: { n:"DefaultRowHeight", f:parse_DefaultRowHeight },
277600x0236: { n:"Table" },
277610x023e: { n:"Window2", f:parse_Window2 },
277620x027e: { n:"RK", f:parse_RK },
277630x0293: { n:"Style" },
277640x0406: { n:"Formula", f:parse_Formula },
277650x0418: { n:"BigName" },
277660x041e: { n:"Format", f:parse_Format },
277670x043c: { n:"ContinueBigName" },
277680x04bc: { n:"ShrFmla", f:parse_ShrFmla },
277690x0800: { n:"HLinkTooltip", f:parse_HLinkTooltip },
277700x0801: { n:"WebPub" },
277710x0802: { n:"QsiSXTag" },
277720x0803: { n:"DBQueryExt" },
277730x0804: { n:"ExtString" },
277740x0805: { n:"TxtQry" },
277750x0806: { n:"Qsir" },
277760x0807: { n:"Qsif" },
277770x0808: { n:"RRDTQSIF" },
277780x0809: { n:'BOF', f:parse_BOF },
277790x080a: { n:"OleDbConn" },
277800x080b: { n:"WOpt" },
277810x080c: { n:"SXViewEx" },
277820x080d: { n:"SXTH" },
277830x080e: { n:"SXPIEx" },
277840x080f: { n:"SXVDTEx" },
277850x0810: { n:"SXViewEx9" },
277860x0812: { n:"ContinueFrt" },
277870x0813: { n:"RealTimeData" },
277880x0850: { n:"ChartFrtInfo" },
277890x0851: { n:"FrtWrapper" },
277900x0852: { n:"StartBlock" },
277910x0853: { n:"EndBlock" },
277920x0854: { n:"StartObject" },
277930x0855: { n:"EndObject" },
277940x0856: { n:"CatLab" },
277950x0857: { n:"YMult" },
277960x0858: { n:"SXViewLink" },
277970x0859: { n:"PivotChartBits" },
277980x085a: { n:"FrtFontList" },
277990x0862: { n:"SheetExt" },
278000x0863: { n:"BookExt", r:12},
278010x0864: { n:"SXAddl" },
278020x0865: { n:"CrErr" },
278030x0866: { n:"HFPicture" },
278040x0867: { n:'FeatHdr', f:parsenoop2 },
278050x0868: { n:"Feat" },
278060x086a: { n:"DataLabExt" },
278070x086b: { n:"DataLabExtContents" },
278080x086c: { n:"CellWatch" },
278090x0871: { n:"FeatHdr11" },
278100x0872: { n:"Feature11" },
278110x0874: { n:"DropDownObjIds" },
278120x0875: { n:"ContinueFrt11" },
278130x0876: { n:"DConn" },
278140x0877: { n:"List12" },
278150x0878: { n:"Feature12" },
278160x0879: { n:"CondFmt12" },
278170x087a: { n:"CF12" },
278180x087b: { n:"CFEx" },
278190x087c: { n:"XFCRC", f:parse_XFCRC, r:12 },
278200x087d: { n:"XFExt", f:parse_XFExt, r:12 },
278210x087e: { n:"AutoFilter12" },
278220x087f: { n:"ContinueFrt12" },
278230x0884: { n:"MDTInfo" },
278240x0885: { n:"MDXStr" },
278250x0886: { n:"MDXTuple" },
278260x0887: { n:"MDXSet" },
278270x0888: { n:"MDXProp" },
278280x0889: { n:"MDXKPI" },
278290x088a: { n:"MDB" },
278300x088b: { n:"PLV" },
278310x088c: { n:"Compat12", f:parsebool, r:12 },
278320x088d: { n:"DXF" },
278330x088e: { n:"TableStyles", r:12 },
278340x088f: { n:"TableStyle" },
278350x0890: { n:"TableStyleElement" },
278360x0892: { n:"StyleExt" },
278370x0893: { n:"NamePublish" },
278380x0894: { n:"NameCmt", f:parse_NameCmt, r:12 },
278390x0895: { n:"SortData" },
278400x0896: { n:"Theme", f:parse_Theme, r:12 },
278410x0897: { n:"GUIDTypeLib" },
278420x0898: { n:"FnGrp12" },
278430x0899: { n:"NameFnGrp12" },
278440x089a: { n:"MTRSettings", f:parse_MTRSettings, r:12 },
278450x089b: { n:"CompressPictures", f:parsenoop2 },
278460x089c: { n:"HeaderFooter" },
278470x089d: { n:"CrtLayout12" },
278480x089e: { n:"CrtMlFrt" },
278490x089f: { n:"CrtMlFrtContinue" },
278500x08a3: { n:"ForceFullCalculation", f:parse_ForceFullCalculation },
278510x08a4: { n:"ShapePropsStream" },
278520x08a5: { n:"TextPropsStream" },
278530x08a6: { n:"RichTextStream" },
278540x08a7: { n:"CrtLayout12A" },
278550x1001: { n:"Units" },
278560x1002: { n:"Chart" },
278570x1003: { n:"Series" },
278580x1006: { n:"DataFormat" },
278590x1007: { n:"LineFormat" },
278600x1009: { n:"MarkerFormat" },
278610x100a: { n:"AreaFormat" },
278620x100b: { n:"PieFormat" },
278630x100c: { n:"AttachedLabel" },
278640x100d: { n:"SeriesText" },
278650x1014: { n:"ChartFormat" },
278660x1015: { n:"Legend" },
278670x1016: { n:"SeriesList" },
278680x1017: { n:"Bar" },
278690x1018: { n:"Line" },
278700x1019: { n:"Pie" },
278710x101a: { n:"Area" },
278720x101b: { n:"Scatter" },
278730x101c: { n:"CrtLine" },
278740x101d: { n:"Axis" },
278750x101e: { n:"Tick" },
278760x101f: { n:"ValueRange" },
278770x1020: { n:"CatSerRange" },
278780x1021: { n:"AxisLine" },
278790x1022: { n:"CrtLink" },
278800x1024: { n:"DefaultText" },
278810x1025: { n:"Text" },
278820x1026: { n:"FontX", f:parseuint16 },
278830x1027: { n:"ObjectLink" },
278840x1032: { n:"Frame" },
278850x1033: { n:"Begin" },
278860x1034: { n:"End" },
278870x1035: { n:"PlotArea" },
278880x103a: { n:"Chart3d" },
278890x103c: { n:"PicF" },
278900x103d: { n:"DropBar" },
278910x103e: { n:"Radar" },
278920x103f: { n:"Surf" },
278930x1040: { n:"RadarArea" },
278940x1041: { n:"AxisParent" },
278950x1043: { n:"LegendException" },
278960x1044: { n:"ShtProps", f:parse_ShtProps },
278970x1045: { n:"SerToCrt" },
278980x1046: { n:"AxesUsed" },
278990x1048: { n:"SBaseRef" },
279000x104a: { n:"SerParent" },
279010x104b: { n:"SerAuxTrend" },
279020x104e: { n:"IFmtRecord" },
279030x104f: { n:"Pos" },
279040x1050: { n:"AlRuns" },
279050x1051: { n:"BRAI" },
279060x105b: { n:"SerAuxErrBar" },
279070x105c: { n:"ClrtClient", f:parse_ClrtClient },
279080x105d: { n:"SerFmt" },
279090x105f: { n:"Chart3DBarShape" },
279100x1060: { n:"Fbi" },
279110x1061: { n:"BopPop" },
279120x1062: { n:"AxcExt" },
279130x1063: { n:"Dat" },
279140x1064: { n:"PlotGrowth" },
279150x1065: { n:"SIIndex" },
279160x1066: { n:"GelFrame" },
279170x1067: { n:"BopPopCustom" },
279180x1068: { n:"Fbi2" },
27919
279200x0000: { n:"Dimensions", f:parse_Dimensions },
279210x0002: { n:"BIFF2INT", f:parse_BIFF2INT },
279220x0005: { n:"BoolErr", f:parse_BoolErr },
279230x0007: { n:"String", f:parse_BIFF2STRING },
279240x0008: { n:"BIFF2ROW" },
279250x000b: { n:"Index" },
279260x0016: { n:"ExternCount", f:parseuint16 },
279270x001e: { n:"BIFF2FORMAT", f:parse_BIFF2Format },
279280x001f: { n:"BIFF2FMTCNT" }, /* 16-bit cnt of BIFF2FORMAT records */
279290x0020: { n:"BIFF2COLINFO" },
279300x0021: { n:"Array", f:parse_Array },
279310x0025: { n:"DefaultRowHeight", f:parse_DefaultRowHeight },
279320x0032: { n:"BIFF2FONTXTRA", f:parse_BIFF2FONTXTRA },
279330x0034: { n:"DDEObjName" },
279340x003e: { n:"BIFF2WINDOW2" },
279350x0043: { n:"BIFF2XF" },
279360x0045: { n:"BIFF2FONTCLR" },
279370x0056: { n:"BIFF4FMTCNT" }, /* 16-bit cnt, similar to BIFF2 */
279380x007e: { n:"RK" }, /* Not necessarily same as 0x027e */
279390x007f: { n:"ImData", f:parse_ImData },
279400x0087: { n:"Addin" },
279410x0088: { n:"Edg" },
279420x0089: { n:"Pub" },
279430x0091: { n:"Sub" },
279440x0094: { n:"LHRecord" },
279450x0095: { n:"LHNGraph" },
279460x0096: { n:"Sound" },
279470x00a9: { n:"CoordList" },
279480x00ab: { n:"GCW" },
279490x00bc: { n:"ShrFmla" }, /* Not necessarily same as 0x04bc */
279500x00bf: { n:"ToolbarHdr" },
279510x00c0: { n:"ToolbarEnd" },
279520x00c2: { n:"AddMenu" },
279530x00c3: { n:"DelMenu" },
279540x00d6: { n:"RString", f:parse_RString },
279550x00df: { n:"UDDesc" },
279560x00ea: { n:"TabIdConf" },
279570x0162: { n:"XL5Modify" },
279580x01a5: { n:"FileSharing2" },
279590x0209: { n:'BOF', f:parse_BOF },
279600x0218: { n:"Lbl", f:parse_Lbl },
279610x0223: { n:"ExternName", f:parse_ExternName },
279620x0231: { n:"Font" },
279630x0243: { n:"BIFF3XF" },
279640x0409: { n:'BOF', f:parse_BOF },
279650x0443: { n:"BIFF4XF" },
279660x086d: { n:"FeatInfo" },
279670x0873: { n:"FeatInfo11" },
279680x0881: { n:"SXAddl12" },
279690x08c0: { n:"AutoWebPub" },
279700x08c1: { n:"ListObj" },
279710x08c2: { n:"ListField" },
279720x08c3: { n:"ListDV" },
279730x08c4: { n:"ListCondFmt" },
279740x08c5: { n:"ListCF" },
279750x08c6: { n:"FMQry" },
279760x08c7: { n:"FMSQry" },
279770x08c8: { n:"PLV" },
279780x08c9: { n:"LnExt" },
279790x08ca: { n:"MkrExt" },
279800x08cb: { n:"CrtCoopt" },
279810x08d6: { n:"FRTArchId$", r:12 },
27982
279830x7262: {}
27984};
27985
27986var XLSRE = evert_key(XLSRecordEnum, 'n');
27987function write_biff_rec(ba, type, payload, length) {
27988 var t = +type || +XLSRE[type];
27989 if(isNaN(t)) return;
27990 var len = length || (payload||[]).length || 0;
27991 var o = ba.next(4);
27992 o.write_shift(2, t);
27993 o.write_shift(2, len);
27994 if(len > 0 && is_buf(payload)) ba.push(payload);
27995}
27996
27997function write_BIFF2Cell(out, r, c) {
27998 if(!out) out = new_buf(7);
27999 out.write_shift(2, r);
28000 out.write_shift(2, c);
28001 out.write_shift(2, 0);
28002 out.write_shift(1, 0);
28003 return out;
28004}
28005
28006function write_BIFF2BERR(r, c, val, t) {
28007 var out = new_buf(9);
28008 write_BIFF2Cell(out, r, c);
28009 if(t == 'e') { out.write_shift(1, val); out.write_shift(1, 1); }
28010 else { out.write_shift(1, val?1:0); out.write_shift(1, 0); }
28011 return out;
28012}
28013
28014/* TODO: codepage, large strings */
28015function write_BIFF2LABEL(r, c, val) {
28016 var out = new_buf(8 + 2*val.length);
28017 write_BIFF2Cell(out, r, c);
28018 out.write_shift(1, val.length);
28019 out.write_shift(val.length, val, 'sbcs');
28020 return out.l < out.length ? out.slice(0, out.l) : out;
28021}
28022
28023function write_ws_biff2_cell(ba, cell, R, C) {
28024 if(cell.v != null) switch(cell.t) {
28025 case 'd': case 'n':
28026 var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
28027 if((v == (v|0)) && (v >= 0) && (v < 65536))
28028 write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v));
28029 else
28030 write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v));
28031 return;
28032 case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
28033 /* TODO: codepage, sst */
28034 case 's': case 'str':
28035 write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v));
28036 return;
28037 }
28038 write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
28039}
28040
28041function write_ws_biff2(ba, ws, idx, opts) {
28042 var dense = Array.isArray(ws);
28043 var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = [];
28044 if(range.e.c > 0xFF || range.e.r > 0x3FFF) {
28045 if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
28046 range.e.c = Math.min(range.e.c, 0xFF);
28047 range.e.r = Math.min(range.e.c, 0x3FFF);
28048 ref = encode_range(range);
28049 }
28050 for(var R = range.s.r; R <= range.e.r; ++R) {
28051 rr = encode_row(R);
28052 for(var C = range.s.c; C <= range.e.c; ++C) {
28053 if(R === range.s.r) cols[C] = encode_col(C);
28054 ref = cols[C] + rr;
28055 var cell = dense ? (ws[R]||[])[C] : ws[ref];
28056 if(!cell) continue;
28057 /* write cell */
28058 write_ws_biff2_cell(ba, cell, R, C, opts);
28059 }
28060 }
28061}
28062
28063/* Based on test files */
28064function write_biff2_buf(wb, opts) {
28065 var o = opts || {};
28066 if(DENSE != null && o.dense == null) o.dense = DENSE;
28067 var ba = buf_array();
28068 var idx = 0;
28069 for(var i=0;i<wb.SheetNames.length;++i) if(wb.SheetNames[i] == o.sheet) idx=i;
28070 if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet);
28071 write_biff_rec(ba, 0x0009, write_BOF(wb, 0x10, o));
28072 /* ... */
28073 write_ws_biff2(ba, wb.Sheets[wb.SheetNames[idx]], idx, o, wb);
28074 /* ... */
28075 write_biff_rec(ba, 0x000A);
28076 return ba.end();
28077}
28078
28079function write_FONTS_biff8(ba, data, opts) {
28080 write_biff_rec(ba, "Font", write_Font({
28081 sz:12,
28082 color: {theme:1},
28083 name: "Arial",
28084 family: 2,
28085 scheme: "minor"
28086 }, opts));
28087}
28088
28089
28090function write_FMTS_biff8(ba, NF, opts) {
28091 if(!NF) return;
28092 [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) {
28093for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_biff_rec(ba, "Format", write_Format(i, NF[i], opts));
28094 });
28095}
28096
28097function write_FEAT(ba, ws) {
28098 /* [MS-XLS] 2.4.112 */
28099 var o = new_buf(19);
28100 o.write_shift(4, 0x867); o.write_shift(4, 0); o.write_shift(4, 0);
28101 o.write_shift(2, 3); o.write_shift(1, 1); o.write_shift(4, 0);
28102 write_biff_rec(ba, "FeatHdr", o);
28103 /* [MS-XLS] 2.4.111 */
28104 o = new_buf(39);
28105 o.write_shift(4, 0x868); o.write_shift(4, 0); o.write_shift(4, 0);
28106 o.write_shift(2, 3); o.write_shift(1, 0); o.write_shift(4, 0);
28107 o.write_shift(2, 1); o.write_shift(4, 4); o.write_shift(2, 0);
28108 write_Ref8U(safe_decode_range(ws['!ref']||"A1"), o);
28109 o.write_shift(4, 4);
28110 write_biff_rec(ba, "Feat", o);
28111}
28112
28113function write_CELLXFS_biff8(ba, opts) {
28114 for(var i = 0; i < 16; ++i) write_biff_rec(ba, "XF", write_XF({numFmtId:0, style:true}, 0, opts));
28115 opts.cellXfs.forEach(function(c) {
28116 write_biff_rec(ba, "XF", write_XF(c, 0, opts));
28117 });
28118}
28119
28120function write_ws_biff8_hlinks(ba, ws) {
28121 for(var R=0; R<ws['!links'].length; ++R) {
28122 var HL = ws['!links'][R];
28123 write_biff_rec(ba, "HLink", write_HLink(HL));
28124 if(HL[1].Tooltip) write_biff_rec(ba, "HLinkTooltip", write_HLinkTooltip(HL));
28125 }
28126 delete ws['!links'];
28127}
28128
28129function write_ws_biff8_cell(ba, cell, R, C, opts) {
28130 var os = 16 + get_cell_style(opts.cellXfs, cell, opts);
28131 if(cell.v == null && !cell.bf) {
28132 write_biff_rec(ba, "Blank", write_XLSCell(R, C, os));
28133 return;
28134 }
28135 if(cell.bf) write_biff_rec(ba, "Formula", write_Formula(cell, R, C, opts, os));
28136 else switch(cell.t) {
28137 case 'd': case 'n':
28138 var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
28139 /* TODO: emit RK as appropriate */
28140 write_biff_rec(ba, "Number", write_Number(R, C, v, os, opts));
28141 break;
28142 case 'b': case 'e':
28143 write_biff_rec(ba, 0x0205, write_BoolErr(R, C, cell.v, os, opts, cell.t));
28144 break;
28145 /* TODO: codepage, sst */
28146 case 's': case 'str':
28147 write_biff_rec(ba, "Label", write_Label(R, C, cell.v, os, opts));
28148 break;
28149 default:
28150 write_biff_rec(ba, "Blank", write_XLSCell(R, C, os));
28151 }
28152}
28153
28154/* [MS-XLS] 2.1.7.20.5 */
28155function write_ws_biff8(idx, opts, wb) {
28156 var ba = buf_array();
28157 var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {};
28158 var _WB = ((wb||{}).Workbook||{});
28159 var _sheet = ((_WB.Sheets||[])[idx]||{});
28160 var dense = Array.isArray(ws);
28161 var b8 = opts.biff == 8;
28162 var ref, rr = "", cols = [];
28163 var range = safe_decode_range(ws['!ref'] || "A1");
28164 var MAX_ROWS = b8 ? 65536 : 16384;
28165 if(range.e.c > 0xFF || range.e.r >= MAX_ROWS) {
28166 if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384");
28167 range.e.c = Math.min(range.e.c, 0xFF);
28168 range.e.r = Math.min(range.e.c, MAX_ROWS-1);
28169 }
28170
28171 write_biff_rec(ba, 0x0809, write_BOF(wb, 0x10, opts));
28172 /* [Uncalced] Index */
28173 write_biff_rec(ba, "CalcMode", writeuint16(1));
28174 write_biff_rec(ba, "CalcCount", writeuint16(100));
28175 write_biff_rec(ba, "CalcRefMode", writebool(true));
28176 write_biff_rec(ba, "CalcIter", writebool(false));
28177 write_biff_rec(ba, "CalcDelta", write_Xnum(0.001));
28178 write_biff_rec(ba, "CalcSaveRecalc", writebool(true));
28179 write_biff_rec(ba, "PrintRowCol", writebool(false));
28180 write_biff_rec(ba, "PrintGrid", writebool(false));
28181 write_biff_rec(ba, "GridSet", writeuint16(1));
28182 write_biff_rec(ba, "Guts", write_Guts([0,0]));
28183 /* DefaultRowHeight WsBool [Sync] [LPr] [HorizontalPageBreaks] [VerticalPageBreaks] */
28184 /* Header (string) */
28185 /* Footer (string) */
28186 write_biff_rec(ba, "HCenter", writebool(false));
28187 write_biff_rec(ba, "VCenter", writebool(false));
28188 /* ... */
28189 write_biff_rec(ba, 0x200, write_Dimensions(range, opts));
28190 /* ... */
28191
28192 if(b8) ws['!links'] = [];
28193 for(var R = range.s.r; R <= range.e.r; ++R) {
28194 rr = encode_row(R);
28195 for(var C = range.s.c; C <= range.e.c; ++C) {
28196 if(R === range.s.r) cols[C] = encode_col(C);
28197 ref = cols[C] + rr;
28198 var cell = dense ? (ws[R]||[])[C] : ws[ref];
28199 if(!cell) continue;
28200 /* write cell */
28201 write_ws_biff8_cell(ba, cell, R, C, opts);
28202 if(b8 && cell.l) ws['!links'].push([ref, cell.l]);
28203 }
28204 }
28205 var cname = _sheet.CodeName || _sheet.name || s;
28206 /* ... */
28207 if(b8 && _WB.Views) write_biff_rec(ba, "Window2", write_Window2(_WB.Views[0]));
28208 /* ... */
28209 if(b8 && (ws['!merges']||[]).length) write_biff_rec(ba, "MergeCells", write_MergeCells(ws['!merges']));
28210 /* [LRng] *QUERYTABLE [PHONETICINFO] CONDFMTS */
28211 if(b8) write_ws_biff8_hlinks(ba, ws);
28212 /* [DVAL] */
28213 write_biff_rec(ba, "CodeName", write_XLUnicodeString(cname, opts));
28214 /* *WebPub *CellWatch [SheetExt] */
28215 if(b8) write_FEAT(ba, ws);
28216 /* *FEAT11 *RECORD12 */
28217 write_biff_rec(ba, "EOF");
28218 return ba.end();
28219}
28220
28221/* [MS-XLS] 2.1.7.20.3 */
28222function write_biff8_global(wb, bufs, opts) {
28223 var A = buf_array();
28224 var _WB = ((wb||{}).Workbook||{});
28225 var _sheets = (_WB.Sheets||[]);
28226 var _wb = _WB.WBProps||{};
28227 var b8 = opts.biff == 8, b5 = opts.biff == 5;
28228 write_biff_rec(A, 0x0809, write_BOF(wb, 0x05, opts));
28229 if(opts.bookType == "xla") write_biff_rec(A, "Addin");
28230 write_biff_rec(A, "InterfaceHdr", b8 ? writeuint16(0x04b0) : null);
28231 write_biff_rec(A, "Mms", writezeroes(2));
28232 if(b5) write_biff_rec(A, "ToolbarHdr");
28233 if(b5) write_biff_rec(A, "ToolbarEnd");
28234 write_biff_rec(A, "InterfaceEnd");
28235 write_biff_rec(A, "WriteAccess", write_WriteAccess("SheetJS", opts));
28236 /* [FileSharing] */
28237 write_biff_rec(A, "CodePage", writeuint16(b8 ? 0x04b0 : 0x04E4));
28238 /* *2047 Lel */
28239 if(b8) write_biff_rec(A, "DSF", writeuint16(0));
28240 if(b8) write_biff_rec(A, "Excel9File");
28241 write_biff_rec(A, "RRTabId", write_RRTabId(wb.SheetNames.length));
28242 if(b8 && wb.vbaraw) write_biff_rec(A, "ObProj");
28243 /* [ObNoMacros] */
28244 if(b8 && wb.vbaraw) {
28245 var cname = _wb.CodeName || "ThisWorkbook";
28246 write_biff_rec(A, "CodeName", write_XLUnicodeString(cname, opts));
28247 }
28248 write_biff_rec(A, "BuiltInFnGroupCount", writeuint16(0x11));
28249 /* *FnGroupName *FnGrp12 */
28250 /* *Lbl */
28251 /* [OleObjectSize] */
28252 write_biff_rec(A, "WinProtect", writebool(false));
28253 write_biff_rec(A, "Protect", writebool(false));
28254 write_biff_rec(A, "Password", writeuint16(0));
28255 if(b8) write_biff_rec(A, "Prot4Rev", writebool(false));
28256 if(b8) write_biff_rec(A, "Prot4RevPass", writeuint16(0));
28257 write_biff_rec(A, "Window1", write_Window1(opts));
28258 write_biff_rec(A, "Backup", writebool(false));
28259 write_biff_rec(A, "HideObj", writeuint16(0));
28260 write_biff_rec(A, "Date1904", writebool(safe1904(wb)=="true"));
28261 write_biff_rec(A, "CalcPrecision", writebool(true));
28262 if(b8) write_biff_rec(A, "RefreshAll", writebool(false));
28263 write_biff_rec(A, "BookBool", writeuint16(0));
28264 /* ... */
28265 write_FONTS_biff8(A, wb, opts);
28266 write_FMTS_biff8(A, wb.SSF, opts);
28267 write_CELLXFS_biff8(A, opts);
28268 /* ... */
28269 if(b8) write_biff_rec(A, "UsesELFs", writebool(false));
28270 var a = A.end();
28271
28272 var C = buf_array();
28273 /* METADATA [MTRSettings] [ForceFullCalculation] */
28274 if(b8) write_biff_rec(C, "Country", write_Country());
28275 /* *SUPBOOK *LBL *RTD [RecalcId] *HFPicture *MSODRAWINGGROUP */
28276 /* BIFF8: [SST *Continue] ExtSST */
28277 /* *WebPub [WOpt] [CrErr] [BookExt] *FeatHdr *DConn [THEME] [CompressPictures] [Compat12] [GUIDTypeLib] */
28278 write_biff_rec(C, "EOF");
28279 var c = C.end();
28280
28281 var B = buf_array();
28282 var blen = 0, j = 0;
28283 for(j = 0; j < wb.SheetNames.length; ++j) blen += (b8 ? 12 : 11) + (b8 ? 2 : 1) * wb.SheetNames[j].length;
28284 var start = a.length + blen + c.length;
28285 for(j = 0; j < wb.SheetNames.length; ++j) {
28286 var _sheet = _sheets[j] || ({});
28287 write_biff_rec(B, "BoundSheet8", write_BoundSheet8({pos:start, hs:_sheet.Hidden||0, dt:0, name:wb.SheetNames[j]}, opts));
28288 start += bufs[j].length;
28289 }
28290 /* 1*BoundSheet8 */
28291 var b = B.end();
28292 if(blen != b.length) throw new Error("BS8 " + blen + " != " + b.length);
28293
28294 var out = [];
28295 if(a.length) out.push(a);
28296 if(b.length) out.push(b);
28297 if(c.length) out.push(c);
28298 return __toBuffer([out]);
28299}
28300
28301/* [MS-XLS] 2.1.7.20 Workbook Stream */
28302function write_biff8_buf(wb, opts) {
28303 var o = opts || {};
28304 var bufs = [];
28305
28306 if(wb && !wb.SSF) {
28307 wb.SSF = SSF.get_table();
28308 }
28309 if(wb && wb.SSF) {
28310 make_ssf(SSF); SSF.load_table(wb.SSF);
28311 // $FlowIgnore
28312 o.revssf = evert_num(wb.SSF); o.revssf[wb.SSF[65535]] = 0;
28313 o.ssf = wb.SSF;
28314 }
28315
28316 o.Strings = []; o.Strings.Count = 0; o.Strings.Unique = 0;
28317 fix_write_opts(o);
28318
28319 o.cellXfs = [];
28320 get_cell_style(o.cellXfs, {}, {revssf:{"General":0}});
28321
28322 if(!wb.Props) wb.Props = {};
28323
28324 for(var i = 0; i < wb.SheetNames.length; ++i) bufs[bufs.length] = write_ws_biff8(i, o, wb);
28325 bufs.unshift(write_biff8_global(wb, bufs, o));
28326 return __toBuffer([bufs]);
28327}
28328
28329function write_biff_buf(wb, opts) {
28330 var o = opts || {};
28331 switch(o.biff || 2) {
28332 case 8: case 5: return write_biff8_buf(wb, opts);
28333 case 4: case 3: case 2: return write_biff2_buf(wb, opts);
28334 }
28335 throw new Error("invalid type " + o.bookType + " for BIFF");
28336}
28337/* note: browser DOM element cannot see mso- style attrs, must parse */
28338var HTML_ = (function() {
28339 function html_to_sheet(str, _opts) {
28340 var opts = _opts || {};
28341 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
28342 var ws = opts.dense ? ([]) : ({});
28343 str = str.replace(/<!--.*?-->/g, "");
28344 var mtch = str.match(/<table/i);
28345 if(!mtch) throw new Error("Invalid HTML: could not find <table>");
28346 var mtch2 = str.match(/<\/table/i);
28347 var i = mtch.index, j = mtch2 && mtch2.index || str.length;
28348 var rows = split_regex(str.slice(i, j), /(:?<tr[^>]*>)/i, "<tr>");
28349 var R = -1, C = 0, RS = 0, CS = 0;
28350 var range = {s:{r:10000000, c:10000000},e:{r:0,c:0}};
28351 var merges = [];
28352 for(i = 0; i < rows.length; ++i) {
28353 var row = rows[i].trim();
28354 var hd = row.slice(0,3).toLowerCase();
28355 if(hd == "<tr") { ++R; if(opts.sheetRows && opts.sheetRows <= R) { --R; break; } C = 0; continue; }
28356 if(hd != "<td" && hd != "<th") continue;
28357 var cells = row.split(/<\/t[dh]>/i);
28358 for(j = 0; j < cells.length; ++j) {
28359 var cell = cells[j].trim();
28360 if(!cell.match(/<t[dh]/i)) continue;
28361 var m = cell, cc = 0;
28362 /* TODO: parse styles etc */
28363 while(m.charAt(0) == "<" && (cc = m.indexOf(">")) > -1) m = m.slice(cc+1);
28364 for(var midx = 0; midx < merges.length; ++midx) {
28365 var _merge = merges[midx];
28366 if(_merge.s.c == C && _merge.s.r < R && R <= _merge.e.r) { C = _merge.e.c + 1; midx = -1; }
28367 }
28368 var tag = parsexmltag(cell.slice(0, cell.indexOf(">")));
28369 CS = tag.colspan ? +tag.colspan : 1;
28370 if((RS = +tag.rowspan)>1 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
28371 var _t = tag.t || "";
28372 /* TODO: generate stub cells */
28373 if(!m.length) { C += CS; continue; }
28374 m = htmldecode(m);
28375 if(range.s.r > R) range.s.r = R; if(range.e.r < R) range.e.r = R;
28376 if(range.s.c > C) range.s.c = C; if(range.e.c < C) range.e.c = C;
28377 if(!m.length) continue;
28378 var o = {t:'s', v:m};
28379 if(opts.raw || !m.trim().length || _t == 's'){}
28380 else if(m === 'TRUE') o = {t:'b', v:true};
28381 else if(m === 'FALSE') o = {t:'b', v:false};
28382 else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)};
28383 else if(!isNaN(fuzzydate(m).getDate())) {
28384 o = ({t:'d', v:parseDate(m)});
28385 if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)});
28386 o.z = opts.dateNF || SSF._table[14];
28387 }
28388 if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; }
28389 else ws[encode_cell({r:R, c:C})] = o;
28390 C += CS;
28391 }
28392 }
28393 ws['!ref'] = encode_range(range);
28394 if(merges.length) ws["!merges"] = merges;
28395 return ws;
28396 }
28397 function html_to_book(str, opts) {
28398 return sheet_to_workbook(html_to_sheet(str, opts), opts);
28399 }
28400 function make_html_row(ws, r, R, o) {
28401 var M = (ws['!merges'] ||[]);
28402 var oo = [];
28403 for(var C = r.s.c; C <= r.e.c; ++C) {
28404 var RS = 0, CS = 0;
28405 for(var j = 0; j < M.length; ++j) {
28406 if(M[j].s.r > R || M[j].s.c > C) continue;
28407 if(M[j].e.r < R || M[j].e.c < C) continue;
28408 if(M[j].s.r < R || M[j].s.c < C) { RS = -1; break; }
28409 RS = M[j].e.r - M[j].s.r + 1; CS = M[j].e.c - M[j].s.c + 1; break;
28410 }
28411 if(RS < 0) continue;
28412 var coord = encode_cell({r:R,c:C});
28413 var cell = o.dense ? (ws[R]||[])[C] : ws[coord];
28414 /* TODO: html entities */
28415 var w = (cell && cell.v != null) && (cell.h || escapehtml(cell.w || (format_cell(cell), cell.w) || "")) || "";
28416 var sp = ({});
28417 if(RS > 1) sp.rowspan = RS;
28418 if(CS > 1) sp.colspan = CS;
28419 sp.t = cell && cell.t || 'z';
28420 if(o.editable) w = '<span contenteditable="true">' + w + '</span>';
28421 sp.id = (o.id || "sjs") + "-" + coord;
28422 oo.push(writextag('td', w, sp));
28423 }
28424 var preamble = "<tr>";
28425 return preamble + oo.join("") + "</tr>";
28426 }
28427 function make_html_preamble(ws, R, o) {
28428 var out = [];
28429 return out.join("") + '<table' + (o && o.id ? ' id="' + o.id + '"' : "") + '>';
28430 }
28431 var _BEGIN = '<html><head><meta charset="utf-8"/><title>SheetJS Table Export</title></head><body>';
28432 var _END = '</body></html>';
28433 function sheet_to_html(ws, opts/*, wb:?Workbook*/) {
28434 var o = opts || {};
28435 var header = o.header != null ? o.header : _BEGIN;
28436 var footer = o.footer != null ? o.footer : _END;
28437 var out = [header];
28438 var r = decode_range(ws['!ref']);
28439 o.dense = Array.isArray(ws);
28440 out.push(make_html_preamble(ws, r, o));
28441 for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o));
28442 out.push("</table>" + footer);
28443 return out.join("");
28444 }
28445
28446 return {
28447 to_workbook: html_to_book,
28448 to_sheet: html_to_sheet,
28449 _row: make_html_row,
28450 BEGIN: _BEGIN,
28451 END: _END,
28452 _preamble: make_html_preamble,
28453 from_sheet: sheet_to_html
28454 };
28455})();
28456
28457function parse_dom_table(table, _opts) {
28458 var opts = _opts || {};
28459 if(DENSE != null) opts.dense = DENSE;
28460 var ws = opts.dense ? ([]) : ({});
28461 var rows = table.getElementsByTagName('tr');
28462 var sheetRows = opts.sheetRows || 10000000;
28463 var range = {s:{r:0,c:0},e:{r:0,c:0}};
28464 var merges = [], midx = 0;
28465 var rowinfo = [];
28466 var _R = 0, R = 0, _C = 0, C = 0, RS = 0, CS = 0;
28467 for(; _R < rows.length && R < sheetRows; ++_R) {
28468 var row = rows[_R];
28469 if (is_dom_element_hidden(row)) {
28470 if (opts.display) continue;
28471 rowinfo[R] = {hidden: true};
28472 }
28473 var elts = (row.children);
28474 for(_C = C = 0; _C < elts.length; ++_C) {
28475 var elt = elts[_C];
28476 if (opts.display && is_dom_element_hidden(elt)) continue;
28477 var v = htmldecode(elt.innerHTML);
28478 for(midx = 0; midx < merges.length; ++midx) {
28479 var m = merges[midx];
28480 if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; }
28481 }
28482 /* TODO: figure out how to extract nonstandard mso- style */
28483 CS = +elt.getAttribute("colspan") || 1;
28484 if((RS = +elt.getAttribute("rowspan"))>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
28485 var o = {t:'s', v:v};
28486 var _t = elt.getAttribute("t") || "";
28487 if(v != null) {
28488 if(v.length == 0) o.t = _t || 'z';
28489 else if(opts.raw || v.trim().length == 0 || _t == "s"){}
28490 else if(v === 'TRUE') o = {t:'b', v:true};
28491 else if(v === 'FALSE') o = {t:'b', v:false};
28492 else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
28493 else if(!isNaN(fuzzydate(v).getDate())) {
28494 o = ({t:'d', v:parseDate(v)});
28495 if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)});
28496 o.z = opts.dateNF || SSF._table[14];
28497 }
28498 }
28499 if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; }
28500 else ws[encode_cell({c:C, r:R})] = o;
28501 if(range.e.c < C) range.e.c = C;
28502 C += CS;
28503 }
28504 ++R;
28505 }
28506 if(merges.length) ws['!merges'] = merges;
28507 if(rowinfo.length) ws['!rows'] = rowinfo;
28508 range.e.r = R - 1;
28509 ws['!ref'] = encode_range(range);
28510 if(R >= sheetRows) ws['!fullref'] = encode_range((range.e.r = rows.length-_R+R-1,range)); // We can count the real number of rows to parse but we don't to improve the performance
28511 return ws;
28512}
28513
28514function table_to_book(table, opts) {
28515 return sheet_to_workbook(parse_dom_table(table, opts), opts);
28516}
28517
28518function is_dom_element_hidden(element) {
28519 var display = '';
28520 var get_computed_style = get_get_computed_style_function(element);
28521 if(get_computed_style) display = get_computed_style(element).getPropertyValue('display');
28522 if(!display) display = element.style.display; // Fallback for cases when getComputedStyle is not available (e.g. an old browser or some Node.js environments) or doesn't work (e.g. if the element is not inserted to a document)
28523 return display === 'none';
28524}
28525
28526/* global getComputedStyle */
28527function get_get_computed_style_function(element) {
28528 // The proper getComputedStyle implementation is the one defined in the element window
28529 if(element.ownerDocument.defaultView && typeof element.ownerDocument.defaultView.getComputedStyle === 'function') return element.ownerDocument.defaultView.getComputedStyle;
28530 // If it is not available, try to get one from the global namespace
28531 if(typeof getComputedStyle === 'function') return getComputedStyle;
28532 return null;
28533}
28534/* OpenDocument */
28535var parse_content_xml = (function() {
28536
28537 var parse_text_p = function(text) {
28538 /* 6.1.2 White Space Characters */
28539 var fixed = text
28540 .replace(/[\t\r\n]/g, " ").trim().replace(/ +/g, " ")
28541 .replace(/<text:s\/>/g," ")
28542 .replace(/<text:s text:c="(\d+)"\/>/g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); })
28543 .replace(/<text:tab[^>]*\/>/g,"\t")
28544 .replace(/<text:line-break\/>/g,"\n");
28545 var v = unescapexml(fixed.replace(/<[^>]*>/g,""));
28546
28547 return [v];
28548 };
28549
28550 var number_formats = {
28551 /* ods name: [short ssf fmt, long ssf fmt] */
28552 day: ["d", "dd"],
28553 month: ["m", "mm"],
28554 year: ["y", "yy"],
28555 hours: ["h", "hh"],
28556 minutes: ["m", "mm"],
28557 seconds: ["s", "ss"],
28558 "am-pm": ["A/P", "AM/PM"],
28559 "day-of-week": ["ddd", "dddd"],
28560 era: ["e", "ee"],
28561 /* there is no native representation of LO "Q" format */
28562 quarter: ["\\Qm", "m\\\"th quarter\""]
28563 };
28564
28565 return function pcx(d, _opts) {
28566 var opts = _opts || {};
28567 if(DENSE != null && opts.dense == null) opts.dense = DENSE;
28568 var str = xlml_normalize(d);
28569 var state = [], tmp;
28570 var tag;
28571 var NFtag = {name:""}, NF = "", pidx = 0;
28572 var sheetag;
28573 var rowtag;
28574 var Sheets = {}, SheetNames = [];
28575 var ws = opts.dense ? ([]) : ({});
28576 var Rn, q;
28577 var ctag = ({value:""});
28578 var textp = "", textpidx = 0, textptag;
28579 var textR = [];
28580 var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
28581 var row_ol = 0;
28582 var number_format_map = {};
28583 var merges = [], mrange = {}, mR = 0, mC = 0;
28584 var rowinfo = [], rowpeat = 1, colpeat = 1;
28585 var arrayf = [];
28586 var WB = {Names:[]};
28587 var atag = ({});
28588 var _Ref = ["", ""];
28589 var comments = [], comment = ({});
28590 var creator = "", creatoridx = 0;
28591 var isstub = false, intable = false;
28592 var i = 0;
28593 xlmlregex.lastIndex = 0;
28594 str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
28595 while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
28596
28597 case 'table': case '工作表': // 9.1.2 <table:table>
28598 if(Rn[1]==='/') {
28599 if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = encode_range(range);
28600 if(opts.sheetRows > 0 && opts.sheetRows <= range.e.r) {
28601 ws['!fullref'] = ws['!ref'];
28602 range.e.r = opts.sheetRows - 1;
28603 ws['!ref'] = encode_range(range);
28604 }
28605 if(merges.length) ws['!merges'] = merges;
28606 if(rowinfo.length) ws["!rows"] = rowinfo;
28607 sheetag.name = sheetag['名称'] || sheetag.name;
28608 if(typeof JSON !== 'undefined') JSON.stringify(sheetag);
28609 SheetNames.push(sheetag.name);
28610 Sheets[sheetag.name] = ws;
28611 intable = false;
28612 }
28613 else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
28614 sheetag = parsexmltag(Rn[0], false);
28615 R = C = -1;
28616 range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0;
28617 ws = opts.dense ? ([]) : ({}); merges = [];
28618 rowinfo = [];
28619 intable = true;
28620 }
28621 break;
28622
28623 case 'table-row-group': // 9.1.9 <table:table-row-group>
28624 if(Rn[1] === "/") --row_ol; else ++row_ol;
28625 break;
28626 case 'table-row': case '行': // 9.1.3 <table:table-row>
28627 if(Rn[1] === '/') { R+=rowpeat; rowpeat = 1; break; }
28628 rowtag = parsexmltag(Rn[0], false);
28629 if(rowtag['行号']) R = rowtag['行号'] - 1; else if(R == -1) R = 0;
28630 rowpeat = +rowtag['number-rows-repeated'] || 1;
28631 /* TODO: remove magic */
28632 if(rowpeat < 10) for(i = 0; i < rowpeat; ++i) if(row_ol > 0) rowinfo[R + i] = {level: row_ol};
28633 C = -1; break;
28634 case 'covered-table-cell': // 9.1.5 <table:covered-table-cell>
28635 if(Rn[1] !== '/') ++C;
28636 if(opts.sheetStubs) {
28637 if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = {t:'z'}; }
28638 else ws[encode_cell({r:R,c:C})] = {t:'z'};
28639 }
28640 textp = ""; textR = [];
28641 break; /* stub */
28642 case 'table-cell': case '数据':
28643 if(Rn[0].charAt(Rn[0].length-2) === '/') {
28644 ++C;
28645 ctag = parsexmltag(Rn[0], false);
28646 colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
28647 q = ({t:'z', v:null});
28648 if(ctag.formula && opts.cellFormula != false) q.f = ods_to_csf_formula(unescapexml(ctag.formula));
28649 if((ctag['数据类型'] || ctag['value-type']) == "string") {
28650 q.t = "s"; q.v = unescapexml(ctag['string-value'] || "");
28651 if(opts.dense) {
28652 if(!ws[R]) ws[R] = [];
28653 ws[R][C] = q;
28654 } else {
28655 ws[encode_cell({r:R,c:C})] = q;
28656 }
28657 }
28658 C+= colpeat-1;
28659 } else if(Rn[1]!=='/') {
28660 ++C;
28661 colpeat = 1;
28662 var rptR = rowpeat ? R + rowpeat - 1 : R;
28663 if(C > range.e.c) range.e.c = C;
28664 if(C < range.s.c) range.s.c = C;
28665 if(R < range.s.r) range.s.r = R;
28666 if(rptR > range.e.r) range.e.r = rptR;
28667 ctag = parsexmltag(Rn[0], false);
28668 comments = []; comment = ({});
28669 q = ({t:ctag['数据类型'] || ctag['value-type'], v:null});
28670 if(opts.cellFormula) {
28671 if(ctag.formula) ctag.formula = unescapexml(ctag.formula);
28672 if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) {
28673 mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0;
28674 mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0;
28675 mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
28676 q.F = encode_range(mrange);
28677 arrayf.push([mrange, q.F]);
28678 }
28679 if(ctag.formula) q.f = ods_to_csf_formula(ctag.formula);
28680 else for(i = 0; i < arrayf.length; ++i)
28681 if(R >= arrayf[i][0].s.r && R <= arrayf[i][0].e.r)
28682 if(C >= arrayf[i][0].s.c && C <= arrayf[i][0].e.c)
28683 q.F = arrayf[i][1];
28684 }
28685 if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) {
28686 mR = parseInt(ctag['number-rows-spanned'],10) || 0;
28687 mC = parseInt(ctag['number-columns-spanned'],10) || 0;
28688 mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}};
28689 merges.push(mrange);
28690 }
28691
28692 /* 19.675.2 table:number-columns-repeated */
28693 if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10);
28694
28695 /* 19.385 office:value-type */
28696 switch(q.t) {
28697 case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break;
28698 case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break;
28699 case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break;
28700 case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break;
28701 case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']);
28702 if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v); }
28703 q.z = 'm/d/yy'; break;
28704 case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400; break;
28705 case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break;
28706 default:
28707 if(q.t === 'string' || q.t === 'text' || !q.t) {
28708 q.t = 's';
28709 if(ctag['string-value'] != null) { textp = unescapexml(ctag['string-value']); textR = []; }
28710 } else throw new Error('Unsupported value type ' + q.t);
28711 }
28712 } else {
28713 isstub = false;
28714 if(q.t === 's') {
28715 q.v = textp || '';
28716 if(textR.length) q.R = textR;
28717 isstub = textpidx == 0;
28718 }
28719 if(atag.Target) q.l = atag;
28720 if(comments.length > 0) { q.c = comments; comments = []; }
28721 if(textp && opts.cellText !== false) q.w = textp;
28722 if(!isstub || opts.sheetStubs) {
28723 if(!(opts.sheetRows && opts.sheetRows <= R)) {
28724 for(var rpt = 0; rpt < rowpeat; ++rpt) {
28725 colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
28726 if(opts.dense) {
28727 if(!ws[R + rpt]) ws[R + rpt] = [];
28728 ws[R + rpt][C] = rpt == 0 ? q : dup(q);
28729 while(--colpeat > 0) ws[R + rpt][C + colpeat] = dup(q);
28730 } else {
28731 ws[encode_cell({r:R + rpt,c:C})] = q;
28732 while(--colpeat > 0) ws[encode_cell({r:R + rpt,c:C + colpeat})] = dup(q);
28733 }
28734 if(range.e.c <= C) range.e.c = C;
28735 }
28736 }
28737 }
28738 colpeat = parseInt(ctag['number-columns-repeated']||"1", 10);
28739 C += colpeat-1; colpeat = 0;
28740 q = {};
28741 textp = ""; textR = [];
28742 }
28743 atag = ({});
28744 break; // 9.1.4 <table:table-cell>
28745
28746 /* pure state */
28747 case 'document': // TODO: <office:document> is the root for FODS
28748 case 'document-content': case '电子表格文档': // 3.1.3.2 <office:document-content>
28749 case 'spreadsheet': case '主体': // 3.7 <office:spreadsheet>
28750 case 'scripts': // 3.12 <office:scripts>
28751 case 'styles': // TODO <office:styles>
28752 case 'font-face-decls': // 3.14 <office:font-face-decls>
28753 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
28754 else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]);
28755 break;
28756
28757 case 'annotation': // 14.1 <office:annotation>
28758 if(Rn[1]==='/'){
28759 if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
28760 comment.t = textp;
28761 if(textR.length) comment.R = textR;
28762 comment.a = creator;
28763 comments.push(comment);
28764 }
28765 else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);}
28766 creator = ""; creatoridx = 0;
28767 textp = ""; textpidx = 0; textR = [];
28768 break;
28769
28770 case 'creator': // 4.3.2.7 <dc:creator>
28771 if(Rn[1]==='/') { creator = str.slice(creatoridx,Rn.index); }
28772 else creatoridx = Rn.index + Rn[0].length;
28773 break;
28774
28775 /* ignore state */
28776 case 'meta': case '元数据': // TODO: <office:meta> <uof:元数据> FODS/UOF
28777 case 'settings': // TODO: <office:settings>
28778 case 'config-item-set': // TODO: <office:config-item-set>
28779 case 'config-item-map-indexed': // TODO: <office:config-item-map-indexed>
28780 case 'config-item-map-entry': // TODO: <office:config-item-map-entry>
28781 case 'config-item-map-named': // TODO: <office:config-item-map-entry>
28782 case 'shapes': // 9.2.8 <table:shapes>
28783 case 'frame': // 10.4.2 <draw:frame>
28784 case 'text-box': // 10.4.3 <draw:text-box>
28785 case 'image': // 10.4.4 <draw:image>
28786 case 'data-pilot-tables': // 9.6.2 <table:data-pilot-tables>
28787 case 'list-style': // 16.30 <text:list-style>
28788 case 'form': // 13.13 <form:form>
28789 case 'dde-links': // 9.8 <table:dde-links>
28790 case 'event-listeners': // TODO
28791 case 'chart': // TODO
28792 if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;}
28793 else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]);
28794 textp = ""; textpidx = 0; textR = [];
28795 break;
28796
28797 case 'scientific-number': // TODO: <number:scientific-number>
28798 break;
28799 case 'currency-symbol': // TODO: <number:currency-symbol>
28800 break;
28801 case 'currency-style': // TODO: <number:currency-style>
28802 break;
28803 case 'number-style': // 16.27.2 <number:number-style>
28804 case 'percentage-style': // 16.27.9 <number:percentage-style>
28805 case 'date-style': // 16.27.10 <number:date-style>
28806 case 'time-style': // 16.27.18 <number:time-style>
28807 if(Rn[1]==='/'){
28808 number_format_map[NFtag.name] = NF;
28809 if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;
28810 } else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
28811 NF = "";
28812 NFtag = parsexmltag(Rn[0], false);
28813 state.push([Rn[3], true]);
28814 } break;
28815
28816 case 'script': break; // 3.13 <office:script>
28817 case 'libraries': break; // TODO: <ooo:libraries>
28818 case 'automatic-styles': break; // 3.15.3 <office:automatic-styles>
28819 case 'master-styles': break; // TODO: <office:master-styles>
28820
28821 case 'default-style': // TODO: <style:default-style>
28822 case 'page-layout': break; // TODO: <style:page-layout>
28823 case 'style': // 16.2 <style:style>
28824 break;
28825 case 'map': break; // 16.3 <style:map>
28826 case 'font-face': break; // 16.21 <style:font-face>
28827
28828 case 'paragraph-properties': break; // 17.6 <style:paragraph-properties>
28829 case 'table-properties': break; // 17.15 <style:table-properties>
28830 case 'table-column-properties': break; // 17.16 <style:table-column-properties>
28831 case 'table-row-properties': break; // 17.17 <style:table-row-properties>
28832 case 'table-cell-properties': break; // 17.18 <style:table-cell-properties>
28833
28834 case 'number': // 16.27.3 <number:number>
28835 switch(state[state.length-1][0]) {
28836 case 'time-style':
28837 case 'date-style':
28838 tag = parsexmltag(Rn[0], false);
28839 NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
28840 } break;
28841
28842 case 'fraction': break; // TODO 16.27.6 <number:fraction>
28843
28844 case 'day': // 16.27.11 <number:day>
28845 case 'month': // 16.27.12 <number:month>
28846 case 'year': // 16.27.13 <number:year>
28847 case 'era': // 16.27.14 <number:era>
28848 case 'day-of-week': // 16.27.15 <number:day-of-week>
28849 case 'week-of-year': // 16.27.16 <number:week-of-year>
28850 case 'quarter': // 16.27.17 <number:quarter>
28851 case 'hours': // 16.27.19 <number:hours>
28852 case 'minutes': // 16.27.20 <number:minutes>
28853 case 'seconds': // 16.27.21 <number:seconds>
28854 case 'am-pm': // 16.27.22 <number:am-pm>
28855 switch(state[state.length-1][0]) {
28856 case 'time-style':
28857 case 'date-style':
28858 tag = parsexmltag(Rn[0], false);
28859 NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break;
28860 } break;
28861
28862 case 'boolean-style': break; // 16.27.23 <number:boolean-style>
28863 case 'boolean': break; // 16.27.24 <number:boolean>
28864 case 'text-style': break; // 16.27.25 <number:text-style>
28865 case 'text': // 16.27.26 <number:text>
28866 if(Rn[0].slice(-2) === "/>") break;
28867 else if(Rn[1]==="/") switch(state[state.length-1][0]) {
28868 case 'number-style':
28869 case 'date-style':
28870 case 'time-style':
28871 NF += str.slice(pidx, Rn.index);
28872 break;
28873 }
28874 else pidx = Rn.index + Rn[0].length;
28875 break;
28876
28877 case 'named-range': // 9.4.12 <table:named-range>
28878 tag = parsexmltag(Rn[0], false);
28879 _Ref = ods_to_csf_3D(tag['cell-range-address']);
28880 var nrange = ({Name:tag.name, Ref:_Ref[0] + '!' + _Ref[1]});
28881 if(intable) nrange.Sheet = SheetNames.length;
28882 WB.Names.push(nrange);
28883 break;
28884
28885 case 'text-content': break; // 16.27.27 <number:text-content>
28886 case 'text-properties': break; // 16.27.27 <style:text-properties>
28887 case 'embedded-text': break; // 16.27.4 <number:embedded-text>
28888
28889 case 'body': case '电子表格': break; // 3.3 16.9.6 19.726.3
28890
28891 case 'forms': break; // 12.25.2 13.2
28892 case 'table-column': break; // 9.1.6 <table:table-column>
28893 case 'table-header-rows': break; // 9.1.7 <table:table-header-rows>
28894 case 'table-rows': break; // 9.1.12 <table:table-rows>
28895 /* TODO: outline levels */
28896 case 'table-column-group': break; // 9.1.10 <table:table-column-group>
28897 case 'table-header-columns': break; // 9.1.11 <table:table-header-columns>
28898 case 'table-columns': break; // 9.1.12 <table:table-columns>
28899
28900 case 'null-date': break; // 9.4.2 <table:null-date> TODO: date1904
28901
28902 case 'graphic-properties': break; // 17.21 <style:graphic-properties>
28903 case 'calculation-settings': break; // 9.4.1 <table:calculation-settings>
28904 case 'named-expressions': break; // 9.4.11 <table:named-expressions>
28905 case 'label-range': break; // 9.4.9 <table:label-range>
28906 case 'label-ranges': break; // 9.4.10 <table:label-ranges>
28907 case 'named-expression': break; // 9.4.13 <table:named-expression>
28908 case 'sort': break; // 9.4.19 <table:sort>
28909 case 'sort-by': break; // 9.4.20 <table:sort-by>
28910 case 'sort-groups': break; // 9.4.22 <table:sort-groups>
28911
28912 case 'tab': break; // 6.1.4 <text:tab>
28913 case 'line-break': break; // 6.1.5 <text:line-break>
28914 case 'span': break; // 6.1.7 <text:span>
28915 case 'p': case '文本串': // 5.1.3 <text:p>
28916 if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) {
28917 var ptp = parse_text_p(str.slice(textpidx,Rn.index), textptag);
28918 textp = (textp.length > 0 ? textp + "\n" : "") + ptp[0];
28919 } else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
28920 break; // <text:p>
28921 case 's': break; // <text:s>
28922
28923 case 'database-range': // 9.4.15 <table:database-range>
28924 if(Rn[1]==='/') break;
28925 try {
28926 _Ref = ods_to_csf_3D(parsexmltag(Rn[0])['target-range-address']);
28927 Sheets[_Ref[0]]['!autofilter'] = { ref:_Ref[1] };
28928 } catch(e) {/* empty */}
28929 break;
28930
28931 case 'date': break; // <*:date>
28932
28933 case 'object': break; // 10.4.6.2 <draw:object>
28934 case 'title': case '标题': break; // <*:title> OR <uof:标题>
28935 case 'desc': break; // <*:desc>
28936 case 'binary-data': break; // 10.4.5 TODO: b64 blob
28937
28938 /* 9.2 Advanced Tables */
28939 case 'table-source': break; // 9.2.6
28940 case 'scenario': break; // 9.2.6
28941
28942 case 'iteration': break; // 9.4.3 <table:iteration>
28943 case 'content-validations': break; // 9.4.4 <table:
28944 case 'content-validation': break; // 9.4.5 <table:
28945 case 'help-message': break; // 9.4.6 <table:
28946 case 'error-message': break; // 9.4.7 <table:
28947 case 'database-ranges': break; // 9.4.14 <table:database-ranges>
28948 case 'filter': break; // 9.5.2 <table:filter>
28949 case 'filter-and': break; // 9.5.3 <table:filter-and>
28950 case 'filter-or': break; // 9.5.4 <table:filter-or>
28951 case 'filter-condition': break; // 9.5.5 <table:filter-condition>
28952
28953 case 'list-level-style-bullet': break; // 16.31 <text:
28954 case 'list-level-style-number': break; // 16.32 <text:
28955 case 'list-level-properties': break; // 17.19 <style:
28956
28957 /* 7.3 Document Fields */
28958 case 'sender-firstname': // 7.3.6.2
28959 case 'sender-lastname': // 7.3.6.3
28960 case 'sender-initials': // 7.3.6.4
28961 case 'sender-title': // 7.3.6.5
28962 case 'sender-position': // 7.3.6.6
28963 case 'sender-email': // 7.3.6.7
28964 case 'sender-phone-private': // 7.3.6.8
28965 case 'sender-fax': // 7.3.6.9
28966 case 'sender-company': // 7.3.6.10
28967 case 'sender-phone-work': // 7.3.6.11
28968 case 'sender-street': // 7.3.6.12
28969 case 'sender-city': // 7.3.6.13
28970 case 'sender-postal-code': // 7.3.6.14
28971 case 'sender-country': // 7.3.6.15
28972 case 'sender-state-or-province': // 7.3.6.16
28973 case 'author-name': // 7.3.7.1
28974 case 'author-initials': // 7.3.7.2
28975 case 'chapter': // 7.3.8
28976 case 'file-name': // 7.3.9
28977 case 'template-name': // 7.3.9
28978 case 'sheet-name': // 7.3.9
28979 break;
28980
28981 case 'event-listener':
28982 break;
28983 /* TODO: FODS Properties */
28984 case 'initial-creator':
28985 case 'creation-date':
28986 case 'print-date':
28987 case 'generator':
28988 case 'document-statistic':
28989 case 'user-defined':
28990 case 'editing-duration':
28991 case 'editing-cycles':
28992 break;
28993
28994 /* TODO: FODS Config */
28995 case 'config-item':
28996 break;
28997
28998 /* TODO: style tokens */
28999 case 'page-number': break; // TODO <text:page-number>
29000 case 'page-count': break; // TODO <text:page-count>
29001 case 'time': break; // TODO <text:time>
29002
29003 /* 9.3 Advanced Table Cells */
29004 case 'cell-range-source': break; // 9.3.1 <table:
29005 case 'detective': break; // 9.3.2 <table:
29006 case 'operation': break; // 9.3.3 <table:
29007 case 'highlighted-range': break; // 9.3.4 <table:
29008
29009 /* 9.6 Data Pilot Tables <table: */
29010 case 'data-pilot-table': // 9.6.3
29011 case 'source-cell-range': // 9.6.5
29012 case 'source-service': // 9.6.6
29013 case 'data-pilot-field': // 9.6.7
29014 case 'data-pilot-level': // 9.6.8
29015 case 'data-pilot-subtotals': // 9.6.9
29016 case 'data-pilot-subtotal': // 9.6.10
29017 case 'data-pilot-members': // 9.6.11
29018 case 'data-pilot-member': // 9.6.12
29019 case 'data-pilot-display-info': // 9.6.13
29020 case 'data-pilot-sort-info': // 9.6.14
29021 case 'data-pilot-layout-info': // 9.6.15
29022 case 'data-pilot-field-reference': // 9.6.16
29023 case 'data-pilot-groups': // 9.6.17
29024 case 'data-pilot-group': // 9.6.18
29025 case 'data-pilot-group-member': // 9.6.19
29026 break;
29027
29028 /* 10.3 Drawing Shapes */
29029 case 'rect': // 10.3.2
29030 break;
29031
29032 /* 14.6 DDE Connections */
29033 case 'dde-connection-decls': // 14.6.2 <text:
29034 case 'dde-connection-decl': // 14.6.3 <text:
29035 case 'dde-link': // 14.6.4 <table:
29036 case 'dde-source': // 14.6.5 <office:
29037 break;
29038
29039 case 'properties': break; // 13.7 <form:properties>
29040 case 'property': break; // 13.8 <form:property>
29041
29042 case 'a': // 6.1.8 hyperlink
29043 if(Rn[1]!== '/') {
29044 atag = parsexmltag(Rn[0], false);
29045 if(!atag.href) break;
29046 atag.Target = atag.href; delete atag.href;
29047 if(atag.Target.charAt(0) == "#" && atag.Target.indexOf(".") > -1) {
29048 _Ref = ods_to_csf_3D(atag.Target.slice(1));
29049 atag.Target = "#" + _Ref[0] + "!" + _Ref[1];
29050 }
29051 }
29052 break;
29053
29054 /* non-standard */
29055 case 'table-protection': break;
29056 case 'data-pilot-grand-total': break; // <table:
29057 case 'office-document-common-attrs': break; // bare
29058 default: switch(Rn[2]) {
29059 case 'dc:': // TODO: properties
29060 case 'calcext:': // ignore undocumented extensions
29061 case 'loext:': // ignore undocumented extensions
29062 case 'ooo:': // ignore undocumented extensions
29063 case 'chartooo:': // ignore undocumented extensions
29064 case 'draw:': // TODO: drawing
29065 case 'style:': // TODO: styles
29066 case 'chart:': // TODO: charts
29067 case 'form:': // TODO: forms
29068 case 'uof:': // TODO: uof
29069 case '表:': // TODO: uof
29070 case '字:': // TODO: uof
29071 break;
29072 default: if(opts.WTF) throw new Error(Rn);
29073 }
29074 }
29075 var out = ({
29076 Sheets: Sheets,
29077 SheetNames: SheetNames,
29078 Workbook: WB
29079 });
29080 if(opts.bookSheets) delete out.Sheets;
29081 return out;
29082 };
29083})();
29084
29085function parse_ods(zip, opts) {
29086 opts = opts || ({});
29087 var ods = !!safegetzipfile(zip, 'objectdata');
29088 if(ods) parse_manifest(getzipdata(zip, 'META-INF/manifest.xml'), opts);
29089 var content = getzipstr(zip, 'content.xml');
29090 if(!content) throw new Error("Missing content.xml in " + (ods ? "ODS" : "UOF")+ " file");
29091 var wb = parse_content_xml(ods ? content : utf8read(content), opts);
29092 if(safegetzipfile(zip, 'meta.xml')) wb.Props = parse_core_props(getzipdata(zip, 'meta.xml'));
29093 return wb;
29094}
29095function parse_fods(data, opts) {
29096 return parse_content_xml(data, opts);
29097}
29098
29099/* OpenDocument */
29100var write_styles_ods = (function() {
29101 var payload = '<office:document-styles ' + wxt_helper({
29102 'xmlns:office': "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
29103 'xmlns:table': "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
29104 'xmlns:style': "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
29105 'xmlns:text': "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
29106 'xmlns:draw': "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
29107 'xmlns:fo': "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
29108 'xmlns:xlink': "http://www.w3.org/1999/xlink",
29109 'xmlns:dc': "http://purl.org/dc/elements/1.1/",
29110 'xmlns:number': "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",
29111 'xmlns:svg': "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",
29112 'xmlns:of': "urn:oasis:names:tc:opendocument:xmlns:of:1.2",
29113 'office:version': "1.2"
29114 }) + '></office:document-styles>';
29115 return function wso() {
29116 return XML_HEADER + payload;
29117 };
29118})();
29119var write_content_ods = (function() {
29120 /* 6.1.2 White Space Characters */
29121 var write_text_p = function(text) {
29122 return escapexml(text)
29123 .replace(/ +/g, function($$){return '<text:s text:c="'+$$.length+'"/>';})
29124 .replace(/\t/g, "<text:tab/>")
29125 .replace(/\n/g, "<text:line-break/>")
29126 .replace(/^ /, "<text:s/>").replace(/ $/, "<text:s/>");
29127 };
29128
29129 var null_cell_xml = ' <table:table-cell />\n';
29130 var covered_cell_xml = ' <table:covered-table-cell/>\n';
29131 var write_ws = function(ws, wb, i) {
29132 /* Section 9 Tables */
29133 var o = [];
29134 o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '">\n');
29135 var R=0,C=0, range = decode_range(ws['!ref']);
29136 var marr = ws['!merges'] || [], mi = 0;
29137 var dense = Array.isArray(ws);
29138 for(R = 0; R < range.s.r; ++R) o.push(' <table:table-row></table:table-row>\n');
29139 for(; R <= range.e.r; ++R) {
29140 o.push(' <table:table-row>\n');
29141 for(C=0; C < range.s.c; ++C) o.push(null_cell_xml);
29142 for(; C <= range.e.c; ++C) {
29143 var skip = false, ct = {}, textp = "";
29144 for(mi = 0; mi != marr.length; ++mi) {
29145 if(marr[mi].s.c > C) continue;
29146 if(marr[mi].s.r > R) continue;
29147 if(marr[mi].e.c < C) continue;
29148 if(marr[mi].e.r < R) continue;
29149 if(marr[mi].s.c != C || marr[mi].s.r != R) skip = true;
29150 ct['table:number-columns-spanned'] = (marr[mi].e.c - marr[mi].s.c + 1);
29151 ct['table:number-rows-spanned'] = (marr[mi].e.r - marr[mi].s.r + 1);
29152 break;
29153 }
29154 if(skip) { o.push(covered_cell_xml); continue; }
29155 var ref = encode_cell({r:R, c:C}), cell = dense ? (ws[R]||[])[C]: ws[ref];
29156 if(cell && cell.f) {
29157 ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f));
29158 if(cell.F) {
29159 if(cell.F.slice(0, ref.length) == ref) {
29160 var _Fref = decode_range(cell.F);
29161 ct['table:number-matrix-columns-spanned'] = (_Fref.e.c - _Fref.s.c + 1);
29162 ct['table:number-matrix-rows-spanned'] = (_Fref.e.r - _Fref.s.r + 1);
29163 }
29164 }
29165 }
29166 if(!cell) { o.push(null_cell_xml); continue; }
29167 switch(cell.t) {
29168 case 'b':
29169 textp = (cell.v ? 'TRUE' : 'FALSE');
29170 ct['office:value-type'] = "boolean";
29171 ct['office:boolean-value'] = (cell.v ? 'true' : 'false');
29172 break;
29173 case 'n':
29174 textp = (cell.w||String(cell.v||0));
29175 ct['office:value-type'] = "float";
29176 ct['office:value'] = (cell.v||0);
29177 break;
29178 case 's': case 'str':
29179 textp = cell.v;
29180 ct['office:value-type'] = "string";
29181 break;
29182 case 'd':
29183 textp = (cell.w||(parseDate(cell.v).toISOString()));
29184 ct['office:value-type'] = "date";
29185 ct['office:date-value'] = (parseDate(cell.v).toISOString());
29186 ct['table:style-name'] = "ce1";
29187 break;
29188 //case 'e':
29189 default: o.push(null_cell_xml); continue;
29190 }
29191 var text_p = write_text_p(textp);
29192 if(cell.l && cell.l.Target) {
29193 var _tgt = cell.l.Target; _tgt = _tgt.charAt(0) == "#" ? "#" + csf_to_ods_3D(_tgt.slice(1)) : _tgt;
29194 text_p = writextag('text:a', text_p, {'xlink:href': _tgt});
29195 }
29196 o.push(' ' + writextag('table:table-cell', writextag('text:p', text_p, {}), ct) + '\n');
29197 }
29198 o.push(' </table:table-row>\n');
29199 }
29200 o.push(' </table:table>\n');
29201 return o.join("");
29202 };
29203
29204 var write_automatic_styles_ods = function(o) {
29205 o.push(' <office:automatic-styles>\n');
29206 o.push(' <number:date-style style:name="N37" number:automatic-order="true">\n');
29207 o.push(' <number:month number:style="long"/>\n');
29208 o.push(' <number:text>/</number:text>\n');
29209 o.push(' <number:day number:style="long"/>\n');
29210 o.push(' <number:text>/</number:text>\n');
29211 o.push(' <number:year/>\n');
29212 o.push(' </number:date-style>\n');
29213 o.push(' <style:style style:name="ce1" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N37"/>\n');
29214 o.push(' </office:automatic-styles>\n');
29215 };
29216
29217 return function wcx(wb, opts) {
29218 var o = [XML_HEADER];
29219 /* 3.1.3.2 */
29220 var attr = wxt_helper({
29221 'xmlns:office': "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
29222 'xmlns:table': "urn:oasis:names:tc:opendocument:xmlns:table:1.0",
29223 'xmlns:style': "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
29224 'xmlns:text': "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
29225 'xmlns:draw': "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
29226 'xmlns:fo': "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
29227 'xmlns:xlink': "http://www.w3.org/1999/xlink",
29228 'xmlns:dc': "http://purl.org/dc/elements/1.1/",
29229 'xmlns:meta': "urn:oasis:names:tc:opendocument:xmlns:meta:1.0",
29230 'xmlns:number': "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0",
29231 'xmlns:presentation': "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0",
29232 'xmlns:svg': "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0",
29233 'xmlns:chart': "urn:oasis:names:tc:opendocument:xmlns:chart:1.0",
29234 'xmlns:dr3d': "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0",
29235 'xmlns:math': "http://www.w3.org/1998/Math/MathML",
29236 'xmlns:form': "urn:oasis:names:tc:opendocument:xmlns:form:1.0",
29237 'xmlns:script': "urn:oasis:names:tc:opendocument:xmlns:script:1.0",
29238 'xmlns:ooo': "http://openoffice.org/2004/office",
29239 'xmlns:ooow': "http://openoffice.org/2004/writer",
29240 'xmlns:oooc': "http://openoffice.org/2004/calc",
29241 'xmlns:dom': "http://www.w3.org/2001/xml-events",
29242 'xmlns:xforms': "http://www.w3.org/2002/xforms",
29243 'xmlns:xsd': "http://www.w3.org/2001/XMLSchema",
29244 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance",
29245 'xmlns:sheet': "urn:oasis:names:tc:opendocument:sh33tjs:1.0",
29246 'xmlns:rpt': "http://openoffice.org/2005/report",
29247 'xmlns:of': "urn:oasis:names:tc:opendocument:xmlns:of:1.2",
29248 'xmlns:xhtml': "http://www.w3.org/1999/xhtml",
29249 'xmlns:grddl': "http://www.w3.org/2003/g/data-view#",
29250 'xmlns:tableooo': "http://openoffice.org/2009/table",
29251 'xmlns:drawooo': "http://openoffice.org/2010/draw",
29252 'xmlns:calcext': "urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0",
29253 'xmlns:loext': "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0",
29254 'xmlns:field': "urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0",
29255 'xmlns:formx': "urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0",
29256 'xmlns:css3t': "http://www.w3.org/TR/css3-text/",
29257 'office:version': "1.2"
29258 });
29259
29260 var fods = wxt_helper({
29261 'xmlns:config': "urn:oasis:names:tc:opendocument:xmlns:config:1.0",
29262 'office:mimetype': "application/vnd.oasis.opendocument.spreadsheet"
29263 });
29264
29265 if(opts.bookType == "fods") o.push('<office:document' + attr + fods + '>\n');
29266 else o.push('<office:document-content' + attr + '>\n');
29267 write_automatic_styles_ods(o);
29268 o.push(' <office:body>\n');
29269 o.push(' <office:spreadsheet>\n');
29270 for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts));
29271 o.push(' </office:spreadsheet>\n');
29272 o.push(' </office:body>\n');
29273 if(opts.bookType == "fods") o.push('</office:document>');
29274 else o.push('</office:document-content>');
29275 return o.join("");
29276 };
29277})();
29278
29279function write_ods(wb, opts) {
29280 if(opts.bookType == "fods") return write_content_ods(wb, opts);
29281
29282var zip = zip_new();
29283 var f = "";
29284
29285 var manifest = [];
29286 var rdf = [];
29287
29288 /* Part 3 Section 3.3 MIME Media Type */
29289 f = "mimetype";
29290 zip_add_file(zip, f, "application/vnd.oasis.opendocument.spreadsheet");
29291
29292 /* Part 1 Section 2.2 Documents */
29293 f = "content.xml";
29294 zip_add_file(zip, f, write_content_ods(wb, opts));
29295 manifest.push([f, "text/xml"]);
29296 rdf.push([f, "ContentFile"]);
29297
29298 /* TODO: these are hard-coded styles to satiate excel */
29299 f = "styles.xml";
29300 zip_add_file(zip, f, write_styles_ods(wb, opts));
29301 manifest.push([f, "text/xml"]);
29302 rdf.push([f, "StylesFile"]);
29303
29304 /* TODO: this is hard-coded to satiate excel */
29305 f = "meta.xml";
29306 zip_add_file(zip, f, write_meta_ods());
29307 manifest.push([f, "text/xml"]);
29308 rdf.push([f, "MetadataFile"]);
29309
29310 /* Part 3 Section 6 Metadata Manifest File */
29311 f = "manifest.rdf";
29312 zip_add_file(zip, f, write_rdf(rdf/*, opts*/));
29313 manifest.push([f, "application/rdf+xml"]);
29314
29315 /* Part 3 Section 4 Manifest File */
29316 f = "META-INF/manifest.xml";
29317 zip_add_file(zip, f, write_manifest(manifest/*, opts*/));
29318
29319 return zip;
29320}
29321
29322function write_sheet_index(wb, sheet) {
29323 if(!sheet) return 0;
29324 var idx = wb.SheetNames.indexOf(sheet);
29325 if(idx == -1) throw new Error("Sheet not found: " + sheet);
29326 return idx;
29327}
29328
29329function write_obj_str(factory) {
29330 return function write_str(wb, o) {
29331 var idx = write_sheet_index(wb, o.sheet);
29332 return factory.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb);
29333 };
29334}
29335
29336var write_htm_str = write_obj_str(HTML_);
29337var write_csv_str = write_obj_str({from_sheet:sheet_to_csv});
29338var write_slk_str = write_obj_str(typeof SYLK !== "undefined" ? SYLK : {});
29339var write_dif_str = write_obj_str(typeof DIF !== "undefined" ? DIF : {});
29340var write_prn_str = write_obj_str(typeof PRN !== "undefined" ? PRN : {});
29341var write_rtf_str = write_obj_str(typeof RTF !== "undefined" ? RTF : {});
29342var write_txt_str = write_obj_str({from_sheet:sheet_to_txt});
29343var write_dbf_buf = write_obj_str(typeof DBF !== "undefined" ? DBF : {});
29344var write_eth_str = write_obj_str(typeof ETH !== "undefined" ? ETH : {});
29345
29346function fix_opts_func(defaults) {
29347 return function fix_opts(opts) {
29348 for(var i = 0; i != defaults.length; ++i) {
29349 var d = defaults[i];
29350 if(opts[d[0]] === undefined) opts[d[0]] = d[1];
29351 if(d[2] === 'n') opts[d[0]] = Number(opts[d[0]]);
29352 }
29353 };
29354}
29355
29356var fix_read_opts = fix_opts_func([
29357 ['cellNF', false], /* emit cell number format string as .z */
29358 ['cellHTML', true], /* emit html string as .h */
29359 ['cellFormula', true], /* emit formulae as .f */
29360 ['cellStyles', false], /* emits style/theme as .s */
29361 ['cellText', true], /* emit formatted text as .w */
29362 ['cellDates', false], /* emit date cells with type `d` */
29363
29364 ['sheetStubs', false], /* emit empty cells */
29365 ['sheetRows', 0, 'n'], /* read n rows (0 = read all rows) */
29366
29367 ['bookDeps', false], /* parse calculation chains */
29368 ['bookSheets', false], /* only try to get sheet names (no Sheets) */
29369 ['bookProps', false], /* only try to get properties (no Sheets) */
29370 ['bookFiles', false], /* include raw file structure (keys, files, cfb) */
29371 ['bookVBA', false], /* include vba raw data (vbaraw) */
29372
29373 ['password',''], /* password */
29374 ['WTF', false] /* WTF mode (throws errors) */
29375]);
29376
29377
29378var fix_write_opts = fix_opts_func([
29379 ['cellDates', false], /* write date cells with type `d` */
29380
29381 ['bookSST', false], /* Generate Shared String Table */
29382
29383 ['bookType', 'xlsx'], /* Type of workbook (xlsx/m/b) */
29384
29385 ['compression', false], /* Use file compression */
29386
29387 ['WTF', false] /* WTF mode (throws errors) */
29388]);
29389function get_sheet_type(n) {
29390 if(RELS.WS.indexOf(n) > -1) return "sheet";
29391 if(RELS.CS && n == RELS.CS) return "chart";
29392 if(RELS.DS && n == RELS.DS) return "dialog";
29393 if(RELS.MS && n == RELS.MS) return "macro";
29394 return (n && n.length) ? n : "sheet";
29395}
29396function safe_parse_wbrels(wbrels, sheets) {
29397 if(!wbrels) return 0;
29398 try {
29399 wbrels = sheets.map(function pwbr(w) { if(!w.id) w.id = w.strRelID; return [w.name, wbrels['!id'][w.id].Target, get_sheet_type(wbrels['!id'][w.id].Type)]; });
29400 } catch(e) { return null; }
29401 return !wbrels || wbrels.length === 0 ? null : wbrels;
29402}
29403
29404function safe_parse_sheet(zip, path, relsPath, sheet, idx, sheetRels, sheets, stype, opts, wb, themes, styles) {
29405 try {
29406 sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path);
29407 var data = getzipdata(zip, path);
29408 var _ws;
29409 switch(stype) {
29410 case 'sheet': _ws = parse_ws(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
29411 case 'chart': _ws = parse_cs(data, path, idx, opts, sheetRels[sheet], wb, themes, styles);
29412 if(!_ws || !_ws['!drawel']) break;
29413 var dfile = resolve_path(_ws['!drawel'].Target, path);
29414 var drelsp = get_rels_path(dfile);
29415 var draw = parse_drawing(getzipstr(zip, dfile, true), parse_rels(getzipstr(zip, drelsp, true), dfile));
29416 var chartp = resolve_path(draw, dfile);
29417 var crelsp = get_rels_path(chartp);
29418 _ws = parse_chart(getzipstr(zip, chartp, true), chartp, opts, parse_rels(getzipstr(zip, crelsp, true), chartp), wb, _ws);
29419 break;
29420 case 'macro': _ws = parse_ms(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
29421 case 'dialog': _ws = parse_ds(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break;
29422 default: throw new Error("Unrecognized sheet type " + stype);
29423 }
29424 sheets[sheet] = _ws;
29425
29426 /* scan rels for comments */
29427 var comments = [];
29428 if(sheetRels && sheetRels[sheet]) keys(sheetRels[sheet]).forEach(function(n) {
29429 if(sheetRels[sheet][n].Type == RELS.CMNT) {
29430 var dfile = resolve_path(sheetRels[sheet][n].Target, path);
29431 comments = parse_cmnt(getzipdata(zip, dfile, true), dfile, opts);
29432 if(!comments || !comments.length) return;
29433 sheet_insert_comments(_ws, comments);
29434 }
29435 });
29436 } catch(e) { if(opts.WTF) throw e; }
29437}
29438
29439function strip_front_slash(x) { return x.charAt(0) == '/' ? x.slice(1) : x; }
29440
29441function parse_zip(zip, opts) {
29442 make_ssf(SSF);
29443 opts = opts || {};
29444 fix_read_opts(opts);
29445
29446 /* OpenDocument Part 3 Section 2.2.1 OpenDocument Package */
29447 if(safegetzipfile(zip, 'META-INF/manifest.xml')) return parse_ods(zip, opts);
29448 /* UOC */
29449 if(safegetzipfile(zip, 'objectdata.xml')) return parse_ods(zip, opts);
29450 /* Numbers */
29451 if(safegetzipfile(zip, 'Index/Document.iwa')) throw new Error('Unsupported NUMBERS file');
29452
29453 var entries = zipentries(zip);
29454 var dir = parse_ct((getzipstr(zip, '[Content_Types].xml')));
29455 var xlsb = false;
29456 var sheets, binname;
29457 if(dir.workbooks.length === 0) {
29458 binname = "xl/workbook.xml";
29459 if(getzipdata(zip,binname, true)) dir.workbooks.push(binname);
29460 }
29461 if(dir.workbooks.length === 0) {
29462 binname = "xl/workbook.bin";
29463 if(!getzipdata(zip,binname,true)) throw new Error("Could not find workbook");
29464 dir.workbooks.push(binname);
29465 xlsb = true;
29466 }
29467 if(dir.workbooks[0].slice(-3) == "bin") xlsb = true;
29468
29469 var themes = ({});
29470 var styles = ({});
29471 if(!opts.bookSheets && !opts.bookProps) {
29472 strs = [];
29473 if(dir.sst) try { strs=parse_sst(getzipdata(zip, strip_front_slash(dir.sst)), dir.sst, opts); } catch(e) { if(opts.WTF) throw e; }
29474
29475 if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"",dir.themes[0], opts);
29476
29477 if(dir.style) styles = parse_sty(getzipdata(zip, strip_front_slash(dir.style)), dir.style, themes, opts);
29478 }
29479
29480 /*var externbooks = */dir.links.map(function(link) {
29481 try {
29482 var rels = parse_rels(getzipstr(zip, get_rels_path(strip_front_slash(link))), link);
29483 return parse_xlink(getzipdata(zip, strip_front_slash(link)), rels, link, opts);
29484 } catch(e) {}
29485 });
29486
29487 var wb = parse_wb(getzipdata(zip, strip_front_slash(dir.workbooks[0])), dir.workbooks[0], opts);
29488
29489 var props = {}, propdata = "";
29490
29491 if(dir.coreprops.length) {
29492 propdata = getzipdata(zip, strip_front_slash(dir.coreprops[0]), true);
29493 if(propdata) props = parse_core_props(propdata);
29494 if(dir.extprops.length !== 0) {
29495 propdata = getzipdata(zip, strip_front_slash(dir.extprops[0]), true);
29496 if(propdata) parse_ext_props(propdata, props, opts);
29497 }
29498 }
29499
29500 var custprops = {};
29501 if(!opts.bookSheets || opts.bookProps) {
29502 if (dir.custprops.length !== 0) {
29503 propdata = getzipstr(zip, strip_front_slash(dir.custprops[0]), true);
29504 if(propdata) custprops = parse_cust_props(propdata, opts);
29505 }
29506 }
29507
29508 var out = ({});
29509 if(opts.bookSheets || opts.bookProps) {
29510 if(wb.Sheets) sheets = wb.Sheets.map(function pluck(x){ return x.name; });
29511 else if(props.Worksheets && props.SheetNames.length > 0) sheets=props.SheetNames;
29512 if(opts.bookProps) { out.Props = props; out.Custprops = custprops; }
29513 if(opts.bookSheets && typeof sheets !== 'undefined') out.SheetNames = sheets;
29514 if(opts.bookSheets ? out.SheetNames : opts.bookProps) return out;
29515 }
29516 sheets = {};
29517
29518 var deps = {};
29519 if(opts.bookDeps && dir.calcchain) deps=parse_cc(getzipdata(zip, strip_front_slash(dir.calcchain)),dir.calcchain,opts);
29520
29521 var i=0;
29522 var sheetRels = ({});
29523 var path, relsPath;
29524
29525 {
29526 var wbsheets = wb.Sheets;
29527 props.Worksheets = wbsheets.length;
29528 props.SheetNames = [];
29529 for(var j = 0; j != wbsheets.length; ++j) {
29530 props.SheetNames[j] = wbsheets[j].name;
29531 }
29532 }
29533
29534 var wbext = xlsb ? "bin" : "xml";
29535 var wbrelsi = dir.workbooks[0].lastIndexOf("/");
29536 var wbrelsfile = (dir.workbooks[0].slice(0, wbrelsi+1) + "_rels/" + dir.workbooks[0].slice(wbrelsi+1) + ".rels").replace(/^\//,"");
29537 if(!safegetzipfile(zip, wbrelsfile)) wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels';
29538 var wbrels = parse_rels(getzipstr(zip, wbrelsfile, true), wbrelsfile);
29539 if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets);
29540
29541 /* Numbers iOS hack */
29542 var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0;
29543 for(i = 0; i != props.Worksheets; ++i) {
29544 var stype = "sheet";
29545 if(wbrels && wbrels[i]) {
29546 path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, "");
29547 if(!safegetzipfile(zip, path)) path = wbrels[i][1];
29548 if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/.*$/,"") + wbrels[i][1];
29549 stype = wbrels[i][2];
29550 } else {
29551 path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext;
29552 path = path.replace(/sheet0\./,"sheet.");
29553 }
29554 relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
29555 safe_parse_sheet(zip, path, relsPath, props.SheetNames[i], i, sheetRels, sheets, stype, opts, wb, themes, styles);
29556 }
29557
29558 out = ({
29559 Directory: dir,
29560 Workbook: wb,
29561 Props: props,
29562 Custprops: custprops,
29563 Deps: deps,
29564 Sheets: sheets,
29565 SheetNames: props.SheetNames,
29566 Strings: strs,
29567 Styles: styles,
29568 Themes: themes,
29569 SSF: SSF.get_table()
29570 });
29571 if(opts.bookFiles) {
29572 out.keys = entries;
29573 out.files = zip.files;
29574 }
29575 if(opts.bookVBA) {
29576 if(dir.vba.length > 0) out.vbaraw = getzipdata(zip,strip_front_slash(dir.vba[0]),true);
29577 else if(dir.defaults && dir.defaults.bin === CT_VBA) out.vbaraw = getzipdata(zip, 'xl/vbaProject.bin',true);
29578 }
29579 return out;
29580}
29581
29582/* [MS-OFFCRYPTO] 2.1.1 */
29583function parse_xlsxcfb(cfb, _opts) {
29584 var opts = _opts || {};
29585 var f = 'Workbook', data = CFB.find(cfb, f);
29586 try {
29587 f = '/!DataSpaces/Version';
29588 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
29589 /*var version = */parse_DataSpaceVersionInfo(data.content);
29590
29591 /* 2.3.4.1 */
29592 f = '/!DataSpaces/DataSpaceMap';
29593 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
29594 var dsm = parse_DataSpaceMap(data.content);
29595 if(dsm.length !== 1 || dsm[0].comps.length !== 1 || dsm[0].comps[0].t !== 0 || dsm[0].name !== "StrongEncryptionDataSpace" || dsm[0].comps[0].v !== "EncryptedPackage")
29596 throw new Error("ECMA-376 Encrypted file bad " + f);
29597
29598 /* 2.3.4.2 */
29599 f = '/!DataSpaces/DataSpaceInfo/StrongEncryptionDataSpace';
29600 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
29601 var seds = parse_DataSpaceDefinition(data.content);
29602 if(seds.length != 1 || seds[0] != "StrongEncryptionTransform")
29603 throw new Error("ECMA-376 Encrypted file bad " + f);
29604
29605 /* 2.3.4.3 */
29606 f = '/!DataSpaces/TransformInfo/StrongEncryptionTransform/!Primary';
29607 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
29608 /*var hdr = */parse_Primary(data.content);
29609 } catch(e) {}
29610
29611 f = '/EncryptionInfo';
29612 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
29613 var einfo = parse_EncryptionInfo(data.content);
29614
29615 /* 2.3.4.4 */
29616 f = '/EncryptedPackage';
29617 data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f);
29618
29619/*global decrypt_agile */
29620if(einfo[0] == 0x04 && typeof decrypt_agile !== 'undefined') return decrypt_agile(einfo[1], data.content, opts.password || "", opts);
29621/*global decrypt_std76 */
29622if(einfo[0] == 0x02 && typeof decrypt_std76 !== 'undefined') return decrypt_std76(einfo[1], data.content, opts.password || "", opts);
29623 throw new Error("File is password-protected");
29624}
29625
29626function write_zip(wb, opts) {
29627 _shapeid = 1024;
29628 if(opts.bookType == "ods") return write_ods(wb, opts);
29629 if(wb && !wb.SSF) {
29630 wb.SSF = SSF.get_table();
29631 }
29632 if(wb && wb.SSF) {
29633 make_ssf(SSF); SSF.load_table(wb.SSF);
29634 // $FlowIgnore
29635 opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0;
29636 opts.ssf = wb.SSF;
29637 }
29638 opts.rels = {}; opts.wbrels = {};
29639 opts.Strings = []; opts.Strings.Count = 0; opts.Strings.Unique = 0;
29640 if(browser_has_Map) opts.revStrings = new Map();
29641 else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; }
29642 var wbext = opts.bookType == "xlsb" ? "bin" : "xml";
29643 var vbafmt = VBAFMTS.indexOf(opts.bookType) > -1;
29644 var ct = new_ct();
29645 fix_write_opts(opts = opts || {});
29646var zip = zip_new();
29647 var f = "", rId = 0;
29648
29649 opts.cellXfs = [];
29650 get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}});
29651
29652 if(!wb.Props) wb.Props = {};
29653
29654 f = "docProps/core.xml";
29655 zip_add_file(zip, f, write_core_props(wb.Props, opts));
29656 ct.coreprops.push(f);
29657 add_rels(opts.rels, 2, f, RELS.CORE_PROPS);
29658
29659f = "docProps/app.xml";
29660 if(wb.Props && wb.Props.SheetNames){/* empty */}
29661 else if(!wb.Workbook || !wb.Workbook.Sheets) wb.Props.SheetNames = wb.SheetNames;
29662 else {
29663 var _sn = [];
29664 for(var _i = 0; _i < wb.SheetNames.length; ++_i)
29665 if((wb.Workbook.Sheets[_i]||{}).Hidden != 2) _sn.push(wb.SheetNames[_i]);
29666 wb.Props.SheetNames = _sn;
29667 }
29668 wb.Props.Worksheets = wb.Props.SheetNames.length;
29669 zip_add_file(zip, f, write_ext_props(wb.Props, opts));
29670 ct.extprops.push(f);
29671 add_rels(opts.rels, 3, f, RELS.EXT_PROPS);
29672
29673 if(wb.Custprops !== wb.Props && keys(wb.Custprops||{}).length > 0) {
29674 f = "docProps/custom.xml";
29675 zip_add_file(zip, f, write_cust_props(wb.Custprops, opts));
29676 ct.custprops.push(f);
29677 add_rels(opts.rels, 4, f, RELS.CUST_PROPS);
29678 }
29679
29680 for(rId=1;rId <= wb.SheetNames.length; ++rId) {
29681 var wsrels = {'!id':{}};
29682 var ws = wb.Sheets[wb.SheetNames[rId-1]];
29683 var _type = (ws || {})["!type"] || "sheet";
29684 switch(_type) {
29685 case "chart":
29686 /* falls through */
29687 default:
29688 f = "xl/worksheets/sheet" + rId + "." + wbext;
29689 zip_add_file(zip, f, write_ws(rId-1, f, opts, wb, wsrels));
29690 ct.sheets.push(f);
29691 add_rels(opts.wbrels, -1, "worksheets/sheet" + rId + "." + wbext, RELS.WS[0]);
29692 }
29693
29694 if(ws) {
29695 var comments = ws['!comments'];
29696 var need_vml = false;
29697 if(comments && comments.length > 0) {
29698 var cf = "xl/comments" + rId + "." + wbext;
29699 zip_add_file(zip, cf, write_cmnt(comments, cf, opts));
29700 ct.comments.push(cf);
29701 add_rels(wsrels, -1, "../comments" + rId + "." + wbext, RELS.CMNT);
29702 need_vml = true;
29703 }
29704 if(ws['!legacy']) {
29705 if(need_vml) zip_add_file(zip, "xl/drawings/vmlDrawing" + (rId) + ".vml", write_comments_vml(rId, ws['!comments']));
29706 }
29707 delete ws['!comments'];
29708 delete ws['!legacy'];
29709 }
29710
29711 if(wsrels['!id'].rId1) zip_add_file(zip, get_rels_path(f), write_rels(wsrels));
29712 }
29713
29714 if(opts.Strings != null && opts.Strings.length > 0) {
29715 f = "xl/sharedStrings." + wbext;
29716 zip_add_file(zip, f, write_sst(opts.Strings, f, opts));
29717 ct.strs.push(f);
29718 add_rels(opts.wbrels, -1, "sharedStrings." + wbext, RELS.SST);
29719 }
29720
29721 f = "xl/workbook." + wbext;
29722 zip_add_file(zip, f, write_wb(wb, f, opts));
29723 ct.workbooks.push(f);
29724 add_rels(opts.rels, 1, f, RELS.WB);
29725
29726 /* TODO: something more intelligent with themes */
29727
29728 f = "xl/theme/theme1.xml";
29729 zip_add_file(zip, f, write_theme(wb.Themes, opts));
29730 ct.themes.push(f);
29731 add_rels(opts.wbrels, -1, "theme/theme1.xml", RELS.THEME);
29732
29733 /* TODO: something more intelligent with styles */
29734
29735 f = "xl/styles." + wbext;
29736 zip_add_file(zip, f, write_sty(wb, f, opts));
29737 ct.styles.push(f);
29738 add_rels(opts.wbrels, -1, "styles." + wbext, RELS.STY);
29739
29740 if(wb.vbaraw && vbafmt) {
29741 f = "xl/vbaProject.bin";
29742 zip_add_file(zip, f, wb.vbaraw);
29743 ct.vba.push(f);
29744 add_rels(opts.wbrels, -1, "vbaProject.bin", RELS.VBA);
29745 }
29746
29747 zip_add_file(zip, "[Content_Types].xml", write_ct(ct, opts));
29748 zip_add_file(zip, '_rels/.rels', write_rels(opts.rels));
29749 zip_add_file(zip, 'xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));
29750
29751 delete opts.revssf; delete opts.ssf;
29752 return zip;
29753}
29754function firstbyte(f,o) {
29755 var x = "";
29756 switch((o||{}).type || "base64") {
29757 case 'buffer': return [f[0], f[1], f[2], f[3]];
29758 case 'base64': x = Base64.decode(f.slice(0,24)); break;
29759 case 'binary': x = f; break;
29760 case 'array': return [f[0], f[1], f[2], f[3]];
29761 default: throw new Error("Unrecognized type " + (o && o.type || "undefined"));
29762 }
29763 return [x.charCodeAt(0), x.charCodeAt(1), x.charCodeAt(2), x.charCodeAt(3)];
29764}
29765
29766function read_cfb(cfb, opts) {
29767 if(CFB.find(cfb, "EncryptedPackage")) return parse_xlsxcfb(cfb, opts);
29768 return parse_xlscfb(cfb, opts);
29769}
29770
29771function read_zip(data, opts) {
29772var zip, d = data;
29773 var o = opts||{};
29774 if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
29775 zip = zip_read(d, o);
29776 return parse_zip(zip, o);
29777}
29778
29779function read_plaintext(data, o) {
29780 var i = 0;
29781 main: while(i < data.length) switch(data.charCodeAt(i)) {
29782 case 0x0A: case 0x0D: case 0x20: ++i; break;
29783 case 0x3C: return parse_xlml(data.slice(i),o);
29784 default: break main;
29785 }
29786 return PRN.to_workbook(data, o);
29787}
29788
29789function read_plaintext_raw(data, o) {
29790 var str = "", bytes = firstbyte(data, o);
29791 switch(o.type) {
29792 case 'base64': str = Base64.decode(data); break;
29793 case 'binary': str = data; break;
29794 case 'buffer': str = data.toString('binary'); break;
29795 case 'array': str = cc2str(data); break;
29796 default: throw new Error("Unrecognized type " + o.type);
29797 }
29798 if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str);
29799 return read_plaintext(str, o);
29800}
29801
29802function read_utf16(data, o) {
29803 var d = data;
29804 if(o.type == 'base64') d = Base64.decode(d);
29805 d = cptable.utils.decode(1200, d.slice(2), 'str');
29806 o.type = "binary";
29807 return read_plaintext(d, o);
29808}
29809
29810function bstrify(data) {
29811 return !data.match(/[^\x00-\x7F]/) ? data : utf8write(data);
29812}
29813
29814function read_prn(data, d, o, str) {
29815 if(str) { o.type = "string"; return PRN.to_workbook(data, o); }
29816 return PRN.to_workbook(d, o);
29817}
29818
29819function readSync(data, opts) {
29820 reset_cp();
29821 if(typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) return readSync(new Uint8Array(data), opts);
29822 var d = data, n = [0,0,0,0], str = false;
29823 var o = opts||{};
29824 if(o.cellStyles) { o.cellNF = true; }
29825 _ssfopts = {};
29826 if(o.dateNF) _ssfopts.dateNF = o.dateNF;
29827 if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64";
29828 if(o.type == "file") { o.type = has_buf ? "buffer" : "binary"; d = read_binary(data); }
29829 if(o.type == "string") { str = true; o.type = "binary"; o.codepage = 65001; d = bstrify(data); }
29830 if(o.type == 'array' && typeof Uint8Array !== 'undefined' && data instanceof Uint8Array && typeof ArrayBuffer !== 'undefined') {
29831 // $FlowIgnore
29832 var ab=new ArrayBuffer(3), vu=new Uint8Array(ab); vu.foo="bar";
29833 // $FlowIgnore
29834 if(!vu.foo) {o=dup(o); o.type='array'; return readSync(ab2a(d), o);}
29835 }
29836 switch((n = firstbyte(d, o))[0]) {
29837 case 0xD0: return read_cfb(CFB.read(d, o), o);
29838 case 0x09: if(n[1] <= 0x04) return parse_xlscfb(d, o); break;
29839 case 0x3C: return parse_xlml(d, o);
29840 case 0x49: if(n[1] === 0x44) return read_wb_ID(d, o); break;
29841 case 0x54: if(n[1] === 0x41 && n[2] === 0x42 && n[3] === 0x4C) return DIF.to_workbook(d, o); break;
29842 case 0x50: return (n[1] === 0x4B && n[2] < 0x09 && n[3] < 0x09) ? read_zip(d, o) : read_prn(data, d, o, str);
29843 case 0xEF: return n[3] === 0x3C ? parse_xlml(d, o) : read_prn(data, d, o, str);
29844 case 0xFF: if(n[1] === 0xFE) { return read_utf16(d, o); } break;
29845 case 0x00: if(n[1] === 0x00 && n[2] >= 0x02 && n[3] === 0x00) return WK_.to_workbook(d, o); break;
29846 case 0x03: case 0x83: case 0x8B: case 0x8C: return DBF.to_workbook(d, o);
29847 case 0x7B: if(n[1] === 0x5C && n[2] === 0x72 && n[3] === 0x74) return RTF.to_workbook(d, o); break;
29848 case 0x0A: case 0x0D: case 0x20: return read_plaintext_raw(d, o);
29849 }
29850 if(n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o);
29851 return read_prn(data, d, o, str);
29852}
29853
29854function readFileSync(filename, opts) {
29855 var o = opts||{}; o.type = 'file';
29856 return readSync(filename, o);
29857}
29858function write_cfb_ctr(cfb, o) {
29859 switch(o.type) {
29860 case "base64": case "binary": break;
29861 case "buffer": case "array": o.type = ""; break;
29862 case "file": return write_dl(o.file, CFB.write(cfb, {type:has_buf ? 'buffer' : ""}));
29863 case "string": throw new Error("'string' output type invalid for '" + o.bookType + "' files");
29864 default: throw new Error("Unrecognized type " + o.type);
29865 }
29866 return CFB.write(cfb, o);
29867}
29868
29869/*global encrypt_agile */
29870function write_zip_type(wb, opts) {
29871 var o = opts||{};
29872 var z = write_zip(wb, o);
29873 var oopts = {};
29874 if(o.compression) oopts.compression = 'DEFLATE';
29875 if(o.password) oopts.type = has_buf ? "nodebuffer" : "string";
29876 else switch(o.type) {
29877 case "base64": oopts.type = "base64"; break;
29878 case "binary": oopts.type = "string"; break;
29879 case "string": throw new Error("'string' output type invalid for '" + o.bookType + "' files");
29880 case "buffer":
29881 case "file": oopts.type = has_buf ? "nodebuffer" : "string"; break;
29882 default: throw new Error("Unrecognized type " + o.type);
29883 }
29884 var out = z.FullPaths ? CFB.write(z, {fileType:"zip", type: {"nodebuffer": "buffer", "string": "binary"}[oopts.type] || oopts.type}) : z.generate(oopts);
29885 if(o.password && typeof encrypt_agile !== 'undefined') return write_cfb_ctr(encrypt_agile(out, o.password), o);
29886 if(o.type === "file") return write_dl(o.file, out);
29887 return o.type == "string" ? utf8read(out) : out;
29888}
29889
29890function write_cfb_type(wb, opts) {
29891 var o = opts||{};
29892 var cfb = write_xlscfb(wb, o);
29893 return write_cfb_ctr(cfb, o);
29894}
29895
29896function write_string_type(out, opts, bom) {
29897 if(!bom) bom = "";
29898 var o = bom + out;
29899 switch(opts.type) {
29900 case "base64": return Base64.encode(utf8write(o));
29901 case "binary": return utf8write(o);
29902 case "string": return out;
29903 case "file": return write_dl(opts.file, o, 'utf8');
29904 case "buffer": {
29905 if(has_buf) return Buffer_from(o, 'utf8');
29906 else return write_string_type(o, {type:'binary'}).split("").map(function(c) { return c.charCodeAt(0); });
29907 }
29908 }
29909 throw new Error("Unrecognized type " + opts.type);
29910}
29911
29912function write_stxt_type(out, opts) {
29913 switch(opts.type) {
29914 case "base64": return Base64.encode(out);
29915 case "binary": return out;
29916 case "string": return out; /* override in sheet_to_txt */
29917 case "file": return write_dl(opts.file, out, 'binary');
29918 case "buffer": {
29919 if(has_buf) return Buffer_from(out, 'binary');
29920 else return out.split("").map(function(c) { return c.charCodeAt(0); });
29921 }
29922 }
29923 throw new Error("Unrecognized type " + opts.type);
29924}
29925
29926/* TODO: test consistency */
29927function write_binary_type(out, opts) {
29928 switch(opts.type) {
29929 case "string":
29930 case "base64":
29931 case "binary":
29932 var bstr = "";
29933 // $FlowIgnore
29934 for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]);
29935 return opts.type == 'base64' ? Base64.encode(bstr) : opts.type == 'string' ? utf8read(bstr) : bstr;
29936 case "file": return write_dl(opts.file, out);
29937 case "buffer": return out;
29938 default: throw new Error("Unrecognized type " + opts.type);
29939 }
29940}
29941
29942function writeSync(wb, opts) {
29943 reset_cp();
29944 check_wb(wb);
29945 var o = opts||{};
29946 if(o.cellStyles) { o.cellNF = true; }
29947 if(o.type == "array") { o.type = "binary"; var out = (writeSync(wb, o)); o.type = "array"; return s2ab(out); }
29948 switch(o.bookType || 'xlsb') {
29949 case 'xml':
29950 case 'xlml': return write_string_type(write_xlml(wb, o), o);
29951 case 'slk':
29952 case 'sylk': return write_string_type(write_slk_str(wb, o), o);
29953 case 'htm':
29954 case 'html': return write_string_type(write_htm_str(wb, o), o);
29955 case 'txt': return write_stxt_type(write_txt_str(wb, o), o);
29956 case 'csv': return write_string_type(write_csv_str(wb, o), o, "\ufeff");
29957 case 'dif': return write_string_type(write_dif_str(wb, o), o);
29958 case 'dbf': return write_binary_type(write_dbf_buf(wb, o), o);
29959 case 'prn': return write_string_type(write_prn_str(wb, o), o);
29960 case 'rtf': return write_string_type(write_rtf_str(wb, o), o);
29961 case 'eth': return write_string_type(write_eth_str(wb, o), o);
29962 case 'fods': return write_string_type(write_ods(wb, o), o);
29963 case 'biff2': if(!o.biff) o.biff = 2; /* falls through */
29964 case 'biff3': if(!o.biff) o.biff = 3; /* falls through */
29965 case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o);
29966 case 'biff5': if(!o.biff) o.biff = 5; /* falls through */
29967 case 'biff8':
29968 case 'xla':
29969 case 'xls': if(!o.biff) o.biff = 8; return write_cfb_type(wb, o);
29970 case 'xlsx':
29971 case 'xlsm':
29972 case 'xlam':
29973 case 'xlsb':
29974 case 'ods': return write_zip_type(wb, o);
29975 default: throw new Error ("Unrecognized bookType |" + o.bookType + "|");
29976 }
29977}
29978
29979function resolve_book_type(o) {
29980 if(o.bookType) return;
29981 var _BT = {
29982 "xls": "biff8",
29983 "htm": "html",
29984 "slk": "sylk",
29985 "socialcalc": "eth",
29986 "Sh33tJS": "WTF"
29987 };
29988 var ext = o.file.slice(o.file.lastIndexOf(".")).toLowerCase();
29989 if(ext.match(/^\.[a-z]+$/)) o.bookType = ext.slice(1);
29990 o.bookType = _BT[o.bookType] || o.bookType;
29991}
29992
29993function writeFileSync(wb, filename, opts) {
29994 var o = opts||{}; o.type = 'file';
29995 o.file = filename;
29996 resolve_book_type(o);
29997 return writeSync(wb, o);
29998}
29999
30000function writeFileAsync(filename, wb, opts, cb) {
30001 var o = opts||{}; o.type = 'file';
30002 o.file = filename;
30003 resolve_book_type(o);
30004 o.type = 'buffer';
30005 var _cb = cb; if(!(_cb instanceof Function)) _cb = (opts);
30006 return _fs.writeFile(filename, writeSync(wb, o), _cb);
30007}
30008function make_json_row(sheet, r, R, cols, header, hdr, dense, o) {
30009 var rr = encode_row(R);
30010 var defval = o.defval, raw = o.raw || !o.hasOwnProperty("raw");
30011 var isempty = true;
30012 var row = (header === 1) ? [] : {};
30013 if(header !== 1) {
30014 if(Object.defineProperty) try { Object.defineProperty(row, '__rowNum__', {value:R, enumerable:false}); } catch(e) { row.__rowNum__ = R; }
30015 else row.__rowNum__ = R;
30016 }
30017 if(!dense || sheet[R]) for (var C = r.s.c; C <= r.e.c; ++C) {
30018 var val = dense ? sheet[R][C] : sheet[cols[C] + rr];
30019 if(val === undefined || val.t === undefined) {
30020 if(defval === undefined) continue;
30021 if(hdr[C] != null) { row[hdr[C]] = defval; }
30022 continue;
30023 }
30024 var v = val.v;
30025 switch(val.t){
30026 case 'z': if(v == null) break; continue;
30027 case 'e': v = void 0; break;
30028 case 's': case 'd': case 'b': case 'n': break;
30029 default: throw new Error('unrecognized type ' + val.t);
30030 }
30031 if(hdr[C] != null) {
30032 if(v == null) {
30033 if(defval !== undefined) row[hdr[C]] = defval;
30034 else if(raw && v === null) row[hdr[C]] = null;
30035 else continue;
30036 } else {
30037 row[hdr[C]] = raw ? v : format_cell(val,v,o);
30038 }
30039 if(v != null) isempty = false;
30040 }
30041 }
30042 return { row: row, isempty: isempty };
30043}
30044
30045
30046function sheet_to_json(sheet, opts) {
30047 if(sheet == null || sheet["!ref"] == null) return [];
30048 var val = {t:'n',v:0}, header = 0, offset = 1, hdr = [], v=0, vv="";
30049 var r = {s:{r:0,c:0},e:{r:0,c:0}};
30050 var o = opts || {};
30051 var range = o.range != null ? o.range : sheet["!ref"];
30052 if(o.header === 1) header = 1;
30053 else if(o.header === "A") header = 2;
30054 else if(Array.isArray(o.header)) header = 3;
30055 else if(o.header == null) header = 0;
30056 switch(typeof range) {
30057 case 'string': r = safe_decode_range(range); break;
30058 case 'number': r = safe_decode_range(sheet["!ref"]); r.s.r = range; break;
30059 default: r = range;
30060 }
30061 if(header > 0) offset = 0;
30062 var rr = encode_row(r.s.r);
30063 var cols = [];
30064 var out = [];
30065 var outi = 0, counter = 0;
30066 var dense = Array.isArray(sheet);
30067 var R = r.s.r, C = 0, CC = 0;
30068 if(dense && !sheet[R]) sheet[R] = [];
30069 for(C = r.s.c; C <= r.e.c; ++C) {
30070 cols[C] = encode_col(C);
30071 val = dense ? sheet[R][C] : sheet[cols[C] + rr];
30072 switch(header) {
30073 case 1: hdr[C] = C - r.s.c; break;
30074 case 2: hdr[C] = cols[C]; break;
30075 case 3: hdr[C] = o.header[C - r.s.c]; break;
30076 default:
30077 if(val == null) val = {w: "__EMPTY", t: "s"};
30078 vv = v = format_cell(val, null, o);
30079 counter = 0;
30080 for(CC = 0; CC < hdr.length; ++CC) if(hdr[CC] == vv) vv = v + "_" + (++counter);
30081 hdr[C] = vv;
30082 }
30083 }
30084 for (R = r.s.r + offset; R <= r.e.r; ++R) {
30085 var row = make_json_row(sheet, r, R, cols, header, hdr, dense, o);
30086 if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) out[outi++] = row.row;
30087 }
30088 out.length = outi;
30089 return out;
30090}
30091
30092var qreg = /"/g;
30093function make_csv_row(sheet, r, R, cols, fs, rs, FS, o) {
30094 var isempty = true;
30095 var row = [], txt = "", rr = encode_row(R);
30096 for(var C = r.s.c; C <= r.e.c; ++C) {
30097 if (!cols[C]) continue;
30098 var val = o.dense ? (sheet[R]||[])[C]: sheet[cols[C] + rr];
30099 if(val == null) txt = "";
30100 else if(val.v != null) {
30101 isempty = false;
30102 txt = ''+format_cell(val, null, o);
30103 for(var i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) {txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
30104 if(txt == "ID") txt = '"ID"';
30105 } else if(val.f != null && !val.F) {
30106 isempty = false;
30107 txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"';
30108 } else txt = "";
30109 /* NOTE: Excel CSV does not support array formulae */
30110 row.push(txt);
30111 }
30112 if(o.blankrows === false && isempty) return null;
30113 return row.join(FS);
30114}
30115
30116function sheet_to_csv(sheet, opts) {
30117 var out = [];
30118 var o = opts == null ? {} : opts;
30119 if(sheet == null || sheet["!ref"] == null) return "";
30120 var r = safe_decode_range(sheet["!ref"]);
30121 var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
30122 var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
30123 var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
30124 var row = "", cols = [];
30125 o.dense = Array.isArray(sheet);
30126 var colinfo = o.skipHidden && sheet["!cols"] || [];
30127 var rowinfo = o.skipHidden && sheet["!rows"] || [];
30128 for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C);
30129 for(var R = r.s.r; R <= r.e.r; ++R) {
30130 if ((rowinfo[R]||{}).hidden) continue;
30131 row = make_csv_row(sheet, r, R, cols, fs, rs, FS, o);
30132 if(row == null) { continue; }
30133 if(o.strip) row = row.replace(endregex,"");
30134 out.push(row + RS);
30135 }
30136 delete o.dense;
30137 return out.join("");
30138}
30139
30140function sheet_to_txt(sheet, opts) {
30141 if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n";
30142 var s = sheet_to_csv(sheet, opts);
30143 if(typeof cptable == 'undefined' || opts.type == 'string') return s;
30144 var o = cptable.utils.encode(1200, s, 'str');
30145 return String.fromCharCode(255) + String.fromCharCode(254) + o;
30146}
30147
30148function sheet_to_formulae(sheet) {
30149 var y = "", x, val="";
30150 if(sheet == null || sheet["!ref"] == null) return [];
30151 var r = safe_decode_range(sheet['!ref']), rr = "", cols = [], C;
30152 var cmds = [];
30153 var dense = Array.isArray(sheet);
30154 for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C);
30155 for(var R = r.s.r; R <= r.e.r; ++R) {
30156 rr = encode_row(R);
30157 for(C = r.s.c; C <= r.e.c; ++C) {
30158 y = cols[C] + rr;
30159 x = dense ? (sheet[R]||[])[C] : sheet[y];
30160 val = "";
30161 if(x === undefined) continue;
30162 else if(x.F != null) {
30163 y = x.F;
30164 if(!x.f) continue;
30165 val = x.f;
30166 if(y.indexOf(":") == -1) y = y + ":" + y;
30167 }
30168 if(x.f != null) val = x.f;
30169 else if(x.t == 'z') continue;
30170 else if(x.t == 'n' && x.v != null) val = "" + x.v;
30171 else if(x.t == 'b') val = x.v ? "TRUE" : "FALSE";
30172 else if(x.w !== undefined) val = "'" + x.w;
30173 else if(x.v === undefined) continue;
30174 else if(x.t == 's') val = "'" + x.v;
30175 else val = ""+x.v;
30176 cmds[cmds.length] = y + "=" + val;
30177 }
30178 }
30179 return cmds;
30180}
30181
30182function sheet_add_json(_ws, js, opts) {
30183 var o = opts || {};
30184 var offset = +!o.skipHeader;
30185 var ws = _ws || ({});
30186 var _R = 0, _C = 0;
30187 if(ws && o.origin != null) {
30188 if(typeof o.origin == 'number') _R = o.origin;
30189 else {
30190 var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
30191 _R = _origin.r; _C = _origin.c;
30192 }
30193 }
30194 var cell;
30195 var range = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}});
30196 if(ws['!ref']) {
30197 var _range = safe_decode_range(ws['!ref']);
30198 range.e.c = Math.max(range.e.c, _range.e.c);
30199 range.e.r = Math.max(range.e.r, _range.e.r);
30200 if(_R == -1) { _R = range.e.r + 1; range.e.r = _R + js.length - 1 + offset; }
30201 }
30202 var hdr = o.header || [], C = 0;
30203
30204 js.forEach(function (JS, R) {
30205 keys(JS).forEach(function(k) {
30206 if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k;
30207 var v = JS[k];
30208 var t = 'z';
30209 var z = "";
30210 var ref = encode_cell({c:_C + C,r:_R + R + offset});
30211 cell = utils.sheet_get_cell(ws, ref);
30212 if(v && typeof v === 'object' && !(v instanceof Date)){
30213 ws[ref] = v;
30214 } else {
30215 if(typeof v == 'number') t = 'n';
30216 else if(typeof v == 'boolean') t = 'b';
30217 else if(typeof v == 'string') t = 's';
30218 else if(v instanceof Date) {
30219 t = 'd';
30220 if(!o.cellDates) { t = 'n'; v = datenum(v); }
30221 z = (o.dateNF || SSF._table[14]);
30222 }
30223 if(!cell) ws[ref] = cell = ({t:t, v:v});
30224 else {
30225 cell.t = t; cell.v = v;
30226 delete cell.w; delete cell.R;
30227 if(z) cell.z = z;
30228 }
30229 if(z) cell.z = z;
30230 }
30231 });
30232 });
30233 range.e.c = Math.max(range.e.c, _C + hdr.length - 1);
30234 var __R = encode_row(_R);
30235 if(offset) for(C = 0; C < hdr.length; ++C) ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]};
30236 ws['!ref'] = encode_range(range);
30237 return ws;
30238}
30239function json_to_sheet(js, opts) { return sheet_add_json(null, js, opts); }
30240
30241var utils = {
30242 encode_col: encode_col,
30243 encode_row: encode_row,
30244 encode_cell: encode_cell,
30245 encode_range: encode_range,
30246 decode_col: decode_col,
30247 decode_row: decode_row,
30248 split_cell: split_cell,
30249 decode_cell: decode_cell,
30250 decode_range: decode_range,
30251 format_cell: format_cell,
30252 get_formulae: sheet_to_formulae,
30253 make_csv: sheet_to_csv,
30254 make_json: sheet_to_json,
30255 make_formulae: sheet_to_formulae,
30256 sheet_add_aoa: sheet_add_aoa,
30257 sheet_add_json: sheet_add_json,
30258 aoa_to_sheet: aoa_to_sheet,
30259 json_to_sheet: json_to_sheet,
30260 table_to_sheet: parse_dom_table,
30261 table_to_book: table_to_book,
30262 sheet_to_csv: sheet_to_csv,
30263 sheet_to_txt: sheet_to_txt,
30264 sheet_to_json: sheet_to_json,
30265 sheet_to_html: HTML_.from_sheet,
30266 sheet_to_formulae: sheet_to_formulae,
30267 sheet_to_row_object_array: sheet_to_json
30268};
30269
30270(function(utils) {
30271utils.consts = utils.consts || {};
30272function add_consts(R/*Array<any>*/) { R.forEach(function(a){ utils.consts[a[0]] = a[1]; }); }
30273
30274function get_default(x, y, z) { return x[y] != null ? x[y] : (x[y] = z); }
30275
30276/* get cell, creating a stub if necessary */
30277function ws_get_cell_stub(ws, R, C) {
30278 /* A1 cell address */
30279 if(typeof R == "string") {
30280 /* dense */
30281 if(Array.isArray(ws)) {
30282 var RC = decode_cell(R);
30283 if(!ws[RC.r]) ws[RC.r] = [];
30284 return ws[RC.r][RC.c] || (ws[RC.r][RC.c] = {t:'z'});
30285 }
30286 return ws[R] || (ws[R] = {t:'z'});
30287 }
30288 /* cell address object */
30289 if(typeof R != "number") return ws_get_cell_stub(ws, encode_cell(R));
30290 /* R and C are 0-based indices */
30291 return ws_get_cell_stub(ws, encode_cell({r:R,c:C||0}));
30292}
30293utils.sheet_get_cell = ws_get_cell_stub;
30294
30295/* find sheet index for given name / validate index */
30296function wb_sheet_idx(wb, sh) {
30297 if(typeof sh == "number") {
30298 if(sh >= 0 && wb.SheetNames.length > sh) return sh;
30299 throw new Error("Cannot find sheet # " + sh);
30300 } else if(typeof sh == "string") {
30301 var idx = wb.SheetNames.indexOf(sh);
30302 if(idx > -1) return idx;
30303 throw new Error("Cannot find sheet name |" + sh + "|");
30304 } else throw new Error("Cannot find sheet |" + sh + "|");
30305}
30306
30307/* simple blank workbook object */
30308utils.book_new = function() {
30309 return { SheetNames: [], Sheets: {} };
30310};
30311
30312/* add a worksheet to the end of a given workbook */
30313utils.book_append_sheet = function(wb, ws, name) {
30314 if(!name) for(var i = 1; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break;
30315 if(!name) throw new Error("Too many worksheets");
30316 check_ws_name(name);
30317 if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!");
30318
30319 wb.SheetNames.push(name);
30320 wb.Sheets[name] = ws;
30321};
30322
30323/* set sheet visibility (visible/hidden/very hidden) */
30324utils.book_set_sheet_visibility = function(wb, sh, vis) {
30325 get_default(wb,"Workbook",{});
30326 get_default(wb.Workbook,"Sheets",[]);
30327
30328 var idx = wb_sheet_idx(wb, sh);
30329 // $FlowIgnore
30330 get_default(wb.Workbook.Sheets,idx, {});
30331
30332 switch(vis) {
30333 case 0: case 1: case 2: break;
30334 default: throw new Error("Bad sheet visibility setting " + vis);
30335 }
30336 // $FlowIgnore
30337 wb.Workbook.Sheets[idx].Hidden = vis;
30338};
30339add_consts([
30340 ["SHEET_VISIBLE", 0],
30341 ["SHEET_HIDDEN", 1],
30342 ["SHEET_VERY_HIDDEN", 2]
30343]);
30344
30345/* set number format */
30346utils.cell_set_number_format = function(cell, fmt) {
30347 cell.z = fmt;
30348 return cell;
30349};
30350
30351/* set cell hyperlink */
30352utils.cell_set_hyperlink = function(cell, target, tooltip) {
30353 if(!target) {
30354 delete cell.l;
30355 } else {
30356 cell.l = ({ Target: target });
30357 if(tooltip) cell.l.Tooltip = tooltip;
30358 }
30359 return cell;
30360};
30361utils.cell_set_internal_link = function(cell, range, tooltip) { return utils.cell_set_hyperlink(cell, "#" + range, tooltip); };
30362
30363/* add to cell comments */
30364utils.cell_add_comment = function(cell, text, author) {
30365 if(!cell.c) cell.c = [];
30366 cell.c.push({t:text, a:author||"SheetJS"});
30367};
30368
30369/* set array formula and flush related cells */
30370utils.sheet_set_array_formula = function(ws, range, formula) {
30371 var rng = typeof range != "string" ? range : safe_decode_range(range);
30372 var rngstr = typeof range == "string" ? range : encode_range(range);
30373 for(var R = rng.s.r; R <= rng.e.r; ++R) for(var C = rng.s.c; C <= rng.e.c; ++C) {
30374 var cell = ws_get_cell_stub(ws, R, C);
30375 cell.t = 'n';
30376 cell.F = rngstr;
30377 delete cell.v;
30378 if(R == rng.s.r && C == rng.s.c) cell.f = formula;
30379 }
30380 return ws;
30381};
30382
30383return utils;
30384})(utils);
30385
30386if(has_buf && typeof require != 'undefined') (function() {
30387 var Readable = {}.Readable;
30388
30389 var write_csv_stream = function(sheet, opts) {
30390 var stream = Readable();
30391 var o = opts == null ? {} : opts;
30392 if(sheet == null || sheet["!ref"] == null) { stream.push(null); return stream; }
30393 var r = safe_decode_range(sheet["!ref"]);
30394 var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0);
30395 var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0);
30396 var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$");
30397 var row = "", cols = [];
30398 o.dense = Array.isArray(sheet);
30399 var colinfo = o.skipHidden && sheet["!cols"] || [];
30400 var rowinfo = o.skipHidden && sheet["!rows"] || [];
30401 for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C);
30402 var R = r.s.r;
30403 var BOM = false;
30404 stream._read = function() {
30405 if(!BOM) { BOM = true; return stream.push("\uFEFF"); }
30406 while(R <= r.e.r) {
30407 ++R;
30408 if ((rowinfo[R-1]||{}).hidden) continue;
30409 row = make_csv_row(sheet, r, R-1, cols, fs, rs, FS, o);
30410 if(row != null) {
30411 if(o.strip) row = row.replace(endregex,"");
30412 stream.push(row + RS);
30413 break;
30414 }
30415 }
30416 if(R > r.e.r) return stream.push(null);
30417 };
30418 return stream;
30419 };
30420
30421 var write_html_stream = function(ws, opts) {
30422 var stream = Readable();
30423
30424 var o = opts || {};
30425 var header = o.header != null ? o.header : HTML_.BEGIN;
30426 var footer = o.footer != null ? o.footer : HTML_.END;
30427 stream.push(header);
30428 var r = decode_range(ws['!ref']);
30429 o.dense = Array.isArray(ws);
30430 stream.push(HTML_._preamble(ws, r, o));
30431 var R = r.s.r;
30432 var end = false;
30433 stream._read = function() {
30434 if(R > r.e.r) {
30435 if(!end) { end = true; stream.push("</table>" + footer); }
30436 return stream.push(null);
30437 }
30438 while(R <= r.e.r) {
30439 stream.push(HTML_._row(ws, r, R, o));
30440 ++R;
30441 break;
30442 }
30443 };
30444 return stream;
30445 };
30446
30447 var write_json_stream = function(sheet, opts) {
30448 var stream = Readable({objectMode:true});
30449
30450 if(sheet == null || sheet["!ref"] == null) { stream.push(null); return stream; }
30451 var val = {t:'n',v:0}, header = 0, offset = 1, hdr = [], v=0, vv="";
30452 var r = {s:{r:0,c:0},e:{r:0,c:0}};
30453 var o = opts || {};
30454 var range = o.range != null ? o.range : sheet["!ref"];
30455 if(o.header === 1) header = 1;
30456 else if(o.header === "A") header = 2;
30457 else if(Array.isArray(o.header)) header = 3;
30458 switch(typeof range) {
30459 case 'string': r = safe_decode_range(range); break;
30460 case 'number': r = safe_decode_range(sheet["!ref"]); r.s.r = range; break;
30461 default: r = range;
30462 }
30463 if(header > 0) offset = 0;
30464 var rr = encode_row(r.s.r);
30465 var cols = [];
30466 var counter = 0;
30467 var dense = Array.isArray(sheet);
30468 var R = r.s.r, C = 0, CC = 0;
30469 if(dense && !sheet[R]) sheet[R] = [];
30470 for(C = r.s.c; C <= r.e.c; ++C) {
30471 cols[C] = encode_col(C);
30472 val = dense ? sheet[R][C] : sheet[cols[C] + rr];
30473 switch(header) {
30474 case 1: hdr[C] = C - r.s.c; break;
30475 case 2: hdr[C] = cols[C]; break;
30476 case 3: hdr[C] = o.header[C - r.s.c]; break;
30477 default:
30478 if(val == null) val = {w: "__EMPTY", t: "s"};
30479 vv = v = format_cell(val, null, o);
30480 counter = 0;
30481 for(CC = 0; CC < hdr.length; ++CC) if(hdr[CC] == vv) vv = v + "_" + (++counter);
30482 hdr[C] = vv;
30483 }
30484 }
30485 R = r.s.r + offset;
30486 stream._read = function() {
30487 if(R > r.e.r) return stream.push(null);
30488 while(R <= r.e.r) {
30489 //if ((rowinfo[R-1]||{}).hidden) continue;
30490 var row = make_json_row(sheet, r, R, cols, header, hdr, dense, o);
30491 ++R;
30492 if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) {
30493 stream.push(row.row);
30494 break;
30495 }
30496 }
30497 };
30498 return stream;
30499 };
30500
30501 XLSX.stream = {
30502 to_json: write_json_stream,
30503 to_html: write_html_stream,
30504 to_csv: write_csv_stream
30505 };
30506})();
30507
30508if(typeof parse_xlscfb !== "undefined") XLSX.parse_xlscfb = parse_xlscfb;
30509XLSX.parse_zip = parse_zip;
30510XLSX.read = readSync; //xlsread
30511XLSX.readFile = readFileSync; //readFile
30512XLSX.readFileSync = readFileSync;
30513XLSX.write = writeSync;
30514XLSX.writeFile = writeFileSync;
30515XLSX.writeFileSync = writeFileSync;
30516XLSX.writeFileAsync = writeFileAsync;
30517XLSX.utils = utils;
30518XLSX.SSF = SSF;
30519if(typeof CFB !== "undefined") XLSX.CFB = CFB;
30520}
30521/*global define */
30522if(typeof exports !== 'undefined') make_xlsx_lib(exports);
30523else if(typeof module !== 'undefined' && module.exports) make_xlsx_lib(module.exports);
30524else if(typeof define === 'function' && define.amd) define('xlsx', function() { if(!XLSX.version) make_xlsx_lib(XLSX); return XLSX; });
30525else make_xlsx_lib(XLSX);
30526/*exported XLS, ODS */
30527var XLS = XLSX, ODS = XLSX;