Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
adavies42 committed Jul 16, 2021
1 parent 467c9d8 commit 95db517
Showing 1 changed file with 115 additions and 45 deletions.
160 changes: 115 additions & 45 deletions q/unzip/unzip.q
Original file line number Diff line number Diff line change
Expand Up @@ -115,58 +115,81 @@

// Field names and widths for end-of-central-directory.
.finos.unzip.priv.wecd:.finos.util.dict(
`sig;4;
`dnu;2;
`dcd;2;
`den;2;
`ten;2;
`csz;4;
`cof;4;
`cln;2;
`cmt;0;
`sig;4; / end of central dir signature 4 bytes (0x06054b50)
`dnu;2; / number of this disk 2 bytes
`dcd;2; / number of the disk with the start of the central directory 2 bytes
`den;2; / total number of entries in the central directory on this disk 2 bytes
`ten;2; / total number of entries in the central directory 2 bytes
`csz;4; / size of the central directory 4 bytes
`cof;4; / offset of start of central directory with respect to the starting disk number 4 bytes
`cln;2; / .ZIP file comment length 2 bytes
`cmt;0; / .ZIP file comment (variable size)
)

// Field names and widths for ZIP64 end-of-central-directory locator.
.finos.unzip.priv.wecl64:.finos.util.dict(
`sig;4; / zip64 end of central dir locator signature 4 bytes (0x07064b50)
`dcd;4; / number of the disk with the start of the zip64 end of central directory 4 bytes
`cof;8; / relative offset of the zip64 end of central directory record 8 bytes
`tnd;4; / total number of disks 4 bytes
)

// Field names and widths for ZIP64 end-of-central-directory.
.finos.unzip.priv.wecd64:.finos.util.dict(
`sig;4; / zip64 end of central dir signature 4 bytes (0x06064b50)
`s64;8; / size of zip64 end of central directory record 8 bytes
`ver;2; / version made by 2 bytes
`vrr;2; / version needed to extract 2 bytes
`dnu;4; / number of this disk 4 bytes
`dcd;4; / number of the disk with the start of the central directory 4 bytes
`den;8; / total number of entries in the central directory on this disk 8 bytes
`ten;8; / total number of entries in the central directory 8 bytes
`csz;8; / size of the central directory 8 bytes
`cof;8; / offset of start of central directory with respect to the starting disk number 8 bytes
`xln;0; / zip64 extensible data sector (variable size)
)

// Field names and widths for file data.
.finos.unzip.priv.wfd:.finos.util.dict(
`sig;4;
`ver;1;
`os ;1;
`flg;2;
`cmp;2;
`mtm;2;
`mdt;2;
`crc;4;
`csz;4;
`usz;4;
`nln;2;
`xln;2;
`sig;4; / local file header signature 4 bytes (0x04034b50)
`ver;1; / version needed to extract 2 bytes
`os ;1; / ??
`flg;2; / general purpose bit flag 2 bytes
`cmp;2; / compression method 2 bytes
`mtm;2; / last mod file time 2 bytes
`mdt;2; / last mod file date 2 bytes
`crc;4; / crc-32 4 bytes
`csz;4; / compressed size 4 bytes
`usz;4; / uncompressed size 4 bytes
`nln;2; / file name length 2 bytes
`xln;2; / extra field length 2 bytes
)

// Field names and widths for central directory.
.finos.unzip.priv.wcd:.finos.util.dict(
`sig;4;
`ver;2;
`vrr;2;
`flg;2;
`cmp;2;
`mtm;2;
`mdt;2;
`crc;4;
`csz;4;
`usz;4;
`nln;2;
`xln;2;
`cln;2;
`dnu;2;
`iat;2;
`xat;4;
`lof;4;
`sig;4; / central file header signature 4 bytes (0x02014b50)
`ver;2; / version made by 2 bytes
`vrr;2; / version needed to extract 2 bytes
`flg;2; / general purpose bit flag 2 bytes
`cmp;2; / compression method 2 bytes
`mtm;2; / last mod file time 2 bytes
`mdt;2; / last mod file date 2 bytes
`crc;4; / crc-32 4 bytes
`csz;4; / compressed size 4 bytes
`usz;4; / uncompressed size 4 bytes
`nln;2; / file name length 2 bytes
`xln;2; / extra field length 2 bytes
`cln;2; / file comment length 2 bytes
`dnu;2; / disk number start 2 bytes
`iat;2; / internal file attributes 2 bytes
`xat;4; / external file attributes 4 bytes
`lof;4; / relative offset of local header 4 bytes
)

// Field names and widths for extra field.
.finos.unzip.priv.wxfd:.finos.util.dict(
`id;2;
`sz;2;
`id ;2; / header id 2 bytes
`sz ;2; / data size 2 bytes
)


Expand Down Expand Up @@ -216,8 +239,27 @@
cmt:"c"$x y+nln+xln+til cln
from r;

break;

(r;exec y+nln+xln+cln from r)}

// Parse ZIP64 end-of-central-directory locator record.
// @param x bytes
// @return ZIP64 end-of-central-directory locator record
.finos.unzip.priv.pecl64:{
r:.finos.unzip.priv.split[.finos.unzip.priv.wecl64;0]x;
r:![r;();0b;{y!x y}[{(.finos.unzip.priv.parseNum;x)}'](key r)except`sig`cmt];
r}

// Parse ZIP64 end-of-central-directory record.
// @param x bytes
// @return ZIP64 end-of-central-directory record
.finos.unzip.priv.pecd64:{
r:.finos.unzip.priv.split[.finos.unzip.priv.wecd64;0]x;
r:![r;();0b;{y!x y}[{(.finos.unzip.priv.parseNum;x)}'](key r)except`sig`cmt];
r:update cmt:"c"$(neg cln)#x from r;
r}

// Parse an extra field record.
// @param x (bytes;extra)
// @param y index
Expand Down Expand Up @@ -438,7 +480,9 @@
/ (n will be () if x is not an hsym)
if[-11h=type y;
n:y;
.finos.log.info"reading ",1_string n;
y:read1 y;
.finos.log.info"done reading ",1_string n;
];

/ accept chars
Expand Down Expand Up @@ -469,17 +513,43 @@
cds:last cds;

/ parse end-of-central-directory record
ecd:.finos.unzip.priv.pecd y(first cds)+til(count y)-first cds;
ecd:.finos.unzip.priv.pecd y cds+til(count y)-cds;

/ punt on multi-disk archives
if[0<>ecd`dnu;'`nyi];
if[0<>ecd`dcd;'`nyi];

/ bytes of central directory record
cd:y(ecd`cof)+til ecd`csz;
/ zip64
$[
-1=ecd`cof;
[
/ look for zip64 end of central directory locator signature
ecls64:("c"$y)ss"c"$0x504b0607;
if[1>count ecls64;
'"no end of central directory locator";
];
ecls64:last ecls64;
break;

/ parse zip64 end-of-central-directory locator record
ecl64:.finos.unzip.priv.pecl64 y ecls64+til(count y)-ecls64;

/ bytes of zip64 central directory record
cd:y(ecl64`cof)+til .finos.unzip.priv.parseNum y(4+ecl64`cof)+til 8;

/ parse central directory
cd:.finos.unzip.priv.parse[(.finos.unzip.priv.pcd;.finos.unzip.priv.wcd);cd;count cd];
/ parse zip64 end-of-central-directory record
cd:.finos.unzip.priv.parse[(.finos.unzip.priv.pcd;.finos.unzip.priv.wcd);cd;count cd];

];
[
/ bytes of central directory record
cd:y(ecd`cof)+til ecd`csz;

/ parse central directory
.finos.log.debug"parsing central directory";
cd:.finos.unzip.priv.parse[(.finos.unzip.priv.pcd;.finos.unzip.priv.wcd);cd;count cd];
.finos.log.debug"done parsing central directory";
]];

r:$[
`list=x;
Expand Down

0 comments on commit 95db517

Please sign in to comment.