103 lines
2.8 KiB
JavaScript
103 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: 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*/));
|
|
}
|