js-cfb/bits/83_zwrite.js

106 lines
2.8 KiB
JavaScript

function write_zip(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes*/ {
var _opts = options || {};
var out = [], cdirs = [];
var o/*:CFBlob*/ = new_buf(1);
var method = (_opts.compression ? 8 : 0), flags = 0;
var desc = false;
if(desc) flags |= 8;
var i = 0, j = 0;
var start_cd = 0, fcnt = 0;
var root = cfb.FullPaths[0], fp = root, fi = cfb.FileIndex[0];
var crcs = [];
var sz_cd = 0;
for(i = 1; i < cfb.FullPaths.length; ++i) {
fp = cfb.FullPaths[i].slice(root.length); fi = cfb.FileIndex[i];
if(!fi.size || !fi.content || fp == "\u0001Sh33tJ5") continue;
var start = start_cd;
/* TODO: CP437 filename */
var namebuf = new_buf(fp.length);
for(j = 0; j < fp.length; ++j) namebuf.write_shift(1, fp.charCodeAt(j) & 0x7F);
namebuf = namebuf.slice(0, namebuf.l);
crcs[fcnt] = CRC32.buf(/*::((*/fi.content/*::||[]):any)*/, 0);
var outbuf = fi.content/*::||[]*/;
if(method == 8) outbuf = _deflateRawSync(outbuf);
/* local file header */
o = new_buf(30);
o.write_shift(4, 0x04034b50);
o.write_shift(2, 20);
o.write_shift(2, flags);
o.write_shift(2, method);
/* TODO: last mod file time/date */
if(fi.mt) write_dos_date(o, fi.mt);
else o.write_shift(4, 0);
o.write_shift(-4, (flags & 8) ? 0 : crcs[fcnt]);
o.write_shift(4, (flags & 8) ? 0 : outbuf.length);
o.write_shift(4, (flags & 8) ? 0 : /*::(*/fi.content/*::||[])*/.length);
o.write_shift(2, namebuf.length);
o.write_shift(2, 0);
start_cd += o.length;
out.push(o);
start_cd += namebuf.length;
out.push(namebuf);
/* TODO: extra fields? */
/* TODO: encryption header ? */
start_cd += outbuf.length;
out.push(outbuf);
/* data descriptor */
if(flags & 8) {
o = new_buf(12);
o.write_shift(-4, crcs[fcnt]);
o.write_shift(4, outbuf.length);
o.write_shift(4, /*::(*/fi.content/*::||[])*/.length);
start_cd += o.l;
out.push(o);
}
/* central directory */
o = new_buf(46);
o.write_shift(4, 0x02014b50);
o.write_shift(2, 0);
o.write_shift(2, 20);
o.write_shift(2, flags);
o.write_shift(2, method);
o.write_shift(4, 0); /* TODO: last mod file time/date */
o.write_shift(-4, crcs[fcnt]);
o.write_shift(4, outbuf.length);
o.write_shift(4, /*::(*/fi.content/*::||[])*/.length);
o.write_shift(2, namebuf.length);
o.write_shift(2, 0);
o.write_shift(2, 0);
o.write_shift(2, 0);
o.write_shift(2, 0);
o.write_shift(4, 0);
o.write_shift(4, start);
sz_cd += o.l;
cdirs.push(o);
sz_cd += namebuf.length;
cdirs.push(namebuf);
++fcnt;
}
/* end of central directory */
o = new_buf(22);
o.write_shift(4, 0x06054b50);
o.write_shift(2, 0);
o.write_shift(2, 0);
o.write_shift(2, fcnt);
o.write_shift(2, fcnt);
o.write_shift(4, sz_cd);
o.write_shift(4, start_cd);
o.write_shift(2, 0);
return bconcat(([bconcat((out/*:any*/)), bconcat(cdirs), o]/*:any*/));
}