zip.c 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498
  1. /*
  2. Copyright (c) 2010, Florian Reuter
  3. All rights reserved.
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions
  6. are met:
  7. * Redistributions of source code must retain the above copyright
  8. notice, this list of conditions and the following disclaimer.
  9. * Redistributions in binary form must reproduce the above copyright
  10. notice, this list of conditions and the following disclaimer in
  11. the documentation and/or other materials provided with the
  12. distribution.
  13. * Neither the name of Florian Reuter nor the names of its contributors
  14. may be used to endorse or promote products derived from this
  15. software without specific prior written permission.
  16. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  17. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  18. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  19. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  20. COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  21. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  22. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  25. STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  27. OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #include <opc/opc.h>
  30. #include <opc/helper.h>
  31. #include <libxml/xmlmemory.h>
  32. #include <libxml/globals.h>
  33. #include <string.h>
  34. #include <stdio.h>
  35. #include "internal.h"
  36. static void* ensureItem(void **array_, puint32_t items, puint32_t item_size) {
  37. *array_=xmlRealloc(*array_, (items+1)*item_size);
  38. return *array_;
  39. }
  40. static opcZipSegment* ensureSegment(opcZip *zip) {
  41. return ((opcZipSegment*)ensureItem((void**)&zip->segment_array, zip->segment_items, sizeof(opcZipSegment)))+zip->segment_items;
  42. }
  43. static inline opc_uint32_t _opcZipFileRead(opcIO_t *io, opc_uint8_t *buf, opc_uint32_t buf_len) {
  44. OPC_ASSERT(NULL!=io && io->_ioread!=NULL && NULL!=buf);
  45. opc_uint32_t ret=0;
  46. if (OPC_ERROR_NONE==io->state.err) {
  47. int len=io->_ioread(io->iocontext, (char *)buf, buf_len);
  48. if (ret<0) {
  49. io->state.err=OPC_ERROR_STREAM;
  50. } else {
  51. ret=(opc_uint32_t)len;
  52. io->state.buf_pos+=ret;
  53. }
  54. }
  55. return ret;
  56. }
  57. static inline opc_uint32_t _opcZipFileWrite(opcIO_t *io, const opc_uint8_t *buf, opc_uint32_t buf_len) {
  58. OPC_ASSERT(NULL!=io && io->_iowrite!=NULL && NULL!=buf);
  59. opc_uint32_t ret=0;
  60. if (OPC_ERROR_NONE==io->state.err) {
  61. int len=io->_iowrite(io->iocontext, (const char *)buf, buf_len);
  62. if (ret<0) {
  63. io->state.err=OPC_ERROR_STREAM;
  64. } else {
  65. ret=(opc_uint32_t)len;
  66. io->state.buf_pos+=ret;
  67. if (io->state.buf_pos>io->file_size) io->file_size=io->state.buf_pos;
  68. }
  69. }
  70. return ret;
  71. }
  72. static inline opc_error_t _opcZipFileClose(opcIO_t *io) {
  73. OPC_ASSERT(NULL!=io && io->_ioclose!=NULL);
  74. if (0!=io->_ioclose(io->iocontext)) {
  75. if (OPC_ERROR_NONE==io->state.err) {
  76. io->state.err=OPC_ERROR_STREAM;
  77. }
  78. }
  79. return io->state.err;
  80. }
  81. static inline opc_ofs_t _opcZipFileSeek(opcIO_t *io, opc_ofs_t ofs, opcFileSeekMode whence) {
  82. OPC_ASSERT(NULL!=io && (opcFileSeekSet==whence || opcFileSeekCur==whence || opcFileSeekEnd==whence));
  83. opc_ofs_t abs=io->state.buf_pos;
  84. if (OPC_ERROR_NONE==io->state.err) {
  85. switch (whence) {
  86. case opcFileSeekSet: abs=ofs; break;
  87. case opcFileSeekCur: abs+=ofs; break;
  88. case opcFileSeekEnd: abs=io->file_size-ofs; break;
  89. }
  90. if (abs<0 || abs>io->file_size) {
  91. io->state.err=OPC_ERROR_STREAM;
  92. } else if (io->state.buf_pos!=abs) {
  93. if (NULL!=io->_ioseek) {
  94. int _ofs=io->_ioseek(io->iocontext, abs);
  95. if (_ofs!=abs) {
  96. io->state.err=OPC_ERROR_STREAM;
  97. } else {
  98. io->state.buf_pos=abs;
  99. }
  100. } else {
  101. io->state.err=OPC_ERROR_SEEK;
  102. }
  103. }
  104. }
  105. return abs;
  106. }
  107. static inline opc_error_t _opcZipFileGrow(opcIO_t *io, opc_uint32_t abs) {
  108. if (OPC_ERROR_NONE==io->state.err) {
  109. if (abs>io->file_size) {
  110. io->file_size=abs; //@TODO add error handling here if e.g. file can not grow because disk is full etc...
  111. }
  112. }
  113. return io->state.err;
  114. }
  115. opc_error_t _opcZipFileMove(opcIO_t *io, opc_ofs_t dest, opc_ofs_t src, opc_ofs_t len) {
  116. opc_uint8_t buf[1024];
  117. while(len>0) {
  118. opc_ofs_t delta=(dest<src?src-dest:dest-src);
  119. opc_uint32_t chunk=(delta>sizeof(buf)?(opc_uint32_t)sizeof(buf):(opc_uint32_t)delta);
  120. if (chunk>len) chunk=len;
  121. OPC_ENSURE(src==_opcZipFileSeek(io, src, opcFileSeekSet));
  122. OPC_ENSURE(chunk==_opcZipFileRead(io, buf, chunk));
  123. OPC_ENSURE(dest==_opcZipFileSeek(io, dest, opcFileSeekSet));
  124. OPC_ENSURE(chunk==_opcZipFileWrite(io, buf, chunk));
  125. OPC_ASSERT(chunk<=len);
  126. len-=chunk;
  127. dest+=chunk;
  128. src+=chunk;
  129. }
  130. OPC_ASSERT(0==len);
  131. return io->state.err;
  132. }
  133. opc_error_t _opcZipFileTrim(opcIO_t *io, opc_ofs_t new_size) {
  134. OPC_ASSERT(new_size<=io->file_size);
  135. int ret=(NULL!=io->_iotrim?io->_iotrim(io->iocontext, new_size):-1);
  136. return (0==ret?OPC_ERROR_NONE:OPC_ERROR_STREAM);
  137. }
  138. opc_error_t _opcZipFileFlush(opcIO_t *io) {
  139. int ret=(NULL!=io->_ioflush?io->_ioflush(io->iocontext):-1);
  140. return (0==ret?OPC_ERROR_NONE:OPC_ERROR_STREAM);
  141. }
  142. opcZip *opcZipCreate(opcIO_t *io) {
  143. opcZip *zip=(opcZip*)xmlMalloc(sizeof(opcZip));
  144. if (NULL!=zip) {
  145. memset(zip, 0, sizeof(*zip));
  146. zip->first_free_segment_id=-1;
  147. zip->io=io;
  148. }
  149. return zip;
  150. }
  151. void opcZipClose(opcZip *zip, opcZipSegmentReleaseCallback* releaseCallback) {
  152. if (NULL!=zip) {
  153. if (NULL!=releaseCallback) {
  154. for(opc_uint32_t i=0;i<zip->segment_items;i++) {
  155. if (!zip->segment_array[i].deleted_segment) {
  156. releaseCallback(zip, i);
  157. }
  158. }
  159. }
  160. OPC_ASSERT(NULL!=zip->io->_ioclose);
  161. OPC_ENSURE(0==zip->io->_ioclose(zip->io->iocontext));
  162. if (NULL!=zip->segment_array) {
  163. xmlFree(zip->segment_array);
  164. zip->segment_array=NULL;
  165. }
  166. xmlFree(zip);
  167. }
  168. }
  169. static inline opc_error_t _opcZipFileSeekRawState(opcIO_t *io, opcFileRawState *rawState, puint32_t new_ofs) {
  170. if (OPC_ERROR_NONE==rawState->err) {
  171. rawState->err=io->state.err;
  172. }
  173. if (OPC_ERROR_NONE==rawState->err) {
  174. if (_opcZipFileSeek(io, new_ofs, opcFileSeekSet)!=new_ofs) {
  175. *rawState=io->state; // indicate an error
  176. } else {
  177. rawState->buf_pos=new_ofs; // all OK
  178. }
  179. }
  180. return rawState->err;
  181. }
  182. static inline opc_uint32_t opcZipRawWrite(opcIO_t *io, opcFileRawState *raw, const opc_uint8_t *buffer, opc_uint32_t len) {
  183. opc_uint32_t ret=0;
  184. if (OPC_ERROR_NONE==raw->err) {
  185. if (OPC_ERROR_NONE==io->state.err) {
  186. if (raw->buf_pos==io->state.buf_pos) {
  187. ret=_opcZipFileWrite(io, buffer, len);
  188. *raw=io->state;
  189. } else {
  190. raw->err=OPC_ERROR_SEEK;
  191. }
  192. } else {
  193. *raw=io->state;
  194. }
  195. }
  196. return ret;
  197. }
  198. static inline opc_error_t opcZipInitRawState(opcIO_t *io, opcFileRawState *rawState) {
  199. *rawState=io->state;
  200. return rawState->err;
  201. }
  202. static inline int opcZipRawWriteU8(opcIO_t *io, opcFileRawState *raw, opc_uint8_t val) {
  203. return opcZipRawWrite(io, raw, (const opc_uint8_t *)&val, sizeof(opc_uint8_t));
  204. }
  205. static inline int opcZipRawWrite8(opcIO_t *io, opcFileRawState *raw, opc_int8_t val) {
  206. return opcZipRawWriteU8(io, raw, (opc_uint8_t)val);
  207. }
  208. static inline int opcZipRawWriteZero(opcIO_t *io, opcFileRawState *raw, opc_uint32_t count) {
  209. int ret=0;
  210. opc_uint8_t val=0;
  211. //@TODO may speed me up a bit (using fappend...)
  212. for(opc_uint32_t i=0;i<count;i++) {
  213. ret+=opcZipRawWriteU8(io, raw, val);
  214. }
  215. return ret;
  216. }
  217. static inline int opcZipRawWriteU16(opcIO_t *io, opcFileRawState *raw, opc_uint16_t val) {
  218. int i=0;
  219. while(OPC_ERROR_NONE==raw->err && i<sizeof(val) && 1==opcZipRawWriteU8(io, raw, (opc_uint8_t)(((unsigned)val)>>(i<<3)))) {
  220. i++;
  221. }
  222. return i;
  223. }
  224. static inline int opcZipRawWriteU32(opcIO_t *io, opcFileRawState *raw, opc_uint32_t val) {
  225. int i=0;
  226. while(OPC_ERROR_NONE==raw->err && i<sizeof(val) && 1==opcZipRawWriteU8(io, raw, (opc_uint8_t)(((unsigned)val)>>(i<<3)))) {
  227. i++;
  228. }
  229. return i;
  230. }
  231. static opc_error_t opcZipInitRawBuffer(opcIO_t *io, opcFileRawBuffer *rawBuffer) {
  232. opc_bzero_mem(rawBuffer, sizeof(*rawBuffer));
  233. return opcZipInitRawState(io, &rawBuffer->state);;
  234. }
  235. static inline opc_uint16_t opcZipCalculateHeaderSize(const char *name8, opc_uint16_t name8_len, opc_bool_t extra, opc_uint16_t *name8_max) {
  236. opc_uint16_t len=(NULL!=name8_max?*name8_max:name8_len);
  237. return 4*4+7*2+(extra?4*2:0)+len;
  238. }
  239. static opc_uint32_t opcZipRawWriteSegmentHeaderEx(opcIO_t *io,
  240. opcFileRawState *rawState,
  241. const char *name8, opc_uint16_t name8_len,
  242. opc_uint16_t bit_flag,
  243. opc_uint32_t crc32,
  244. opc_uint16_t compression_method,
  245. opc_ofs_t compressed_size,
  246. opc_ofs_t uncompressed_size,
  247. opc_uint16_t header_size,
  248. opc_uint16_t growth_hint) {
  249. opc_uint32_t ret=0;
  250. OPC_ASSERT(opcZipCalculateHeaderSize(name8, name8_len, OPC_FALSE, NULL)<=header_size);
  251. opc_bool_t extra=opcZipCalculateHeaderSize(name8, name8_len, OPC_TRUE, NULL)<=header_size;
  252. if (opcZipCalculateHeaderSize(name8, name8_len, extra, NULL)<=header_size) {
  253. opc_uint16_t padding=(extra?header_size-opcZipCalculateHeaderSize(name8, name8_len, extra, NULL):0);
  254. OPC_ASSERT(padding==0 || extra); // padding!=0 implies extra... you need the extra header to be able to add padding!
  255. if ((4==(ret+=opcZipRawWriteU32(io, rawState, 0x04034b50)))
  256. && (6==(ret+=opcZipRawWriteU16(io, rawState, 20))) //version needed to extract
  257. && (8==(ret+=opcZipRawWriteU16(io, rawState, bit_flag))) // bit flag
  258. && (10==(ret+=opcZipRawWriteU16(io, rawState, compression_method))) // compression method
  259. && (12==(ret+=opcZipRawWriteU16(io, rawState, 0x0))) // last mod file time
  260. && (14==(ret+=opcZipRawWriteU16(io, rawState, 0x0))) // last mod file date
  261. && (18==(ret+=opcZipRawWriteU32(io, rawState, crc32))) // crc32
  262. && (22==(ret+=opcZipRawWriteU32(io, rawState, compressed_size))) // compressed size
  263. && (26==(ret+=opcZipRawWriteU32(io, rawState, uncompressed_size))) // uncompressed size
  264. && (28==(ret+=opcZipRawWriteU16(io, rawState, name8_len))) // filename length
  265. && (30==(ret+=opcZipRawWriteU16(io, rawState, (extra?4*2+padding:0)))) // extra length
  266. && (30+name8_len==(ret+=opcZipRawWrite(io, rawState, (opc_uint8_t *)name8, name8_len)))
  267. && (!extra || 32+name8_len==(ret+=opcZipRawWriteU16(io, rawState, 0xa220))) // extra: Microsoft Open Packaging Growth Hint
  268. && (!extra || 34+name8_len==(ret+=opcZipRawWriteU16(io, rawState, 2+2+padding))) // extra: size of Sig + PadVal + Padding
  269. && (!extra || 36+name8_len==(ret+=opcZipRawWriteU16(io, rawState, 0xa028))) // extra: verification signature (A028)
  270. && (!extra || 38+name8_len==(ret+=opcZipRawWriteU16(io, rawState, growth_hint))) // extra: Initial padding value
  271. && (!extra || 38+name8_len+padding==(ret+=opcZipRawWriteZero(io, rawState, padding)))) { // extra: filled with NULL characters
  272. OPC_ASSERT(opcZipCalculateHeaderSize(name8, name8_len, extra, NULL)+padding==ret);
  273. }
  274. return (opcZipCalculateHeaderSize(name8, name8_len, extra, NULL)+padding==ret?ret:0);
  275. } else {
  276. return 0; // no enough space to write header!
  277. }
  278. }
  279. static opc_error_t opcZipRawWriteCentralDirectoryEx(opcIO_t *io,
  280. opcFileRawState *rawState,
  281. const char *name8, opc_uint16_t name8_len,
  282. opc_uint16_t bit_flag,
  283. opc_uint32_t crc32,
  284. opc_uint16_t compression_method,
  285. opc_ofs_t compressed_size,
  286. opc_ofs_t uncompressed_size,
  287. opc_uint16_t header_size,
  288. opc_uint16_t growth_hint,
  289. opc_ofs_t stream_ofs) {
  290. if (OPC_ERROR_NONE==rawState->err) {
  291. if((4==opcZipRawWriteU32(io, rawState, 0x02014b50))
  292. && (2==opcZipRawWriteU16(io, rawState, 20)) // version made by
  293. && (2==opcZipRawWriteU16(io, rawState, 20)) // version needed to extract
  294. && (2==opcZipRawWriteU16(io, rawState, bit_flag)) // bit flag
  295. && (2==opcZipRawWriteU16(io, rawState, compression_method)) // compression method
  296. && (2==opcZipRawWriteU16(io, rawState, 0x0)) // last mod file time
  297. && (2==opcZipRawWriteU16(io, rawState, 0x0)) // last mod file date
  298. && (4==opcZipRawWriteU32(io, rawState, crc32)) // crc32
  299. && (4==opcZipRawWriteU32(io, rawState, compressed_size)) // compressed size
  300. && (4==opcZipRawWriteU32(io, rawState, uncompressed_size)) // uncompressed size
  301. && (2==opcZipRawWriteU16(io, rawState, name8_len)) // filename length
  302. && (2==opcZipRawWriteU16(io, rawState, 0x0)) // extra length
  303. && (2==opcZipRawWriteU16(io, rawState, 0x0)) // comment length
  304. && (2==opcZipRawWriteU16(io, rawState, 0x0)) // disk number start
  305. && (2==opcZipRawWriteU16(io, rawState, 0x0)) // internal file attributes
  306. && (4==opcZipRawWriteU32(io, rawState, 0x0)) // external file attributes
  307. && (4==opcZipRawWriteU32(io, rawState, stream_ofs)) // relative offset of local header
  308. && (name8_len==opcZipRawWrite(io, rawState, (opc_uint8_t*)name8, name8_len))) {
  309. } else {
  310. rawState->err=OPC_ERROR_STREAM;
  311. }
  312. }
  313. return rawState->err;
  314. }
  315. static opc_error_t opcZipRawWriteEndOfCentralDirectoryEx(opcIO_t *io,
  316. opcFileRawState *rawState,
  317. opc_ofs_t central_dir_start_ofs,
  318. opc_uint32_t segments) {
  319. opc_ofs_t central_dir_end_ofs=rawState->buf_pos;
  320. OPC_ASSERT(central_dir_start_ofs<=central_dir_end_ofs);
  321. if (OPC_ERROR_NONE==rawState->err) {
  322. if((4==opcZipRawWriteU32(io, rawState, 0x06054b50))
  323. && (2==opcZipRawWriteU16(io, rawState, 0x0)) // number of this disk
  324. && (2==opcZipRawWriteU16(io, rawState, 0x0)) // number of the disk with the start of the central directory
  325. && (2==opcZipRawWriteU16(io, rawState, segments)) // total number of entries in the central directory on this disk
  326. && (2==opcZipRawWriteU16(io, rawState, segments)) // total number of entries in the central directory
  327. && (4==opcZipRawWriteU32(io, rawState, central_dir_end_ofs-central_dir_start_ofs)) // size of the central directory
  328. && (4==opcZipRawWriteU32(io, rawState, central_dir_start_ofs)) // offset of start of central directory with respect to the starting disk number
  329. && (2==opcZipRawWriteU16(io, rawState, 0x0))) {// .ZIP file comment length
  330. } else {
  331. rawState->err=OPC_ERROR_STREAM;
  332. }
  333. }
  334. return rawState->err;
  335. }
  336. static inline int opcZipRawReadBuffer(opcIO_t *io, opcFileRawBuffer *raw, opc_uint8_t *buffer, opc_uint32_t buf_len) {
  337. OPC_ASSERT(NULL!=raw);
  338. OPC_ASSERT(OPC_ERROR_NONE!=raw->state.err || raw->buf_ofs<=raw->buf_len);
  339. opc_uint32_t buf_ofs=0;
  340. while(OPC_ERROR_NONE==raw->state.err && buf_ofs<buf_len) {
  341. opc_uint32_t req_size=buf_len-buf_ofs;
  342. if (raw->buf_ofs<raw->buf_len) {
  343. opc_uint32_t size=raw->buf_len-raw->buf_ofs;
  344. if (size>req_size) size=req_size;
  345. memcpy(buffer+buf_ofs, raw->buf+raw->buf_ofs, size);
  346. raw->buf_ofs+=size;
  347. buf_ofs+=size;
  348. raw->state.buf_pos+=size;
  349. } else {
  350. OPC_ASSERT(raw->buf_ofs==raw->buf_len);
  351. int ret=_opcZipFileRead(io, buffer+buf_ofs, req_size);
  352. if (0==ret) {
  353. buf_len=0; // causes the loop to exit
  354. } else if (ret<0) {
  355. raw->state.err=OPC_ERROR_STREAM;
  356. } else {
  357. buf_ofs+=ret;
  358. raw->state.buf_pos+=ret;
  359. }
  360. }
  361. }
  362. return buf_ofs;
  363. }
  364. static inline opc_uint32_t opcZipRawPeekHeaderSignature(opcIO_t *io, opcFileRawBuffer *raw) {
  365. OPC_ASSERT(NULL!=io && NULL!=raw);
  366. if (OPC_ERROR_NONE==raw->state.err && raw->buf_ofs+4>raw->buf_len) {
  367. // less than four bytes available...
  368. if (raw->buf_ofs>0) { // move the bytes to the beginning
  369. opc_uint32_t delta=raw->buf_len-raw->buf_ofs;
  370. OPC_ASSERT(delta<=4);
  371. for(opc_uint32_t i=0;i<delta;i++) {
  372. raw->buf[i]=raw->buf[i+raw->buf_ofs];
  373. }
  374. raw->buf_len-=raw->buf_ofs;
  375. raw->buf_ofs=0;
  376. }
  377. // fill the remaining buffer
  378. OPC_ASSERT(0==raw->buf_ofs && raw->buf_len<sizeof(raw->buf));
  379. int ret=_opcZipFileRead(io, raw->buf+raw->buf_len, (sizeof(raw->buf)-raw->buf_len));
  380. if (ret<0) {
  381. raw->state.err=OPC_ERROR_STREAM;
  382. } else {
  383. raw->buf_len+=ret;
  384. }
  385. OPC_ASSERT(0==raw->buf_ofs && raw->buf_len<=sizeof(raw->buf));
  386. }
  387. if (OPC_ERROR_NONE==raw->state.err && 0==raw->buf_len) {
  388. return 0; // end of file
  389. } else if (OPC_ERROR_NONE!=raw->state.err || raw->buf_ofs+4>raw->buf_len) {
  390. // either an error or not enough bytes
  391. return -1;
  392. } else {
  393. OPC_ASSERT(OPC_ERROR_NONE==raw->state.err && raw->buf_ofs+4<=raw->buf_len); // enough bytes...
  394. return (raw->buf[raw->buf_ofs]<<0)
  395. +(raw->buf[raw->buf_ofs+1]<<8)
  396. +(raw->buf[raw->buf_ofs+2]<<16)
  397. +(raw->buf[raw->buf_ofs+3]<<24);
  398. }
  399. }
  400. static inline opc_error_t opcZipRawFill(opcIO_t *io, opcFileRawBuffer *raw, opc_uint32_t max) {
  401. OPC_ASSERT(OPC_ERROR_NONE!=raw->state.err || raw->buf_ofs<=raw->buf_len);
  402. if (OPC_ERROR_NONE==raw->state.err && raw->buf_ofs==raw->buf_len) {
  403. opc_uint32_t const len=(sizeof(raw->buf)<max?sizeof(raw->buf):max);
  404. int ret=_opcZipFileRead(io, raw->buf, len);
  405. if (ret<0) {
  406. raw->state.err=OPC_ERROR_STREAM;
  407. raw->buf_len=0;
  408. } else {
  409. raw->buf_len=ret;
  410. }
  411. raw->buf_ofs=0;
  412. }
  413. OPC_ASSERT(OPC_ERROR_NONE==raw->state.err || 0==raw->buf_len || raw->buf_ofs<raw->buf_len);
  414. return raw->state.err;
  415. }
  416. static inline opc_uint32_t opcZipRawInflateBuffer(opcIO_t *io, opcFileRawBuffer *raw, opcZipInflateState *state, opc_uint8_t *buffer, opc_uint32_t buf_len) {
  417. OPC_ASSERT(NULL!=raw);
  418. OPC_ASSERT(OPC_ERROR_NONE!=raw->state.err || raw->buf_ofs<=raw->buf_len);
  419. opc_uint32_t buf_ofs=0;
  420. while(OPC_ERROR_NONE==raw->state.err && Z_OK==state->inflate_state && buf_ofs<buf_len) {
  421. int const max_stream=state->compressed_size-state->stream.total_in;
  422. if (OPC_ERROR_NONE==opcZipRawFill(io, raw, max_stream)) {
  423. state->stream.next_in=raw->buf+raw->buf_ofs;
  424. state->stream.avail_in=raw->buf_len-raw->buf_ofs;
  425. state->stream.next_out=buffer+buf_ofs;
  426. state->stream.avail_out=buf_len-buf_ofs;
  427. if (Z_OK==(state->inflate_state=inflate(&state->stream, Z_SYNC_FLUSH)) || Z_STREAM_END==state->inflate_state) {
  428. opc_uint32_t const consumed_in=raw->buf_len-raw->buf_ofs-state->stream.avail_in;
  429. opc_uint32_t const consumed_out=buf_len-buf_ofs-state->stream.avail_out;
  430. raw->buf_ofs+=consumed_in;
  431. raw->state.buf_pos+=consumed_in;
  432. buf_ofs+=consumed_out;
  433. if (0==consumed_out && 0==consumed_in) {
  434. raw->state.err=OPC_ERROR_DEFLATE; // protect us from an endless loop. shlould not happen
  435. }
  436. } else {
  437. raw->state.err=OPC_ERROR_DEFLATE;
  438. }
  439. }
  440. }
  441. return buf_ofs;
  442. }
  443. static inline int opcZipRawReadU8(opcIO_t *io, opcFileRawBuffer *raw, opc_uint8_t *val) {
  444. OPC_ASSERT(NULL!=raw);
  445. opcZipRawFill(io, raw, -1);
  446. OPC_ASSERT(OPC_ERROR_NONE==raw->state.err || 0==raw->buf_len || raw->buf_ofs<raw->buf_len);
  447. if (OPC_ERROR_NONE!=raw->state.err) {
  448. if (NULL!=val) {
  449. *val=-1;
  450. }
  451. return -1;
  452. } else if (0==raw->buf_len) {
  453. if (NULL!=val) {
  454. *val=0;
  455. }
  456. return 0;
  457. } else {
  458. if (NULL!=val) {
  459. *val=raw->buf[raw->buf_ofs];
  460. }
  461. raw->buf_ofs++;
  462. raw->state.buf_pos++;
  463. return 1;
  464. }
  465. }
  466. static inline int opcZipRawRead8(opcIO_t *io, opcFileRawBuffer *raw, opc_int8_t *val) {
  467. return opcZipRawReadU8(io, raw, (opc_uint8_t*)val);
  468. }
  469. #define OPC_READ_LITTLE_ENDIAN(io, raw, type, val) \
  470. opc_uint8_t aux;\
  471. int ret;\
  472. int i=0;\
  473. if (NULL!=val) {\
  474. *val=0;\
  475. }\
  476. while(i<sizeof(type) && (1==(ret=opcZipRawReadU8(io, raw, &aux)))) {\
  477. if (NULL!=val) {\
  478. *val|=((type)aux)<<(i<<3);\
  479. }\
  480. i++;\
  481. }\
  482. return (i==sizeof(type)?i:ret);\
  483. static inline int opcZipRawReadU16(opcIO_t *io, opcFileRawBuffer *raw, opc_uint16_t *val) {
  484. OPC_READ_LITTLE_ENDIAN(io, raw, opc_uint16_t, val);
  485. }
  486. static inline int opcZipRawRead16(opcIO_t *io, opcFileRawBuffer *raw, opc_int16_t *val) {
  487. OPC_READ_LITTLE_ENDIAN(io, raw, opc_int16_t, val);
  488. }
  489. static inline int opcZipRawReadU32(opcIO_t *io, opcFileRawBuffer *raw, opc_uint32_t *val) {
  490. OPC_READ_LITTLE_ENDIAN(io, raw, opc_uint32_t, val);
  491. }
  492. static inline int opcZipRawRead32(opcIO_t *io, opcFileRawBuffer *raw, opc_int32_t *val) {
  493. OPC_READ_LITTLE_ENDIAN(io, raw, opc_int32_t, val);
  494. }
  495. static inline int opcZipRawReadU64(opcIO_t *io, opcFileRawBuffer *raw, opc_uint64_t *val) {
  496. OPC_READ_LITTLE_ENDIAN(io, raw, opc_uint64_t, val);
  497. }
  498. static inline int opcZipRawRead64(opcIO_t *io, opcFileRawBuffer *raw, opc_int64_t *val) {
  499. OPC_READ_LITTLE_ENDIAN(io, raw, opc_int64_t, val);
  500. }
  501. static inline int opcZipRawSkipBytes(opcIO_t *io, opcFileRawBuffer *raw, opc_uint32_t len) {
  502. if (OPC_ERROR_NONE!=raw->state.err) {
  503. return 0;
  504. } else {
  505. //@TODO speed me up! when seek is available
  506. int ret=0;
  507. opc_uint32_t i=0;
  508. opc_uint8_t val;
  509. while(i<len && (1==(ret=opcZipRawReadU8(io, raw, &val)))) i++;
  510. return (i==len?i:ret);
  511. }
  512. }
  513. static inline int opcZipRawReadString(opcIO_t *io, opcFileRawBuffer *raw, xmlChar *str, opc_uint32_t str_len, opc_uint32_t str_max) {
  514. opc_uint32_t str_ofs=0;
  515. opc_uint32_t flag=1;
  516. while(OPC_ERROR_NONE==raw->state.err && str_ofs<str_len && str_ofs+1<str_max && flag>0) {
  517. opc_uint8_t ch=0;
  518. if (1==(flag=opcZipRawReadU8(io, raw, &ch))) {
  519. if ('%'==ch) {
  520. opc_uint8_t hex1=0;
  521. opc_uint8_t hex2=0;
  522. if (1==(flag=opcZipRawReadU8(io, raw, &hex1)) && 1==(flag=opcZipRawReadU8(io, raw, &hex2))) {
  523. opc_uint32_t hi=0;
  524. if (hex1>='0' && hex1<='9') hi=hex1-'0';
  525. else if (hex1>='A' && hex1<='F') hi=hex1-'A'+10;
  526. else if (hex1>='a' && hex1<='f') hi=hex1-'a'+10;
  527. else flag=0; // error
  528. opc_uint32_t low=0;
  529. if (hex1>='0' && hex1<='9') low=hex1-'0';
  530. else if (hex1>='A' && hex1<='F') low=hex1-'A'+10;
  531. else if (hex1>='a' && hex1<='f') low=hex1-'a'+10;
  532. else flag=0; // error
  533. if (flag) {
  534. str[str_ofs++]=hi*16+low;
  535. }
  536. }
  537. } else {
  538. str[str_ofs++]=ch;
  539. }
  540. }
  541. }
  542. OPC_ASSERT(str_ofs+1<str_max);
  543. str[str_ofs]=0; // terminate string
  544. return str_ofs;
  545. }
  546. static opc_bool_t opcZipRawReadLocalFileEx(opcIO_t *io, opcFileRawBuffer *raw,
  547. xmlChar *name, opc_uint32_t name_size, opc_uint32_t *name_len,
  548. opc_uint32_t *header_size,
  549. opc_uint32_t *min_header_size,
  550. opc_uint32_t *compressed_size,
  551. opc_uint32_t *uncompressed_size,
  552. opc_uint16_t *bit_flag,
  553. opc_uint32_t *crc32,
  554. opc_uint16_t *compression_method,
  555. opc_ofs_t *stream_ofs,
  556. opc_uint16_t *growth_hint) {
  557. opc_bool_t ret=OPC_FALSE;
  558. opc_uint32_t sig=opcZipRawPeekHeaderSignature(io, raw);
  559. if (0x04034b50==sig) {
  560. *stream_ofs=raw->state.buf_pos;
  561. opc_uint32_t header_signature;
  562. opc_uint16_t filename_length;
  563. opc_uint16_t extra_length;
  564. opc_uint16_t dummy;
  565. if (4==opcZipRawReadU32(io, raw, &header_signature) && header_signature==sig) // version_needed
  566. if (2==opcZipRawReadU16(io, raw, &dummy)) // version_needed
  567. if (2==opcZipRawReadU16(io, raw, bit_flag))
  568. if (2==opcZipRawReadU16(io, raw, compression_method))
  569. if (2==opcZipRawReadU16(io, raw, NULL)) // last_mod_time
  570. if (2==opcZipRawReadU16(io, raw, NULL)) // last_mod_date
  571. if (4==opcZipRawReadU32(io, raw, crc32)) //
  572. if (4==opcZipRawReadU32(io, raw, compressed_size))
  573. if (4==opcZipRawReadU32(io, raw, uncompressed_size))
  574. if (2==opcZipRawReadU16(io, raw, &filename_length))
  575. if (2==opcZipRawReadU16(io, raw, &extra_length))
  576. if ((*name_len=opcZipRawReadString(io, raw, name, filename_length, name_size))<=filename_length) {
  577. *header_size=4*4+7*2+filename_length+extra_length;
  578. *min_header_size=4*4+7*2+filename_length;
  579. if (extra_length>=8) {
  580. *min_header_size+=8; // reserve space for the Microsoft Open Packaging Growth Hint
  581. }
  582. while(OPC_ERROR_NONE==raw->state.err && extra_length>0) {
  583. opc_uint16_t extra_id;
  584. opc_uint16_t extra_size;
  585. if (2==opcZipRawReadU16(io, raw, &extra_id) && 2==opcZipRawReadU16(io, raw, &extra_size)) {
  586. switch(extra_id) {
  587. case 0xa220: // Microsoft Open Packaging Growth Hint => ignore
  588. {
  589. opc_uint16_t sig;
  590. opc_uint16_t padVal;
  591. if (2==opcZipRawReadU16(io, raw, &sig) && 0xa028==sig
  592. && 2==opcZipRawReadU16(io, raw, &padVal)
  593. && extra_size>=4 && extra_size-4==opcZipRawSkipBytes(io, raw, extra_size-4)) {
  594. *growth_hint=padVal;
  595. extra_length-=4+extra_size;
  596. } else {
  597. raw->state.err=OPC_ERROR_STREAM;
  598. }
  599. }
  600. break;
  601. default: // just ignore
  602. opc_logf("**ignoring extra data id=%02X size=%02X\n", extra_id, extra_size);
  603. // no break;
  604. if (extra_size==opcZipRawSkipBytes(io, raw, extra_size)) {
  605. extra_length-=4+extra_size;
  606. } else {
  607. raw->state.err=OPC_ERROR_STREAM;
  608. }
  609. break;
  610. }
  611. }
  612. }
  613. ret=(OPC_ERROR_NONE==raw->state.err && 0==extra_length);
  614. }
  615. }
  616. return ret;
  617. }
  618. static opc_error_t opcZipRawSkipFileData(opcIO_t *io, opcFileRawBuffer *raw, opc_uint32_t compressed_size) {
  619. if (compressed_size!=opcZipRawSkipBytes(io, raw, compressed_size) && OPC_ERROR_NONE==raw->state.err) {
  620. raw->state.err=OPC_ERROR_STREAM;
  621. }
  622. return raw->state.err;
  623. }
  624. static opc_error_t opcZipRawReadDataDescriptor(opcIO_t *io, opcFileRawBuffer *raw, opc_uint16_t bit_flag, opc_uint32_t *compressed_size, opc_uint32_t *uncompressed_size, opc_uint32_t *crc32, opc_uint32_t *trailing_bytes) {
  625. OPC_ASSERT(0==*trailing_bytes);
  626. if (0x8==(bit_flag & 0x8) && OPC_ERROR_NONE==raw->state.err) {
  627. // streaming mode
  628. OPC_ASSERT(0==*compressed_size);
  629. opc_uint32_t sig=opcZipRawPeekHeaderSignature(io, raw);
  630. if (0x08074b50==sig) {
  631. opc_uint32_t header_signature;
  632. OPC_ENSURE(4==opcZipRawReadU32(io, raw, &header_signature) && header_signature==sig);
  633. *trailing_bytes+=4;
  634. }
  635. if (OPC_ERROR_NONE==raw->state.err) {
  636. if ((4==opcZipRawReadU32(io, raw, crc32))
  637. && (4==opcZipRawReadU32(io, raw, compressed_size))
  638. && (4==opcZipRawReadU32(io, raw, uncompressed_size))) {
  639. OPC_ASSERT(OPC_ERROR_NONE==raw->state.err);
  640. *trailing_bytes+=3*4;
  641. } else if (OPC_ERROR_NONE==raw->state.err) {
  642. raw->state.err=OPC_ERROR_STREAM;
  643. }
  644. }
  645. }
  646. return raw->state.err;
  647. }
  648. static opc_error_t opcZipInitInflateState(opcFileRawState *rawState,
  649. opc_uint32_t compressed_size,
  650. opc_uint32_t uncompressed_size,
  651. opc_uint16_t compression_method,
  652. opcZipInflateState *state) {
  653. memset(state, 0, sizeof(*state));
  654. state->stream.zalloc = Z_NULL;
  655. state->stream.zfree = Z_NULL;
  656. state->stream.opaque = Z_NULL;
  657. state->stream.next_in = Z_NULL;
  658. state->stream.avail_in = 0;
  659. state->compressed_size=compressed_size;
  660. state->compression_method=compression_method;
  661. state->inflate_state = Z_STREAM_ERROR;
  662. if (OPC_ERROR_NONE!=rawState->err) {
  663. return rawState->err;
  664. } else if (0==state->compression_method) { // STORE
  665. return rawState->err;
  666. } else if (8==state->compression_method) { // DEFLATE
  667. if (Z_OK!=(state->inflate_state=inflateInit2(&state->stream, -MAX_WBITS))) {
  668. rawState->err=OPC_ERROR_DEFLATE;
  669. }
  670. return rawState->err;
  671. } else {
  672. rawState->err=OPC_ERROR_UNSUPPORTED_COMPRESSION;
  673. return rawState->err;
  674. }
  675. }
  676. static opc_error_t opcZipCleanupInflateState(opcFileRawState *rawState,
  677. opc_uint32_t compressed_size,
  678. opc_uint32_t uncompressed_size,
  679. opcZipInflateState *state) {
  680. if (OPC_ERROR_NONE==rawState->err) {
  681. if (0==state->compression_method) { // STORE
  682. if (state->stream.total_in!=compressed_size) {
  683. rawState->err=OPC_ERROR_DEFLATE;
  684. }
  685. } else if (8==state->compression_method) { // DEFLATE
  686. if (Z_OK!=(state->inflate_state=inflateEnd(&state->stream))) {
  687. rawState->err=OPC_ERROR_DEFLATE;
  688. } else if (state->stream.total_in!=compressed_size || state->stream.total_out!=uncompressed_size) {
  689. rawState->err=OPC_ERROR_DEFLATE;
  690. }
  691. } else {
  692. rawState->err=OPC_ERROR_UNSUPPORTED_COMPRESSION;
  693. }
  694. }
  695. return rawState->err;
  696. }
  697. static opc_uint32_t opcZipRawReadFileData(opcIO_t *io, opcFileRawBuffer *rawBuffer, opcZipInflateState *state, opc_uint8_t *buffer, opc_uint32_t buf_len) {
  698. if (8==state->compression_method) {
  699. return opcZipRawInflateBuffer(io, rawBuffer, state, buffer, buf_len);
  700. } else if (0==state->compression_method) {
  701. opc_uint32_t const max_stream=state->compressed_size-state->stream.total_in;
  702. opc_uint32_t const max_in=buf_len<max_stream?buf_len:max_stream;
  703. int ret=opcZipRawReadBuffer(io, rawBuffer, buffer, max_in);
  704. state->stream.total_in+=ret;
  705. return ret;
  706. } else {
  707. return OPC_ERROR_UNSUPPORTED_COMPRESSION;
  708. }
  709. }
  710. struct OPC_ZIPLOADER_IO_HELPER_STRUCT {
  711. opcIO_t *io;
  712. opcZipInflateState inflateState;
  713. opcFileRawBuffer rawBuffer;
  714. opcZipSegmentInfo_t info;
  715. };
  716. static int opcZipLoaderOpen(void *iocontext) {
  717. struct OPC_ZIPLOADER_IO_HELPER_STRUCT *helper=(struct OPC_ZIPLOADER_IO_HELPER_STRUCT *)iocontext;
  718. opc_error_t err=opcZipInitInflateState(&helper->rawBuffer.state, helper->info.compressed_size, helper->info.uncompressed_size, helper->info.compression_method, &helper->inflateState);
  719. return (OPC_ERROR_NONE==err?0:-1);
  720. }
  721. static int opcZipLoaderRead(void *iocontext, char *buffer, int len) {
  722. struct OPC_ZIPLOADER_IO_HELPER_STRUCT *helper=(struct OPC_ZIPLOADER_IO_HELPER_STRUCT *)iocontext;
  723. opc_uint32_t ret=opcZipRawReadFileData(helper->io, &helper->rawBuffer, &helper->inflateState, (opc_uint8_t*)buffer, len);
  724. return (OPC_ERROR_NONE==helper->rawBuffer.state.err?(int)ret:-1);
  725. }
  726. static int opcZipLoaderClose(void *iocontext) {
  727. struct OPC_ZIPLOADER_IO_HELPER_STRUCT *helper=(struct OPC_ZIPLOADER_IO_HELPER_STRUCT *)iocontext;
  728. opc_error_t err=opcZipRawReadDataDescriptor(helper->io, &helper->rawBuffer, helper->info.bit_flag, &helper->info.compressed_size, &helper->info.uncompressed_size, &helper->info.data_crc, &helper->info.trailing_bytes);
  729. if (OPC_ERROR_NONE==err) {
  730. err=opcZipCleanupInflateState(&helper->rawBuffer.state, helper->info.compressed_size, helper->info.uncompressed_size, &helper->inflateState);
  731. }
  732. return (OPC_ERROR_NONE==err?0:-1);
  733. }
  734. static int opcZipLoaderSkip(void *iocontext) {
  735. struct OPC_ZIPLOADER_IO_HELPER_STRUCT *helper=(struct OPC_ZIPLOADER_IO_HELPER_STRUCT *)iocontext;
  736. opc_error_t err=OPC_ERROR_NONE;
  737. if (0x8==(helper->info.bit_flag & 0x8)) {
  738. // streaming mode
  739. if (8==helper->info.compression_method) {
  740. if (0==opcZipLoaderOpen(iocontext)) {
  741. char buf[OPC_DEFLATE_BUFFER_SIZE];
  742. int ret=0;
  743. while ((ret=opcZipLoaderRead(iocontext, buf, sizeof(buf)))>0);
  744. if (OPC_ERROR_NONE==err && ret!=0) {
  745. err=OPC_ERROR_STREAM;
  746. }
  747. if (opcZipLoaderClose(iocontext)!=0 && OPC_ERROR_NONE==err) {
  748. err=OPC_ERROR_STREAM;
  749. }
  750. } else {
  751. err=OPC_ERROR_STREAM;
  752. }
  753. } else {
  754. OPC_ASSERT(0==helper->info.compression_method);
  755. opc_uint8_t buf[3*sizeof(opc_uint32_t)];
  756. if (sizeof(buf)==opcZipRawReadBuffer(helper->io, &helper->rawBuffer, buf, sizeof(buf))) {
  757. opc_uint32_t stream_len=0;
  758. opc_uint32_t crc=0;
  759. do {
  760. opc_uint32_t v[3];
  761. opc_uint32_t k=0;
  762. for(opc_uint32_t j=0;j<3;j++) {
  763. v[j]=0;
  764. for(opc_uint32_t i=0;i<sizeof(opc_uint32_t);i++) {
  765. v[j]|=(opc_uint32_t)buf[(stream_len+(j*sizeof(v[0]))+i)%sizeof(buf)]<<(i<<3);
  766. }
  767. }
  768. opc_uint32_t skip_len=0;
  769. if (0x08074b50==v[0]) {
  770. // useless data descriptor signature, recalc v0..v3
  771. for(opc_uint32_t i=0;i<2;i++) v[i]=v[i+1];
  772. v[2]=opcZipRawPeekHeaderSignature(helper->io, &helper->rawBuffer);
  773. skip_len=sizeof(opc_uint32_t);
  774. }
  775. if (crc==v[0] && stream_len==v[1] && stream_len==v[2]) {
  776. if (OPC_ERROR_NONE==err && skip_len>0) {
  777. err=opcZipRawSkipFileData(helper->io, &helper->rawBuffer, skip_len);
  778. }
  779. // found valid data descriptor, assume this is the end of the local content
  780. if (OPC_ERROR_NONE==err) {
  781. helper->info.data_crc=v[0];
  782. helper->info.compressed_size=v[1];
  783. helper->info.uncompressed_size=v[2];
  784. helper->info.trailing_bytes=sizeof(buf)+skip_len;
  785. }
  786. break;
  787. } else {
  788. // check next byte
  789. crc=crc32(crc, &buf[stream_len%sizeof(buf)], sizeof(buf[0]));
  790. if (sizeof(buf[0])==opcZipRawReadBuffer(helper->io, &helper->rawBuffer, &buf[stream_len%sizeof(buf)], sizeof(buf[0]))) {
  791. stream_len++;
  792. } else {
  793. err=OPC_ERROR_STREAM;
  794. break;
  795. }
  796. }
  797. } while(OPC_ERROR_NONE==helper->rawBuffer.state.err);
  798. } else {
  799. err=OPC_ERROR_STREAM; // not enough bytes for the trailing data descriptor => error
  800. }
  801. }
  802. } else {
  803. err=opcZipRawSkipFileData(helper->io, &helper->rawBuffer, helper->info.compressed_size);
  804. }
  805. return (OPC_ERROR_NONE==err?0:-1);
  806. }
  807. opc_error_t opcZipLoader(opcIO_t *io, void *userctx, opcZipLoaderSegmentCallback_t *segmentCallback) {
  808. struct OPC_ZIPLOADER_IO_HELPER_STRUCT helper;
  809. opc_bzero_mem(&helper, sizeof(helper));
  810. helper.io=io;
  811. OPC_ENSURE(OPC_ERROR_NONE==opcZipInitRawBuffer(io, &helper.rawBuffer));
  812. while(OPC_ERROR_NONE==helper.rawBuffer.state.err &&
  813. opcZipRawReadLocalFileEx(io, &helper.rawBuffer, helper.info.name, sizeof(helper.info.name), &helper.info.name_len,
  814. &helper.info.header_size, &helper.info.min_header_size, &helper.info.compressed_size, &helper.info.uncompressed_size, &helper.info.bit_flag, &helper.info.data_crc, &helper.info.compression_method, &helper.info.stream_ofs, &helper.info.growth_hint)) {
  815. OPC_ASSERT(helper.info.min_header_size<=helper.info.header_size);
  816. helper.info.trailing_bytes=0;
  817. OPC_ASSERT(NULL!=segmentCallback);
  818. OPC_ENSURE(OPC_ERROR_NONE==opcHelperSplitFilename(helper.info.name, helper.info.name_len, &helper.info.segment_number, &helper.info.last_segment, &helper.info.rels_segment));
  819. opc_error_t ret=segmentCallback(&helper, userctx, &helper.info, opcZipLoaderOpen, opcZipLoaderRead, opcZipLoaderClose, opcZipLoaderSkip);
  820. OPC_ASSERT(OPC_ERROR_NONE==ret);
  821. if (OPC_ERROR_NONE==helper.rawBuffer.state.err && OPC_ERROR_NONE!=ret) {
  822. helper.rawBuffer.state.err=ret; // indicate an error
  823. }
  824. }
  825. //@TODO verify directoy etc..
  826. #if 0
  827. opcZipSegment segment;
  828. xmlChar *name=NULL;
  829. opc_uint32_t segment_number;
  830. opc_bool_t last_segment;
  831. while(opcZipRawReadCentralDirectory(zip, &rawBuffer, &segment, &name, &segment_number, &last_segment, NULL)) {
  832. OPC_ENSURE(OPC_ERROR_NONE==opcZipCleanupSegment(&segment));
  833. xmlFree(name);
  834. }
  835. opc_uint16_t central_dir_entries=0;
  836. OPC_ENSURE(opcZipRawReadEndOfCentralDirectory(zip, &rawBuffer, &central_dir_entries));
  837. for(opc_uint32_t i=0;i<container.part_items;i++) {
  838. opcZipSegmentInputStream *stream=opcZipCreateSegmentInputStream(zip, &container.part_array[i].segment);
  839. opc_uint8_t buf[OPC_DEFLATE_BUFFER_SIZE];
  840. opc_uint32_t len=0;
  841. opc_uint32_t crc=0;
  842. while((len=opcZipReadSegmentInputStream(zip, stream, buf, sizeof(buf)))>0) {
  843. crc=crc32(crc, buf, len);
  844. }
  845. OPC_ASSERT(crc==container.part_array[i].segment.crc32);
  846. printf("%s [%08X]\n", container.part_array[i].name, crc);
  847. OPC_ENSURE(OPC_ERROR_NONE==opcZipCloseSegmentInputStream(zip, &container.part_array[i].segment, stream));
  848. }
  849. for(opc_uint32_t i=0;i<container.part_items;i++) {
  850. OPC_ENSURE(OPC_ERROR_NONE==opcZipCleanupSegment(&container.part_array[i].segment));
  851. xmlFree(container.part_array[i].name);
  852. }
  853. #endif
  854. return helper.rawBuffer.state.err;
  855. }
  856. opcZipInputStream *opcZipOpenInputStream(opcZip *zip, opc_uint32_t segment_id) {
  857. OPC_ASSERT(segment_id>=0 && segment_id<zip->segment_items);
  858. opcZipInputStream *stream=(opcZipInputStream *)xmlMalloc(sizeof(opcZipInputStream));
  859. if (NULL!=stream) {
  860. opc_bzero_mem(stream, sizeof(*stream));
  861. stream->segment_id=segment_id;
  862. opcZipSegment *segment=&zip->segment_array[segment_id];
  863. stream->rawBuffer.state.buf_pos=segment->stream_ofs+segment->padding+segment->header_size;
  864. if (OPC_ERROR_NONE!=opcZipInitInflateState(&stream->rawBuffer.state,
  865. segment->compressed_size,
  866. segment->uncompressed_size,
  867. segment->compression_method,
  868. &stream->inflateState)) {
  869. // error
  870. xmlFree(stream); stream=NULL;
  871. }
  872. }
  873. return stream;
  874. }
  875. opc_error_t opcZipCloseInputStream(opcZip *zip, opcZipInputStream *stream) {
  876. OPC_ASSERT(NULL!=zip && NULL!=stream);
  877. OPC_ASSERT(stream->segment_id>=0 && stream->segment_id<zip->segment_items);
  878. opcZipSegment *segment=&zip->segment_array[stream->segment_id];
  879. opc_error_t err=opcZipCleanupInflateState(&stream->rawBuffer.state,
  880. segment->compressed_size,
  881. segment->uncompressed_size,
  882. &stream->inflateState);
  883. xmlFree(stream); stream=NULL;
  884. return err;
  885. }
  886. opc_uint32_t opcZipReadInputStream(opcZip *zip, opcZipInputStream *stream, opc_uint8_t *buf, opc_uint32_t buf_len) {
  887. OPC_ASSERT(NULL!=zip && NULL!=stream);
  888. OPC_ENSURE(stream->rawBuffer.state.buf_pos+stream->rawBuffer.buf_len-stream->rawBuffer.buf_ofs==_opcZipFileSeek(zip->io, stream->rawBuffer.state.buf_pos+stream->rawBuffer.buf_len-stream->rawBuffer.buf_ofs, opcFileSeekSet));
  889. OPC_ASSERT(zip->io->state.buf_pos==stream->rawBuffer.state.buf_pos+stream->rawBuffer.buf_len-stream->rawBuffer.buf_ofs);
  890. // OPC_ENSURE(stream->rawBuffer.state.buf_pos==_opcZipFileSeek(zip->io, stream->rawBuffer.state.buf_pos, opcFileSeekSet));
  891. opc_uint32_t ret=opcZipRawReadFileData(zip->io, &stream->rawBuffer, &stream->inflateState, buf, buf_len);
  892. return ret;
  893. }
  894. static opc_uint32_t opcZipAppendSegmentEx(opcZip *zip,
  895. opc_ofs_t stream_ofs,
  896. opc_ofs_t segment_size,
  897. opc_uint16_t padding,
  898. opc_uint32_t header_size,
  899. opc_uint16_t bit_flag,
  900. opc_uint32_t crc32,
  901. opc_uint16_t compression_method,
  902. opc_ofs_t compressed_size,
  903. opc_ofs_t uncompressed_size,
  904. opc_uint32_t growth_hint,
  905. const xmlChar *partName,
  906. opc_bool_t relsSegment) {
  907. opc_uint32_t segment_id=-1;
  908. opcZipSegment *segment=ensureSegment(zip);
  909. if (NULL!=segment) {
  910. segment_id=zip->segment_items++;
  911. opc_bzero_mem(segment, sizeof(*segment));
  912. segment->stream_ofs=stream_ofs;
  913. segment->padding=padding;
  914. segment->header_size=header_size;
  915. segment->segment_size=segment_size;
  916. segment->bit_flag=bit_flag;
  917. segment->crc32=crc32;
  918. segment->compression_method=compression_method;
  919. segment->compressed_size=compressed_size;
  920. segment->uncompressed_size=uncompressed_size;
  921. segment->growth_hint=growth_hint;
  922. segment->partName=partName;
  923. segment->rels_segment=(relsSegment?1:0);
  924. segment->next_segment_id=-1;
  925. }
  926. return segment_id;
  927. }
  928. opc_uint32_t opcZipLoadSegment(opcZip *zip, const xmlChar *partName, opc_bool_t rels_segment, opcZipSegmentInfo_t *info) {
  929. opc_uint32_t ret=opcZipAppendSegmentEx(zip,
  930. info->stream_ofs,
  931. info->header_size+info->compressed_size+info->trailing_bytes,
  932. info->header_size-info->min_header_size,
  933. info->min_header_size,
  934. info->bit_flag,
  935. info->data_crc,
  936. info->compression_method,
  937. info->compressed_size,
  938. info->uncompressed_size,
  939. info->growth_hint,
  940. partName,
  941. rels_segment);
  942. return ret;
  943. }
  944. opc_uint32_t opcZipCreateSegment(opcZip *zip,
  945. const xmlChar *partName,
  946. opc_bool_t relsSegment,
  947. opc_uint32_t segment_size,
  948. opc_uint32_t growth_hint,
  949. opc_uint16_t compression_method,
  950. opc_uint16_t bit_flag) {
  951. OPC_ASSERT(0==compression_method || 8==compression_method); // either STORE or DEFLATE
  952. OPC_ASSERT(8!=compression_method || (0<<1==bit_flag || 1<<1==bit_flag || 2<<1==bit_flag || 3<<1==bit_flag)); // WHEN DELFATE set bit_flag to NORMAL, MAXIMUM, FAST or SUPERFAST compression
  953. opc_uint32_t segment_id=-1;
  954. //@TODO find free segment
  955. if (-1==segment_id) {
  956. opc_ofs_t stream_ofs=(zip->segment_items>0?zip->segment_array[zip->segment_items-1].stream_ofs+zip->segment_array[zip->segment_items-1].segment_size:0);
  957. opc_uint32_t _growth_hint=(growth_hint>0?growth_hint:OPC_DEFAULT_GROWTH_HINT);
  958. opc_ofs_t _segment_size=(segment_size>0?segment_size:_growth_hint);
  959. char name8[OPC_MAX_PATH];
  960. opc_uint16_t name8_len=opcHelperAssembleSegmentName(name8, sizeof(name8), partName, 0, -1, relsSegment, NULL);
  961. opc_uint32_t header_size=opcZipCalculateHeaderSize(name8, name8_len, OPC_TRUE, NULL);
  962. if (OPC_ERROR_NONE==_opcZipFileGrow(zip->io, stream_ofs+_segment_size)) {
  963. segment_id=opcZipAppendSegmentEx(zip, stream_ofs, _segment_size, 0, header_size, bit_flag, 0, compression_method, 0, 0, _growth_hint, partName, relsSegment);
  964. }
  965. }
  966. return segment_id;
  967. }
  968. opc_error_t opcZipGC(opcZip *zip) {
  969. for(opc_uint32_t i=1;i<zip->segment_items;i++) {
  970. OPC_ASSERT(zip->segment_array[i-1].stream_ofs+zip->segment_array[i-1].segment_size==zip->segment_array[i].stream_ofs);
  971. if (!zip->segment_array[i-1].deleted_segment && !zip->segment_array[i].deleted_segment) {
  972. opcZipSegment *segment=&zip->segment_array[i];
  973. char name8[OPC_MAX_PATH];
  974. opc_uint16_t name8_len=opcHelperAssembleSegmentName(name8, sizeof(name8), segment->partName, 0, -1, segment->rels_segment, NULL);
  975. name8[name8_len]=0;
  976. opc_uint32_t header_size=opcZipCalculateHeaderSize(name8, name8_len, OPC_TRUE, NULL);
  977. if (header_size>segment->header_size) {
  978. header_size=opcZipCalculateHeaderSize(name8, name8_len, OPC_FALSE, NULL);
  979. }
  980. OPC_ASSERT(header_size<=segment->header_size);
  981. opc_uint32_t const free_space=segment->padding+(segment->header_size-header_size);
  982. zip->segment_array[i-1].segment_size+=free_space;
  983. OPC_ASSERT(segment->padding<=segment->segment_size);
  984. segment->stream_ofs+=free_space;
  985. segment->segment_size-=segment->padding;
  986. segment->padding=0;
  987. segment->header_size=header_size;
  988. }
  989. OPC_ASSERT(zip->segment_array[i-1].stream_ofs+zip->segment_array[i-1].segment_size==zip->segment_array[i].stream_ofs);
  990. }
  991. return OPC_ERROR_NONE;
  992. }
  993. static void opcZipSegmentCalcReal(opcZip *zip, opc_uint32_t segment_id, opc_ofs_t *real_padding, opc_ofs_t *real_ofs) {
  994. OPC_ASSERT(segment_id>=0 && segment_id<zip->segment_items);
  995. *real_padding=zip->segment_array[segment_id].padding;
  996. opc_uint32_t i=segment_id;
  997. for(;i>0 && zip->segment_array[i-1].deleted_segment;i--) {
  998. *real_padding+=zip->segment_array[i-1].segment_size;
  999. }
  1000. *real_ofs=zip->segment_array[i].stream_ofs;
  1001. if (i>0) {
  1002. OPC_ASSERT(!zip->segment_array[i-1].deleted_segment);
  1003. opc_ofs_t trailing_space=zip->segment_array[i].stream_ofs
  1004. -zip->segment_array[i-1].stream_ofs
  1005. -zip->segment_array[i-1].padding
  1006. -zip->segment_array[i-1].header_size
  1007. -zip->segment_array[i-1].compressed_size;
  1008. *real_ofs-=trailing_space;
  1009. *real_padding+=trailing_space;
  1010. }
  1011. }
  1012. static opc_bool_t opcZipValidate(opcZip *zip, opc_ofs_t *append_ofs) {
  1013. opc_bool_t valid=OPC_TRUE;
  1014. for(opc_uint32_t i=0;i<zip->segment_items;i++) { if (!zip->segment_array[i].deleted_segment) {
  1015. opc_ofs_t real_padding=0;
  1016. opc_ofs_t real_ofs=0;
  1017. opcZipSegmentCalcReal(zip, i, &real_padding, &real_ofs);
  1018. char name8[OPC_MAX_PATH];
  1019. opc_uint16_t name8_len=opcHelperAssembleSegmentName(name8, sizeof(name8), zip->segment_array[i].partName, 0, -1, zip->segment_array[i].rels_segment, NULL);
  1020. name8[name8_len]=0;
  1021. opc_uint32_t header_size=opcZipCalculateHeaderSize(name8, name8_len, OPC_TRUE, NULL);
  1022. valid=valid && (real_padding==0 || header_size<=zip->segment_array[i].header_size); // check padding>0 needs extra!
  1023. valid=valid&&(real_padding<65000); //@TODO get real value for max padding!
  1024. if (NULL!=append_ofs) *append_ofs=real_ofs+real_padding+zip->segment_array[i].compressed_size+zip->segment_array[i].header_size;
  1025. } }
  1026. return valid;
  1027. }
  1028. static void opcZipTrim(opcZip *zip, opc_ofs_t *append_ofs) {
  1029. opc_ofs_t ofs=0;
  1030. for(opc_uint32_t i=0;i<zip->segment_items;i++) {
  1031. if (!zip->segment_array[i].deleted_segment) {
  1032. opc_ofs_t real_padding=0;
  1033. opc_ofs_t real_ofs=0;
  1034. opcZipSegmentCalcReal(zip, i, &real_padding, &real_ofs);
  1035. OPC_ASSERT(ofs<=real_ofs);
  1036. if (real_padding>0 || ofs<real_ofs) {
  1037. opc_ofs_t src_ofs=real_ofs+real_padding+zip->segment_array[i].header_size;
  1038. opc_ofs_t dest_ofs=ofs+zip->segment_array[i].header_size;
  1039. opc_ofs_t len=zip->segment_array[i].compressed_size;
  1040. OPC_ASSERT(dest_ofs<src_ofs);
  1041. if (dest_ofs<src_ofs) {
  1042. OPC_ENSURE(OPC_ERROR_NONE==_opcZipFileMove(zip->io, dest_ofs, src_ofs, len));
  1043. }
  1044. }
  1045. zip->segment_array[i].stream_ofs=ofs;
  1046. zip->segment_array[i].padding=0;
  1047. zip->segment_array[i].segment_size=zip->segment_array[i].header_size+zip->segment_array[i].compressed_size;
  1048. for(opc_uint32_t j=i;j>0 && zip->segment_array[j-1].deleted_segment;j--) {
  1049. zip->segment_array[j-1].stream_ofs=ofs;
  1050. zip->segment_array[j-1].segment_size=0; // make it a "ZOMBI" segment
  1051. zip->segment_array[j-1].header_size=0;
  1052. zip->segment_array[j-1].padding=0;
  1053. }
  1054. ofs+=zip->segment_array[i].segment_size;
  1055. }
  1056. }
  1057. for(opc_uint32_t j=zip->segment_items;j>0 && zip->segment_array[j-1].deleted_segment;j--) {
  1058. zip->segment_array[j-1].stream_ofs=ofs;
  1059. zip->segment_array[j-1].segment_size=0; // make it a "ZOMBI" segment
  1060. zip->segment_array[j-1].header_size=0;
  1061. zip->segment_array[j-1].padding=0;
  1062. }
  1063. for(opc_uint32_t i=1;i<zip->segment_items;i++) {
  1064. OPC_ASSERT(zip->segment_array[i-1].stream_ofs+zip->segment_array[i-1].segment_size==zip->segment_array[i].stream_ofs);
  1065. }
  1066. if (NULL!=append_ofs) *append_ofs=ofs;
  1067. }
  1068. static void opcZipUpdateLocalFileHeader(opcZip *zip) {
  1069. for(opc_uint32_t i=0;i<zip->segment_items;i++) { if (!zip->segment_array[i].deleted_segment) {
  1070. opc_ofs_t real_padding=0;
  1071. opc_ofs_t real_ofs=0;
  1072. opcZipSegmentCalcReal(zip, i, &real_padding, &real_ofs);
  1073. OPC_ENSURE(_opcZipFileSeek(zip->io, real_ofs, opcFileSeekSet)==real_ofs);
  1074. char name8[OPC_MAX_PATH];
  1075. opc_uint16_t name8_len=opcHelperAssembleSegmentName(name8, sizeof(name8), zip->segment_array[i].partName, 0, -1, zip->segment_array[i].rels_segment, NULL);
  1076. // opc_uint32_t header_size=opcZipCalculateHeaderSize(name8, name8_len, OPC_TRUE, NULL);
  1077. OPC_ASSERT(zip->segment_array[i].stream_ofs+zip->segment_array[i].padding==real_ofs+real_padding);
  1078. OPC_ENSURE(opcZipRawWriteSegmentHeaderEx(zip->io, &zip->io->state,
  1079. name8, name8_len,
  1080. zip->segment_array[i].bit_flag,
  1081. zip->segment_array[i].crc32,
  1082. zip->segment_array[i].compression_method,
  1083. zip->segment_array[i].compressed_size,
  1084. zip->segment_array[i].uncompressed_size,
  1085. zip->segment_array[i].header_size+real_padding,
  1086. zip->segment_array[i].growth_hint)==zip->segment_array[i].header_size+real_padding);
  1087. OPC_ASSERT(zip->segment_array[i].stream_ofs+zip->segment_array[i].padding+zip->segment_array[i].header_size==zip->io->state.buf_pos);
  1088. } }
  1089. }
  1090. static void opcZipAppendDirectory(opcZip *zip, opc_ofs_t append_ofs) {
  1091. OPC_ENSURE(_opcZipFileSeek(zip->io, append_ofs, opcFileSeekSet)==append_ofs);
  1092. opc_uint32_t real_segments=0;
  1093. for(opc_uint32_t i=0;i<zip->segment_items;i++) { if (!zip->segment_array[i].deleted_segment) {
  1094. opc_ofs_t real_padding=0;
  1095. opc_ofs_t real_ofs=0;
  1096. opcZipSegmentCalcReal(zip, i, &real_padding, &real_ofs);
  1097. char name8[OPC_MAX_PATH];
  1098. opc_uint16_t name8_len=opcHelperAssembleSegmentName(name8, sizeof(name8), zip->segment_array[i].partName, 0, -1, zip->segment_array[i].rels_segment, NULL);
  1099. OPC_ENSURE(OPC_ERROR_NONE==opcZipRawWriteCentralDirectoryEx(zip->io, &zip->io->state,
  1100. name8, name8_len,
  1101. zip->segment_array[i].bit_flag,
  1102. zip->segment_array[i].crc32,
  1103. zip->segment_array[i].compression_method,
  1104. zip->segment_array[i].compressed_size,
  1105. zip->segment_array[i].uncompressed_size,
  1106. zip->segment_array[i].header_size+real_padding,
  1107. zip->segment_array[i].growth_hint,
  1108. real_ofs));
  1109. real_segments++;
  1110. } }
  1111. OPC_ENSURE(OPC_ERROR_NONE==opcZipRawWriteEndOfCentralDirectoryEx(zip->io, &zip->io->state, append_ofs, real_segments));
  1112. OPC_ENSURE(OPC_ERROR_NONE==_opcZipFileTrim(zip->io, zip->io->state.buf_pos));
  1113. }
  1114. opc_error_t opcZipCommit(opcZip *zip, opc_bool_t trim) {
  1115. opc_ofs_t append_ofs=0;
  1116. if (!opcZipValidate(zip, &append_ofs) || trim) {
  1117. opcZipTrim(zip, &append_ofs);
  1118. OPC_ASSERT(opcZipValidate(zip, NULL));
  1119. }
  1120. opcZipUpdateLocalFileHeader(zip);
  1121. opcZipAppendDirectory(zip, append_ofs);
  1122. OPC_ENSURE(OPC_ERROR_NONE==_opcZipFileFlush(zip->io));
  1123. return zip->io->state.err;
  1124. }
  1125. opcZipOutputStream *opcZipOpenOutputStream(opcZip *zip, opc_uint32_t *segment_id) {
  1126. OPC_ASSERT(NULL!=zip && NULL!=segment_id && -1!=*segment_id);
  1127. OPC_ASSERT(*segment_id>=0 && *segment_id<zip->segment_items);
  1128. opcZipSegment *segment=&zip->segment_array[*segment_id];
  1129. OPC_ASSERT(segment->header_size+segment->padding<=segment->segment_size);
  1130. opc_ofs_t free_size=segment->segment_size-segment->header_size-segment->padding;
  1131. opc_uint32_t buf_size=(free_size>OPC_DEFLATE_BUFFER_SIZE?OPC_DEFLATE_BUFFER_SIZE:free_size);
  1132. opcZipOutputStream *out=(opcZipOutputStream *)xmlMalloc(sizeof(opcZipOutputStream)+OPC_DEFLATE_BUFFER_SIZE);
  1133. if (NULL!=out) {
  1134. opc_bzero_mem(out, sizeof(*out));
  1135. out->buf=(opc_uint8_t*)((&out->buf)+1); // buffer starts right after me...
  1136. out->buf_size=buf_size;
  1137. out->segment_id=*segment_id;
  1138. *segment_id=-1; // take ownership
  1139. segment->compressed_size=0;
  1140. segment->uncompressed_size=0;
  1141. segment->crc32=0;
  1142. out->compression_method=segment->compression_method;
  1143. OPC_ASSERT(0==out->compression_method || 8==out->compression_method);
  1144. if (8==out->compression_method) { // delfate
  1145. out->stream.zalloc = Z_NULL;
  1146. out->stream.zfree = Z_NULL;
  1147. out->stream.opaque = Z_NULL;
  1148. int level=Z_DEFAULT_COMPRESSION;
  1149. switch ((segment->bit_flag>>1) & 0x3) {
  1150. default:
  1151. case 0: level=Z_DEFAULT_COMPRESSION;
  1152. break;
  1153. case 1: level=Z_BEST_COMPRESSION;
  1154. break;
  1155. case 2: level=Z_BEST_SPEED;
  1156. break;
  1157. case 3: level=Z_BEST_SPEED;
  1158. break;
  1159. }
  1160. if (Z_OK!=(out->inflate_state=deflateInit2(&out->stream, level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY))) {
  1161. xmlFree(out); out=NULL;
  1162. }
  1163. }
  1164. }
  1165. return out;
  1166. }
  1167. opcZipOutputStream *opcZipCreateOutputStream(opcZip *zip,
  1168. opc_uint32_t *segment_id,
  1169. const xmlChar *partName,
  1170. opc_bool_t relsSegment,
  1171. opc_uint32_t segment_size,
  1172. opc_uint32_t growth_hint,
  1173. opc_uint16_t compression_method,
  1174. opc_uint16_t bit_flag) {
  1175. opcZipOutputStream *ret=NULL;
  1176. OPC_ASSERT(NULL!=segment_id);
  1177. if (NULL!=segment_id) {
  1178. if (-1==*segment_id) {
  1179. *segment_id=opcZipCreateSegment(zip, partName, relsSegment, segment_size, growth_hint, compression_method, bit_flag);
  1180. } else {
  1181. OPC_ASSERT(*segment_id>=0 && *segment_id<zip->segment_items);
  1182. opcZipSegment *segment=&zip->segment_array[*segment_id];
  1183. segment->bit_flag=bit_flag;
  1184. segment->compression_method=compression_method;
  1185. }
  1186. ret=opcZipOpenOutputStream(zip, segment_id);
  1187. }
  1188. return ret;
  1189. }
  1190. static opc_uint32_t opcZipOutputStreamFill(opcZip *zip, opcZipOutputStream *stream, const opc_uint8_t *data, opc_uint32_t data_len) {
  1191. OPC_ASSERT(NULL!=stream && NULL!=stream->buf && NULL!=data && stream->buf_ofs+stream->buf_len<=stream->buf_size);
  1192. opc_uint32_t const free=stream->buf_size-stream->buf_ofs-stream->buf_len;
  1193. opc_uint32_t const len=(free<data_len?free:data_len);
  1194. opc_uint32_t ret=0;
  1195. OPC_ASSERT(len<=data_len && len<=stream->buf_size-(stream->buf_ofs+stream->buf_len));
  1196. if (len>0) {
  1197. if (0==stream->compression_method) { // STORE
  1198. stream->stream.total_in+=len;
  1199. stream->stream.total_out+=len;
  1200. stream->crc32=crc32(stream->crc32, data, len);
  1201. memcpy(stream->buf+stream->buf_ofs, data, len);
  1202. stream->buf_len+=len;
  1203. ret=len;
  1204. } else if (8==stream->compression_method) { // DEFLATE
  1205. stream->stream.avail_in=data_len;
  1206. stream->stream.next_in=(Bytef*)data;
  1207. stream->stream.avail_out=free;
  1208. stream->stream.next_out=stream->buf+stream->buf_ofs;
  1209. if (Z_OK==(stream->inflate_state=deflate(&stream->stream, Z_NO_FLUSH))) {
  1210. opc_uint32_t const bytes_in=data_len-stream->stream.avail_in;
  1211. opc_uint32_t const bytes_out=free-stream->stream.avail_out;
  1212. stream->crc32=crc32(stream->crc32, data, bytes_in);
  1213. ret=bytes_in;
  1214. stream->buf_len+=bytes_out;
  1215. } else {
  1216. zip->io->state.err=OPC_ERROR_DEFLATE;
  1217. }
  1218. } else {
  1219. zip->io->state.err=OPC_ERROR_UNSUPPORTED_COMPRESSION;
  1220. }
  1221. }
  1222. return ret;
  1223. }
  1224. static opc_bool_t opcZipOutputStreamFinishCompression(opcZip *zip, opcZipOutputStream *stream) {
  1225. opc_bool_t ret=OPC_FALSE;
  1226. if (OPC_ERROR_NONE==zip->io->state.err) {
  1227. if (0==stream->compression_method) { // STORE
  1228. OPC_ASSERT(Z_OK==stream->inflate_state);
  1229. stream->inflate_state=Z_STREAM_END;
  1230. ret=(Z_STREAM_END==stream->inflate_state);
  1231. } else if (8==stream->compression_method) { // DEFLATE
  1232. opc_uint32_t const free=stream->buf_size-stream->buf_ofs-stream->buf_len;
  1233. OPC_ASSERT(free>0); // hmmm --- no space? make sure you correcly growed the segment...
  1234. stream->stream.avail_in=0;
  1235. stream->stream.next_in=0;
  1236. stream->stream.avail_out=free;
  1237. stream->stream.next_out=stream->buf+stream->buf_ofs;
  1238. if (Z_OK==(stream->inflate_state=deflate(&stream->stream, Z_FINISH)) || Z_STREAM_END==stream->inflate_state) {
  1239. opc_uint32_t const bytes_out=free-stream->stream.avail_out;
  1240. stream->buf_len+=bytes_out;
  1241. ret=(Z_STREAM_END==stream->inflate_state);
  1242. } else {
  1243. zip->io->state.err=OPC_ERROR_DEFLATE;
  1244. }
  1245. } else {
  1246. zip->io->state.err=OPC_ERROR_UNSUPPORTED_COMPRESSION;
  1247. }
  1248. }
  1249. return ret;
  1250. }
  1251. static void opcZipMarkSegmentDeleted(opcZip *zip, opc_uint32_t segment_id, opcZipSegmentReleaseCallback* releaseCallback) {
  1252. OPC_ASSERT(segment_id>=0 && segment_id<zip->segment_items);
  1253. opcZipSegment *segment=&zip->segment_array[segment_id];
  1254. if (NULL!=releaseCallback) releaseCallback(zip, segment_id);
  1255. segment->deleted_segment=1;
  1256. segment->partName=NULL; // should have been released in "releaseCallback" above
  1257. segment->next_segment_id=zip->first_free_segment_id;
  1258. zip->first_free_segment_id=segment_id;
  1259. }
  1260. static void opcZipOutputStreamFlushAndGrow(opcZip *zip, opcZipOutputStream *stream) {
  1261. opc_error_t err=OPC_ERROR_NONE;
  1262. if (stream->buf_len>0 && OPC_ERROR_NONE==zip->io->state.err) {
  1263. OPC_ASSERT(stream->segment_id>=0 && stream->segment_id<zip->segment_items);
  1264. opcZipSegment *segment=&zip->segment_array[stream->segment_id];
  1265. opc_ofs_t ofs=segment->padding+segment->header_size+segment->compressed_size;
  1266. OPC_ASSERT(ofs<=segment->segment_size);
  1267. opc_ofs_t free_space=segment->segment_size-ofs;
  1268. if (stream->buf_len>free_space && stream->segment_id+1==zip->segment_items) {
  1269. // not enoght space and last segment => simply grow it...
  1270. segment->growth_hint=(segment->growth_hint<=0?OPC_DEFAULT_GROWTH_HINT:segment->growth_hint);
  1271. OPC_ASSERT(segment->growth_hint>0);
  1272. while(segment->segment_size-ofs<stream->buf_len) segment->segment_size+=segment->growth_hint;
  1273. free_space=segment->segment_size-ofs;
  1274. OPC_ASSERT(stream->buf_len<=free_space);
  1275. OPC_ENSURE(OPC_ERROR_NONE==_opcZipFileGrow(zip->io, segment->stream_ofs+segment->segment_size));
  1276. }
  1277. if (stream->buf_len>free_space) {
  1278. // can't grow it, so move to a new segment!
  1279. opc_ofs_t size_needed=segment->segment_size+stream->buf_len+segment->header_size;
  1280. opc_uint32_t new_segment_id=opcZipCreateSegment(zip, segment->partName, segment->rels_segment, size_needed, segment->growth_hint, segment->compression_method, segment->bit_flag);
  1281. segment=&zip->segment_array[stream->segment_id]; // recalc segment, since create can realloc base address
  1282. if (OPC_ERROR_NONE==err && -1!=new_segment_id) {
  1283. OPC_ASSERT(new_segment_id>=0 && new_segment_id<zip->segment_items);
  1284. opcZipSegment *new_segment=&zip->segment_array[new_segment_id];
  1285. opc_ofs_t const free_size=new_segment->segment_size-new_segment->header_size-new_segment->padding;
  1286. OPC_ASSERT(segment->compressed_size<free_size);
  1287. err=_opcZipFileMove(zip->io,
  1288. new_segment->stream_ofs+new_segment->padding+new_segment->header_size, // dest
  1289. segment->stream_ofs+segment->padding+segment->header_size, // src
  1290. segment->compressed_size);
  1291. new_segment->compressed_size=segment->compressed_size;
  1292. segment->partName=NULL; // ownership transfered to new_segment
  1293. opcZipMarkSegmentDeleted(zip, stream->segment_id, NULL /* no release needed, since partName is copied to new segment */);
  1294. OPC_ASSERT(1==segment->deleted_segment);
  1295. segment=new_segment;
  1296. stream->segment_id=new_segment_id;
  1297. opc_uint32_t buf_size=(free_size>OPC_DEFLATE_BUFFER_SIZE?OPC_DEFLATE_BUFFER_SIZE:free_size);
  1298. OPC_ASSERT(stream->buf_size<=buf_size);
  1299. stream->buf_size=buf_size;
  1300. ofs=segment->padding+segment->header_size+segment->compressed_size;
  1301. free_space=segment->segment_size-ofs;
  1302. OPC_ASSERT(stream->buf_len<=free_space);
  1303. }
  1304. }
  1305. if (stream->buf_len<=free_space) {
  1306. // enought free space in the current segment
  1307. OPC_ENSURE(_opcZipFileSeek(zip->io, segment->stream_ofs+ofs, opcFileSeekSet)==segment->stream_ofs+ofs);
  1308. OPC_ENSURE(_opcZipFileWrite(zip->io, stream->buf+stream->buf_ofs, stream->buf_len)==stream->buf_len);
  1309. segment->compressed_size+=stream->buf_len;
  1310. stream->buf_ofs=0;
  1311. stream->buf_len=0;
  1312. } else {
  1313. OPC_ASSERT(0); // should not happend! => can't get enought space!
  1314. err=OPC_ERROR_STREAM;
  1315. }
  1316. if (OPC_ERROR_NONE!=err && OPC_ERROR_NONE==zip->io->state.err) {
  1317. zip->io->state.err=err;
  1318. }
  1319. }
  1320. }
  1321. static void opcZipOutputStreamFinishSegment(opcZip *zip, opcZipOutputStream *stream) {
  1322. opc_bool_t done=OPC_FALSE;
  1323. while(!done && OPC_ERROR_NONE==zip->io->state.err) {
  1324. done=opcZipOutputStreamFinishCompression(zip, stream);
  1325. opcZipOutputStreamFlushAndGrow(zip, stream);
  1326. }
  1327. }
  1328. opc_error_t opcZipCloseOutputStream(opcZip *zip, opcZipOutputStream *stream, opc_uint32_t *segment_id) {
  1329. OPC_ASSERT(NULL!=zip && NULL!=segment_id && -1==*segment_id);
  1330. opcZipOutputStreamFinishSegment(zip, stream);
  1331. OPC_ASSERT(stream->segment_id>=0 && stream->segment_id<zip->segment_items);
  1332. opcZipSegment *segment=&zip->segment_array[stream->segment_id];
  1333. *segment_id=stream->segment_id;
  1334. OPC_ASSERT(segment->compressed_size==stream->stream.total_out);
  1335. segment->uncompressed_size=stream->stream.total_in;
  1336. segment->crc32=stream->crc32;
  1337. deflateEnd(&stream->stream);
  1338. xmlFree(stream); stream=NULL;
  1339. return zip->io->state.err;
  1340. }
  1341. opc_uint32_t opcZipWriteOutputStream(opcZip *zip, opcZipOutputStream *stream, const opc_uint8_t *buf, opc_uint32_t buf_len) {
  1342. opc_uint32_t out=0;
  1343. do {
  1344. out+=opcZipOutputStreamFill(zip, stream, buf+out, buf_len-out);
  1345. OPC_ASSERT(out<=buf_len);
  1346. opcZipOutputStreamFlushAndGrow(zip, stream);
  1347. } while (out<buf_len);
  1348. return out;
  1349. }
  1350. opc_uint32_t opcZipGetFirstSegmentId(opcZip *zip) {
  1351. opc_uint32_t i=0;
  1352. while(i<zip->segment_items && zip->segment_array[i].deleted_segment) i++;
  1353. return (i<zip->segment_items?i:-1);
  1354. }
  1355. opc_uint32_t opcZipGetNextSegmentId(opcZip *zip, opc_uint32_t segment_id) {
  1356. OPC_ASSERT(segment_id>=0 && segment_id<zip->segment_items);
  1357. if (segment_id>=0 && segment_id<zip->segment_items) {
  1358. opc_uint32_t i=segment_id+1;
  1359. while(i<zip->segment_items && zip->segment_array[i].deleted_segment) i++;
  1360. return (i<zip->segment_items?i:-1);
  1361. } else {
  1362. return -1;
  1363. }
  1364. }
  1365. opc_error_t opcZipGetSegmentInfo(opcZip *zip, opc_uint32_t segment_id, const xmlChar **name, opc_bool_t *rels_segment, opc_uint32_t *crc) {
  1366. OPC_ASSERT(segment_id>=0 && segment_id<zip->segment_items);
  1367. if (NULL!=name) {
  1368. *name=zip->segment_array[segment_id].partName;
  1369. }
  1370. if (NULL!=rels_segment) {
  1371. *rels_segment=zip->segment_array[segment_id].rels_segment;
  1372. }
  1373. if (NULL!=crc) {
  1374. *crc=zip->segment_array[segment_id].crc32;
  1375. }
  1376. return OPC_ERROR_NONE;
  1377. }
  1378. opc_bool_t opcZipSegmentDelete(opcZip *zip, opc_uint32_t *first_segment, opc_uint32_t *last_segment, opcZipSegmentReleaseCallback* releaseCallback) {
  1379. OPC_ASSERT(NULL==last_segment || *first_segment==*last_segment); // not not implemented... needed for fragmented containers
  1380. OPC_ASSERT(*first_segment>=0 && *first_segment<zip->segment_items);
  1381. opc_bool_t ret=OPC_FALSE;
  1382. opc_uint32_t segment_id=*first_segment;
  1383. while(segment_id>=0 && segment_id<zip->segment_items) {
  1384. opc_uint32_t next_segment_id=zip->segment_array[segment_id].next_segment_id;
  1385. opcZipMarkSegmentDeleted(zip, segment_id, releaseCallback);
  1386. segment_id=next_segment_id;
  1387. }
  1388. if (NULL!=last_segment) {
  1389. OPC_ASSERT(*last_segment=segment_id);
  1390. *last_segment=-1;
  1391. }
  1392. *first_segment=-1;
  1393. return ret;
  1394. }