mz_zip_rw.c 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103
  1. /* mz_zip_rw.c -- Zip reader/writer
  2. Version 2.9.2, February 12, 2020
  3. part of the MiniZip project
  4. Copyright (C) 2010-2020 Nathan Moinvaziri
  5. https://github.com/nmoinvaz/minizip
  6. This program is distributed under the terms of the same license as zlib.
  7. See the accompanying LICENSE file for the full text of the license.
  8. */
  9. #include "mz.h"
  10. #include "mz_crypt.h"
  11. #include "mz_os.h"
  12. #include "mz_strm.h"
  13. #include "mz_strm_buf.h"
  14. #include "mz_strm_mem.h"
  15. #include "mz_strm_os.h"
  16. #include "mz_strm_split.h"
  17. #include "mz_strm_wzaes.h"
  18. #include "mz_zip.h"
  19. #include "mz_zip_rw.h"
  20. /***************************************************************************/
  21. #define MZ_DEFAULT_PROGRESS_INTERVAL (1000u)
  22. #define MZ_ZIP_CD_FILENAME ("__cdcd__")
  23. /***************************************************************************/
  24. typedef struct mz_zip_reader_s {
  25. void *zip_handle;
  26. void *file_stream;
  27. void *buffered_stream;
  28. void *split_stream;
  29. void *mem_stream;
  30. void *hash;
  31. uint16_t hash_algorithm;
  32. uint16_t hash_digest_size;
  33. mz_zip_file *file_info;
  34. const char *pattern;
  35. uint8_t pattern_ignore_case;
  36. const char *password;
  37. void *overwrite_userdata;
  38. mz_zip_reader_overwrite_cb
  39. overwrite_cb;
  40. void *password_userdata;
  41. mz_zip_reader_password_cb
  42. password_cb;
  43. void *progress_userdata;
  44. mz_zip_reader_progress_cb
  45. progress_cb;
  46. uint32_t progress_cb_interval_ms;
  47. void *entry_userdata;
  48. mz_zip_reader_entry_cb
  49. entry_cb;
  50. uint8_t raw;
  51. uint8_t buffer[UINT16_MAX];
  52. int32_t encoding;
  53. uint8_t sign_required;
  54. uint8_t cd_verified;
  55. uint8_t cd_zipped;
  56. uint8_t entry_verified;
  57. } mz_zip_reader;
  58. /***************************************************************************/
  59. int32_t mz_zip_reader_is_open(void *handle)
  60. {
  61. mz_zip_reader *reader = (mz_zip_reader *)handle;
  62. if (reader == NULL)
  63. return MZ_PARAM_ERROR;
  64. if (reader->zip_handle == NULL)
  65. return MZ_PARAM_ERROR;
  66. return MZ_OK;
  67. }
  68. int32_t mz_zip_reader_open(void *handle, void *stream)
  69. {
  70. mz_zip_reader *reader = (mz_zip_reader *)handle;
  71. int32_t err = MZ_OK;
  72. reader->cd_verified = 0;
  73. reader->cd_zipped = 0;
  74. mz_zip_create(&reader->zip_handle);
  75. mz_zip_set_recover(reader->zip_handle, 1);
  76. err = mz_zip_open(reader->zip_handle, stream, MZ_OPEN_MODE_READ);
  77. if (err != MZ_OK)
  78. {
  79. mz_zip_reader_close(handle);
  80. return err;
  81. }
  82. mz_zip_reader_unzip_cd(reader);
  83. return MZ_OK;
  84. }
  85. int32_t mz_zip_reader_open_file(void *handle, const char *path)
  86. {
  87. mz_zip_reader *reader = (mz_zip_reader *)handle;
  88. int32_t err = MZ_OK;
  89. mz_zip_reader_close(handle);
  90. mz_stream_os_create(&reader->file_stream);
  91. mz_stream_buffered_create(&reader->buffered_stream);
  92. mz_stream_split_create(&reader->split_stream);
  93. mz_stream_set_base(reader->buffered_stream, reader->file_stream);
  94. mz_stream_set_base(reader->split_stream, reader->buffered_stream);
  95. err = mz_stream_open(reader->split_stream, path, MZ_OPEN_MODE_READ);
  96. if (err == MZ_OK)
  97. err = mz_zip_reader_open(handle, reader->split_stream);
  98. return err;
  99. }
  100. int32_t mz_zip_reader_open_file_in_memory(void *handle, const char *path)
  101. {
  102. mz_zip_reader *reader = (mz_zip_reader *)handle;
  103. void *file_stream = NULL;
  104. int64_t file_size = 0;
  105. int32_t err = 0;
  106. mz_zip_reader_close(handle);
  107. mz_stream_os_create(&file_stream);
  108. err = mz_stream_os_open(file_stream, path, MZ_OPEN_MODE_READ);
  109. if (err != MZ_OK)
  110. {
  111. mz_stream_os_delete(&file_stream);
  112. mz_zip_reader_close(handle);
  113. return err;
  114. }
  115. mz_stream_os_seek(file_stream, 0, MZ_SEEK_END);
  116. file_size = mz_stream_os_tell(file_stream);
  117. mz_stream_os_seek(file_stream, 0, MZ_SEEK_SET);
  118. if ((file_size <= 0) || (file_size > UINT32_MAX))
  119. {
  120. /* Memory size is too large or too small */
  121. mz_stream_os_close(file_stream);
  122. mz_stream_os_delete(&file_stream);
  123. mz_zip_reader_close(handle);
  124. return MZ_MEM_ERROR;
  125. }
  126. mz_stream_mem_create(&reader->mem_stream);
  127. mz_stream_mem_set_grow_size(reader->mem_stream, (int32_t)file_size);
  128. mz_stream_mem_open(reader->mem_stream, NULL, MZ_OPEN_MODE_CREATE);
  129. err = mz_stream_copy(reader->mem_stream, file_stream, (int32_t)file_size);
  130. mz_stream_os_close(file_stream);
  131. mz_stream_os_delete(&file_stream);
  132. if (err == MZ_OK)
  133. err = mz_zip_reader_open(handle, reader->mem_stream);
  134. if (err != MZ_OK)
  135. mz_zip_reader_close(handle);
  136. return err;
  137. }
  138. int32_t mz_zip_reader_open_buffer(void *handle, uint8_t *buf, int32_t len, uint8_t copy)
  139. {
  140. mz_zip_reader *reader = (mz_zip_reader *)handle;
  141. int32_t err = MZ_OK;
  142. mz_zip_reader_close(handle);
  143. mz_stream_mem_create(&reader->mem_stream);
  144. if (copy)
  145. {
  146. mz_stream_mem_set_grow_size(reader->mem_stream, len);
  147. mz_stream_mem_open(reader->mem_stream, NULL, MZ_OPEN_MODE_CREATE);
  148. mz_stream_mem_write(reader->mem_stream, buf, len);
  149. mz_stream_mem_seek(reader->mem_stream, 0, MZ_SEEK_SET);
  150. }
  151. else
  152. {
  153. mz_stream_mem_open(reader->mem_stream, NULL, MZ_OPEN_MODE_READ);
  154. mz_stream_mem_set_buffer(reader->mem_stream, buf, len);
  155. }
  156. if (err == MZ_OK)
  157. err = mz_zip_reader_open(handle, reader->mem_stream);
  158. return err;
  159. }
  160. int32_t mz_zip_reader_close(void *handle)
  161. {
  162. mz_zip_reader *reader = (mz_zip_reader *)handle;
  163. int32_t err = MZ_OK;
  164. if (reader->zip_handle != NULL)
  165. {
  166. err = mz_zip_close(reader->zip_handle);
  167. mz_zip_delete(&reader->zip_handle);
  168. }
  169. if (reader->split_stream != NULL)
  170. {
  171. mz_stream_split_close(reader->split_stream);
  172. mz_stream_split_delete(&reader->split_stream);
  173. }
  174. if (reader->buffered_stream != NULL)
  175. mz_stream_buffered_delete(&reader->buffered_stream);
  176. if (reader->file_stream != NULL)
  177. mz_stream_os_delete(&reader->file_stream);
  178. if (reader->mem_stream != NULL)
  179. {
  180. mz_stream_mem_close(reader->mem_stream);
  181. mz_stream_mem_delete(&reader->mem_stream);
  182. }
  183. return err;
  184. }
  185. /***************************************************************************/
  186. int32_t mz_zip_reader_unzip_cd(void *handle)
  187. {
  188. mz_zip_reader *reader = (mz_zip_reader *)handle;
  189. mz_zip_file *cd_info = NULL;
  190. void *cd_mem_stream = NULL;
  191. void *new_cd_stream = NULL;
  192. void *file_extra_stream = NULL;
  193. uint64_t number_entry = 0;
  194. int32_t err = MZ_OK;
  195. err = mz_zip_reader_goto_first_entry(handle);
  196. if (err != MZ_OK)
  197. return err;
  198. err = mz_zip_reader_entry_get_info(handle, &cd_info);
  199. if (err != MZ_OK)
  200. return err;
  201. if (strcmp(cd_info->filename, MZ_ZIP_CD_FILENAME) != 0)
  202. return mz_zip_reader_goto_first_entry(handle);
  203. err = mz_zip_reader_entry_open(handle);
  204. if (err != MZ_OK)
  205. return err;
  206. mz_stream_mem_create(&file_extra_stream);
  207. mz_stream_mem_set_buffer(file_extra_stream, (void *)cd_info->extrafield, cd_info->extrafield_size);
  208. err = mz_zip_extrafield_find(file_extra_stream, MZ_ZIP_EXTENSION_CDCD, NULL);
  209. if (err == MZ_OK)
  210. err = mz_stream_read_uint64(file_extra_stream, &number_entry);
  211. mz_stream_mem_delete(&file_extra_stream);
  212. if (err != MZ_OK)
  213. return err;
  214. mz_zip_get_cd_mem_stream(reader->zip_handle, &cd_mem_stream);
  215. if (mz_stream_mem_is_open(cd_mem_stream) != MZ_OK)
  216. mz_stream_mem_open(cd_mem_stream, NULL, MZ_OPEN_MODE_CREATE);
  217. err = mz_stream_seek(cd_mem_stream, 0, MZ_SEEK_SET);
  218. if (err == MZ_OK)
  219. err = mz_stream_copy_stream(cd_mem_stream, NULL, handle, mz_zip_reader_entry_read,
  220. (int32_t)cd_info->uncompressed_size);
  221. if (err == MZ_OK)
  222. {
  223. reader->cd_zipped = 1;
  224. mz_zip_set_cd_stream(reader->zip_handle, 0, cd_mem_stream);
  225. mz_zip_set_number_entry(reader->zip_handle, number_entry);
  226. err = mz_zip_reader_goto_first_entry(handle);
  227. }
  228. reader->cd_verified = reader->entry_verified;
  229. mz_stream_mem_delete(&new_cd_stream);
  230. return err;
  231. }
  232. /***************************************************************************/
  233. static int32_t mz_zip_reader_locate_entry_cb(void *handle, void *userdata, mz_zip_file *file_info)
  234. {
  235. mz_zip_reader *reader = (mz_zip_reader *)userdata;
  236. int32_t result = 0;
  237. MZ_UNUSED(handle);
  238. result = mz_path_compare_wc(file_info->filename, reader->pattern, reader->pattern_ignore_case);
  239. return result;
  240. }
  241. int32_t mz_zip_reader_goto_first_entry(void *handle)
  242. {
  243. mz_zip_reader *reader = (mz_zip_reader *)handle;
  244. int32_t err = MZ_OK;
  245. if (mz_zip_reader_is_open(handle) != MZ_OK)
  246. return MZ_PARAM_ERROR;
  247. if (mz_zip_entry_is_open(reader->zip_handle) == MZ_OK)
  248. mz_zip_reader_entry_close(handle);
  249. if (reader->pattern == NULL)
  250. err = mz_zip_goto_first_entry(reader->zip_handle);
  251. else
  252. err = mz_zip_locate_first_entry(reader->zip_handle, reader, mz_zip_reader_locate_entry_cb);
  253. reader->file_info = NULL;
  254. if (err == MZ_OK)
  255. err = mz_zip_entry_get_info(reader->zip_handle, &reader->file_info);
  256. return err;
  257. }
  258. int32_t mz_zip_reader_goto_next_entry(void *handle)
  259. {
  260. mz_zip_reader *reader = (mz_zip_reader *)handle;
  261. int32_t err = MZ_OK;
  262. if (mz_zip_reader_is_open(handle) != MZ_OK)
  263. return MZ_PARAM_ERROR;
  264. if (mz_zip_entry_is_open(reader->zip_handle) == MZ_OK)
  265. mz_zip_reader_entry_close(handle);
  266. if (reader->pattern == NULL)
  267. err = mz_zip_goto_next_entry(reader->zip_handle);
  268. else
  269. err = mz_zip_locate_next_entry(reader->zip_handle, reader, mz_zip_reader_locate_entry_cb);
  270. reader->file_info = NULL;
  271. if (err == MZ_OK)
  272. err = mz_zip_entry_get_info(reader->zip_handle, &reader->file_info);
  273. return err;
  274. }
  275. int32_t mz_zip_reader_locate_entry(void *handle, const char *filename, uint8_t ignore_case)
  276. {
  277. mz_zip_reader *reader = (mz_zip_reader *)handle;
  278. int32_t err = MZ_OK;
  279. if (mz_zip_entry_is_open(reader->zip_handle) == MZ_OK)
  280. mz_zip_reader_entry_close(handle);
  281. err = mz_zip_locate_entry(reader->zip_handle, filename, ignore_case);
  282. reader->file_info = NULL;
  283. if (err == MZ_OK)
  284. err = mz_zip_entry_get_info(reader->zip_handle, &reader->file_info);
  285. return err;
  286. }
  287. /***************************************************************************/
  288. int32_t mz_zip_reader_entry_open(void *handle)
  289. {
  290. mz_zip_reader *reader = (mz_zip_reader *)handle;
  291. int32_t err = MZ_OK;
  292. const char *password = NULL;
  293. char password_buf[120];
  294. reader->entry_verified = 0;
  295. if (mz_zip_reader_is_open(reader) != MZ_OK)
  296. return MZ_PARAM_ERROR;
  297. if (reader->file_info == NULL)
  298. return MZ_PARAM_ERROR;
  299. /* If the entry isn't open for reading, open it */
  300. if (mz_zip_entry_is_open(reader->zip_handle) == MZ_OK)
  301. return MZ_OK;
  302. password = reader->password;
  303. /* Check if we need a password and ask for it if we need to */
  304. if ((reader->file_info->flag & MZ_ZIP_FLAG_ENCRYPTED) && (password == NULL) &&
  305. (reader->password_cb != NULL))
  306. {
  307. reader->password_cb(handle, reader->password_userdata, reader->file_info,
  308. password_buf, sizeof(password_buf));
  309. password = password_buf;
  310. }
  311. err = mz_zip_entry_read_open(reader->zip_handle, reader->raw, password);
  312. #ifndef MZ_ZIP_NO_ENCRYPTION
  313. if (err != MZ_OK)
  314. return err;
  315. if (mz_zip_reader_entry_get_first_hash(handle, &reader->hash_algorithm, &reader->hash_digest_size) == MZ_OK)
  316. {
  317. mz_crypt_sha_create(&reader->hash);
  318. if (reader->hash_algorithm == MZ_HASH_SHA1)
  319. mz_crypt_sha_set_algorithm(reader->hash, MZ_HASH_SHA1);
  320. else if (reader->hash_algorithm == MZ_HASH_SHA256)
  321. mz_crypt_sha_set_algorithm(reader->hash, MZ_HASH_SHA256);
  322. else
  323. err = MZ_SUPPORT_ERROR;
  324. if (err == MZ_OK)
  325. mz_crypt_sha_begin(reader->hash);
  326. #ifdef MZ_ZIP_SIGNING
  327. if (err == MZ_OK)
  328. {
  329. if (mz_zip_reader_entry_has_sign(handle) == MZ_OK)
  330. {
  331. err = mz_zip_reader_entry_sign_verify(handle);
  332. if (err == MZ_OK)
  333. reader->entry_verified = 1;
  334. }
  335. else if (reader->sign_required && !reader->cd_verified)
  336. err = MZ_SIGN_ERROR;
  337. }
  338. #endif
  339. }
  340. else if (reader->sign_required && !reader->cd_verified)
  341. err = MZ_SIGN_ERROR;
  342. #endif
  343. return err;
  344. }
  345. int32_t mz_zip_reader_entry_close(void *handle)
  346. {
  347. mz_zip_reader *reader = (mz_zip_reader *)handle;
  348. int32_t err = MZ_OK;
  349. int32_t err_close = MZ_OK;
  350. #ifndef MZ_ZIP_NO_ENCRYPTION
  351. int32_t err_hash = MZ_OK;
  352. uint8_t computed_hash[MZ_HASH_MAX_SIZE];
  353. uint8_t expected_hash[MZ_HASH_MAX_SIZE];
  354. if (reader->hash != NULL)
  355. {
  356. mz_crypt_sha_end(reader->hash, computed_hash, sizeof(computed_hash));
  357. mz_crypt_sha_delete(&reader->hash);
  358. err_hash = mz_zip_reader_entry_get_hash(handle, reader->hash_algorithm, expected_hash,
  359. reader->hash_digest_size);
  360. if (err_hash == MZ_OK)
  361. {
  362. /* Verify expected hash against computed hash */
  363. if (memcmp(computed_hash, expected_hash, reader->hash_digest_size) != 0)
  364. err = MZ_CRC_ERROR;
  365. }
  366. }
  367. #endif
  368. err_close = mz_zip_entry_close(reader->zip_handle);
  369. if (err == MZ_OK)
  370. err = err_close;
  371. return err;
  372. }
  373. int32_t mz_zip_reader_entry_read(void *handle, void *buf, int32_t len)
  374. {
  375. mz_zip_reader *reader = (mz_zip_reader *)handle;
  376. int32_t read = 0;
  377. read = mz_zip_entry_read(reader->zip_handle, buf, len);
  378. #ifndef MZ_ZIP_NO_ENCRYPTION
  379. if ((read > 0) && (reader->hash != NULL))
  380. mz_crypt_sha_update(reader->hash, buf, read);
  381. #endif
  382. return read;
  383. }
  384. int32_t mz_zip_reader_entry_has_sign(void *handle)
  385. {
  386. mz_zip_reader *reader = (mz_zip_reader *)handle;
  387. if (reader == NULL || mz_zip_entry_is_open(reader->zip_handle) != MZ_OK)
  388. return MZ_PARAM_ERROR;
  389. return mz_zip_extrafield_contains(reader->file_info->extrafield,
  390. reader->file_info->extrafield_size, MZ_ZIP_EXTENSION_SIGN, NULL);
  391. }
  392. #if !defined(MZ_ZIP_NO_ENCRYPTION) && defined(MZ_ZIP_SIGNING)
  393. int32_t mz_zip_reader_entry_sign_verify(void *handle)
  394. {
  395. mz_zip_reader *reader = (mz_zip_reader *)handle;
  396. void *file_extra_stream = NULL;
  397. int32_t err = MZ_OK;
  398. uint8_t *signature = NULL;
  399. uint16_t signature_size = 0;
  400. uint8_t hash[MZ_HASH_MAX_SIZE];
  401. if (reader == NULL || mz_zip_entry_is_open(reader->zip_handle) != MZ_OK)
  402. return MZ_PARAM_ERROR;
  403. mz_stream_mem_create(&file_extra_stream);
  404. mz_stream_mem_set_buffer(file_extra_stream, (void *)reader->file_info->extrafield,
  405. reader->file_info->extrafield_size);
  406. err = mz_zip_extrafield_find(file_extra_stream, MZ_ZIP_EXTENSION_SIGN, &signature_size);
  407. if ((err == MZ_OK) && (signature_size > 0))
  408. {
  409. signature = (uint8_t *)MZ_ALLOC(signature_size);
  410. if (mz_stream_read(file_extra_stream, signature, signature_size) != signature_size)
  411. err = MZ_READ_ERROR;
  412. }
  413. mz_stream_mem_delete(&file_extra_stream);
  414. if (err == MZ_OK)
  415. {
  416. /* Get most secure hash to verify signature against */
  417. err = mz_zip_reader_entry_get_hash(handle, reader->hash_algorithm, hash, reader->hash_digest_size);
  418. }
  419. if (err == MZ_OK)
  420. {
  421. /* Verify the pkcs signature */
  422. err = mz_crypt_sign_verify(hash, reader->hash_digest_size, signature, signature_size);
  423. }
  424. if (signature != NULL)
  425. MZ_FREE(signature);
  426. return err;
  427. }
  428. #endif
  429. int32_t mz_zip_reader_entry_get_hash(void *handle, uint16_t algorithm, uint8_t *digest, int32_t digest_size)
  430. {
  431. mz_zip_reader *reader = (mz_zip_reader *)handle;
  432. void *file_extra_stream = NULL;
  433. int32_t err = MZ_OK;
  434. int32_t return_err = MZ_EXIST_ERROR;
  435. uint16_t cur_algorithm = 0;
  436. uint16_t cur_digest_size = 0;
  437. mz_stream_mem_create(&file_extra_stream);
  438. mz_stream_mem_set_buffer(file_extra_stream, (void *)reader->file_info->extrafield,
  439. reader->file_info->extrafield_size);
  440. do
  441. {
  442. err = mz_zip_extrafield_find(file_extra_stream, MZ_ZIP_EXTENSION_HASH, NULL);
  443. if (err != MZ_OK)
  444. break;
  445. err = mz_stream_read_uint16(file_extra_stream, &cur_algorithm);
  446. if (err == MZ_OK)
  447. err = mz_stream_read_uint16(file_extra_stream, &cur_digest_size);
  448. if ((err == MZ_OK) && (cur_algorithm == algorithm) && (cur_digest_size <= digest_size) &&
  449. (cur_digest_size <= MZ_HASH_MAX_SIZE))
  450. {
  451. /* Read hash digest */
  452. if (mz_stream_read(file_extra_stream, digest, digest_size) == cur_digest_size)
  453. return_err = MZ_OK;
  454. break;
  455. }
  456. else
  457. {
  458. err = mz_stream_seek(file_extra_stream, cur_digest_size, MZ_SEEK_CUR);
  459. }
  460. }
  461. while (err == MZ_OK);
  462. mz_stream_mem_delete(&file_extra_stream);
  463. return return_err;
  464. }
  465. int32_t mz_zip_reader_entry_get_first_hash(void *handle, uint16_t *algorithm, uint16_t *digest_size)
  466. {
  467. mz_zip_reader *reader = (mz_zip_reader *)handle;
  468. void *file_extra_stream = NULL;
  469. int32_t err = MZ_OK;
  470. uint16_t cur_algorithm = 0;
  471. uint16_t cur_digest_size = 0;
  472. if (reader == NULL || algorithm == NULL)
  473. return MZ_PARAM_ERROR;
  474. mz_stream_mem_create(&file_extra_stream);
  475. mz_stream_mem_set_buffer(file_extra_stream, (void *)reader->file_info->extrafield,
  476. reader->file_info->extrafield_size);
  477. err = mz_zip_extrafield_find(file_extra_stream, MZ_ZIP_EXTENSION_HASH, NULL);
  478. if (err == MZ_OK)
  479. err = mz_stream_read_uint16(file_extra_stream, &cur_algorithm);
  480. if (err == MZ_OK)
  481. err = mz_stream_read_uint16(file_extra_stream, &cur_digest_size);
  482. if (algorithm != NULL)
  483. *algorithm = cur_algorithm;
  484. if (digest_size != NULL)
  485. *digest_size = cur_digest_size;
  486. mz_stream_mem_delete(&file_extra_stream);
  487. return err;
  488. }
  489. int32_t mz_zip_reader_entry_get_info(void *handle, mz_zip_file **file_info)
  490. {
  491. mz_zip_reader *reader = (mz_zip_reader *)handle;
  492. int32_t err = MZ_OK;
  493. if (file_info == NULL || mz_zip_reader_is_open(handle) != MZ_OK)
  494. return MZ_PARAM_ERROR;
  495. *file_info = reader->file_info;
  496. if (*file_info == NULL)
  497. return MZ_EXIST_ERROR;
  498. return err;
  499. }
  500. int32_t mz_zip_reader_entry_is_dir(void *handle)
  501. {
  502. mz_zip_reader *reader = (mz_zip_reader *)handle;
  503. if (mz_zip_reader_is_open(handle) != MZ_OK)
  504. return MZ_PARAM_ERROR;
  505. return mz_zip_entry_is_dir(reader->zip_handle);
  506. }
  507. int32_t mz_zip_reader_entry_save_process(void *handle, void *stream, mz_stream_write_cb write_cb)
  508. {
  509. mz_zip_reader *reader = (mz_zip_reader *)handle;
  510. int32_t err = MZ_OK;
  511. int32_t read = 0;
  512. int32_t written = 0;
  513. if (mz_zip_reader_is_open(reader) != MZ_OK)
  514. return MZ_PARAM_ERROR;
  515. if (reader->file_info == NULL)
  516. return MZ_PARAM_ERROR;
  517. if (write_cb == NULL)
  518. return MZ_PARAM_ERROR;
  519. /* If the entry isn't open for reading, open it */
  520. if (mz_zip_entry_is_open(reader->zip_handle) != MZ_OK)
  521. err = mz_zip_reader_entry_open(handle);
  522. if (err != MZ_OK)
  523. return err;
  524. /* Unzip entry in zip file */
  525. read = mz_zip_reader_entry_read(handle, reader->buffer, sizeof(reader->buffer));
  526. if (read == 0)
  527. {
  528. /* If we are done close the entry */
  529. err = mz_zip_reader_entry_close(handle);
  530. if (err != MZ_OK)
  531. return err;
  532. return MZ_END_OF_STREAM;
  533. }
  534. if (read > 0)
  535. {
  536. /* Write the data to the specified stream */
  537. written = write_cb(stream, reader->buffer, read);
  538. if (written != read)
  539. return MZ_WRITE_ERROR;
  540. }
  541. return read;
  542. }
  543. int32_t mz_zip_reader_entry_save(void *handle, void *stream, mz_stream_write_cb write_cb)
  544. {
  545. mz_zip_reader *reader = (mz_zip_reader *)handle;
  546. uint64_t current_time = 0;
  547. uint64_t update_time = 0;
  548. int64_t current_pos = 0;
  549. int64_t update_pos = 0;
  550. int32_t err = MZ_OK;
  551. int32_t written = 0;
  552. if (mz_zip_reader_is_open(reader) != MZ_OK)
  553. return MZ_PARAM_ERROR;
  554. if (reader->file_info == NULL)
  555. return MZ_PARAM_ERROR;
  556. /* Update the progress at the beginning */
  557. if (reader->progress_cb != NULL)
  558. reader->progress_cb(handle, reader->progress_userdata, reader->file_info, current_pos);
  559. /* Write data to stream until done */
  560. while (err == MZ_OK)
  561. {
  562. written = mz_zip_reader_entry_save_process(handle, stream, write_cb);
  563. if (written == MZ_END_OF_STREAM)
  564. break;
  565. if (written > 0)
  566. current_pos += written;
  567. if (written < 0)
  568. err = written;
  569. /* Update progress if enough time have passed */
  570. current_time = mz_os_ms_time();
  571. if ((current_time - update_time) > reader->progress_cb_interval_ms)
  572. {
  573. if (reader->progress_cb != NULL)
  574. reader->progress_cb(handle, reader->progress_userdata, reader->file_info, current_pos);
  575. update_pos = current_pos;
  576. update_time = current_time;
  577. }
  578. }
  579. /* Update the progress at the end */
  580. if (reader->progress_cb != NULL && update_pos != current_pos)
  581. reader->progress_cb(handle, reader->progress_userdata, reader->file_info, current_pos);
  582. return err;
  583. }
  584. int32_t mz_zip_reader_entry_save_file(void *handle, const char *path)
  585. {
  586. mz_zip_reader *reader = (mz_zip_reader *)handle;
  587. void *stream = NULL;
  588. uint32_t target_attrib = 0;
  589. int32_t err_attrib = 0;
  590. int32_t err = MZ_OK;
  591. int32_t err_cb = MZ_OK;
  592. char pathwfs[512];
  593. char directory[512];
  594. if (mz_zip_reader_is_open(reader) != MZ_OK)
  595. return MZ_PARAM_ERROR;
  596. if (reader->file_info == NULL || path == NULL)
  597. return MZ_PARAM_ERROR;
  598. /* Convert to forward slashes for unix which doesn't like backslashes */
  599. strncpy(pathwfs, path, sizeof(pathwfs) - 1);
  600. pathwfs[sizeof(pathwfs) - 1] = 0;
  601. mz_path_convert_slashes(pathwfs, MZ_PATH_SLASH_UNIX);
  602. if (reader->entry_cb != NULL)
  603. reader->entry_cb(handle, reader->entry_userdata, reader->file_info, pathwfs);
  604. strncpy(directory, pathwfs, sizeof(directory) - 1);
  605. directory[sizeof(directory) - 1] = 0;
  606. mz_path_remove_filename(directory);
  607. /* If it is a directory entry then create a directory instead of writing file */
  608. if ((mz_zip_entry_is_dir(reader->zip_handle) == MZ_OK) &&
  609. (mz_zip_entry_is_symlink(reader->zip_handle) != MZ_OK))
  610. {
  611. err = mz_dir_make(directory);
  612. return err;
  613. }
  614. /* Check if file exists and ask if we want to overwrite */
  615. if ((mz_os_file_exists(pathwfs) == MZ_OK) && (reader->overwrite_cb != NULL))
  616. {
  617. err_cb = reader->overwrite_cb(handle, reader->overwrite_userdata, reader->file_info, pathwfs);
  618. if (err_cb != MZ_OK)
  619. return err;
  620. /* We want to overwrite the file so we delete the existing one */
  621. mz_os_unlink(pathwfs);
  622. }
  623. /* If symbolic link then properly construct destination path and link path */
  624. if (mz_zip_entry_is_symlink(reader->zip_handle) == MZ_OK)
  625. {
  626. mz_path_remove_slash(pathwfs);
  627. mz_path_remove_filename(directory);
  628. }
  629. /* Create the output directory if it doesn't already exist */
  630. if (mz_os_is_dir(directory) != MZ_OK)
  631. {
  632. err = mz_dir_make(directory);
  633. if (err != MZ_OK)
  634. return err;
  635. }
  636. /* If it is a symbolic link then create symbolic link instead of writing file */
  637. if (mz_zip_entry_is_symlink(reader->zip_handle) == MZ_OK)
  638. {
  639. mz_os_make_symlink(pathwfs, reader->file_info->linkname);
  640. /* Don't check return value because we aren't validating symbolic link target */
  641. return err;
  642. }
  643. /* Create the file on disk so we can save to it */
  644. mz_stream_os_create(&stream);
  645. err = mz_stream_os_open(stream, pathwfs, MZ_OPEN_MODE_CREATE);
  646. if (err == MZ_OK)
  647. err = mz_zip_reader_entry_save(handle, stream, mz_stream_write);
  648. mz_stream_close(stream);
  649. mz_stream_delete(&stream);
  650. if (err == MZ_OK)
  651. {
  652. /* Set the time of the file that has been created */
  653. mz_os_set_file_date(pathwfs, reader->file_info->modified_date,
  654. reader->file_info->accessed_date, reader->file_info->creation_date);
  655. }
  656. if (err == MZ_OK)
  657. {
  658. /* Set file attributes for the correct system */
  659. err_attrib = mz_zip_attrib_convert(MZ_HOST_SYSTEM(reader->file_info->version_madeby),
  660. reader->file_info->external_fa, MZ_VERSION_MADEBY_HOST_SYSTEM, &target_attrib);
  661. if (err_attrib == MZ_OK)
  662. mz_os_set_file_attribs(pathwfs, target_attrib);
  663. }
  664. return err;
  665. }
  666. int32_t mz_zip_reader_entry_save_buffer(void *handle, void *buf, int32_t len)
  667. {
  668. mz_zip_reader *reader = (mz_zip_reader *)handle;
  669. void *mem_stream = NULL;
  670. int32_t err = MZ_OK;
  671. if (mz_zip_reader_is_open(reader) != MZ_OK)
  672. return MZ_PARAM_ERROR;
  673. if (reader->file_info == NULL)
  674. return MZ_PARAM_ERROR;
  675. if (reader->file_info->uncompressed_size > INT32_MAX)
  676. return MZ_PARAM_ERROR;
  677. if (len != (int32_t)reader->file_info->uncompressed_size)
  678. return MZ_BUF_ERROR;
  679. /* Create a memory stream backed by our buffer and save to it */
  680. mz_stream_mem_create(&mem_stream);
  681. mz_stream_mem_set_buffer(mem_stream, buf, len);
  682. err = mz_stream_mem_open(mem_stream, NULL, MZ_OPEN_MODE_READ);
  683. if (err == MZ_OK)
  684. err = mz_zip_reader_entry_save(handle, mem_stream, mz_stream_mem_write);
  685. mz_stream_mem_delete(&mem_stream);
  686. return err;
  687. }
  688. int32_t mz_zip_reader_entry_save_buffer_length(void *handle)
  689. {
  690. mz_zip_reader *reader = (mz_zip_reader *)handle;
  691. if (mz_zip_reader_is_open(reader) != MZ_OK)
  692. return MZ_PARAM_ERROR;
  693. if (reader->file_info == NULL)
  694. return MZ_PARAM_ERROR;
  695. if (reader->file_info->uncompressed_size > INT32_MAX)
  696. return MZ_PARAM_ERROR;
  697. /* Get the maximum size required for the save buffer */
  698. return (int32_t)reader->file_info->uncompressed_size;
  699. }
  700. /***************************************************************************/
  701. int32_t mz_zip_reader_save_all(void *handle, const char *destination_dir)
  702. {
  703. mz_zip_reader *reader = (mz_zip_reader *)handle;
  704. int32_t err = MZ_OK;
  705. uint8_t *utf8_string = NULL;
  706. char path[512];
  707. char utf8_name[256];
  708. char resolved_name[256];
  709. err = mz_zip_reader_goto_first_entry(handle);
  710. if (err == MZ_END_OF_LIST)
  711. return err;
  712. while (err == MZ_OK)
  713. {
  714. /* Construct output path */
  715. path[0] = 0;
  716. strncpy(utf8_name, reader->file_info->filename, sizeof(utf8_name) - 1);
  717. utf8_name[sizeof(utf8_name) - 1] = 0;
  718. if ((reader->encoding > 0) && (reader->file_info->flag & MZ_ZIP_FLAG_UTF8) == 0)
  719. {
  720. utf8_string = mz_os_utf8_string_create(reader->file_info->filename, reader->encoding);
  721. if (utf8_string)
  722. {
  723. strncpy(utf8_name, (char *)utf8_string, sizeof(utf8_name) - 1);
  724. utf8_name[sizeof(utf8_name) - 1] = 0;
  725. mz_os_utf8_string_delete(&utf8_string);
  726. }
  727. }
  728. err = mz_path_resolve(utf8_name, resolved_name, sizeof(resolved_name));
  729. if (err != MZ_OK)
  730. break;
  731. if (destination_dir != NULL)
  732. mz_path_combine(path, destination_dir, sizeof(path));
  733. mz_path_combine(path, resolved_name, sizeof(path));
  734. /* Save file to disk */
  735. err = mz_zip_reader_entry_save_file(handle, path);
  736. if (err == MZ_OK)
  737. err = mz_zip_reader_goto_next_entry(handle);
  738. }
  739. if (err == MZ_END_OF_LIST)
  740. return MZ_OK;
  741. return err;
  742. }
  743. /***************************************************************************/
  744. void mz_zip_reader_set_pattern(void *handle, const char *pattern, uint8_t ignore_case)
  745. {
  746. mz_zip_reader *reader = (mz_zip_reader *)handle;
  747. reader->pattern = pattern;
  748. reader->pattern_ignore_case = ignore_case;
  749. }
  750. void mz_zip_reader_set_password(void *handle, const char *password)
  751. {
  752. mz_zip_reader *reader = (mz_zip_reader *)handle;
  753. reader->password = password;
  754. }
  755. void mz_zip_reader_set_raw(void *handle, uint8_t raw)
  756. {
  757. mz_zip_reader *reader = (mz_zip_reader *)handle;
  758. reader->raw = raw;
  759. }
  760. int32_t mz_zip_reader_get_raw(void *handle, uint8_t *raw)
  761. {
  762. mz_zip_reader *reader = (mz_zip_reader *)handle;
  763. if (raw == NULL)
  764. return MZ_PARAM_ERROR;
  765. *raw = reader->raw;
  766. return MZ_OK;
  767. }
  768. int32_t mz_zip_reader_get_zip_cd(void *handle, uint8_t *zip_cd)
  769. {
  770. mz_zip_reader *reader = (mz_zip_reader *)handle;
  771. if (zip_cd == NULL)
  772. return MZ_PARAM_ERROR;
  773. *zip_cd = reader->cd_zipped;
  774. return MZ_OK;
  775. }
  776. int32_t mz_zip_reader_get_comment(void *handle, const char **comment)
  777. {
  778. mz_zip_reader *reader = (mz_zip_reader *)handle;
  779. if (mz_zip_reader_is_open(reader) != MZ_OK)
  780. return MZ_PARAM_ERROR;
  781. if (comment == NULL)
  782. return MZ_PARAM_ERROR;
  783. return mz_zip_get_comment(reader->zip_handle, comment);
  784. }
  785. void mz_zip_reader_set_encoding(void *handle, int32_t encoding)
  786. {
  787. mz_zip_reader *reader = (mz_zip_reader *)handle;
  788. reader->encoding = encoding;
  789. }
  790. void mz_zip_reader_set_sign_required(void *handle, uint8_t sign_required)
  791. {
  792. mz_zip_reader *reader = (mz_zip_reader *)handle;
  793. reader->sign_required = sign_required;
  794. }
  795. void mz_zip_reader_set_overwrite_cb(void *handle, void *userdata, mz_zip_reader_overwrite_cb cb)
  796. {
  797. mz_zip_reader *reader = (mz_zip_reader *)handle;
  798. reader->overwrite_cb = cb;
  799. reader->overwrite_userdata = userdata;
  800. }
  801. void mz_zip_reader_set_password_cb(void *handle, void *userdata, mz_zip_reader_password_cb cb)
  802. {
  803. mz_zip_reader *reader = (mz_zip_reader *)handle;
  804. reader->password_cb = cb;
  805. reader->password_userdata = userdata;
  806. }
  807. void mz_zip_reader_set_progress_cb(void *handle, void *userdata, mz_zip_reader_progress_cb cb)
  808. {
  809. mz_zip_reader *reader = (mz_zip_reader *)handle;
  810. reader->progress_cb = cb;
  811. reader->progress_userdata = userdata;
  812. }
  813. void mz_zip_reader_set_progress_interval(void *handle, uint32_t milliseconds)
  814. {
  815. mz_zip_reader *reader = (mz_zip_reader *)handle;
  816. reader->progress_cb_interval_ms = milliseconds;
  817. }
  818. void mz_zip_reader_set_entry_cb(void *handle, void *userdata, mz_zip_reader_entry_cb cb)
  819. {
  820. mz_zip_reader *reader = (mz_zip_reader *)handle;
  821. reader->entry_cb = cb;
  822. reader->entry_userdata = userdata;
  823. }
  824. int32_t mz_zip_reader_get_zip_handle(void *handle, void **zip_handle)
  825. {
  826. mz_zip_reader *reader = (mz_zip_reader *)handle;
  827. if (zip_handle == NULL)
  828. return MZ_PARAM_ERROR;
  829. *zip_handle = reader->zip_handle;
  830. if (*zip_handle == NULL)
  831. return MZ_EXIST_ERROR;
  832. return MZ_OK;
  833. }
  834. /***************************************************************************/
  835. void *mz_zip_reader_create(void **handle)
  836. {
  837. mz_zip_reader *reader = NULL;
  838. reader = (mz_zip_reader *)MZ_ALLOC(sizeof(mz_zip_reader));
  839. if (reader != NULL)
  840. {
  841. memset(reader, 0, sizeof(mz_zip_reader));
  842. reader->progress_cb_interval_ms = MZ_DEFAULT_PROGRESS_INTERVAL;
  843. *handle = reader;
  844. }
  845. return reader;
  846. }
  847. void mz_zip_reader_delete(void **handle)
  848. {
  849. mz_zip_reader *reader = NULL;
  850. if (handle == NULL)
  851. return;
  852. reader = (mz_zip_reader *)*handle;
  853. if (reader != NULL)
  854. {
  855. mz_zip_reader_close(reader);
  856. MZ_FREE(reader);
  857. }
  858. *handle = NULL;
  859. }
  860. /***************************************************************************/
  861. typedef struct mz_zip_writer_s {
  862. void *zip_handle;
  863. void *file_stream;
  864. void *buffered_stream;
  865. void *split_stream;
  866. void *sha256;
  867. void *mem_stream;
  868. void *file_extra_stream;
  869. mz_zip_file file_info;
  870. void *overwrite_userdata;
  871. mz_zip_writer_overwrite_cb
  872. overwrite_cb;
  873. void *password_userdata;
  874. mz_zip_writer_password_cb
  875. password_cb;
  876. void *progress_userdata;
  877. mz_zip_writer_progress_cb
  878. progress_cb;
  879. uint32_t progress_cb_interval_ms;
  880. void *entry_userdata;
  881. mz_zip_writer_entry_cb
  882. entry_cb;
  883. const char *password;
  884. const char *comment;
  885. uint8_t *cert_data;
  886. int32_t cert_data_size;
  887. const char *cert_pwd;
  888. uint16_t compress_method;
  889. int16_t compress_level;
  890. uint8_t follow_links;
  891. uint8_t store_links;
  892. uint8_t zip_cd;
  893. uint8_t aes;
  894. uint8_t raw;
  895. uint8_t buffer[UINT16_MAX];
  896. } mz_zip_writer;
  897. /***************************************************************************/
  898. int32_t mz_zip_writer_zip_cd(void *handle)
  899. {
  900. mz_zip_writer *writer = (mz_zip_writer *)handle;
  901. mz_zip_file cd_file;
  902. uint64_t number_entry = 0;
  903. int64_t cd_mem_length = 0;
  904. int32_t err = MZ_OK;
  905. int32_t extrafield_size = 0;
  906. void *file_extra_stream = NULL;
  907. void *cd_mem_stream = NULL;
  908. memset(&cd_file, 0, sizeof(cd_file));
  909. mz_zip_get_number_entry(writer->zip_handle, &number_entry);
  910. mz_zip_get_cd_mem_stream(writer->zip_handle, &cd_mem_stream);
  911. mz_stream_seek(cd_mem_stream, 0, MZ_SEEK_END);
  912. cd_mem_length = (uint32_t)mz_stream_tell(cd_mem_stream);
  913. mz_stream_seek(cd_mem_stream, 0, MZ_SEEK_SET);
  914. cd_file.filename = MZ_ZIP_CD_FILENAME;
  915. cd_file.modified_date = time(NULL);
  916. cd_file.version_madeby = MZ_VERSION_MADEBY;
  917. cd_file.compression_method = writer->compress_method;
  918. cd_file.uncompressed_size = (int32_t)cd_mem_length;
  919. cd_file.flag = MZ_ZIP_FLAG_UTF8;
  920. if (writer->password != NULL)
  921. cd_file.flag |= MZ_ZIP_FLAG_ENCRYPTED;
  922. mz_stream_mem_create(&file_extra_stream);
  923. mz_stream_mem_open(file_extra_stream, NULL, MZ_OPEN_MODE_CREATE);
  924. mz_zip_extrafield_write(file_extra_stream, MZ_ZIP_EXTENSION_CDCD, 8);
  925. mz_stream_write_uint64(file_extra_stream, number_entry);
  926. mz_stream_mem_get_buffer(file_extra_stream, (const void **)&cd_file.extrafield);
  927. mz_stream_mem_get_buffer_length(file_extra_stream, &extrafield_size);
  928. cd_file.extrafield_size = (uint16_t)extrafield_size;
  929. err = mz_zip_writer_entry_open(handle, &cd_file);
  930. if (err == MZ_OK)
  931. {
  932. mz_stream_copy_stream(handle, mz_zip_writer_entry_write, cd_mem_stream,
  933. NULL, (int32_t)cd_mem_length);
  934. mz_stream_seek(cd_mem_stream, 0, MZ_SEEK_SET);
  935. mz_stream_mem_set_buffer_limit(cd_mem_stream, 0);
  936. err = mz_zip_writer_entry_close(writer);
  937. }
  938. mz_stream_mem_delete(&file_extra_stream);
  939. return err;
  940. }
  941. /***************************************************************************/
  942. int32_t mz_zip_writer_is_open(void *handle)
  943. {
  944. mz_zip_writer *writer = (mz_zip_writer *)handle;
  945. if (writer == NULL)
  946. return MZ_PARAM_ERROR;
  947. if (writer->zip_handle == NULL)
  948. return MZ_PARAM_ERROR;
  949. return MZ_OK;
  950. }
  951. static int32_t mz_zip_writer_open_int(void *handle, void *stream, int32_t mode)
  952. {
  953. mz_zip_writer *writer = (mz_zip_writer *)handle;
  954. int32_t err = MZ_OK;
  955. mz_zip_create(&writer->zip_handle);
  956. err = mz_zip_open(writer->zip_handle, stream, mode);
  957. if (err != MZ_OK)
  958. {
  959. mz_zip_writer_close(handle);
  960. return err;
  961. }
  962. return MZ_OK;
  963. }
  964. int32_t mz_zip_writer_open(void *handle, void *stream)
  965. {
  966. return mz_zip_writer_open_int(handle, stream, MZ_OPEN_MODE_WRITE);
  967. }
  968. int32_t mz_zip_writer_open_file(void *handle, const char *path, int64_t disk_size, uint8_t append)
  969. {
  970. mz_zip_writer *writer = (mz_zip_writer *)handle;
  971. int32_t mode = MZ_OPEN_MODE_READWRITE;
  972. int32_t err = MZ_OK;
  973. int32_t err_cb = 0;
  974. char directory[320];
  975. mz_zip_writer_close(handle);
  976. if (mz_os_file_exists(path) != MZ_OK)
  977. {
  978. /* If the file doesn't exist, we don't append file */
  979. mode |= MZ_OPEN_MODE_CREATE;
  980. /* Create destination directory if it doesn't already exist */
  981. if (strchr(path, '/') != NULL || strrchr(path, '\\') != NULL)
  982. {
  983. strncpy(directory, path, sizeof(directory));
  984. mz_path_remove_filename(directory);
  985. if (mz_os_file_exists(directory) != MZ_OK)
  986. mz_dir_make(directory);
  987. }
  988. }
  989. else if (append)
  990. {
  991. mode |= MZ_OPEN_MODE_APPEND;
  992. }
  993. else
  994. {
  995. if (writer->overwrite_cb != NULL)
  996. err_cb = writer->overwrite_cb(handle, writer->overwrite_userdata, path);
  997. if (err_cb == MZ_INTERNAL_ERROR)
  998. return err;
  999. if (err_cb == MZ_OK)
  1000. mode |= MZ_OPEN_MODE_CREATE;
  1001. else
  1002. mode |= MZ_OPEN_MODE_APPEND;
  1003. }
  1004. mz_stream_os_create(&writer->file_stream);
  1005. mz_stream_buffered_create(&writer->buffered_stream);
  1006. mz_stream_split_create(&writer->split_stream);
  1007. mz_stream_set_base(writer->buffered_stream, writer->file_stream);
  1008. mz_stream_set_base(writer->split_stream, writer->buffered_stream);
  1009. mz_stream_split_set_prop_int64(writer->split_stream, MZ_STREAM_PROP_DISK_SIZE, disk_size);
  1010. err = mz_stream_open(writer->split_stream, path, mode);
  1011. if (err == MZ_OK)
  1012. err = mz_zip_writer_open_int(handle, writer->split_stream, mode);
  1013. return err;
  1014. }
  1015. int32_t mz_zip_writer_open_file_in_memory(void *handle, const char *path)
  1016. {
  1017. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1018. void *file_stream = NULL;
  1019. int64_t file_size = 0;
  1020. int32_t err = 0;
  1021. mz_zip_writer_close(handle);
  1022. mz_stream_os_create(&file_stream);
  1023. err = mz_stream_os_open(file_stream, path, MZ_OPEN_MODE_READ);
  1024. if (err != MZ_OK)
  1025. {
  1026. mz_stream_os_delete(&file_stream);
  1027. mz_zip_writer_close(handle);
  1028. return err;
  1029. }
  1030. mz_stream_os_seek(file_stream, 0, MZ_SEEK_END);
  1031. file_size = mz_stream_os_tell(file_stream);
  1032. mz_stream_os_seek(file_stream, 0, MZ_SEEK_SET);
  1033. if ((file_size <= 0) || (file_size > UINT32_MAX))
  1034. {
  1035. /* Memory size is too large or too small */
  1036. mz_stream_os_close(file_stream);
  1037. mz_stream_os_delete(&file_stream);
  1038. mz_zip_writer_close(handle);
  1039. return MZ_MEM_ERROR;
  1040. }
  1041. mz_stream_mem_create(&writer->mem_stream);
  1042. mz_stream_mem_set_grow_size(writer->mem_stream, (int32_t)file_size);
  1043. mz_stream_mem_open(writer->mem_stream, NULL, MZ_OPEN_MODE_CREATE);
  1044. err = mz_stream_copy(writer->mem_stream, file_stream, (int32_t)file_size);
  1045. mz_stream_os_close(file_stream);
  1046. mz_stream_os_delete(&file_stream);
  1047. if (err == MZ_OK)
  1048. err = mz_zip_writer_open(handle, writer->mem_stream);
  1049. if (err != MZ_OK)
  1050. mz_zip_writer_close(handle);
  1051. return err;
  1052. }
  1053. int32_t mz_zip_writer_close(void *handle)
  1054. {
  1055. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1056. int32_t err = MZ_OK;
  1057. if (writer->zip_handle != NULL)
  1058. {
  1059. mz_zip_set_version_madeby(writer->zip_handle, MZ_VERSION_MADEBY);
  1060. if (writer->comment)
  1061. mz_zip_set_comment(writer->zip_handle, writer->comment);
  1062. if (writer->zip_cd)
  1063. mz_zip_writer_zip_cd(writer);
  1064. err = mz_zip_close(writer->zip_handle);
  1065. mz_zip_delete(&writer->zip_handle);
  1066. }
  1067. if (writer->split_stream != NULL)
  1068. {
  1069. mz_stream_split_close(writer->split_stream);
  1070. mz_stream_split_delete(&writer->split_stream);
  1071. }
  1072. if (writer->buffered_stream != NULL)
  1073. mz_stream_buffered_delete(&writer->buffered_stream);
  1074. if (writer->file_stream != NULL)
  1075. mz_stream_os_delete(&writer->file_stream);
  1076. if (writer->mem_stream != NULL)
  1077. {
  1078. mz_stream_mem_close(writer->mem_stream);
  1079. mz_stream_mem_delete(&writer->mem_stream);
  1080. }
  1081. return err;
  1082. }
  1083. /***************************************************************************/
  1084. int32_t mz_zip_writer_entry_open(void *handle, mz_zip_file *file_info)
  1085. {
  1086. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1087. int32_t err = MZ_OK;
  1088. const char *password = NULL;
  1089. char password_buf[120];
  1090. /* Copy file info to access data upon close */
  1091. memcpy(&writer->file_info, file_info, sizeof(mz_zip_file));
  1092. if (writer->entry_cb != NULL)
  1093. writer->entry_cb(handle, writer->entry_userdata, &writer->file_info);
  1094. password = writer->password;
  1095. /* Check if we need a password and ask for it if we need to */
  1096. if ((writer->file_info.flag & MZ_ZIP_FLAG_ENCRYPTED) && (password == NULL) &&
  1097. (writer->password_cb != NULL))
  1098. {
  1099. writer->password_cb(handle, writer->password_userdata, &writer->file_info,
  1100. password_buf, sizeof(password_buf));
  1101. password = password_buf;
  1102. }
  1103. #ifndef MZ_ZIP_NO_ENCRYPTION
  1104. if (mz_zip_attrib_is_dir(writer->file_info.external_fa, writer->file_info.version_madeby) != MZ_OK)
  1105. {
  1106. /* Start calculating sha256 */
  1107. mz_crypt_sha_create(&writer->sha256);
  1108. mz_crypt_sha_set_algorithm(writer->sha256, MZ_HASH_SHA256);
  1109. mz_crypt_sha_begin(writer->sha256);
  1110. }
  1111. #endif
  1112. /* Open entry in zip */
  1113. err = mz_zip_entry_write_open(writer->zip_handle, &writer->file_info, writer->compress_level,
  1114. writer->raw, password);
  1115. return err;
  1116. }
  1117. #if !defined(MZ_ZIP_NO_ENCRYPTION) && defined(MZ_ZIP_SIGNING)
  1118. int32_t mz_zip_writer_entry_sign(void *handle, uint8_t *message, int32_t message_size,
  1119. uint8_t *cert_data, int32_t cert_data_size, const char *cert_pwd)
  1120. {
  1121. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1122. int32_t err = MZ_OK;
  1123. int32_t signature_size = 0;
  1124. uint8_t *signature = NULL;
  1125. if (writer == NULL || cert_data == NULL || cert_data_size <= 0)
  1126. return MZ_PARAM_ERROR;
  1127. if (mz_zip_entry_is_open(writer->zip_handle) != MZ_OK)
  1128. return MZ_PARAM_ERROR;
  1129. /* Sign message with certificate */
  1130. err = mz_crypt_sign(message, message_size, cert_data, cert_data_size, cert_pwd,
  1131. &signature, &signature_size);
  1132. if ((err == MZ_OK) && (signature != NULL))
  1133. {
  1134. /* Write signature zip extra field */
  1135. err = mz_zip_extrafield_write(writer->file_extra_stream, MZ_ZIP_EXTENSION_SIGN,
  1136. (uint16_t)signature_size);
  1137. if (err == MZ_OK)
  1138. {
  1139. if (mz_stream_write(writer->file_extra_stream, signature, signature_size) != signature_size)
  1140. err = MZ_WRITE_ERROR;
  1141. }
  1142. MZ_FREE(signature);
  1143. }
  1144. return err;
  1145. }
  1146. #endif
  1147. int32_t mz_zip_writer_entry_close(void *handle)
  1148. {
  1149. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1150. int32_t err = MZ_OK;
  1151. #ifndef MZ_ZIP_NO_ENCRYPTION
  1152. const uint8_t *extrafield = NULL;
  1153. int32_t extrafield_size = 0;
  1154. int16_t field_length_hash = 0;
  1155. uint8_t sha256[MZ_HASH_SHA256_SIZE];
  1156. if (writer->sha256 != NULL)
  1157. {
  1158. mz_crypt_sha_end(writer->sha256, sha256, sizeof(sha256));
  1159. mz_crypt_sha_delete(&writer->sha256);
  1160. /* Copy extrafield so we can append our own fields before close */
  1161. mz_stream_mem_create(&writer->file_extra_stream);
  1162. mz_stream_mem_open(writer->file_extra_stream, NULL, MZ_OPEN_MODE_CREATE);
  1163. /* Write sha256 hash to extrafield */
  1164. field_length_hash = 4 + MZ_HASH_SHA256_SIZE;
  1165. err = mz_zip_extrafield_write(writer->file_extra_stream, MZ_ZIP_EXTENSION_HASH, field_length_hash);
  1166. if (err == MZ_OK)
  1167. err = mz_stream_write_uint16(writer->file_extra_stream, MZ_HASH_SHA256);
  1168. if (err == MZ_OK)
  1169. err = mz_stream_write_uint16(writer->file_extra_stream, MZ_HASH_SHA256_SIZE);
  1170. if (err == MZ_OK)
  1171. {
  1172. if (mz_stream_write(writer->file_extra_stream, sha256, sizeof(sha256)) != MZ_HASH_SHA256_SIZE)
  1173. err = MZ_WRITE_ERROR;
  1174. }
  1175. #ifdef MZ_ZIP_SIGNING
  1176. if ((err == MZ_OK) && (writer->cert_data != NULL) && (writer->cert_data_size > 0))
  1177. {
  1178. /* Sign entry if not zipping cd or if it is cd being zipped */
  1179. if (!writer->zip_cd || strcmp(writer->file_info.filename, MZ_ZIP_CD_FILENAME) == 0)
  1180. {
  1181. err = mz_zip_writer_entry_sign(handle, sha256, sizeof(sha256),
  1182. writer->cert_data, writer->cert_data_size, writer->cert_pwd);
  1183. }
  1184. }
  1185. #endif
  1186. if ((writer->file_info.extrafield != NULL) && (writer->file_info.extrafield_size > 0))
  1187. mz_stream_mem_write(writer->file_extra_stream, writer->file_info.extrafield,
  1188. writer->file_info.extrafield_size);
  1189. /* Update extra field for central directory after adding extra fields */
  1190. mz_stream_mem_get_buffer(writer->file_extra_stream, (const void **)&extrafield);
  1191. mz_stream_mem_get_buffer_length(writer->file_extra_stream, &extrafield_size);
  1192. mz_zip_entry_set_extrafield(writer->zip_handle, extrafield, (uint16_t)extrafield_size);
  1193. }
  1194. #endif
  1195. if (err == MZ_OK)
  1196. {
  1197. if (writer->raw)
  1198. err = mz_zip_entry_close_raw(writer->zip_handle, writer->file_info.uncompressed_size,
  1199. writer->file_info.crc);
  1200. else
  1201. err = mz_zip_entry_close(writer->zip_handle);
  1202. }
  1203. if (writer->file_extra_stream != NULL)
  1204. mz_stream_mem_delete(&writer->file_extra_stream);
  1205. return err;
  1206. }
  1207. int32_t mz_zip_writer_entry_write(void *handle, const void *buf, int32_t len)
  1208. {
  1209. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1210. int32_t written = 0;
  1211. written = mz_zip_entry_write(writer->zip_handle, buf, len);
  1212. #ifndef MZ_ZIP_NO_ENCRYPTION
  1213. if ((written > 0) && (writer->sha256 != NULL))
  1214. mz_crypt_sha_update(writer->sha256, buf, written);
  1215. #endif
  1216. return written;
  1217. }
  1218. /***************************************************************************/
  1219. int32_t mz_zip_writer_add_process(void *handle, void *stream, mz_stream_read_cb read_cb)
  1220. {
  1221. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1222. int32_t read = 0;
  1223. int32_t written = 0;
  1224. int32_t err = MZ_OK;
  1225. if (mz_zip_writer_is_open(writer) != MZ_OK)
  1226. return MZ_PARAM_ERROR;
  1227. /* If the entry isn't open for writing, open it */
  1228. if (mz_zip_entry_is_open(writer->zip_handle) != MZ_OK)
  1229. return MZ_PARAM_ERROR;
  1230. if (read_cb == NULL)
  1231. return MZ_PARAM_ERROR;
  1232. read = read_cb(stream, writer->buffer, sizeof(writer->buffer));
  1233. if (read == 0)
  1234. return MZ_END_OF_STREAM;
  1235. if (read < 0)
  1236. {
  1237. err = read;
  1238. return err;
  1239. }
  1240. written = mz_zip_writer_entry_write(handle, writer->buffer, read);
  1241. if (written != read)
  1242. return MZ_WRITE_ERROR;
  1243. return written;
  1244. }
  1245. int32_t mz_zip_writer_add(void *handle, void *stream, mz_stream_read_cb read_cb)
  1246. {
  1247. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1248. uint64_t current_time = 0;
  1249. uint64_t update_time = 0;
  1250. int64_t current_pos = 0;
  1251. int64_t update_pos = 0;
  1252. int32_t err = MZ_OK;
  1253. int32_t written = 0;
  1254. /* Update the progress at the beginning */
  1255. if (writer->progress_cb != NULL)
  1256. writer->progress_cb(handle, writer->progress_userdata, &writer->file_info, current_pos);
  1257. /* Write data to stream until done */
  1258. while (err == MZ_OK)
  1259. {
  1260. written = mz_zip_writer_add_process(handle, stream, read_cb);
  1261. if (written == MZ_END_OF_STREAM)
  1262. break;
  1263. if (written > 0)
  1264. current_pos += written;
  1265. if (written < 0)
  1266. err = written;
  1267. /* Update progress if enough time have passed */
  1268. current_time = mz_os_ms_time();
  1269. if ((current_time - update_time) > writer->progress_cb_interval_ms)
  1270. {
  1271. if (writer->progress_cb != NULL)
  1272. writer->progress_cb(handle, writer->progress_userdata, &writer->file_info, current_pos);
  1273. update_pos = current_pos;
  1274. update_time = current_time;
  1275. }
  1276. }
  1277. /* Update the progress at the end */
  1278. if (writer->progress_cb != NULL && update_pos != current_pos)
  1279. writer->progress_cb(handle, writer->progress_userdata, &writer->file_info, current_pos);
  1280. return err;
  1281. }
  1282. int32_t mz_zip_writer_add_info(void *handle, void *stream, mz_stream_read_cb read_cb, mz_zip_file *file_info)
  1283. {
  1284. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1285. int32_t err = MZ_OK;
  1286. if (mz_zip_writer_is_open(handle) != MZ_OK)
  1287. return MZ_PARAM_ERROR;
  1288. if (file_info == NULL)
  1289. return MZ_PARAM_ERROR;
  1290. /* Add to zip */
  1291. err = mz_zip_writer_entry_open(handle, file_info);
  1292. if (err != MZ_OK)
  1293. return err;
  1294. if (stream != NULL)
  1295. {
  1296. if (mz_zip_attrib_is_dir(writer->file_info.external_fa, writer->file_info.version_madeby) != MZ_OK)
  1297. {
  1298. err = mz_zip_writer_add(handle, stream, read_cb);
  1299. if (err != MZ_OK)
  1300. return err;
  1301. }
  1302. }
  1303. err = mz_zip_writer_entry_close(handle);
  1304. return err;
  1305. }
  1306. int32_t mz_zip_writer_add_buffer(void *handle, void *buf, int32_t len, mz_zip_file *file_info)
  1307. {
  1308. void *mem_stream = NULL;
  1309. int32_t err = MZ_OK;
  1310. if (mz_zip_writer_is_open(handle) != MZ_OK)
  1311. return MZ_PARAM_ERROR;
  1312. if (buf == NULL)
  1313. return MZ_PARAM_ERROR;
  1314. /* Create a memory stream backed by our buffer and add from it */
  1315. mz_stream_mem_create(&mem_stream);
  1316. mz_stream_mem_set_buffer(mem_stream, buf, len);
  1317. err = mz_stream_mem_open(mem_stream, NULL, MZ_OPEN_MODE_READ);
  1318. if (err == MZ_OK)
  1319. err = mz_zip_writer_add_info(handle, mem_stream, mz_stream_mem_read, file_info);
  1320. mz_stream_mem_delete(&mem_stream);
  1321. return err;
  1322. }
  1323. int32_t mz_zip_writer_add_file(void *handle, const char *path, const char *filename_in_zip)
  1324. {
  1325. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1326. mz_zip_file file_info;
  1327. uint32_t target_attrib = 0;
  1328. uint32_t src_attrib = 0;
  1329. int32_t err = MZ_OK;
  1330. uint8_t src_sys = 0;
  1331. void *stream = NULL;
  1332. char link_path[1024];
  1333. const char *filename = filename_in_zip;
  1334. if (mz_zip_writer_is_open(handle) != MZ_OK)
  1335. return MZ_PARAM_ERROR;
  1336. if (path == NULL)
  1337. return MZ_PARAM_ERROR;
  1338. if (filename == NULL)
  1339. {
  1340. err = mz_path_get_filename(path, &filename);
  1341. if (err != MZ_OK)
  1342. return err;
  1343. }
  1344. memset(&file_info, 0, sizeof(file_info));
  1345. /* The path name saved, should not include a leading slash. */
  1346. /* If it did, windows/xp and dynazip couldn't read the zip file. */
  1347. while (filename[0] == '\\' || filename[0] == '/')
  1348. filename += 1;
  1349. /* Get information about the file on disk so we can store it in zip */
  1350. file_info.version_madeby = MZ_VERSION_MADEBY;
  1351. file_info.compression_method = writer->compress_method;
  1352. file_info.filename = filename;
  1353. file_info.uncompressed_size = mz_os_get_file_size(path);
  1354. file_info.flag = MZ_ZIP_FLAG_UTF8;
  1355. if (writer->zip_cd)
  1356. file_info.flag |= MZ_ZIP_FLAG_MASK_LOCAL_INFO;
  1357. if (writer->aes)
  1358. file_info.aes_version = MZ_AES_VERSION;
  1359. mz_os_get_file_date(path, &file_info.modified_date, &file_info.accessed_date,
  1360. &file_info.creation_date);
  1361. mz_os_get_file_attribs(path, &src_attrib);
  1362. src_sys = MZ_HOST_SYSTEM(file_info.version_madeby);
  1363. if ((src_sys != MZ_HOST_SYSTEM_MSDOS) && (src_sys != MZ_HOST_SYSTEM_WINDOWS_NTFS))
  1364. {
  1365. /* High bytes are OS specific attributes, low byte is always DOS attributes */
  1366. if (mz_zip_attrib_convert(src_sys, src_attrib, MZ_HOST_SYSTEM_MSDOS, &target_attrib) == MZ_OK)
  1367. file_info.external_fa = target_attrib;
  1368. file_info.external_fa |= (src_attrib << 16);
  1369. }
  1370. else
  1371. {
  1372. file_info.external_fa = src_attrib;
  1373. }
  1374. if (writer->store_links && mz_os_is_symlink(path) == MZ_OK)
  1375. {
  1376. err = mz_os_read_symlink(path, link_path, sizeof(link_path));
  1377. if (err == MZ_OK)
  1378. file_info.linkname = link_path;
  1379. }
  1380. if (mz_os_is_dir(path) != MZ_OK)
  1381. {
  1382. mz_stream_os_create(&stream);
  1383. err = mz_stream_os_open(stream, path, MZ_OPEN_MODE_READ);
  1384. }
  1385. if (err == MZ_OK)
  1386. err = mz_zip_writer_add_info(handle, stream, mz_stream_read, &file_info);
  1387. if (stream != NULL)
  1388. {
  1389. mz_stream_close(stream);
  1390. mz_stream_delete(&stream);
  1391. }
  1392. return err;
  1393. }
  1394. int32_t mz_zip_writer_add_path(void *handle, const char *path, const char *root_path,
  1395. uint8_t include_path, uint8_t recursive)
  1396. {
  1397. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1398. DIR *dir = NULL;
  1399. struct dirent *entry = NULL;
  1400. int32_t err = MZ_OK;
  1401. int16_t is_dir = 0;
  1402. const char *filename = NULL;
  1403. const char *filenameinzip = path;
  1404. char *wildcard_ptr = NULL;
  1405. char full_path[1024];
  1406. char path_dir[1024];
  1407. if (strrchr(path, '*') != NULL)
  1408. {
  1409. strncpy(path_dir, path, sizeof(path_dir) - 1);
  1410. path_dir[sizeof(path_dir) - 1] = 0;
  1411. mz_path_remove_filename(path_dir);
  1412. wildcard_ptr = path_dir + strlen(path_dir) + 1;
  1413. root_path = path = path_dir;
  1414. }
  1415. else
  1416. {
  1417. if (mz_os_is_dir(path) == MZ_OK)
  1418. is_dir = 1;
  1419. /* Construct the filename that our file will be stored in the zip as */
  1420. if (root_path == NULL)
  1421. root_path = path;
  1422. /* Should the file be stored with any path info at all? */
  1423. if (!include_path)
  1424. {
  1425. if (!is_dir && root_path == path)
  1426. {
  1427. if (mz_path_get_filename(filenameinzip, &filename) == MZ_OK)
  1428. filenameinzip = filename;
  1429. }
  1430. else
  1431. {
  1432. filenameinzip += strlen(root_path);
  1433. }
  1434. }
  1435. if (!writer->store_links && !writer->follow_links)
  1436. {
  1437. if (mz_os_is_symlink(path) == MZ_OK)
  1438. return err;
  1439. }
  1440. if (*filenameinzip != 0)
  1441. err = mz_zip_writer_add_file(handle, path, filenameinzip);
  1442. if (!is_dir)
  1443. return err;
  1444. if (writer->store_links)
  1445. {
  1446. if (mz_os_is_symlink(path) == MZ_OK)
  1447. return err;
  1448. }
  1449. }
  1450. dir = mz_os_open_dir(path);
  1451. if (dir == NULL)
  1452. return MZ_EXIST_ERROR;
  1453. while ((entry = mz_os_read_dir(dir)) != NULL)
  1454. {
  1455. if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
  1456. continue;
  1457. full_path[0] = 0;
  1458. mz_path_combine(full_path, path, sizeof(full_path));
  1459. mz_path_combine(full_path, entry->d_name, sizeof(full_path));
  1460. if (!recursive && mz_os_is_dir(full_path) == MZ_OK)
  1461. continue;
  1462. if ((wildcard_ptr != NULL) && (mz_path_compare_wc(entry->d_name, wildcard_ptr, 1) != MZ_OK))
  1463. continue;
  1464. err = mz_zip_writer_add_path(handle, full_path, root_path, include_path, recursive);
  1465. if (err != MZ_OK)
  1466. return err;
  1467. }
  1468. mz_os_close_dir(dir);
  1469. return MZ_OK;
  1470. }
  1471. int32_t mz_zip_writer_copy_from_reader(void *handle, void *reader)
  1472. {
  1473. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1474. mz_zip_file *file_info = NULL;
  1475. int64_t compressed_size = 0;
  1476. int64_t uncompressed_size = 0;
  1477. uint32_t crc32 = 0;
  1478. int32_t err = MZ_OK;
  1479. uint8_t original_raw = 0;
  1480. void *reader_zip_handle = NULL;
  1481. void *writer_zip_handle = NULL;
  1482. if (mz_zip_reader_is_open(reader) != MZ_OK)
  1483. return MZ_PARAM_ERROR;
  1484. if (mz_zip_writer_is_open(writer) != MZ_OK)
  1485. return MZ_PARAM_ERROR;
  1486. err = mz_zip_reader_entry_get_info(reader, &file_info);
  1487. if (err != MZ_OK)
  1488. return err;
  1489. mz_zip_reader_get_zip_handle(reader, &reader_zip_handle);
  1490. mz_zip_writer_get_zip_handle(writer, &writer_zip_handle);
  1491. /* Open entry for raw reading */
  1492. err = mz_zip_entry_read_open(reader_zip_handle, 1, NULL);
  1493. if (err == MZ_OK)
  1494. {
  1495. /* Write entry raw, save original raw value */
  1496. original_raw = writer->raw;
  1497. writer->raw = 1;
  1498. err = mz_zip_writer_entry_open(writer, file_info);
  1499. if ((err == MZ_OK) &&
  1500. (mz_zip_attrib_is_dir(writer->file_info.external_fa, writer->file_info.version_madeby) != MZ_OK))
  1501. {
  1502. err = mz_zip_writer_add(writer, reader_zip_handle, mz_zip_entry_read);
  1503. }
  1504. if (err == MZ_OK)
  1505. {
  1506. err = mz_zip_entry_read_close(reader_zip_handle, &crc32, &compressed_size, &uncompressed_size);
  1507. if (err == MZ_OK)
  1508. err = mz_zip_entry_write_close(writer_zip_handle, crc32, compressed_size, uncompressed_size);
  1509. }
  1510. if (mz_zip_entry_is_open(reader_zip_handle) == MZ_OK)
  1511. mz_zip_entry_close(reader_zip_handle);
  1512. if (mz_zip_entry_is_open(writer_zip_handle) == MZ_OK)
  1513. mz_zip_entry_close(writer_zip_handle);
  1514. writer->raw = original_raw;
  1515. }
  1516. return err;
  1517. }
  1518. /***************************************************************************/
  1519. void mz_zip_writer_set_password(void *handle, const char *password)
  1520. {
  1521. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1522. writer->password = password;
  1523. }
  1524. void mz_zip_writer_set_comment(void *handle, const char *comment)
  1525. {
  1526. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1527. writer->comment = comment;
  1528. }
  1529. void mz_zip_writer_set_raw(void *handle, uint8_t raw)
  1530. {
  1531. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1532. writer->raw = raw;
  1533. }
  1534. int32_t mz_zip_writer_get_raw(void *handle, uint8_t *raw)
  1535. {
  1536. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1537. if (raw == NULL)
  1538. return MZ_PARAM_ERROR;
  1539. *raw = writer->raw;
  1540. return MZ_OK;
  1541. }
  1542. void mz_zip_writer_set_aes(void *handle, uint8_t aes)
  1543. {
  1544. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1545. writer->aes = aes;
  1546. }
  1547. void mz_zip_writer_set_compress_method(void *handle, uint16_t compress_method)
  1548. {
  1549. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1550. writer->compress_method = compress_method;
  1551. }
  1552. void mz_zip_writer_set_compress_level(void *handle, int16_t compress_level)
  1553. {
  1554. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1555. writer->compress_level = compress_level;
  1556. }
  1557. void mz_zip_writer_set_follow_links(void *handle, uint8_t follow_links)
  1558. {
  1559. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1560. writer->follow_links = follow_links;
  1561. }
  1562. void mz_zip_writer_set_store_links(void *handle, uint8_t store_links)
  1563. {
  1564. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1565. writer->store_links = store_links;
  1566. }
  1567. void mz_zip_writer_set_zip_cd(void *handle, uint8_t zip_cd)
  1568. {
  1569. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1570. writer->zip_cd = zip_cd;
  1571. }
  1572. int32_t mz_zip_writer_set_certificate(void *handle, const char *cert_path, const char *cert_pwd)
  1573. {
  1574. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1575. void *cert_stream = NULL;
  1576. uint8_t *cert_data = NULL;
  1577. int32_t cert_data_size = 0;
  1578. int32_t err = MZ_OK;
  1579. if (cert_path == NULL)
  1580. return MZ_PARAM_ERROR;
  1581. cert_data_size = (int32_t)mz_os_get_file_size(cert_path);
  1582. if (cert_data_size == 0)
  1583. return MZ_PARAM_ERROR;
  1584. if (writer->cert_data != NULL)
  1585. {
  1586. MZ_FREE(writer->cert_data);
  1587. writer->cert_data = NULL;
  1588. }
  1589. cert_data = (uint8_t *)MZ_ALLOC(cert_data_size);
  1590. /* Read pkcs12 certificate from disk */
  1591. mz_stream_os_create(&cert_stream);
  1592. err = mz_stream_os_open(cert_stream, cert_path, MZ_OPEN_MODE_READ);
  1593. if (err == MZ_OK)
  1594. {
  1595. if (mz_stream_os_read(cert_stream, cert_data, cert_data_size) != cert_data_size)
  1596. err = MZ_READ_ERROR;
  1597. mz_stream_os_close(cert_stream);
  1598. }
  1599. mz_stream_os_delete(&cert_stream);
  1600. if (err == MZ_OK)
  1601. {
  1602. writer->cert_data = cert_data;
  1603. writer->cert_data_size = cert_data_size;
  1604. writer->cert_pwd = cert_pwd;
  1605. }
  1606. else
  1607. {
  1608. MZ_FREE(cert_data);
  1609. }
  1610. return err;
  1611. }
  1612. void mz_zip_writer_set_overwrite_cb(void *handle, void *userdata, mz_zip_writer_overwrite_cb cb)
  1613. {
  1614. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1615. writer->overwrite_cb = cb;
  1616. writer->overwrite_userdata = userdata;
  1617. }
  1618. void mz_zip_writer_set_password_cb(void *handle, void *userdata, mz_zip_writer_password_cb cb)
  1619. {
  1620. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1621. writer->password_cb = cb;
  1622. writer->password_userdata = userdata;
  1623. }
  1624. void mz_zip_writer_set_progress_cb(void *handle, void *userdata, mz_zip_writer_progress_cb cb)
  1625. {
  1626. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1627. writer->progress_cb = cb;
  1628. writer->progress_userdata = userdata;
  1629. }
  1630. void mz_zip_writer_set_progress_interval(void *handle, uint32_t milliseconds)
  1631. {
  1632. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1633. writer->progress_cb_interval_ms = milliseconds;
  1634. }
  1635. void mz_zip_writer_set_entry_cb(void *handle, void *userdata, mz_zip_writer_entry_cb cb)
  1636. {
  1637. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1638. writer->entry_cb = cb;
  1639. writer->entry_userdata = userdata;
  1640. }
  1641. int32_t mz_zip_writer_get_zip_handle(void *handle, void **zip_handle)
  1642. {
  1643. mz_zip_writer *writer = (mz_zip_writer *)handle;
  1644. if (zip_handle == NULL)
  1645. return MZ_PARAM_ERROR;
  1646. *zip_handle = writer->zip_handle;
  1647. if (*zip_handle == NULL)
  1648. return MZ_EXIST_ERROR;
  1649. return MZ_OK;
  1650. }
  1651. /***************************************************************************/
  1652. void *mz_zip_writer_create(void **handle)
  1653. {
  1654. mz_zip_writer *writer = NULL;
  1655. writer = (mz_zip_writer *)MZ_ALLOC(sizeof(mz_zip_writer));
  1656. if (writer != NULL)
  1657. {
  1658. memset(writer, 0, sizeof(mz_zip_writer));
  1659. #if defined(HAVE_WZAES)
  1660. writer->aes = 1;
  1661. #endif
  1662. #if defined(HAVE_ZLIB) || defined(HAVE_LIBCOMP)
  1663. writer->compress_method = MZ_COMPRESS_METHOD_DEFLATE;
  1664. #elif defined(HAVE_BZIP2)
  1665. writer->compress_method = MZ_COMPRESS_METHOD_BZIP2;
  1666. #elif defined(HAVE_LZMA)
  1667. writer->compress_method = MZ_COMPRESS_METHOD_LZMA;
  1668. #else
  1669. writer->compress_method = MZ_COMPRESS_METHOD_STORE;
  1670. #endif
  1671. writer->compress_level = MZ_COMPRESS_LEVEL_BEST;
  1672. writer->progress_cb_interval_ms = MZ_DEFAULT_PROGRESS_INTERVAL;
  1673. *handle = writer;
  1674. }
  1675. return writer;
  1676. }
  1677. void mz_zip_writer_delete(void **handle)
  1678. {
  1679. mz_zip_writer *writer = NULL;
  1680. if (handle == NULL)
  1681. return;
  1682. writer = (mz_zip_writer *)*handle;
  1683. if (writer != NULL)
  1684. {
  1685. mz_zip_writer_close(writer);
  1686. if (writer->cert_data != NULL)
  1687. MZ_FREE(writer->cert_data);
  1688. writer->cert_data = NULL;
  1689. writer->cert_data_size = 0;
  1690. MZ_FREE(writer);
  1691. }
  1692. *handle = NULL;
  1693. }
  1694. /***************************************************************************/