entryHeader.js 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. var Utils = require("../util"),
  2. Constants = Utils.Constants;
  3. /* The central directory file header */
  4. module.exports = function () {
  5. var _verMade = 0x0A,
  6. _version = 0x0A,
  7. _flags = 0,
  8. _method = 0,
  9. _time = 0,
  10. _crc = 0,
  11. _compressedSize = 0,
  12. _size = 0,
  13. _fnameLen = 0,
  14. _extraLen = 0,
  15. _comLen = 0,
  16. _diskStart = 0,
  17. _inattr = 0,
  18. _attr = 0,
  19. _offset = 0;
  20. var _dataHeader = {};
  21. function setTime(val) {
  22. val = new Date(val);
  23. _time = (val.getFullYear() - 1980 & 0x7f) << 25 // b09-16 years from 1980
  24. | (val.getMonth() + 1) << 21 // b05-08 month
  25. | val.getDate() << 16 // b00-04 hour
  26. // 2 bytes time
  27. | val.getHours() << 11 // b11-15 hour
  28. | val.getMinutes() << 5 // b05-10 minute
  29. | val.getSeconds() >> 1; // b00-04 seconds divided by 2
  30. }
  31. setTime(+new Date());
  32. return {
  33. get made () { return _verMade; },
  34. set made (val) { _verMade = val; },
  35. get version () { return _version; },
  36. set version (val) { _version = val },
  37. get flags () { return _flags },
  38. set flags (val) { _flags = val; },
  39. get method () { return _method; },
  40. set method (val) { _method = val; },
  41. get time () { return new Date(
  42. ((_time >> 25) & 0x7f) + 1980,
  43. ((_time >> 21) & 0x0f) - 1,
  44. (_time >> 16) & 0x1f,
  45. (_time >> 11) & 0x1f,
  46. (_time >> 5) & 0x3f,
  47. (_time & 0x1f) << 1
  48. );
  49. },
  50. set time (val) {
  51. setTime(val);
  52. },
  53. get crc () { return _crc; },
  54. set crc (val) { _crc = val; },
  55. get compressedSize () { return _compressedSize; },
  56. set compressedSize (val) { _compressedSize = val; },
  57. get size () { return _size; },
  58. set size (val) { _size = val; },
  59. get fileNameLength () { return _fnameLen; },
  60. set fileNameLength (val) { _fnameLen = val; },
  61. get extraLength () { return _extraLen },
  62. set extraLength (val) { _extraLen = val; },
  63. get commentLength () { return _comLen },
  64. set commentLength (val) { _comLen = val },
  65. get diskNumStart () { return _diskStart },
  66. set diskNumStart (val) { _diskStart = val },
  67. get inAttr () { return _inattr },
  68. set inAttr (val) { _inattr = val },
  69. get attr () { return _attr },
  70. set attr (val) { _attr = val },
  71. get offset () { return _offset },
  72. set offset (val) { _offset = val },
  73. get encripted () { return (_flags & 1) === 1 },
  74. get entryHeaderSize () {
  75. return Constants.CENHDR + _fnameLen + _extraLen + _comLen;
  76. },
  77. get realDataOffset () {
  78. return _offset + Constants.LOCHDR + _dataHeader.fnameLen + _dataHeader.extraLen;
  79. },
  80. get dataHeader () {
  81. return _dataHeader;
  82. },
  83. loadDataHeaderFromBinary : function(/*Buffer*/input) {
  84. var data = input.slice(_offset, _offset + Constants.LOCHDR);
  85. // 30 bytes and should start with "PK\003\004"
  86. if (data.readUInt32LE(0) !== Constants.LOCSIG) {
  87. throw Utils.Errors.INVALID_LOC;
  88. }
  89. _dataHeader = {
  90. // version needed to extract
  91. version : data.readUInt16LE(Constants.LOCVER),
  92. // general purpose bit flag
  93. flags : data.readUInt16LE(Constants.LOCFLG),
  94. // compression method
  95. method : data.readUInt16LE(Constants.LOCHOW),
  96. // modification time (2 bytes time, 2 bytes date)
  97. time : data.readUInt32LE(Constants.LOCTIM),
  98. // uncompressed file crc-32 value
  99. crc : data.readUInt32LE(Constants.LOCCRC),
  100. // compressed size
  101. compressedSize : data.readUInt32LE(Constants.LOCSIZ),
  102. // uncompressed size
  103. size : data.readUInt32LE(Constants.LOCLEN),
  104. // filename length
  105. fnameLen : data.readUInt16LE(Constants.LOCNAM),
  106. // extra field length
  107. extraLen : data.readUInt16LE(Constants.LOCEXT)
  108. }
  109. },
  110. loadFromBinary : function(/*Buffer*/data) {
  111. // data should be 46 bytes and start with "PK 01 02"
  112. if (data.length !== Constants.CENHDR || data.readUInt32LE(0) !== Constants.CENSIG) {
  113. throw Utils.Errors.INVALID_CEN;
  114. }
  115. // version made by
  116. _verMade = data.readUInt16LE(Constants.CENVEM);
  117. // version needed to extract
  118. _version = data.readUInt16LE(Constants.CENVER);
  119. // encrypt, decrypt flags
  120. _flags = data.readUInt16LE(Constants.CENFLG);
  121. // compression method
  122. _method = data.readUInt16LE(Constants.CENHOW);
  123. // modification time (2 bytes time, 2 bytes date)
  124. _time = data.readUInt32LE(Constants.CENTIM);
  125. // uncompressed file crc-32 value
  126. _crc = data.readUInt32LE(Constants.CENCRC);
  127. // compressed size
  128. _compressedSize = data.readUInt32LE(Constants.CENSIZ);
  129. // uncompressed size
  130. _size = data.readUInt32LE(Constants.CENLEN);
  131. // filename length
  132. _fnameLen = data.readUInt16LE(Constants.CENNAM);
  133. // extra field length
  134. _extraLen = data.readUInt16LE(Constants.CENEXT);
  135. // file comment length
  136. _comLen = data.readUInt16LE(Constants.CENCOM);
  137. // volume number start
  138. _diskStart = data.readUInt16LE(Constants.CENDSK);
  139. // internal file attributes
  140. _inattr = data.readUInt16LE(Constants.CENATT);
  141. // external file attributes
  142. _attr = data.readUInt32LE(Constants.CENATX);
  143. // LOC header offset
  144. _offset = data.readUInt32LE(Constants.CENOFF);
  145. },
  146. dataHeaderToBinary : function() {
  147. // LOC header size (30 bytes)
  148. var data = Buffer.alloc(Constants.LOCHDR);
  149. // "PK\003\004"
  150. data.writeUInt32LE(Constants.LOCSIG, 0);
  151. // version needed to extract
  152. data.writeUInt16LE(_version, Constants.LOCVER);
  153. // general purpose bit flag
  154. data.writeUInt16LE(_flags, Constants.LOCFLG);
  155. // compression method
  156. data.writeUInt16LE(_method, Constants.LOCHOW);
  157. // modification time (2 bytes time, 2 bytes date)
  158. data.writeUInt32LE(_time, Constants.LOCTIM);
  159. // uncompressed file crc-32 value
  160. data.writeUInt32LE(_crc, Constants.LOCCRC);
  161. // compressed size
  162. data.writeUInt32LE(_compressedSize, Constants.LOCSIZ);
  163. // uncompressed size
  164. data.writeUInt32LE(_size, Constants.LOCLEN);
  165. // filename length
  166. data.writeUInt16LE(_fnameLen, Constants.LOCNAM);
  167. // extra field length
  168. data.writeUInt16LE(_extraLen, Constants.LOCEXT);
  169. return data;
  170. },
  171. entryHeaderToBinary : function() {
  172. // CEN header size (46 bytes)
  173. var data = Buffer.alloc(Constants.CENHDR + _fnameLen + _extraLen + _comLen);
  174. // "PK\001\002"
  175. data.writeUInt32LE(Constants.CENSIG, 0);
  176. // version made by
  177. data.writeUInt16LE(_verMade, Constants.CENVEM);
  178. // version needed to extract
  179. data.writeUInt16LE(_version, Constants.CENVER);
  180. // encrypt, decrypt flags
  181. data.writeUInt16LE(_flags, Constants.CENFLG);
  182. // compression method
  183. data.writeUInt16LE(_method, Constants.CENHOW);
  184. // modification time (2 bytes time, 2 bytes date)
  185. data.writeUInt32LE(_time, Constants.CENTIM);
  186. // uncompressed file crc-32 value
  187. data.writeUInt32LE(_crc, Constants.CENCRC);
  188. // compressed size
  189. data.writeUInt32LE(_compressedSize, Constants.CENSIZ);
  190. // uncompressed size
  191. data.writeUInt32LE(_size, Constants.CENLEN);
  192. // filename length
  193. data.writeUInt16LE(_fnameLen, Constants.CENNAM);
  194. // extra field length
  195. data.writeUInt16LE(_extraLen, Constants.CENEXT);
  196. // file comment length
  197. data.writeUInt16LE(_comLen, Constants.CENCOM);
  198. // volume number start
  199. data.writeUInt16LE(_diskStart, Constants.CENDSK);
  200. // internal file attributes
  201. data.writeUInt16LE(_inattr, Constants.CENATT);
  202. // external file attributes
  203. data.writeUInt32LE(_attr, Constants.CENATX);
  204. // LOC header offset
  205. data.writeUInt32LE(_offset, Constants.CENOFF);
  206. // fill all with
  207. data.fill(0x00, Constants.CENHDR);
  208. return data;
  209. },
  210. toString : function() {
  211. return '{\n' +
  212. '\t"made" : ' + _verMade + ",\n" +
  213. '\t"version" : ' + _version + ",\n" +
  214. '\t"flags" : ' + _flags + ",\n" +
  215. '\t"method" : ' + Utils.methodToString(_method) + ",\n" +
  216. '\t"time" : ' + this.time + ",\n" +
  217. '\t"crc" : 0x' + _crc.toString(16).toUpperCase() + ",\n" +
  218. '\t"compressedSize" : ' + _compressedSize + " bytes,\n" +
  219. '\t"size" : ' + _size + " bytes,\n" +
  220. '\t"fileNameLength" : ' + _fnameLen + ",\n" +
  221. '\t"extraLength" : ' + _extraLen + " bytes,\n" +
  222. '\t"commentLength" : ' + _comLen + " bytes,\n" +
  223. '\t"diskNumStart" : ' + _diskStart + ",\n" +
  224. '\t"inAttr" : ' + _inattr + ",\n" +
  225. '\t"attr" : ' + _attr + ",\n" +
  226. '\t"offset" : ' + _offset + ",\n" +
  227. '\t"entryHeaderSize" : ' + (Constants.CENHDR + _fnameLen + _extraLen + _comLen) + " bytes\n" +
  228. '}';
  229. }
  230. }
  231. };