php_zip.c 81 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | https://www.php.net/license/3_01.txt |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Author: Piere-Alain Joye <pierre@php.net> |
  14. +----------------------------------------------------------------------+
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #include "php.h"
  20. #include "php_ini.h"
  21. #include "ext/standard/info.h"
  22. #include "ext/standard/file.h"
  23. #include "ext/standard/php_string.h"
  24. #include "ext/pcre/php_pcre.h"
  25. #include "ext/standard/php_filestat.h"
  26. #include "zend_interfaces.h"
  27. #include "php_zip.h"
  28. #include "php_zip_arginfo.h"
  29. #ifdef HAVE_GLOB
  30. #ifndef PHP_WIN32
  31. #include <glob.h>
  32. #else
  33. #include "win32/glob.h"
  34. #endif
  35. #endif
  36. /* {{{ Resource le */
  37. static int le_zip_dir;
  38. #define le_zip_dir_name "Zip Directory"
  39. static int le_zip_entry;
  40. #define le_zip_entry_name "Zip Entry"
  41. /* }}} */
  42. /* {{{ PHP_ZIP_STAT_INDEX(za, index, flags, sb) */
  43. #define PHP_ZIP_STAT_INDEX(za, index, flags, sb) \
  44. if (zip_stat_index(za, index, flags, &sb) != 0) { \
  45. RETURN_FALSE; \
  46. }
  47. /* }}} */
  48. /* {{{ PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb)
  49. This is always used for the first argument*/
  50. #define PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) \
  51. if (path_len == 0) { \
  52. zend_argument_value_error(1, "cannot be empty"); \
  53. RETURN_THROWS(); \
  54. } \
  55. if (zip_stat(za, path, flags, &sb) != 0) { \
  56. RETURN_FALSE; \
  57. }
  58. /* }}} */
  59. /* {{{ PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) */
  60. #define PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) \
  61. if (comment_len == 0) { \
  62. /* Passing NULL remove the existing comment */ \
  63. if (zip_file_set_comment(za, index, NULL, 0, 0) < 0) { \
  64. RETURN_FALSE; \
  65. } \
  66. } else if (zip_file_set_comment(za, index, comment, comment_len, 0) < 0) { \
  67. RETURN_FALSE; \
  68. } \
  69. RETURN_TRUE;
  70. /* }}} */
  71. # define add_ascii_assoc_string add_assoc_string
  72. # define add_ascii_assoc_long add_assoc_long
  73. /* Flatten a path by making a relative path (to .)*/
  74. static char * php_zip_make_relative_path(char *path, size_t path_len) /* {{{ */
  75. {
  76. char *path_begin = path;
  77. size_t i;
  78. if (path_len < 1 || path == NULL) {
  79. return NULL;
  80. }
  81. if (IS_ABSOLUTE_PATH(path, path_len)) {
  82. return path + COPY_WHEN_ABSOLUTE(path) + 1;
  83. }
  84. i = path_len;
  85. while (1) {
  86. while (i > 0 && !IS_SLASH(path[i])) {
  87. i--;
  88. }
  89. if (!i) {
  90. return path;
  91. }
  92. if (i >= 2 && path[i -1] == '.') {
  93. /* i is the position of ., add 1 for / */
  94. path_begin = path + i + 1;
  95. break;
  96. }
  97. i--;
  98. }
  99. return path_begin;
  100. }
  101. /* }}} */
  102. # define CWD_STATE_ALLOC(l) emalloc(l)
  103. # define CWD_STATE_FREE(s) efree(s)
  104. /* {{{ php_zip_extract_file */
  105. static int php_zip_extract_file(struct zip * za, char *dest, char *file, size_t file_len)
  106. {
  107. php_stream_statbuf ssb;
  108. struct zip_file *zf;
  109. struct zip_stat sb;
  110. char b[8192];
  111. int n, ret;
  112. php_stream *stream;
  113. char *fullpath;
  114. char *file_dirname_fullpath;
  115. char file_dirname[MAXPATHLEN];
  116. size_t dir_len, len;
  117. int is_dir_only = 0;
  118. char *path_cleaned;
  119. size_t path_cleaned_len;
  120. cwd_state new_state;
  121. zend_string *file_basename;
  122. new_state.cwd = CWD_STATE_ALLOC(1);
  123. new_state.cwd[0] = '\0';
  124. new_state.cwd_length = 0;
  125. /* Clean/normlize the path and then transform any path (absolute or relative)
  126. to a path relative to cwd (../../mydir/foo.txt > mydir/foo.txt)
  127. */
  128. virtual_file_ex(&new_state, file, NULL, CWD_EXPAND);
  129. path_cleaned = php_zip_make_relative_path(new_state.cwd, new_state.cwd_length);
  130. if(!path_cleaned) {
  131. CWD_STATE_FREE(new_state.cwd);
  132. return 0;
  133. }
  134. path_cleaned_len = strlen(path_cleaned);
  135. if (path_cleaned_len >= MAXPATHLEN || zip_stat(za, file, 0, &sb) != 0) {
  136. CWD_STATE_FREE(new_state.cwd);
  137. return 0;
  138. }
  139. /* it is a directory only, see #40228 */
  140. if (path_cleaned_len > 1 && IS_SLASH(path_cleaned[path_cleaned_len - 1])) {
  141. len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, path_cleaned);
  142. is_dir_only = 1;
  143. } else {
  144. memcpy(file_dirname, path_cleaned, path_cleaned_len);
  145. dir_len = php_dirname(file_dirname, path_cleaned_len);
  146. if (!dir_len || (dir_len == 1 && file_dirname[0] == '.')) {
  147. len = spprintf(&file_dirname_fullpath, 0, "%s", dest);
  148. } else {
  149. len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file_dirname);
  150. }
  151. file_basename = php_basename(path_cleaned, path_cleaned_len, NULL, 0);
  152. if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname_fullpath)) {
  153. efree(file_dirname_fullpath);
  154. zend_string_release_ex(file_basename, 0);
  155. CWD_STATE_FREE(new_state.cwd);
  156. return 0;
  157. }
  158. }
  159. /* let see if the path already exists */
  160. if (php_stream_stat_path_ex(file_dirname_fullpath, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
  161. ret = php_stream_mkdir(file_dirname_fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE|REPORT_ERRORS, NULL);
  162. if (!ret) {
  163. efree(file_dirname_fullpath);
  164. if (!is_dir_only) {
  165. zend_string_release_ex(file_basename, 0);
  166. }
  167. CWD_STATE_FREE(new_state.cwd);
  168. return 0;
  169. }
  170. }
  171. /* it is a standalone directory, job done */
  172. if (is_dir_only) {
  173. efree(file_dirname_fullpath);
  174. CWD_STATE_FREE(new_state.cwd);
  175. return 1;
  176. }
  177. len = spprintf(&fullpath, 0, "%s/%s", file_dirname_fullpath, ZSTR_VAL(file_basename));
  178. if (!len) {
  179. efree(file_dirname_fullpath);
  180. zend_string_release_ex(file_basename, 0);
  181. CWD_STATE_FREE(new_state.cwd);
  182. return 0;
  183. } else if (len > MAXPATHLEN) {
  184. php_error_docref(NULL, E_WARNING, "Full extraction path exceed MAXPATHLEN (%i)", MAXPATHLEN);
  185. efree(file_dirname_fullpath);
  186. zend_string_release_ex(file_basename, 0);
  187. CWD_STATE_FREE(new_state.cwd);
  188. return 0;
  189. }
  190. /* check again the full path, not sure if it
  191. * is required, does a file can have a different
  192. * safemode status as its parent folder?
  193. */
  194. if (ZIP_OPENBASEDIR_CHECKPATH(fullpath)) {
  195. efree(fullpath);
  196. efree(file_dirname_fullpath);
  197. zend_string_release_ex(file_basename, 0);
  198. CWD_STATE_FREE(new_state.cwd);
  199. return 0;
  200. }
  201. zf = zip_fopen(za, file, 0);
  202. if (zf == NULL) {
  203. n = -1;
  204. goto done;
  205. }
  206. stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS, NULL);
  207. if (stream == NULL) {
  208. n = -1;
  209. zip_fclose(zf);
  210. goto done;
  211. }
  212. n = 0;
  213. while ((n=zip_fread(zf, b, sizeof(b))) > 0) {
  214. php_stream_write(stream, b, n);
  215. }
  216. if (stream->wrapper->wops->stream_metadata) {
  217. struct utimbuf ut;
  218. ut.modtime = ut.actime = sb.mtime;
  219. stream->wrapper->wops->stream_metadata(stream->wrapper, fullpath, PHP_STREAM_META_TOUCH, &ut, NULL);
  220. }
  221. php_stream_close(stream);
  222. n = zip_fclose(zf);
  223. done:
  224. efree(fullpath);
  225. zend_string_release_ex(file_basename, 0);
  226. efree(file_dirname_fullpath);
  227. CWD_STATE_FREE(new_state.cwd);
  228. if (n<0) {
  229. return 0;
  230. } else {
  231. return 1;
  232. }
  233. }
  234. /* }}} */
  235. static int php_zip_add_file(ze_zip_object *obj, const char *filename, size_t filename_len,
  236. char *entry_name, size_t entry_name_len, /* unused if replace >= 0 */
  237. zip_uint64_t offset_start, zip_uint64_t offset_len,
  238. zend_long replace, /* index to replace, add new file if < 0 */
  239. zip_flags_t flags
  240. ) /* {{{ */
  241. {
  242. struct zip_source *zs;
  243. char resolved_path[MAXPATHLEN];
  244. php_stream_statbuf ssb;
  245. if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
  246. return -1;
  247. }
  248. if (!expand_filepath(filename, resolved_path)) {
  249. php_error_docref(NULL, E_WARNING, "No such file or directory");
  250. return -1;
  251. }
  252. if (php_stream_stat_path_ex(resolved_path, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL)) {
  253. php_error_docref(NULL, E_WARNING, "No such file or directory");
  254. return -1;
  255. }
  256. zs = zip_source_file(obj->za, resolved_path, offset_start, offset_len);
  257. if (!zs) {
  258. return -1;
  259. }
  260. /* Replace */
  261. if (replace >= 0) {
  262. if (zip_file_replace(obj->za, replace, zs, flags) < 0) {
  263. zip_source_free(zs);
  264. return -1;
  265. }
  266. zip_error_clear(obj->za);
  267. return 1;
  268. }
  269. /* Add */
  270. obj->last_id = zip_file_add(obj->za, entry_name, zs, flags);
  271. if (obj->last_id < 0) {
  272. zip_source_free(zs);
  273. return -1;
  274. }
  275. zip_error_clear(obj->za);
  276. return 1;
  277. }
  278. /* }}} */
  279. typedef struct {
  280. zend_long remove_all_path;
  281. char *remove_path;
  282. size_t remove_path_len;
  283. char *add_path;
  284. size_t add_path_len;
  285. zip_flags_t flags;
  286. zip_int32_t comp_method;
  287. zip_uint32_t comp_flags;
  288. #ifdef HAVE_ENCRYPTION
  289. zip_int16_t enc_method;
  290. char *enc_password;
  291. #endif
  292. } zip_options;
  293. static int php_zip_parse_options(HashTable *options, zip_options *opts)
  294. /* {{{ */
  295. {
  296. zval *option;
  297. /* default values */
  298. memset(opts, 0, sizeof(zip_options));
  299. opts->flags = ZIP_FL_OVERWRITE;
  300. opts->comp_method = -1; /* -1 to not change default */
  301. #ifdef HAVE_ENCRYPTION
  302. opts->enc_method = -1; /* -1 to not change default */
  303. #endif
  304. if ((option = zend_hash_str_find(options, "remove_all_path", sizeof("remove_all_path") - 1)) != NULL) {
  305. if (Z_TYPE_P(option) != IS_FALSE && Z_TYPE_P(option) != IS_TRUE) {
  306. php_error_docref(NULL, E_WARNING, "Option \"remove_all_path\" must be of type bool, %s given",
  307. zend_zval_type_name(option));
  308. }
  309. opts->remove_all_path = zval_get_long(option);
  310. }
  311. if ((option = zend_hash_str_find(options, "comp_method", sizeof("comp_method") - 1)) != NULL) {
  312. if (Z_TYPE_P(option) != IS_LONG) {
  313. php_error_docref(NULL, E_WARNING, "Option \"comp_method\" must be of type int, %s given",
  314. zend_zval_type_name(option));
  315. }
  316. opts->comp_method = zval_get_long(option);
  317. if ((option = zend_hash_str_find(options, "comp_flags", sizeof("comp_flags") - 1)) != NULL) {
  318. if (Z_TYPE_P(option) != IS_LONG) {
  319. php_error_docref(NULL, E_WARNING, "Option \"comp_flags\" must be of type int, %s given",
  320. zend_zval_type_name(option));
  321. }
  322. opts->comp_flags = zval_get_long(option);
  323. }
  324. }
  325. #ifdef HAVE_ENCRYPTION
  326. if ((option = zend_hash_str_find(options, "enc_method", sizeof("enc_method") - 1)) != NULL) {
  327. if (Z_TYPE_P(option) != IS_LONG) {
  328. php_error_docref(NULL, E_WARNING, "Option \"enc_method\" must be of type int, %s given",
  329. zend_zval_type_name(option));
  330. }
  331. opts->enc_method = zval_get_long(option);
  332. if ((option = zend_hash_str_find(options, "enc_password", sizeof("enc_password") - 1)) != NULL) {
  333. if (Z_TYPE_P(option) != IS_STRING) {
  334. zend_type_error("Option \"enc_password\" must be of type string, %s given",
  335. zend_zval_type_name(option));
  336. return -1;
  337. }
  338. opts->enc_password = Z_STRVAL_P(option);
  339. }
  340. }
  341. #endif
  342. if ((option = zend_hash_str_find(options, "remove_path", sizeof("remove_path") - 1)) != NULL) {
  343. if (Z_TYPE_P(option) != IS_STRING) {
  344. zend_type_error("Option \"remove_path\" must be of type string, %s given",
  345. zend_zval_type_name(option));
  346. return -1;
  347. }
  348. if (Z_STRLEN_P(option) == 0) {
  349. zend_value_error("Option \"remove_path\" cannot be empty");
  350. return -1;
  351. }
  352. if (Z_STRLEN_P(option) >= MAXPATHLEN) {
  353. zend_value_error("Option \"remove_path\" must be less than %d bytes", MAXPATHLEN - 1);
  354. return -1;
  355. }
  356. opts->remove_path_len = Z_STRLEN_P(option);
  357. opts->remove_path = Z_STRVAL_P(option);
  358. }
  359. if ((option = zend_hash_str_find(options, "add_path", sizeof("add_path") - 1)) != NULL) {
  360. if (Z_TYPE_P(option) != IS_STRING) {
  361. zend_type_error("Option \"add_path\" must be of type string, %s given",
  362. zend_zval_type_name(option));
  363. return -1;
  364. }
  365. if (Z_STRLEN_P(option) == 0) {
  366. zend_value_error("Option \"add_path\" cannot be empty");
  367. return -1;
  368. }
  369. if (Z_STRLEN_P(option) >= MAXPATHLEN) {
  370. zend_value_error("Option \"add_path\" must be less than %d bytes", MAXPATHLEN - 1);
  371. return -1;
  372. }
  373. opts->add_path_len = Z_STRLEN_P(option);
  374. opts->add_path = Z_STRVAL_P(option);
  375. }
  376. if ((option = zend_hash_str_find(options, "flags", sizeof("flags") - 1)) != NULL) {
  377. if (Z_TYPE_P(option) != IS_LONG) {
  378. zend_type_error("Option \"flags\" must be of type int, %s given",
  379. zend_zval_type_name(option));
  380. return -1;
  381. }
  382. opts->flags = Z_LVAL_P(option);
  383. }
  384. return 1;
  385. }
  386. /* }}} */
  387. /* {{{ REGISTER_ZIP_CLASS_CONST_LONG */
  388. #define REGISTER_ZIP_CLASS_CONST_LONG(const_name, value) \
  389. zend_declare_class_constant_long(zip_class_entry, const_name, sizeof(const_name)-1, (zend_long)value);
  390. /* }}} */
  391. /* {{{ ZIP_FROM_OBJECT */
  392. #define ZIP_FROM_OBJECT(intern, object) \
  393. { \
  394. ze_zip_object *obj = Z_ZIP_P(object); \
  395. intern = obj->za; \
  396. if (!intern) { \
  397. zend_value_error("Invalid or uninitialized Zip object"); \
  398. RETURN_THROWS(); \
  399. } \
  400. }
  401. /* }}} */
  402. /* {{{ RETURN_SB(sb) */
  403. #ifdef HAVE_ENCRYPTION
  404. #define RETURN_SB(sb) \
  405. { \
  406. array_init(return_value); \
  407. add_ascii_assoc_string(return_value, "name", (char *)(sb)->name); \
  408. add_ascii_assoc_long(return_value, "index", (zend_long) (sb)->index); \
  409. add_ascii_assoc_long(return_value, "crc", (zend_long) (sb)->crc); \
  410. add_ascii_assoc_long(return_value, "size", (zend_long) (sb)->size); \
  411. add_ascii_assoc_long(return_value, "mtime", (zend_long) (sb)->mtime); \
  412. add_ascii_assoc_long(return_value, "comp_size", (zend_long) (sb)->comp_size); \
  413. add_ascii_assoc_long(return_value, "comp_method", (zend_long) (sb)->comp_method); \
  414. add_ascii_assoc_long(return_value, "encryption_method", (zend_long) (sb)->encryption_method); \
  415. }
  416. #else
  417. #define RETURN_SB(sb) \
  418. { \
  419. array_init(return_value); \
  420. add_ascii_assoc_string(return_value, "name", (char *)(sb)->name); \
  421. add_ascii_assoc_long(return_value, "index", (zend_long) (sb)->index); \
  422. add_ascii_assoc_long(return_value, "crc", (zend_long) (sb)->crc); \
  423. add_ascii_assoc_long(return_value, "size", (zend_long) (sb)->size); \
  424. add_ascii_assoc_long(return_value, "mtime", (zend_long) (sb)->mtime); \
  425. add_ascii_assoc_long(return_value, "comp_size", (zend_long) (sb)->comp_size); \
  426. add_ascii_assoc_long(return_value, "comp_method", (zend_long) (sb)->comp_method); \
  427. }
  428. #endif
  429. /* }}} */
  430. static zend_long php_zip_status(ze_zip_object *obj) /* {{{ */
  431. {
  432. int zep = obj->err_zip; /* saved err if closed */
  433. if (obj->za) {
  434. #if LIBZIP_VERSION_MAJOR < 1
  435. int syp;
  436. zip_error_get(obj->za, &zep, &syp);
  437. #else
  438. zip_error_t *err;
  439. err = zip_get_error(obj->za);
  440. zep = zip_error_code_zip(err);
  441. zip_error_fini(err);
  442. #endif
  443. }
  444. return zep;
  445. }
  446. /* }}} */
  447. static zend_long php_zip_last_id(ze_zip_object *obj) /* {{{ */
  448. {
  449. return obj->last_id;
  450. }
  451. /* }}} */
  452. static zend_long php_zip_status_sys(ze_zip_object *obj) /* {{{ */
  453. {
  454. int syp = obj->err_sys; /* saved err if closed */
  455. if (obj->za) {
  456. #if LIBZIP_VERSION_MAJOR < 1
  457. int zep;
  458. zip_error_get(obj->za, &zep, &syp);
  459. #else
  460. zip_error_t *err;
  461. err = zip_get_error(obj->za);
  462. syp = zip_error_code_system(err);
  463. zip_error_fini(err);
  464. #endif
  465. }
  466. return syp;
  467. }
  468. /* }}} */
  469. static zend_long php_zip_get_num_files(ze_zip_object *obj) /* {{{ */
  470. {
  471. if (obj->za) {
  472. zip_int64_t num = zip_get_num_entries(obj->za, 0);
  473. return MIN(num, ZEND_LONG_MAX);
  474. }
  475. return 0;
  476. }
  477. /* }}} */
  478. static char * php_zipobj_get_filename(ze_zip_object *obj, int *len) /* {{{ */
  479. {
  480. if (obj && obj->filename) {
  481. *len = strlen(obj->filename);
  482. return obj->filename;
  483. }
  484. return NULL;
  485. }
  486. /* }}} */
  487. static char * php_zipobj_get_zip_comment(ze_zip_object *obj, int *len) /* {{{ */
  488. {
  489. if (obj->za) {
  490. return (char *)zip_get_archive_comment(obj->za, len, 0);
  491. }
  492. return NULL;
  493. }
  494. /* }}} */
  495. #ifdef HAVE_GLOB /* {{{ */
  496. #ifndef GLOB_ONLYDIR
  497. #define GLOB_ONLYDIR (1<<30)
  498. #define GLOB_EMULATE_ONLYDIR
  499. #define GLOB_FLAGMASK (~GLOB_ONLYDIR)
  500. #else
  501. #define GLOB_FLAGMASK (~0)
  502. #endif
  503. #ifndef GLOB_BRACE
  504. # define GLOB_BRACE 0
  505. #endif
  506. #ifndef GLOB_MARK
  507. # define GLOB_MARK 0
  508. #endif
  509. #ifndef GLOB_NOSORT
  510. # define GLOB_NOSORT 0
  511. #endif
  512. #ifndef GLOB_NOCHECK
  513. # define GLOB_NOCHECK 0
  514. #endif
  515. #ifndef GLOB_NOESCAPE
  516. # define GLOB_NOESCAPE 0
  517. #endif
  518. #ifndef GLOB_ERR
  519. # define GLOB_ERR 0
  520. #endif
  521. /* This is used for checking validity of passed flags (passing invalid flags causes segfault in glob()!! */
  522. #define GLOB_AVAILABLE_FLAGS (0 | GLOB_BRACE | GLOB_MARK | GLOB_NOSORT | GLOB_NOCHECK | GLOB_NOESCAPE | GLOB_ERR | GLOB_ONLYDIR)
  523. #endif /* }}} */
  524. int php_zip_glob(char *pattern, int pattern_len, zend_long flags, zval *return_value) /* {{{ */
  525. {
  526. #ifdef HAVE_GLOB
  527. int cwd_skip = 0;
  528. #ifdef ZTS
  529. char cwd[MAXPATHLEN];
  530. char work_pattern[MAXPATHLEN];
  531. char *result;
  532. #endif
  533. glob_t globbuf;
  534. size_t n;
  535. int ret;
  536. if (pattern_len >= MAXPATHLEN) {
  537. php_error_docref(NULL, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN);
  538. return -1;
  539. }
  540. if ((GLOB_AVAILABLE_FLAGS & flags) != flags) {
  541. php_error_docref(NULL, E_WARNING, "At least one of the passed flags is invalid or not supported on this platform");
  542. return -1;
  543. }
  544. #ifdef ZTS
  545. if (!IS_ABSOLUTE_PATH(pattern, pattern_len)) {
  546. result = VCWD_GETCWD(cwd, MAXPATHLEN);
  547. if (!result) {
  548. cwd[0] = '\0';
  549. }
  550. #ifdef PHP_WIN32
  551. if (IS_SLASH(*pattern)) {
  552. cwd[2] = '\0';
  553. }
  554. #endif
  555. cwd_skip = strlen(cwd)+1;
  556. snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern);
  557. pattern = work_pattern;
  558. }
  559. #endif
  560. globbuf.gl_offs = 0;
  561. if (0 != (ret = glob(pattern, flags & GLOB_FLAGMASK, NULL, &globbuf))) {
  562. #ifdef GLOB_NOMATCH
  563. if (GLOB_NOMATCH == ret) {
  564. /* Some glob implementation simply return no data if no matches
  565. were found, others return the GLOB_NOMATCH error code.
  566. We don't want to treat GLOB_NOMATCH as an error condition
  567. so that PHP glob() behaves the same on both types of
  568. implementations and so that 'foreach (glob() as ...'
  569. can be used for simple glob() calls without further error
  570. checking.
  571. */
  572. array_init(return_value);
  573. return 0;
  574. }
  575. #endif
  576. return 0;
  577. }
  578. /* now catch the FreeBSD style of "no matches" */
  579. if (!globbuf.gl_pathc || !globbuf.gl_pathv) {
  580. array_init(return_value);
  581. return 0;
  582. }
  583. /* we assume that any glob pattern will match files from one directory only
  584. so checking the dirname of the first match should be sufficient */
  585. if (ZIP_OPENBASEDIR_CHECKPATH(globbuf.gl_pathv[0])) {
  586. return -1;
  587. }
  588. array_init(return_value);
  589. for (n = 0; n < globbuf.gl_pathc; n++) {
  590. /* we need to do this every time since GLOB_ONLYDIR does not guarantee that
  591. * all directories will be filtered. GNU libc documentation states the
  592. * following:
  593. * If the information about the type of the file is easily available
  594. * non-directories will be rejected but no extra work will be done to
  595. * determine the information for each file. I.e., the caller must still be
  596. * able to filter directories out.
  597. */
  598. if (flags & GLOB_ONLYDIR) {
  599. zend_stat_t s;
  600. if (0 != VCWD_STAT(globbuf.gl_pathv[n], &s)) {
  601. continue;
  602. }
  603. if (S_IFDIR != (s.st_mode & S_IFMT)) {
  604. continue;
  605. }
  606. }
  607. add_next_index_string(return_value, globbuf.gl_pathv[n]+cwd_skip);
  608. }
  609. ret = globbuf.gl_pathc;
  610. globfree(&globbuf);
  611. return ret;
  612. #else
  613. zend_throw_error(NULL, "Glob support is not available");
  614. return 0;
  615. #endif /* HAVE_GLOB */
  616. }
  617. /* }}} */
  618. int php_zip_pcre(zend_string *regexp, char *path, int path_len, zval *return_value) /* {{{ */
  619. {
  620. #ifdef ZTS
  621. char cwd[MAXPATHLEN];
  622. char work_path[MAXPATHLEN];
  623. char *result;
  624. #endif
  625. int files_cnt;
  626. zend_string **namelist;
  627. pcre2_match_context *mctx = php_pcre_mctx();
  628. #ifdef ZTS
  629. if (!IS_ABSOLUTE_PATH(path, path_len)) {
  630. result = VCWD_GETCWD(cwd, MAXPATHLEN);
  631. if (!result) {
  632. cwd[0] = '\0';
  633. }
  634. #ifdef PHP_WIN32
  635. if (IS_SLASH(*path)) {
  636. cwd[2] = '\0';
  637. }
  638. #endif
  639. snprintf(work_path, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, path);
  640. path = work_path;
  641. }
  642. #endif
  643. if (ZIP_OPENBASEDIR_CHECKPATH(path)) {
  644. return -1;
  645. }
  646. files_cnt = php_stream_scandir(path, &namelist, NULL, (void *) php_stream_dirent_alphasort);
  647. if (files_cnt > 0) {
  648. pcre2_code *re = NULL;
  649. pcre2_match_data *match_data = NULL;
  650. uint32_t i, capture_count;
  651. int rc;
  652. re = pcre_get_compiled_regex(regexp, &capture_count);
  653. if (!re) {
  654. php_error_docref(NULL, E_WARNING, "Invalid expression");
  655. return -1;
  656. }
  657. array_init(return_value);
  658. /* only the files, directories are ignored */
  659. for (i = 0; i < files_cnt; i++) {
  660. zend_stat_t s;
  661. char fullpath[MAXPATHLEN];
  662. size_t namelist_len = ZSTR_LEN(namelist[i]);
  663. if ((namelist_len == 1 && ZSTR_VAL(namelist[i])[0] == '.') ||
  664. (namelist_len == 2 && ZSTR_VAL(namelist[i])[0] == '.' && ZSTR_VAL(namelist[i])[1] == '.')) {
  665. zend_string_release_ex(namelist[i], 0);
  666. continue;
  667. }
  668. if ((path_len + namelist_len + 1) >= MAXPATHLEN) {
  669. php_error_docref(NULL, E_WARNING, "add_path string too long (max: %u, %zu given)",
  670. MAXPATHLEN - 1, (path_len + namelist_len + 1));
  671. zend_string_release_ex(namelist[i], 0);
  672. break;
  673. }
  674. match_data = php_pcre_create_match_data(capture_count, re);
  675. if (!match_data) {
  676. /* Allocation failed, but can proceed to the next pattern. */
  677. zend_string_release_ex(namelist[i], 0);
  678. continue;
  679. }
  680. rc = pcre2_match(re, (PCRE2_SPTR)ZSTR_VAL(namelist[i]), ZSTR_LEN(namelist[i]), 0, 0, match_data, mctx);
  681. php_pcre_free_match_data(match_data);
  682. /* 0 means that the vector is too small to hold all the captured substring offsets */
  683. if (rc < 0) {
  684. zend_string_release_ex(namelist[i], 0);
  685. continue;
  686. }
  687. snprintf(fullpath, MAXPATHLEN, "%s%c%s", path, DEFAULT_SLASH, ZSTR_VAL(namelist[i]));
  688. if (0 != VCWD_STAT(fullpath, &s)) {
  689. php_error_docref(NULL, E_WARNING, "Cannot read <%s>", fullpath);
  690. zend_string_release_ex(namelist[i], 0);
  691. continue;
  692. }
  693. if (S_IFDIR == (s.st_mode & S_IFMT)) {
  694. zend_string_release_ex(namelist[i], 0);
  695. continue;
  696. }
  697. add_next_index_string(return_value, fullpath);
  698. zend_string_release_ex(namelist[i], 0);
  699. }
  700. efree(namelist);
  701. }
  702. return files_cnt;
  703. }
  704. /* }}} */
  705. /* {{{ ZE2 OO definitions */
  706. static zend_class_entry *zip_class_entry;
  707. static zend_object_handlers zip_object_handlers;
  708. static HashTable zip_prop_handlers;
  709. typedef zend_long (*zip_read_int_t)(ze_zip_object *obj);
  710. typedef char *(*zip_read_const_char_t)(ze_zip_object *obj, int *len);
  711. typedef struct _zip_prop_handler {
  712. zip_read_int_t read_int_func;
  713. zip_read_const_char_t read_const_char_func;
  714. int type;
  715. } zip_prop_handler;
  716. /* }}} */
  717. static void php_zip_register_prop_handler(HashTable *prop_handler, char *name, zip_read_int_t read_int_func, zip_read_const_char_t read_char_func, int rettype) /* {{{ */
  718. {
  719. zip_prop_handler hnd;
  720. zend_string *str;
  721. hnd.read_const_char_func = read_char_func;
  722. hnd.read_int_func = read_int_func;
  723. hnd.type = rettype;
  724. str = zend_string_init_interned(name, strlen(name), 1);
  725. zend_hash_add_mem(prop_handler, str, &hnd, sizeof(zip_prop_handler));
  726. zend_string_release_ex(str, 1);
  727. }
  728. /* }}} */
  729. static zval *php_zip_property_reader(ze_zip_object *obj, zip_prop_handler *hnd, zval *rv) /* {{{ */
  730. {
  731. const char *retchar = NULL;
  732. zend_long retint = 0;
  733. int len = 0;
  734. if (hnd->read_const_char_func) {
  735. retchar = hnd->read_const_char_func(obj, &len);
  736. } else if (hnd->read_int_func) {
  737. retint = hnd->read_int_func(obj);
  738. }
  739. switch (hnd->type) {
  740. case IS_STRING:
  741. if (retchar) {
  742. ZVAL_STRINGL(rv, (char *) retchar, len);
  743. } else {
  744. ZVAL_EMPTY_STRING(rv);
  745. }
  746. break;
  747. case IS_LONG:
  748. ZVAL_LONG(rv, retint);
  749. break;
  750. default:
  751. ZVAL_NULL(rv);
  752. }
  753. return rv;
  754. }
  755. /* }}} */
  756. static zval *php_zip_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot) /* {{{ */
  757. {
  758. ze_zip_object *obj;
  759. zval *retval = NULL;
  760. zip_prop_handler *hnd = NULL;
  761. obj = php_zip_fetch_object(object);
  762. if (obj->prop_handler != NULL) {
  763. hnd = zend_hash_find_ptr(obj->prop_handler, name);
  764. }
  765. if (hnd == NULL) {
  766. retval = zend_std_get_property_ptr_ptr(object, name, type, cache_slot);
  767. }
  768. return retval;
  769. }
  770. /* }}} */
  771. static zval *php_zip_write_property(zend_object *object, zend_string *name, zval *value, void **cache_slot)
  772. {
  773. ze_zip_object *obj;
  774. zip_prop_handler *hnd = NULL;
  775. obj = php_zip_fetch_object(object);
  776. if (obj->prop_handler != NULL) {
  777. hnd = zend_hash_find_ptr(obj->prop_handler, name);
  778. }
  779. if (hnd != NULL) {
  780. zend_throw_error(NULL, "Cannot write read-only property %s::$%s", ZSTR_VAL(object->ce->name), ZSTR_VAL(name));
  781. return &EG(error_zval);
  782. }
  783. return zend_std_write_property(object, name, value, cache_slot);
  784. }
  785. static zval *php_zip_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv) /* {{{ */
  786. {
  787. ze_zip_object *obj;
  788. zval *retval = NULL;
  789. zip_prop_handler *hnd = NULL;
  790. obj = php_zip_fetch_object(object);
  791. if (obj->prop_handler != NULL) {
  792. hnd = zend_hash_find_ptr(obj->prop_handler, name);
  793. }
  794. if (hnd != NULL) {
  795. retval = php_zip_property_reader(obj, hnd, rv);
  796. if (retval == NULL) {
  797. retval = &EG(uninitialized_zval);
  798. }
  799. } else {
  800. retval = zend_std_read_property(object, name, type, cache_slot, rv);
  801. }
  802. return retval;
  803. }
  804. /* }}} */
  805. static int php_zip_has_property(zend_object *object, zend_string *name, int type, void **cache_slot) /* {{{ */
  806. {
  807. ze_zip_object *obj;
  808. zip_prop_handler *hnd = NULL;
  809. int retval = 0;
  810. obj = php_zip_fetch_object(object);
  811. if (obj->prop_handler != NULL) {
  812. hnd = zend_hash_find_ptr(obj->prop_handler, name);
  813. }
  814. if (hnd != NULL) {
  815. zval tmp, *prop;
  816. if (type == 2) {
  817. retval = 1;
  818. } else if ((prop = php_zip_property_reader(obj, hnd, &tmp)) != NULL) {
  819. if (type == 1) {
  820. retval = zend_is_true(&tmp);
  821. } else if (type == 0) {
  822. retval = (Z_TYPE(tmp) != IS_NULL);
  823. }
  824. }
  825. zval_ptr_dtor(&tmp);
  826. } else {
  827. retval = zend_std_has_property(object, name, type, cache_slot);
  828. }
  829. return retval;
  830. }
  831. /* }}} */
  832. static HashTable *php_zip_get_gc(zend_object *object, zval **gc_data, int *gc_data_count) /* {{{ */
  833. {
  834. *gc_data = NULL;
  835. *gc_data_count = 0;
  836. return zend_std_get_properties(object);
  837. }
  838. /* }}} */
  839. static HashTable *php_zip_get_properties(zend_object *object)/* {{{ */
  840. {
  841. ze_zip_object *obj;
  842. HashTable *props;
  843. zip_prop_handler *hnd;
  844. zend_string *key;
  845. obj = php_zip_fetch_object(object);
  846. props = zend_std_get_properties(object);
  847. if (obj->prop_handler == NULL) {
  848. return NULL;
  849. }
  850. ZEND_HASH_FOREACH_STR_KEY_PTR(obj->prop_handler, key, hnd) {
  851. zval *ret, val;
  852. ret = php_zip_property_reader(obj, hnd, &val);
  853. if (ret == NULL) {
  854. ret = &EG(uninitialized_zval);
  855. }
  856. zend_hash_update(props, key, ret);
  857. } ZEND_HASH_FOREACH_END();
  858. return props;
  859. }
  860. /* }}} */
  861. #ifdef HAVE_PROGRESS_CALLBACK
  862. static void _php_zip_progress_callback_free(void *ptr)
  863. {
  864. ze_zip_object *obj = ptr;
  865. if (!Z_ISUNDEF(obj->progress_callback)) {
  866. zval_ptr_dtor(&obj->progress_callback);
  867. ZVAL_UNDEF(&obj->progress_callback);
  868. }
  869. }
  870. #endif
  871. #ifdef HAVE_CANCEL_CALLBACK
  872. static void _php_zip_cancel_callback_free(void *ptr)
  873. {
  874. ze_zip_object *obj = ptr;
  875. if (!Z_ISUNDEF(obj->cancel_callback)) {
  876. zval_ptr_dtor(&obj->cancel_callback);
  877. ZVAL_UNDEF(&obj->cancel_callback);
  878. }
  879. }
  880. #endif
  881. static void php_zip_object_free_storage(zend_object *object) /* {{{ */
  882. {
  883. ze_zip_object * intern = php_zip_fetch_object(object);
  884. int i;
  885. if (!intern) {
  886. return;
  887. }
  888. if (intern->za) {
  889. if (zip_close(intern->za) != 0) {
  890. php_error_docref(NULL, E_WARNING, "Cannot destroy the zip context: %s", zip_strerror(intern->za));
  891. zip_discard(intern->za);
  892. }
  893. }
  894. if (intern->buffers_cnt>0) {
  895. for (i=0; i<intern->buffers_cnt; i++) {
  896. efree(intern->buffers[i]);
  897. }
  898. efree(intern->buffers);
  899. }
  900. #ifdef HAVE_PROGRESS_CALLBACK
  901. /* if not properly called by libzip */
  902. _php_zip_progress_callback_free(intern);
  903. #endif
  904. #ifdef HAVE_CANCEL_CALLBACK
  905. /* if not properly called by libzip */
  906. _php_zip_cancel_callback_free(intern);
  907. #endif
  908. intern->za = NULL;
  909. zend_object_std_dtor(&intern->zo);
  910. if (intern->filename) {
  911. efree(intern->filename);
  912. }
  913. }
  914. /* }}} */
  915. static zend_object *php_zip_object_new(zend_class_entry *class_type) /* {{{ */
  916. {
  917. ze_zip_object *intern;
  918. intern = zend_object_alloc(sizeof(ze_zip_object), class_type);
  919. intern->prop_handler = &zip_prop_handlers;
  920. zend_object_std_init(&intern->zo, class_type);
  921. object_properties_init(&intern->zo, class_type);
  922. intern->zo.handlers = &zip_object_handlers;
  923. intern->last_id = -1;
  924. return &intern->zo;
  925. }
  926. /* }}} */
  927. /* {{{ Resource dtors */
  928. /* {{{ php_zip_free_dir */
  929. static void php_zip_free_dir(zend_resource *rsrc)
  930. {
  931. zip_rsrc * zip_int = (zip_rsrc *) rsrc->ptr;
  932. if (zip_int) {
  933. if (zip_int->za) {
  934. if (zip_close(zip_int->za) != 0) {
  935. php_error_docref(NULL, E_WARNING, "Cannot destroy the zip context");
  936. }
  937. zip_int->za = NULL;
  938. }
  939. efree(rsrc->ptr);
  940. rsrc->ptr = NULL;
  941. }
  942. }
  943. /* }}} */
  944. /* {{{ php_zip_free_entry */
  945. static void php_zip_free_entry(zend_resource *rsrc)
  946. {
  947. zip_read_rsrc *zr_rsrc = (zip_read_rsrc *) rsrc->ptr;
  948. if (zr_rsrc) {
  949. if (zr_rsrc->zf) {
  950. zip_fclose(zr_rsrc->zf);
  951. zr_rsrc->zf = NULL;
  952. }
  953. efree(zr_rsrc);
  954. rsrc->ptr = NULL;
  955. }
  956. }
  957. /* }}} */
  958. /* }}}*/
  959. /* reset macro */
  960. /* {{{ function prototypes */
  961. static PHP_MINIT_FUNCTION(zip);
  962. static PHP_MSHUTDOWN_FUNCTION(zip);
  963. static PHP_MINFO_FUNCTION(zip);
  964. /* }}} */
  965. /* {{{ zip_module_entry */
  966. zend_module_entry zip_module_entry = {
  967. STANDARD_MODULE_HEADER,
  968. "zip",
  969. ext_functions,
  970. PHP_MINIT(zip),
  971. PHP_MSHUTDOWN(zip),
  972. NULL,
  973. NULL,
  974. PHP_MINFO(zip),
  975. PHP_ZIP_VERSION,
  976. STANDARD_MODULE_PROPERTIES
  977. };
  978. /* }}} */
  979. #ifdef COMPILE_DL_ZIP
  980. ZEND_GET_MODULE(zip)
  981. #endif
  982. /* set macro */
  983. /* {{{ Create new zip using source uri for output */
  984. PHP_FUNCTION(zip_open)
  985. {
  986. char resolved_path[MAXPATHLEN + 1];
  987. zip_rsrc *rsrc_int;
  988. int err = 0;
  989. zend_string *filename;
  990. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &filename) == FAILURE) {
  991. RETURN_THROWS();
  992. }
  993. if (ZSTR_LEN(filename) == 0) {
  994. zend_argument_value_error(1, "cannot be empty");
  995. RETURN_THROWS();
  996. }
  997. if (ZIP_OPENBASEDIR_CHECKPATH(ZSTR_VAL(filename))) {
  998. RETURN_FALSE;
  999. }
  1000. if(!expand_filepath(ZSTR_VAL(filename), resolved_path)) {
  1001. php_error_docref(NULL, E_WARNING, "No such file or directory");
  1002. RETURN_FALSE;
  1003. }
  1004. rsrc_int = (zip_rsrc *)emalloc(sizeof(zip_rsrc));
  1005. rsrc_int->za = zip_open(resolved_path, 0, &err);
  1006. if (rsrc_int->za == NULL) {
  1007. efree(rsrc_int);
  1008. RETURN_LONG((zend_long)err);
  1009. }
  1010. rsrc_int->index_current = 0;
  1011. rsrc_int->num_files = zip_get_num_entries(rsrc_int->za, 0);
  1012. RETURN_RES(zend_register_resource(rsrc_int, le_zip_dir));
  1013. }
  1014. /* }}} */
  1015. /* {{{ Close a Zip archive */
  1016. PHP_FUNCTION(zip_close)
  1017. {
  1018. zval * zip;
  1019. zip_rsrc *z_rsrc = NULL;
  1020. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip) == FAILURE) {
  1021. RETURN_THROWS();
  1022. }
  1023. if ((z_rsrc = (zip_rsrc *)zend_fetch_resource(Z_RES_P(zip), le_zip_dir_name, le_zip_dir)) == NULL) {
  1024. RETURN_THROWS();
  1025. }
  1026. /* really close the zip will break BC :-D */
  1027. zend_list_close(Z_RES_P(zip));
  1028. }
  1029. /* }}} */
  1030. /* {{{ Returns the next file in the archive */
  1031. PHP_FUNCTION(zip_read)
  1032. {
  1033. zval *zip_dp;
  1034. zip_read_rsrc *zr_rsrc;
  1035. int ret;
  1036. zip_rsrc *rsrc_int;
  1037. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip_dp) == FAILURE) {
  1038. RETURN_THROWS();
  1039. }
  1040. if ((rsrc_int = (zip_rsrc *)zend_fetch_resource(Z_RES_P(zip_dp), le_zip_dir_name, le_zip_dir)) == NULL) {
  1041. RETURN_THROWS();
  1042. }
  1043. if (rsrc_int && rsrc_int->za) {
  1044. if (rsrc_int->index_current >= rsrc_int->num_files) {
  1045. RETURN_FALSE;
  1046. }
  1047. zr_rsrc = emalloc(sizeof(zip_read_rsrc));
  1048. ret = zip_stat_index(rsrc_int->za, rsrc_int->index_current, 0, &zr_rsrc->sb);
  1049. if (ret != 0) {
  1050. efree(zr_rsrc);
  1051. RETURN_FALSE;
  1052. }
  1053. zr_rsrc->zf = zip_fopen_index(rsrc_int->za, rsrc_int->index_current, 0);
  1054. if (zr_rsrc->zf) {
  1055. rsrc_int->index_current++;
  1056. RETURN_RES(zend_register_resource(zr_rsrc, le_zip_entry));
  1057. } else {
  1058. efree(zr_rsrc);
  1059. RETURN_FALSE;
  1060. }
  1061. } else {
  1062. RETURN_FALSE;
  1063. }
  1064. }
  1065. /* }}} */
  1066. /* {{{ Open a Zip File, pointed by the resource entry */
  1067. /* Dummy function to follow the old API */
  1068. PHP_FUNCTION(zip_entry_open)
  1069. {
  1070. zval * zip;
  1071. zval * zip_entry;
  1072. char *mode = NULL;
  1073. size_t mode_len = 0;
  1074. zip_read_rsrc * zr_rsrc;
  1075. zip_rsrc *z_rsrc;
  1076. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr|s", &zip, &zip_entry, &mode, &mode_len) == FAILURE) {
  1077. RETURN_THROWS();
  1078. }
  1079. if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) {
  1080. RETURN_THROWS();
  1081. }
  1082. if ((z_rsrc = (zip_rsrc *)zend_fetch_resource(Z_RES_P(zip), le_zip_dir_name, le_zip_dir)) == NULL) {
  1083. RETURN_THROWS();
  1084. }
  1085. if (zr_rsrc->zf != NULL) {
  1086. RETURN_TRUE;
  1087. } else {
  1088. RETURN_FALSE;
  1089. }
  1090. }
  1091. /* }}} */
  1092. /* {{{ Close a zip entry */
  1093. PHP_FUNCTION(zip_entry_close)
  1094. {
  1095. zval * zip_entry;
  1096. zip_read_rsrc * zr_rsrc;
  1097. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip_entry) == FAILURE) {
  1098. RETURN_THROWS();
  1099. }
  1100. if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) {
  1101. RETURN_THROWS();
  1102. }
  1103. zend_list_close(Z_RES_P(zip_entry));
  1104. RETURN_TRUE;
  1105. }
  1106. /* }}} */
  1107. /* {{{ Read from an open directory entry */
  1108. PHP_FUNCTION(zip_entry_read)
  1109. {
  1110. zval * zip_entry;
  1111. zend_long len = 0;
  1112. zip_read_rsrc * zr_rsrc;
  1113. zend_string *buffer;
  1114. int n = 0;
  1115. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &zip_entry, &len) == FAILURE) {
  1116. RETURN_THROWS();
  1117. }
  1118. if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) {
  1119. RETURN_THROWS();
  1120. }
  1121. if (len <= 0) {
  1122. len = 1024;
  1123. }
  1124. if (zr_rsrc->zf) {
  1125. buffer = zend_string_safe_alloc(1, len, 0, 0);
  1126. n = zip_fread(zr_rsrc->zf, ZSTR_VAL(buffer), ZSTR_LEN(buffer));
  1127. if (n > 0) {
  1128. ZSTR_VAL(buffer)[n] = '\0';
  1129. ZSTR_LEN(buffer) = n;
  1130. RETURN_NEW_STR(buffer);
  1131. } else {
  1132. zend_string_efree(buffer);
  1133. RETURN_EMPTY_STRING();
  1134. }
  1135. } else {
  1136. RETURN_FALSE;
  1137. }
  1138. }
  1139. /* }}} */
  1140. static void php_zip_entry_get_info(INTERNAL_FUNCTION_PARAMETERS, int opt) /* {{{ */
  1141. {
  1142. zval * zip_entry;
  1143. zip_read_rsrc * zr_rsrc;
  1144. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip_entry) == FAILURE) {
  1145. RETURN_THROWS();
  1146. }
  1147. if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) {
  1148. RETURN_THROWS();
  1149. }
  1150. if (!zr_rsrc->zf) {
  1151. RETURN_FALSE;
  1152. }
  1153. switch (opt) {
  1154. case 0:
  1155. RETURN_STRING((char *)zr_rsrc->sb.name);
  1156. case 1:
  1157. RETURN_LONG((zend_long) (zr_rsrc->sb.comp_size));
  1158. case 2:
  1159. RETURN_LONG((zend_long) (zr_rsrc->sb.size));
  1160. case 3:
  1161. switch (zr_rsrc->sb.comp_method) {
  1162. case 0:
  1163. RETURN_STRING("stored");
  1164. case 1:
  1165. RETURN_STRING("shrunk");
  1166. case 2:
  1167. case 3:
  1168. case 4:
  1169. case 5:
  1170. RETURN_STRING("reduced");
  1171. case 6:
  1172. RETURN_STRING("imploded");
  1173. case 7:
  1174. RETURN_STRING("tokenized");
  1175. break;
  1176. case 8:
  1177. RETURN_STRING("deflated");
  1178. case 9:
  1179. RETURN_STRING("deflatedX");
  1180. break;
  1181. case 10:
  1182. RETURN_STRING("implodedX");
  1183. default:
  1184. RETURN_FALSE;
  1185. }
  1186. }
  1187. }
  1188. /* }}} */
  1189. /* {{{ Return the name given a ZZip entry */
  1190. PHP_FUNCTION(zip_entry_name)
  1191. {
  1192. php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  1193. }
  1194. /* }}} */
  1195. /* {{{ Return the compressed size of a ZZip entry */
  1196. PHP_FUNCTION(zip_entry_compressedsize)
  1197. {
  1198. php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  1199. }
  1200. /* }}} */
  1201. /* {{{ Return the actual filesize of a ZZip entry */
  1202. PHP_FUNCTION(zip_entry_filesize)
  1203. {
  1204. php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
  1205. }
  1206. /* }}} */
  1207. /* {{{ Return a string containing the compression method used on a particular entry */
  1208. PHP_FUNCTION(zip_entry_compressionmethod)
  1209. {
  1210. php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
  1211. }
  1212. /* }}} */
  1213. /* {{{ Create new zip using source uri for output, return TRUE on success or the error code */
  1214. PHP_METHOD(ZipArchive, open)
  1215. {
  1216. struct zip *intern;
  1217. int err = 0;
  1218. zend_long flags = 0;
  1219. char *resolved_path;
  1220. zend_string *filename;
  1221. zval *self = ZEND_THIS;
  1222. ze_zip_object *ze_obj;
  1223. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &filename, &flags) == FAILURE) {
  1224. RETURN_THROWS();
  1225. }
  1226. /* We do not use ZIP_FROM_OBJECT, zip init function here */
  1227. ze_obj = Z_ZIP_P(self);
  1228. if (ZSTR_LEN(filename) == 0) {
  1229. zend_argument_value_error(1, "cannot be empty");
  1230. RETURN_THROWS();
  1231. }
  1232. if (ZIP_OPENBASEDIR_CHECKPATH(ZSTR_VAL(filename))) {
  1233. RETURN_FALSE;
  1234. }
  1235. if (!(resolved_path = expand_filepath(ZSTR_VAL(filename), NULL))) {
  1236. php_error_docref(NULL, E_WARNING, "No such file or directory");
  1237. RETURN_FALSE;
  1238. }
  1239. if (ze_obj->za) {
  1240. /* we already have an opened zip, free it */
  1241. if (zip_close(ze_obj->za) != 0) {
  1242. php_error_docref(NULL, E_WARNING, "Empty string as source");
  1243. efree(resolved_path);
  1244. RETURN_FALSE;
  1245. }
  1246. ze_obj->za = NULL;
  1247. }
  1248. if (ze_obj->filename) {
  1249. efree(ze_obj->filename);
  1250. ze_obj->filename = NULL;
  1251. }
  1252. /* open for write without option to empty the archive */
  1253. #ifdef ZIP_RDONLY
  1254. if ((flags & (ZIP_TRUNCATE | ZIP_RDONLY)) == 0) {
  1255. #else
  1256. if ((flags & ZIP_TRUNCATE) == 0) {
  1257. #endif
  1258. zend_stat_t st;
  1259. /* exists and is empty */
  1260. if (VCWD_STAT(resolved_path, &st) == 0 && st.st_size == 0) {
  1261. php_error_docref(NULL, E_DEPRECATED, "Using empty file as ZipArchive is deprecated");
  1262. /* reduce BC break introduced in libzip 1.6.0
  1263. "Do not accept empty files as valid zip archives any longer" */
  1264. flags |= ZIP_TRUNCATE;
  1265. }
  1266. }
  1267. intern = zip_open(resolved_path, flags, &err);
  1268. if (!intern || err) {
  1269. efree(resolved_path);
  1270. RETURN_LONG((zend_long)err);
  1271. }
  1272. ze_obj->filename = resolved_path;
  1273. ze_obj->filename_len = strlen(resolved_path);
  1274. ze_obj->za = intern;
  1275. RETURN_TRUE;
  1276. }
  1277. /* }}} */
  1278. /* {{{ Set the password for the active archive */
  1279. PHP_METHOD(ZipArchive, setPassword)
  1280. {
  1281. struct zip *intern;
  1282. zval *self = ZEND_THIS;
  1283. char *password;
  1284. size_t password_len;
  1285. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &password, &password_len) == FAILURE) {
  1286. RETURN_THROWS();
  1287. }
  1288. ZIP_FROM_OBJECT(intern, self);
  1289. if (password_len < 1) {
  1290. RETURN_FALSE;
  1291. }
  1292. int res = zip_set_default_password(intern, (const char *)password);
  1293. if (res == 0) {
  1294. RETURN_TRUE;
  1295. } else {
  1296. RETURN_FALSE;
  1297. }
  1298. }
  1299. /* }}} */
  1300. /* {{{ close the zip archive */
  1301. PHP_METHOD(ZipArchive, close)
  1302. {
  1303. struct zip *intern;
  1304. zval *self = ZEND_THIS;
  1305. ze_zip_object *ze_obj;
  1306. int err;
  1307. if (zend_parse_parameters_none() == FAILURE) {
  1308. RETURN_THROWS();
  1309. }
  1310. ZIP_FROM_OBJECT(intern, self);
  1311. ze_obj = Z_ZIP_P(self);
  1312. err = zip_close(intern);
  1313. if (err) {
  1314. php_error_docref(NULL, E_WARNING, "%s", zip_strerror(intern));
  1315. /* Save error for property reader */
  1316. #if LIBZIP_VERSION_MAJOR < 1
  1317. zip_error_get(intern, &ze_obj->err_zip, &ze_obj->err_sys);
  1318. #else
  1319. {
  1320. zip_error_t *ziperr;
  1321. ziperr = zip_get_error(intern);
  1322. ze_obj->err_zip = zip_error_code_zip(ziperr);
  1323. ze_obj->err_sys = zip_error_code_system(ziperr);
  1324. zip_error_fini(ziperr);
  1325. }
  1326. #endif
  1327. zip_discard(intern);
  1328. } else {
  1329. ze_obj->err_zip = 0;
  1330. ze_obj->err_sys = 0;
  1331. }
  1332. /* clear cache as empty zip are not created but deleted */
  1333. php_clear_stat_cache(1, ze_obj->filename, ze_obj->filename_len);
  1334. efree(ze_obj->filename);
  1335. ze_obj->filename = NULL;
  1336. ze_obj->filename_len = 0;
  1337. ze_obj->za = NULL;
  1338. if (!err) {
  1339. RETURN_TRUE;
  1340. } else {
  1341. RETURN_FALSE;
  1342. }
  1343. }
  1344. /* }}} */
  1345. /* {{{ close the zip archive */
  1346. PHP_METHOD(ZipArchive, count)
  1347. {
  1348. struct zip *intern;
  1349. zval *self = ZEND_THIS;
  1350. zip_int64_t num;
  1351. if (zend_parse_parameters_none() == FAILURE) {
  1352. RETURN_THROWS();
  1353. }
  1354. ZIP_FROM_OBJECT(intern, self);
  1355. num = zip_get_num_entries(intern, 0);
  1356. RETVAL_LONG(MIN(num, ZEND_LONG_MAX));
  1357. }
  1358. /* }}} */
  1359. /* {{{ Returns the status error message, system and/or zip messages */
  1360. PHP_METHOD(ZipArchive, getStatusString)
  1361. {
  1362. zval *self = ZEND_THIS;
  1363. #if LIBZIP_VERSION_MAJOR < 1
  1364. int zep, syp, len;
  1365. char error_string[128];
  1366. #endif
  1367. ze_zip_object *ze_obj;
  1368. if (zend_parse_parameters_none() == FAILURE) {
  1369. RETURN_THROWS();
  1370. }
  1371. ze_obj = Z_ZIP_P(self); /* not ZIP_FROM_OBJECT as we can use saved error after close */
  1372. #if LIBZIP_VERSION_MAJOR < 1
  1373. if (ze_obj->za) {
  1374. zip_error_get(ze_obj->za, &zep, &syp);
  1375. len = zip_error_to_str(error_string, 128, zep, syp);
  1376. } else {
  1377. len = zip_error_to_str(error_string, 128, ze_obj->err_zip, ze_obj->err_sys);
  1378. }
  1379. RETVAL_STRINGL(error_string, len);
  1380. #else
  1381. if (ze_obj->za) {
  1382. zip_error_t *err;
  1383. err = zip_get_error(ze_obj->za);
  1384. RETVAL_STRING(zip_error_strerror(err));
  1385. zip_error_fini(err);
  1386. } else {
  1387. zip_error_t err;
  1388. zip_error_init(&err);
  1389. zip_error_set(&err, ze_obj->err_zip, ze_obj->err_sys);
  1390. RETVAL_STRING(zip_error_strerror(&err));
  1391. zip_error_fini(&err);
  1392. }
  1393. #endif
  1394. }
  1395. /* }}} */
  1396. /* {{{ Returns the index of the entry named filename in the archive */
  1397. PHP_METHOD(ZipArchive, addEmptyDir)
  1398. {
  1399. struct zip *intern;
  1400. zval *self = ZEND_THIS;
  1401. char *dirname;
  1402. size_t dirname_len;
  1403. char *s;
  1404. zend_long flags = 0;
  1405. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l",
  1406. &dirname, &dirname_len, &flags) == FAILURE) {
  1407. RETURN_THROWS();
  1408. }
  1409. ZIP_FROM_OBJECT(intern, self);
  1410. if (dirname_len<1) {
  1411. RETURN_FALSE;
  1412. }
  1413. if (dirname[dirname_len-1] != '/') {
  1414. s=(char *)safe_emalloc(dirname_len, 1, 2);
  1415. strcpy(s, dirname);
  1416. s[dirname_len] = '/';
  1417. s[dirname_len+1] = '\0';
  1418. } else {
  1419. s = dirname;
  1420. }
  1421. if ((Z_ZIP_P(self)->last_id = zip_dir_add(intern, (const char *)s, flags)) == -1) {
  1422. RETVAL_FALSE;
  1423. } else {
  1424. zip_error_clear(intern);
  1425. RETVAL_TRUE;
  1426. }
  1427. if (s != dirname) {
  1428. efree(s);
  1429. }
  1430. }
  1431. /* }}} */
  1432. static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
  1433. {
  1434. zval *self = ZEND_THIS;
  1435. char *path = ".";
  1436. size_t path_len = 1;
  1437. zend_long glob_flags = 0;
  1438. HashTable *options = NULL;
  1439. zip_options opts;
  1440. int found;
  1441. zend_string *pattern;
  1442. /* 1 == glob, 2 == pcre */
  1443. if (type == 1) {
  1444. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|lh",
  1445. &pattern, &glob_flags, &options) == FAILURE) {
  1446. RETURN_THROWS();
  1447. }
  1448. } else {
  1449. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|sh",
  1450. &pattern, &path, &path_len, &options) == FAILURE) {
  1451. RETURN_THROWS();
  1452. }
  1453. }
  1454. if (ZSTR_LEN(pattern) == 0) {
  1455. zend_argument_value_error(1, "cannot be empty");
  1456. RETURN_THROWS();
  1457. }
  1458. if (options && zend_hash_num_elements(options) > 0 && (php_zip_parse_options(options, &opts) < 0)) {
  1459. RETURN_THROWS();
  1460. }
  1461. if (type == 1) {
  1462. found = php_zip_glob(ZSTR_VAL(pattern), ZSTR_LEN(pattern), glob_flags, return_value);
  1463. } else {
  1464. found = php_zip_pcre(pattern, path, path_len, return_value);
  1465. }
  1466. if (found > 0) {
  1467. int i;
  1468. zval *zval_file;
  1469. ze_zip_object *ze_obj;
  1470. ze_obj = Z_ZIP_P(self);
  1471. for (i = 0; i < found; i++) {
  1472. char *file_stripped, *entry_name;
  1473. size_t entry_name_len, file_stripped_len;
  1474. char entry_name_buf[MAXPATHLEN];
  1475. zend_string *basename = NULL;
  1476. if ((zval_file = zend_hash_index_find(Z_ARRVAL_P(return_value), i)) != NULL) {
  1477. if (opts.remove_all_path) {
  1478. basename = php_basename(Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), NULL, 0);
  1479. file_stripped = ZSTR_VAL(basename);
  1480. file_stripped_len = ZSTR_LEN(basename);
  1481. } else if (opts.remove_path && strstr(Z_STRVAL_P(zval_file), opts.remove_path) != NULL) {
  1482. if (IS_SLASH(Z_STRVAL_P(zval_file)[opts.remove_path_len])) {
  1483. file_stripped = Z_STRVAL_P(zval_file) + opts.remove_path_len + 1;
  1484. file_stripped_len = Z_STRLEN_P(zval_file) - opts.remove_path_len - 1;
  1485. } else {
  1486. file_stripped = Z_STRVAL_P(zval_file) + opts.remove_path_len;
  1487. file_stripped_len = Z_STRLEN_P(zval_file) - opts.remove_path_len;
  1488. }
  1489. } else {
  1490. file_stripped = Z_STRVAL_P(zval_file);
  1491. file_stripped_len = Z_STRLEN_P(zval_file);
  1492. }
  1493. if (opts.add_path) {
  1494. if ((opts.add_path_len + file_stripped_len) > MAXPATHLEN) {
  1495. php_error_docref(NULL, E_WARNING, "Entry name too long (max: %d, %zd given)",
  1496. MAXPATHLEN - 1, (opts.add_path_len + file_stripped_len));
  1497. zend_array_destroy(Z_ARR_P(return_value));
  1498. RETURN_FALSE;
  1499. }
  1500. snprintf(entry_name_buf, MAXPATHLEN, "%s%s", opts.add_path, file_stripped);
  1501. } else {
  1502. snprintf(entry_name_buf, MAXPATHLEN, "%s", file_stripped);
  1503. }
  1504. entry_name = entry_name_buf;
  1505. entry_name_len = strlen(entry_name);
  1506. if (basename) {
  1507. zend_string_release_ex(basename, 0);
  1508. basename = NULL;
  1509. }
  1510. if (php_zip_add_file(ze_obj, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file),
  1511. entry_name, entry_name_len, 0, 0, -1, opts.flags) < 0) {
  1512. zend_array_destroy(Z_ARR_P(return_value));
  1513. RETURN_FALSE;
  1514. }
  1515. if (opts.comp_method >= 0) {
  1516. if (zip_set_file_compression(ze_obj->za, ze_obj->last_id, opts.comp_method, opts.comp_flags)) {
  1517. zend_array_destroy(Z_ARR_P(return_value));
  1518. RETURN_FALSE;
  1519. }
  1520. }
  1521. #ifdef HAVE_ENCRYPTION
  1522. if (opts.enc_method >= 0) {
  1523. if (zip_file_set_encryption(ze_obj->za, ze_obj->last_id, opts.enc_method, opts.enc_password)) {
  1524. zend_array_destroy(Z_ARR_P(return_value));
  1525. RETURN_FALSE;
  1526. }
  1527. }
  1528. #endif
  1529. }
  1530. }
  1531. }
  1532. }
  1533. /* }}} */
  1534. /* {{{ Add files matching the glob pattern. See php's glob for the pattern syntax. */
  1535. PHP_METHOD(ZipArchive, addGlob)
  1536. {
  1537. php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  1538. }
  1539. /* }}} */
  1540. /* {{{ Add files matching the pcre pattern. See php's pcre for the pattern syntax. */
  1541. PHP_METHOD(ZipArchive, addPattern)
  1542. {
  1543. php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
  1544. }
  1545. /* }}} */
  1546. /* {{{ Add a file in a Zip archive using its path and the name to use. */
  1547. PHP_METHOD(ZipArchive, addFile)
  1548. {
  1549. zval *self = ZEND_THIS;
  1550. char *entry_name = NULL;
  1551. size_t entry_name_len = 0;
  1552. zend_long offset_start = 0, offset_len = 0;
  1553. zend_string *filename;
  1554. zend_long flags = ZIP_FL_OVERWRITE;
  1555. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|slll",
  1556. &filename, &entry_name, &entry_name_len, &offset_start, &offset_len, &flags) == FAILURE) {
  1557. RETURN_THROWS();
  1558. }
  1559. if (ZSTR_LEN(filename) == 0) {
  1560. zend_argument_value_error(1, "cannot be empty");
  1561. RETURN_THROWS();
  1562. }
  1563. if (entry_name_len == 0) {
  1564. entry_name = ZSTR_VAL(filename);
  1565. entry_name_len = ZSTR_LEN(filename);
  1566. }
  1567. if (php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename),
  1568. entry_name, entry_name_len, offset_start, offset_len, -1, flags) < 0) {
  1569. RETURN_FALSE;
  1570. } else {
  1571. RETURN_TRUE;
  1572. }
  1573. }
  1574. /* }}} */
  1575. /* {{{ Add a file in a Zip archive using its path and the name to use. */
  1576. PHP_METHOD(ZipArchive, replaceFile)
  1577. {
  1578. zval *self = ZEND_THIS;
  1579. zend_long index;
  1580. zend_long offset_start = 0, offset_len = 0;
  1581. zend_string *filename;
  1582. zend_long flags = 0;
  1583. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Pl|lll",
  1584. &filename, &index, &offset_start, &offset_len, &flags) == FAILURE) {
  1585. RETURN_THROWS();
  1586. }
  1587. if (ZSTR_LEN(filename) == 0) {
  1588. zend_argument_value_error(1, "cannot be empty");
  1589. RETURN_THROWS();
  1590. }
  1591. if (index < 0) {
  1592. zend_argument_value_error(2, "must be greater than or equal to 0");
  1593. RETURN_THROWS();
  1594. }
  1595. if (php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename),
  1596. NULL, 0, offset_start, offset_len, index, flags) < 0) {
  1597. RETURN_FALSE;
  1598. } else {
  1599. RETURN_TRUE;
  1600. }
  1601. }
  1602. /* }}} */
  1603. /* {{{ Add a file using content and the entry name */
  1604. PHP_METHOD(ZipArchive, addFromString)
  1605. {
  1606. struct zip *intern;
  1607. zval *self = ZEND_THIS;
  1608. zend_string *buffer;
  1609. char *name;
  1610. size_t name_len;
  1611. ze_zip_object *ze_obj;
  1612. struct zip_source *zs;
  1613. int pos = 0;
  1614. zend_long flags = ZIP_FL_OVERWRITE;
  1615. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sS|l",
  1616. &name, &name_len, &buffer, &flags) == FAILURE) {
  1617. RETURN_THROWS();
  1618. }
  1619. ZIP_FROM_OBJECT(intern, self);
  1620. ze_obj = Z_ZIP_P(self);
  1621. if (ze_obj->buffers_cnt) {
  1622. ze_obj->buffers = (char **)safe_erealloc(ze_obj->buffers, sizeof(char *), (ze_obj->buffers_cnt+1), 0);
  1623. pos = ze_obj->buffers_cnt++;
  1624. } else {
  1625. ze_obj->buffers = (char **)emalloc(sizeof(char *));
  1626. ze_obj->buffers_cnt++;
  1627. pos = 0;
  1628. }
  1629. ze_obj->buffers[pos] = (char *)safe_emalloc(ZSTR_LEN(buffer), 1, 1);
  1630. memcpy(ze_obj->buffers[pos], ZSTR_VAL(buffer), ZSTR_LEN(buffer) + 1);
  1631. zs = zip_source_buffer(intern, ze_obj->buffers[pos], ZSTR_LEN(buffer), 0);
  1632. if (zs == NULL) {
  1633. RETURN_FALSE;
  1634. }
  1635. ze_obj->last_id = zip_file_add(intern, name, zs, flags);
  1636. if (ze_obj->last_id == -1) {
  1637. zip_source_free(zs);
  1638. RETURN_FALSE;
  1639. } else {
  1640. zip_error_clear(intern);
  1641. RETURN_TRUE;
  1642. }
  1643. }
  1644. /* }}} */
  1645. /* {{{ Returns the information about a the zip entry filename */
  1646. PHP_METHOD(ZipArchive, statName)
  1647. {
  1648. struct zip *intern;
  1649. zval *self = ZEND_THIS;
  1650. zend_long flags = 0;
  1651. struct zip_stat sb;
  1652. zend_string *name;
  1653. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &name, &flags) == FAILURE) {
  1654. RETURN_THROWS();
  1655. }
  1656. ZIP_FROM_OBJECT(intern, self);
  1657. PHP_ZIP_STAT_PATH(intern, ZSTR_VAL(name), ZSTR_LEN(name), flags, sb);
  1658. RETURN_SB(&sb);
  1659. }
  1660. /* }}} */
  1661. /* {{{ Returns the zip entry information using its index */
  1662. PHP_METHOD(ZipArchive, statIndex)
  1663. {
  1664. struct zip *intern;
  1665. zval *self = ZEND_THIS;
  1666. zend_long index, flags = 0;
  1667. struct zip_stat sb;
  1668. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l",
  1669. &index, &flags) == FAILURE) {
  1670. RETURN_THROWS();
  1671. }
  1672. ZIP_FROM_OBJECT(intern, self);
  1673. if (zip_stat_index(intern, index, flags, &sb) != 0) {
  1674. RETURN_FALSE;
  1675. }
  1676. RETURN_SB(&sb);
  1677. }
  1678. /* }}} */
  1679. /* {{{ Returns the index of the entry named filename in the archive */
  1680. PHP_METHOD(ZipArchive, locateName)
  1681. {
  1682. struct zip *intern;
  1683. zval *self = ZEND_THIS;
  1684. zend_long flags = 0;
  1685. zend_long idx = -1;
  1686. zend_string *name;
  1687. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &name, &flags) == FAILURE) {
  1688. RETURN_THROWS();
  1689. }
  1690. ZIP_FROM_OBJECT(intern, self);
  1691. if (ZSTR_LEN(name) < 1) {
  1692. RETURN_FALSE;
  1693. }
  1694. idx = (zend_long)zip_name_locate(intern, (const char *)ZSTR_VAL(name), flags);
  1695. if (idx >= 0) {
  1696. RETURN_LONG(idx);
  1697. } else {
  1698. RETURN_FALSE;
  1699. }
  1700. }
  1701. /* }}} */
  1702. /* {{{ Returns the name of the file at position index */
  1703. PHP_METHOD(ZipArchive, getNameIndex)
  1704. {
  1705. struct zip *intern;
  1706. zval *self = ZEND_THIS;
  1707. const char *name;
  1708. zend_long flags = 0, index = 0;
  1709. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l",
  1710. &index, &flags) == FAILURE) {
  1711. RETURN_THROWS();
  1712. }
  1713. ZIP_FROM_OBJECT(intern, self);
  1714. name = zip_get_name(intern, (int) index, flags);
  1715. if (name) {
  1716. RETVAL_STRING((char *)name);
  1717. } else {
  1718. RETURN_FALSE;
  1719. }
  1720. }
  1721. /* }}} */
  1722. /* {{{ Set or remove (NULL/'') the comment of the archive */
  1723. PHP_METHOD(ZipArchive, setArchiveComment)
  1724. {
  1725. struct zip *intern;
  1726. zval *self = ZEND_THIS;
  1727. size_t comment_len;
  1728. char * comment;
  1729. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &comment, &comment_len) == FAILURE) {
  1730. RETURN_THROWS();
  1731. }
  1732. ZIP_FROM_OBJECT(intern, self);
  1733. if (comment_len > 0xffff) {
  1734. zend_argument_value_error(1, "must be less than 65535 bytes");
  1735. RETURN_THROWS();
  1736. }
  1737. if (zip_set_archive_comment(intern, (const char *)comment, comment_len)) {
  1738. RETURN_FALSE;
  1739. } else {
  1740. RETURN_TRUE;
  1741. }
  1742. }
  1743. /* }}} */
  1744. /* {{{ Returns the comment of an entry using its index */
  1745. PHP_METHOD(ZipArchive, getArchiveComment)
  1746. {
  1747. struct zip *intern;
  1748. zval *self = ZEND_THIS;
  1749. zend_long flags = 0;
  1750. const char * comment;
  1751. int comment_len = 0;
  1752. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &flags) == FAILURE) {
  1753. RETURN_THROWS();
  1754. }
  1755. ZIP_FROM_OBJECT(intern, self);
  1756. comment = zip_get_archive_comment(intern, &comment_len, (int)flags);
  1757. if(comment==NULL) {
  1758. RETURN_FALSE;
  1759. }
  1760. RETURN_STRINGL((char *)comment, (zend_long)comment_len);
  1761. }
  1762. /* }}} */
  1763. /* {{{ Set or remove (NULL/'') the comment of an entry using its Name */
  1764. PHP_METHOD(ZipArchive, setCommentName)
  1765. {
  1766. struct zip *intern;
  1767. zval *self = ZEND_THIS;
  1768. size_t comment_len, name_len;
  1769. char * comment, *name;
  1770. int idx;
  1771. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  1772. &name, &name_len, &comment, &comment_len) == FAILURE) {
  1773. RETURN_THROWS();
  1774. }
  1775. if (name_len == 0) {
  1776. zend_argument_value_error(1, "cannot be empty");
  1777. RETURN_THROWS();
  1778. }
  1779. ZIP_FROM_OBJECT(intern, self);
  1780. if (comment_len > 0xffff) {
  1781. zend_argument_value_error(2, "must be less than 65535 bytes");
  1782. RETURN_THROWS();
  1783. }
  1784. idx = zip_name_locate(intern, name, 0);
  1785. if (idx < 0) {
  1786. RETURN_FALSE;
  1787. }
  1788. PHP_ZIP_SET_FILE_COMMENT(intern, idx, comment, comment_len);
  1789. }
  1790. /* }}} */
  1791. /* {{{ Set or remove (NULL/'') the comment of an entry using its index */
  1792. PHP_METHOD(ZipArchive, setCommentIndex)
  1793. {
  1794. struct zip *intern;
  1795. zval *self = ZEND_THIS;
  1796. zend_long index;
  1797. size_t comment_len;
  1798. char * comment;
  1799. struct zip_stat sb;
  1800. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls",
  1801. &index, &comment, &comment_len) == FAILURE) {
  1802. RETURN_THROWS();
  1803. }
  1804. ZIP_FROM_OBJECT(intern, self);
  1805. if (comment_len > 0xffff) {
  1806. zend_argument_value_error(2, "must be less than 65535 bytes");
  1807. RETURN_THROWS();
  1808. }
  1809. PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
  1810. PHP_ZIP_SET_FILE_COMMENT(intern, index, comment, comment_len);
  1811. }
  1812. /* }}} */
  1813. /* those constants/functions are only available in libzip since 0.11.2 */
  1814. #ifdef ZIP_OPSYS_DEFAULT
  1815. /* {{{ Set external attributes for file in zip, using its name */
  1816. PHP_METHOD(ZipArchive, setExternalAttributesName)
  1817. {
  1818. struct zip *intern;
  1819. zval *self = ZEND_THIS;
  1820. size_t name_len;
  1821. char *name;
  1822. zend_long flags=0, opsys, attr;
  1823. zip_int64_t idx;
  1824. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sll|l",
  1825. &name, &name_len, &opsys, &attr, &flags) == FAILURE) {
  1826. RETURN_THROWS();
  1827. }
  1828. ZIP_FROM_OBJECT(intern, self);
  1829. if (name_len == 0) {
  1830. zend_argument_value_error(1, "cannot be empty");
  1831. RETURN_THROWS();
  1832. }
  1833. idx = zip_name_locate(intern, name, 0);
  1834. if (idx < 0) {
  1835. RETURN_FALSE;
  1836. }
  1837. if (zip_file_set_external_attributes(intern, idx, (zip_flags_t)flags,
  1838. (zip_uint8_t)(opsys&0xff), (zip_uint32_t)attr) < 0) {
  1839. RETURN_FALSE;
  1840. }
  1841. RETURN_TRUE;
  1842. }
  1843. /* }}} */
  1844. /* {{{ Set external attributes for file in zip, using its index */
  1845. PHP_METHOD(ZipArchive, setExternalAttributesIndex)
  1846. {
  1847. struct zip *intern;
  1848. zval *self = ZEND_THIS;
  1849. zend_long index, flags=0, opsys, attr;
  1850. struct zip_stat sb;
  1851. if (zend_parse_parameters(ZEND_NUM_ARGS(), "lll|l",
  1852. &index, &opsys, &attr, &flags) == FAILURE) {
  1853. RETURN_THROWS();
  1854. }
  1855. ZIP_FROM_OBJECT(intern, self);
  1856. PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
  1857. if (zip_file_set_external_attributes(intern, (zip_uint64_t)index,
  1858. (zip_flags_t)flags, (zip_uint8_t)(opsys&0xff), (zip_uint32_t)attr) < 0) {
  1859. RETURN_FALSE;
  1860. }
  1861. RETURN_TRUE;
  1862. }
  1863. /* }}} */
  1864. /* {{{ Get external attributes for file in zip, using its name */
  1865. PHP_METHOD(ZipArchive, getExternalAttributesName)
  1866. {
  1867. struct zip *intern;
  1868. zval *self = ZEND_THIS, *z_opsys, *z_attr;
  1869. size_t name_len;
  1870. char *name;
  1871. zend_long flags=0;
  1872. zip_uint8_t opsys;
  1873. zip_uint32_t attr;
  1874. zip_int64_t idx;
  1875. if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l",
  1876. &name, &name_len, &z_opsys, &z_attr, &flags) == FAILURE) {
  1877. RETURN_THROWS();
  1878. }
  1879. ZIP_FROM_OBJECT(intern, self);
  1880. if (name_len == 0) {
  1881. zend_argument_value_error(1, "cannot be empty");
  1882. RETURN_THROWS();
  1883. }
  1884. idx = zip_name_locate(intern, name, 0);
  1885. if (idx < 0) {
  1886. RETURN_FALSE;
  1887. }
  1888. if (zip_file_get_external_attributes(intern, idx,
  1889. (zip_flags_t)flags, &opsys, &attr) < 0) {
  1890. RETURN_FALSE;
  1891. }
  1892. ZEND_TRY_ASSIGN_REF_LONG(z_opsys, opsys);
  1893. ZEND_TRY_ASSIGN_REF_LONG(z_attr, attr);
  1894. RETURN_TRUE;
  1895. }
  1896. /* }}} */
  1897. /* {{{ Get external attributes for file in zip, using its index */
  1898. PHP_METHOD(ZipArchive, getExternalAttributesIndex)
  1899. {
  1900. struct zip *intern;
  1901. zval *self = ZEND_THIS, *z_opsys, *z_attr;
  1902. zend_long index, flags=0;
  1903. zip_uint8_t opsys;
  1904. zip_uint32_t attr;
  1905. struct zip_stat sb;
  1906. if (zend_parse_parameters(ZEND_NUM_ARGS(), "lzz|l",
  1907. &index, &z_opsys, &z_attr, &flags) == FAILURE) {
  1908. RETURN_THROWS();
  1909. }
  1910. ZIP_FROM_OBJECT(intern, self);
  1911. PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
  1912. if (zip_file_get_external_attributes(intern, (zip_uint64_t)index,
  1913. (zip_flags_t)flags, &opsys, &attr) < 0) {
  1914. RETURN_FALSE;
  1915. }
  1916. ZEND_TRY_ASSIGN_REF_LONG(z_opsys, opsys);
  1917. ZEND_TRY_ASSIGN_REF_LONG(z_attr, attr);
  1918. RETURN_TRUE;
  1919. }
  1920. /* }}} */
  1921. #endif /* ifdef ZIP_OPSYS_DEFAULT */
  1922. #ifdef HAVE_ENCRYPTION
  1923. /* {{{ Set encryption method for file in zip, using its name */
  1924. PHP_METHOD(ZipArchive, setEncryptionName)
  1925. {
  1926. struct zip *intern;
  1927. zval *self = ZEND_THIS;
  1928. zend_long method;
  1929. zip_int64_t idx;
  1930. char *name, *password = NULL;
  1931. size_t name_len, password_len;
  1932. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|s!",
  1933. &name, &name_len, &method, &password, &password_len) == FAILURE) {
  1934. RETURN_THROWS();
  1935. }
  1936. ZIP_FROM_OBJECT(intern, self);
  1937. if (name_len == 0) {
  1938. zend_argument_value_error(1, "cannot be empty");
  1939. RETURN_THROWS();
  1940. }
  1941. idx = zip_name_locate(intern, name, 0);
  1942. if (idx < 0) {
  1943. RETURN_FALSE;
  1944. }
  1945. if (zip_file_set_encryption(intern, idx, (zip_uint16_t)method, password)) {
  1946. RETURN_FALSE;
  1947. }
  1948. RETURN_TRUE;
  1949. }
  1950. /* }}} */
  1951. /* {{{ Set encryption method for file in zip, using its index */
  1952. PHP_METHOD(ZipArchive, setEncryptionIndex)
  1953. {
  1954. struct zip *intern;
  1955. zval *self = ZEND_THIS;
  1956. zend_long index, method;
  1957. char *password = NULL;
  1958. size_t password_len;
  1959. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|s!",
  1960. &index, &method, &password, &password_len) == FAILURE) {
  1961. RETURN_THROWS();
  1962. }
  1963. ZIP_FROM_OBJECT(intern, self);
  1964. if (zip_file_set_encryption(intern, index, (zip_uint16_t)method, password)) {
  1965. RETURN_FALSE;
  1966. }
  1967. RETURN_TRUE;
  1968. }
  1969. /* }}} */
  1970. #endif
  1971. /* {{{ Returns the comment of an entry using its name */
  1972. PHP_METHOD(ZipArchive, getCommentName)
  1973. {
  1974. struct zip *intern;
  1975. zval *self = ZEND_THIS;
  1976. size_t name_len;
  1977. int idx;
  1978. zend_long flags = 0;
  1979. zip_uint32_t comment_len = 0;
  1980. const char * comment;
  1981. char *name;
  1982. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l",
  1983. &name, &name_len, &flags) == FAILURE) {
  1984. RETURN_THROWS();
  1985. }
  1986. ZIP_FROM_OBJECT(intern, self);
  1987. if (name_len == 0) {
  1988. zend_argument_value_error(1, "cannot be empty");
  1989. RETURN_THROWS();
  1990. }
  1991. idx = zip_name_locate(intern, name, 0);
  1992. if (idx < 0) {
  1993. RETURN_FALSE;
  1994. }
  1995. comment = zip_file_get_comment(intern, idx, &comment_len, (zip_flags_t)flags);
  1996. RETURN_STRINGL((char *)comment, comment_len);
  1997. }
  1998. /* }}} */
  1999. /* {{{ Returns the comment of an entry using its index */
  2000. PHP_METHOD(ZipArchive, getCommentIndex)
  2001. {
  2002. struct zip *intern;
  2003. zval *self = ZEND_THIS;
  2004. zend_long index, flags = 0;
  2005. const char * comment;
  2006. zip_uint32_t comment_len = 0;
  2007. struct zip_stat sb;
  2008. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l",
  2009. &index, &flags) == FAILURE) {
  2010. RETURN_THROWS();
  2011. }
  2012. ZIP_FROM_OBJECT(intern, self);
  2013. PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
  2014. comment = zip_file_get_comment(intern, index, &comment_len, (zip_flags_t)flags);
  2015. RETURN_STRINGL((char *)comment, comment_len);
  2016. }
  2017. /* }}} */
  2018. /* {{{ Set the compression of a file in zip, using its name */
  2019. PHP_METHOD(ZipArchive, setCompressionName)
  2020. {
  2021. struct zip *intern;
  2022. zval *this = ZEND_THIS;
  2023. size_t name_len;
  2024. char *name;
  2025. zip_int64_t idx;
  2026. zend_long comp_method, comp_flags = 0;
  2027. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|l",
  2028. &name, &name_len, &comp_method, &comp_flags) == FAILURE) {
  2029. RETURN_THROWS();
  2030. }
  2031. ZIP_FROM_OBJECT(intern, this);
  2032. if (name_len == 0) {
  2033. zend_argument_value_error(1, "cannot be empty");
  2034. RETURN_THROWS();
  2035. }
  2036. idx = zip_name_locate(intern, name, 0);
  2037. if (idx < 0) {
  2038. RETURN_FALSE;
  2039. }
  2040. if (zip_set_file_compression(intern, (zip_uint64_t)idx,
  2041. (zip_int32_t)comp_method, (zip_uint32_t)comp_flags) != 0) {
  2042. RETURN_FALSE;
  2043. }
  2044. RETURN_TRUE;
  2045. }
  2046. /* }}} */
  2047. /* {{{ Set the compression of a file in zip, using its index */
  2048. PHP_METHOD(ZipArchive, setCompressionIndex)
  2049. {
  2050. struct zip *intern;
  2051. zval *this = ZEND_THIS;
  2052. zend_long index;
  2053. zend_long comp_method, comp_flags = 0;
  2054. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|l",
  2055. &index, &comp_method, &comp_flags) == FAILURE) {
  2056. RETURN_THROWS();
  2057. }
  2058. ZIP_FROM_OBJECT(intern, this);
  2059. if (zip_set_file_compression(intern, (zip_uint64_t)index,
  2060. (zip_int32_t)comp_method, (zip_uint32_t)comp_flags) != 0) {
  2061. RETURN_FALSE;
  2062. }
  2063. RETURN_TRUE;
  2064. }
  2065. /* }}} */
  2066. #ifdef HAVE_SET_MTIME
  2067. /* {{{ Set the modification time of a file in zip, using its name */
  2068. PHP_METHOD(ZipArchive, setMtimeName)
  2069. {
  2070. struct zip *intern;
  2071. zval *this = ZEND_THIS;
  2072. size_t name_len;
  2073. char *name;
  2074. zip_int64_t idx;
  2075. zend_long mtime, flags = 0;
  2076. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|l",
  2077. &name, &name_len, &mtime, &flags) == FAILURE) {
  2078. RETURN_THROWS();
  2079. }
  2080. ZIP_FROM_OBJECT(intern, this);
  2081. if (name_len == 0) {
  2082. zend_argument_value_error(1, "cannot be empty");
  2083. RETURN_THROWS();
  2084. }
  2085. idx = zip_name_locate(intern, name, 0);
  2086. if (idx < 0) {
  2087. RETURN_FALSE;
  2088. }
  2089. if (zip_file_set_mtime(intern, (zip_uint64_t)idx,
  2090. (time_t)mtime, (zip_uint32_t)flags) != 0) {
  2091. RETURN_FALSE;
  2092. }
  2093. RETURN_TRUE;
  2094. }
  2095. /* }}} */
  2096. /* {{{ Set the modification time of a file in zip, using its index */
  2097. PHP_METHOD(ZipArchive, setMtimeIndex)
  2098. {
  2099. struct zip *intern;
  2100. zval *this = ZEND_THIS;
  2101. zend_long index;
  2102. zend_long mtime, flags = 0;
  2103. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|l",
  2104. &index, &mtime, &flags) == FAILURE) {
  2105. RETURN_THROWS();
  2106. }
  2107. ZIP_FROM_OBJECT(intern, this);
  2108. if (zip_file_set_mtime(intern, (zip_uint64_t)index,
  2109. (time_t)mtime, (zip_uint32_t)flags) != 0) {
  2110. RETURN_FALSE;
  2111. }
  2112. RETURN_TRUE;
  2113. }
  2114. /* }}} */
  2115. #endif
  2116. /* {{{ Delete a file using its index */
  2117. PHP_METHOD(ZipArchive, deleteIndex)
  2118. {
  2119. struct zip *intern;
  2120. zval *self = ZEND_THIS;
  2121. zend_long index;
  2122. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
  2123. RETURN_THROWS();
  2124. }
  2125. ZIP_FROM_OBJECT(intern, self);
  2126. if (index < 0) {
  2127. RETURN_FALSE;
  2128. }
  2129. if (zip_delete(intern, index) < 0) {
  2130. RETURN_FALSE;
  2131. }
  2132. RETURN_TRUE;
  2133. }
  2134. /* }}} */
  2135. /* {{{ Delete a file using its index */
  2136. PHP_METHOD(ZipArchive, deleteName)
  2137. {
  2138. struct zip *intern;
  2139. zval *self = ZEND_THIS;
  2140. size_t name_len;
  2141. char *name;
  2142. struct zip_stat sb;
  2143. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
  2144. RETURN_THROWS();
  2145. }
  2146. ZIP_FROM_OBJECT(intern, self);
  2147. if (name_len < 1) {
  2148. RETURN_FALSE;
  2149. }
  2150. PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
  2151. if (zip_delete(intern, sb.index)) {
  2152. RETURN_FALSE;
  2153. }
  2154. RETURN_TRUE;
  2155. }
  2156. /* }}} */
  2157. /* {{{ Rename an entry selected by its index to new_name */
  2158. PHP_METHOD(ZipArchive, renameIndex)
  2159. {
  2160. struct zip *intern;
  2161. zval *self = ZEND_THIS;
  2162. char *new_name;
  2163. size_t new_name_len;
  2164. zend_long index;
  2165. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &index, &new_name, &new_name_len) == FAILURE) {
  2166. RETURN_THROWS();
  2167. }
  2168. if (index < 0) {
  2169. RETURN_FALSE;
  2170. }
  2171. ZIP_FROM_OBJECT(intern, self);
  2172. if (new_name_len == 0) {
  2173. zend_argument_value_error(2, "cannot be empty");
  2174. RETURN_THROWS();
  2175. }
  2176. if (zip_file_rename(intern, index, (const char *)new_name, 0) != 0) {
  2177. RETURN_FALSE;
  2178. }
  2179. RETURN_TRUE;
  2180. }
  2181. /* }}} */
  2182. /* {{{ Rename an entry selected by its name to new_name */
  2183. PHP_METHOD(ZipArchive, renameName)
  2184. {
  2185. struct zip *intern;
  2186. zval *self = ZEND_THIS;
  2187. struct zip_stat sb;
  2188. char *name, *new_name;
  2189. size_t name_len, new_name_len;
  2190. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &name, &name_len, &new_name, &new_name_len) == FAILURE) {
  2191. RETURN_THROWS();
  2192. }
  2193. ZIP_FROM_OBJECT(intern, self);
  2194. if (new_name_len == 0) {
  2195. zend_argument_value_error(2, "cannot be empty");
  2196. RETURN_THROWS();
  2197. }
  2198. PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
  2199. if (zip_file_rename(intern, sb.index, (const char *)new_name, 0)) {
  2200. RETURN_FALSE;
  2201. }
  2202. RETURN_TRUE;
  2203. }
  2204. /* }}} */
  2205. /* {{{ Changes to the file at position index are reverted */
  2206. PHP_METHOD(ZipArchive, unchangeIndex)
  2207. {
  2208. struct zip *intern;
  2209. zval *self = ZEND_THIS;
  2210. zend_long index;
  2211. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
  2212. RETURN_THROWS();
  2213. }
  2214. ZIP_FROM_OBJECT(intern, self);
  2215. if (index < 0) {
  2216. RETURN_FALSE;
  2217. }
  2218. if (zip_unchange(intern, index) != 0) {
  2219. RETURN_FALSE;
  2220. } else {
  2221. RETURN_TRUE;
  2222. }
  2223. }
  2224. /* }}} */
  2225. /* {{{ Changes to the file named 'name' are reverted */
  2226. PHP_METHOD(ZipArchive, unchangeName)
  2227. {
  2228. struct zip *intern;
  2229. zval *self = ZEND_THIS;
  2230. struct zip_stat sb;
  2231. char *name;
  2232. size_t name_len;
  2233. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
  2234. RETURN_THROWS();
  2235. }
  2236. ZIP_FROM_OBJECT(intern, self);
  2237. if (name_len < 1) {
  2238. RETURN_FALSE;
  2239. }
  2240. PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
  2241. if (zip_unchange(intern, sb.index) != 0) {
  2242. RETURN_FALSE;
  2243. } else {
  2244. RETURN_TRUE;
  2245. }
  2246. }
  2247. /* }}} */
  2248. /* {{{ All changes to files and global information in archive are reverted */
  2249. PHP_METHOD(ZipArchive, unchangeAll)
  2250. {
  2251. struct zip *intern;
  2252. zval *self = ZEND_THIS;
  2253. if (zend_parse_parameters_none() == FAILURE) {
  2254. RETURN_THROWS();
  2255. }
  2256. ZIP_FROM_OBJECT(intern, self);
  2257. if (zip_unchange_all(intern) != 0) {
  2258. RETURN_FALSE;
  2259. } else {
  2260. RETURN_TRUE;
  2261. }
  2262. }
  2263. /* }}} */
  2264. /* {{{ Revert all global changes to the archive archive. For now, this only reverts archive comment changes. */
  2265. PHP_METHOD(ZipArchive, unchangeArchive)
  2266. {
  2267. struct zip *intern;
  2268. zval *self = ZEND_THIS;
  2269. if (zend_parse_parameters_none() == FAILURE) {
  2270. RETURN_THROWS();
  2271. }
  2272. ZIP_FROM_OBJECT(intern, self);
  2273. if (zip_unchange_archive(intern) != 0) {
  2274. RETURN_FALSE;
  2275. } else {
  2276. RETURN_TRUE;
  2277. }
  2278. }
  2279. /* }}} */
  2280. /* {{{ Extract one or more file from a zip archive */
  2281. /* TODO:
  2282. * - allow index or array of indices
  2283. * - replace path
  2284. * - patterns
  2285. */
  2286. PHP_METHOD(ZipArchive, extractTo)
  2287. {
  2288. struct zip *intern;
  2289. zval *self = ZEND_THIS;
  2290. zend_string *files_str = NULL;
  2291. HashTable *files_ht = NULL;
  2292. php_stream_statbuf ssb;
  2293. char *pathto;
  2294. size_t pathto_len;
  2295. int ret;
  2296. ZEND_PARSE_PARAMETERS_START(1, 2)
  2297. Z_PARAM_PATH(pathto, pathto_len)
  2298. Z_PARAM_OPTIONAL
  2299. Z_PARAM_ARRAY_HT_OR_STR_OR_NULL(files_ht, files_str)
  2300. ZEND_PARSE_PARAMETERS_END();
  2301. ZIP_FROM_OBJECT(intern, self);
  2302. if (pathto_len < 1) {
  2303. RETURN_FALSE;
  2304. }
  2305. if (php_stream_stat_path_ex(pathto, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
  2306. ret = php_stream_mkdir(pathto, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL);
  2307. if (!ret) {
  2308. RETURN_FALSE;
  2309. }
  2310. }
  2311. uint32_t nelems, i;
  2312. if (files_str) {
  2313. if (!php_zip_extract_file(intern, pathto, ZSTR_VAL(files_str), ZSTR_LEN(files_str))) {
  2314. RETURN_FALSE;
  2315. }
  2316. } else if (files_ht) {
  2317. nelems = zend_hash_num_elements(files_ht);
  2318. if (nelems == 0 ) {
  2319. RETURN_FALSE;
  2320. }
  2321. for (i = 0; i < nelems; i++) {
  2322. zval *zval_file;
  2323. if ((zval_file = zend_hash_index_find_deref(files_ht, i)) != NULL) {
  2324. switch (Z_TYPE_P(zval_file)) {
  2325. case IS_LONG:
  2326. break;
  2327. case IS_STRING:
  2328. if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file))) {
  2329. RETURN_FALSE;
  2330. }
  2331. break;
  2332. }
  2333. }
  2334. }
  2335. } else {
  2336. /* Extract all files */
  2337. zip_int64_t i, filecount = zip_get_num_entries(intern, 0);
  2338. if (filecount == -1) {
  2339. php_error_docref(NULL, E_WARNING, "Illegal archive");
  2340. RETURN_FALSE;
  2341. }
  2342. for (i = 0; i < filecount; i++) {
  2343. char *file = (char*)zip_get_name(intern, i, ZIP_FL_UNCHANGED);
  2344. if (!file || !php_zip_extract_file(intern, pathto, file, strlen(file))) {
  2345. RETURN_FALSE;
  2346. }
  2347. }
  2348. }
  2349. RETURN_TRUE;
  2350. }
  2351. /* }}} */
  2352. static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
  2353. {
  2354. struct zip *intern;
  2355. zval *self = ZEND_THIS;
  2356. struct zip_stat sb;
  2357. struct zip_file *zf;
  2358. zend_long index = -1;
  2359. zend_long flags = 0;
  2360. zend_long len = 0;
  2361. zend_string *filename;
  2362. zend_string *buffer;
  2363. int n = 0;
  2364. if (type == 1) {
  2365. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|ll", &filename, &len, &flags) == FAILURE) {
  2366. RETURN_THROWS();
  2367. }
  2368. ZIP_FROM_OBJECT(intern, self);
  2369. PHP_ZIP_STAT_PATH(intern, ZSTR_VAL(filename), ZSTR_LEN(filename), flags, sb);
  2370. } else {
  2371. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|ll", &index, &len, &flags) == FAILURE) {
  2372. RETURN_THROWS();
  2373. }
  2374. ZIP_FROM_OBJECT(intern, self);
  2375. PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
  2376. }
  2377. if (sb.size < 1) {
  2378. RETURN_EMPTY_STRING();
  2379. }
  2380. if (len < 1) {
  2381. len = sb.size;
  2382. }
  2383. if (index >= 0) {
  2384. zf = zip_fopen_index(intern, index, flags);
  2385. } else {
  2386. zf = zip_fopen(intern, ZSTR_VAL(filename), flags);
  2387. }
  2388. if (zf == NULL) {
  2389. RETURN_FALSE;
  2390. }
  2391. buffer = zend_string_safe_alloc(1, len, 0, 0);
  2392. n = zip_fread(zf, ZSTR_VAL(buffer), ZSTR_LEN(buffer));
  2393. if (n < 1) {
  2394. zend_string_efree(buffer);
  2395. RETURN_EMPTY_STRING();
  2396. }
  2397. zip_fclose(zf);
  2398. ZSTR_VAL(buffer)[n] = '\0';
  2399. ZSTR_LEN(buffer) = n;
  2400. RETURN_NEW_STR(buffer);
  2401. }
  2402. /* }}} */
  2403. /* {{{ get the contents of an entry using its name */
  2404. PHP_METHOD(ZipArchive, getFromName)
  2405. {
  2406. php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  2407. }
  2408. /* }}} */
  2409. /* {{{ get the contents of an entry using its index */
  2410. PHP_METHOD(ZipArchive, getFromIndex)
  2411. {
  2412. php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  2413. }
  2414. /* }}} */
  2415. /* {{{ get a stream for an entry using its name */
  2416. PHP_METHOD(ZipArchive, getStream)
  2417. {
  2418. struct zip *intern;
  2419. zval *self = ZEND_THIS;
  2420. struct zip_stat sb;
  2421. char *mode = "rb";
  2422. zend_string *filename;
  2423. php_stream *stream;
  2424. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &filename) == FAILURE) {
  2425. RETURN_THROWS();
  2426. }
  2427. ZIP_FROM_OBJECT(intern, self);
  2428. if (zip_stat(intern, ZSTR_VAL(filename), 0, &sb) != 0) {
  2429. RETURN_FALSE;
  2430. }
  2431. stream = php_stream_zip_open(intern, ZSTR_VAL(filename), mode STREAMS_CC);
  2432. if (stream) {
  2433. php_stream_to_zval(stream, return_value);
  2434. } else {
  2435. RETURN_FALSE;
  2436. }
  2437. }
  2438. /* }}} */
  2439. #ifdef HAVE_PROGRESS_CALLBACK
  2440. static void _php_zip_progress_callback(zip_t *arch, double state, void *ptr)
  2441. {
  2442. zval cb_args[1];
  2443. zval cb_retval;
  2444. ze_zip_object *obj = ptr;
  2445. ZVAL_DOUBLE(&cb_args[0], state);
  2446. if (call_user_function(EG(function_table), NULL, &obj->progress_callback, &cb_retval, 1, cb_args) == SUCCESS && !Z_ISUNDEF(cb_retval)) {
  2447. zval_ptr_dtor(&cb_retval);
  2448. }
  2449. }
  2450. /* {{{ register a progression callback: void callback(double state); */
  2451. PHP_METHOD(ZipArchive, registerProgressCallback)
  2452. {
  2453. struct zip *intern;
  2454. zval *self = ZEND_THIS;
  2455. double rate;
  2456. zend_fcall_info fci;
  2457. zend_fcall_info_cache fcc;
  2458. ze_zip_object *obj;
  2459. if (zend_parse_parameters(ZEND_NUM_ARGS(), "df", &rate, &fci, &fcc) == FAILURE) {
  2460. RETURN_THROWS();
  2461. }
  2462. ZIP_FROM_OBJECT(intern, self);
  2463. obj = Z_ZIP_P(self);
  2464. /* free if called twice */
  2465. _php_zip_progress_callback_free(obj);
  2466. /* register */
  2467. ZVAL_COPY(&obj->progress_callback, &fci.function_name);
  2468. if (zip_register_progress_callback_with_state(intern, rate, _php_zip_progress_callback, _php_zip_progress_callback_free, obj)) {
  2469. RETURN_FALSE;
  2470. }
  2471. RETURN_TRUE;
  2472. }
  2473. /* }}} */
  2474. #endif
  2475. #ifdef HAVE_CANCEL_CALLBACK
  2476. static int _php_zip_cancel_callback(zip_t *arch, void *ptr)
  2477. {
  2478. zval cb_retval;
  2479. int retval = 0;
  2480. ze_zip_object *obj = ptr;
  2481. if (call_user_function(EG(function_table), NULL, &obj->cancel_callback, &cb_retval, 0, NULL) == SUCCESS && !Z_ISUNDEF(cb_retval)) {
  2482. retval = zval_get_long(&cb_retval);
  2483. zval_ptr_dtor(&cb_retval);
  2484. }
  2485. return retval;
  2486. }
  2487. /* {{{ register a progression callback: int callback(double state); */
  2488. PHP_METHOD(ZipArchive, registerCancelCallback)
  2489. {
  2490. struct zip *intern;
  2491. zval *self = ZEND_THIS;
  2492. zend_fcall_info fci;
  2493. zend_fcall_info_cache fcc;
  2494. ze_zip_object *obj;
  2495. if (zend_parse_parameters(ZEND_NUM_ARGS(), "f", &fci, &fcc) == FAILURE) {
  2496. RETURN_THROWS();
  2497. }
  2498. ZIP_FROM_OBJECT(intern, self);
  2499. obj = Z_ZIP_P(self);
  2500. /* free if called twice */
  2501. _php_zip_cancel_callback_free(obj);
  2502. /* register */
  2503. ZVAL_COPY(&obj->cancel_callback, &fci.function_name);
  2504. if (zip_register_cancel_callback_with_state(intern, _php_zip_cancel_callback, _php_zip_cancel_callback_free, obj)) {
  2505. RETURN_FALSE;
  2506. }
  2507. RETURN_TRUE;
  2508. }
  2509. /* }}} */
  2510. #endif
  2511. #ifdef HAVE_METHOD_SUPPORTED
  2512. /* {{{ check if a compression method is available in used libzip */
  2513. PHP_METHOD(ZipArchive, isCompressionMethodSupported)
  2514. {
  2515. zend_long method;
  2516. bool enc = 1;
  2517. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|b", &method, &enc) == FAILURE) {
  2518. return;
  2519. }
  2520. RETVAL_BOOL(zip_compression_method_supported((zip_int32_t)method, enc));
  2521. }
  2522. /* }}} */
  2523. /* {{{ check if a encryption method is available in used libzip */
  2524. PHP_METHOD(ZipArchive, isEncryptionMethodSupported)
  2525. {
  2526. zend_long method;
  2527. bool enc = 1;
  2528. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|b", &method, &enc) == FAILURE) {
  2529. return;
  2530. }
  2531. RETVAL_BOOL(zip_encryption_method_supported((zip_uint16_t)method, enc));
  2532. }
  2533. /* }}} */
  2534. #endif
  2535. static void php_zip_free_prop_handler(zval *el) /* {{{ */ {
  2536. pefree(Z_PTR_P(el), 1);
  2537. } /* }}} */
  2538. /* {{{ PHP_MINIT_FUNCTION */
  2539. static PHP_MINIT_FUNCTION(zip)
  2540. {
  2541. memcpy(&zip_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
  2542. zip_object_handlers.offset = XtOffsetOf(ze_zip_object, zo);
  2543. zip_object_handlers.free_obj = php_zip_object_free_storage;
  2544. zip_object_handlers.clone_obj = NULL;
  2545. zip_object_handlers.get_property_ptr_ptr = php_zip_get_property_ptr_ptr;
  2546. zip_object_handlers.get_gc = php_zip_get_gc;
  2547. zip_object_handlers.get_properties = php_zip_get_properties;
  2548. zip_object_handlers.read_property = php_zip_read_property;
  2549. zip_object_handlers.has_property = php_zip_has_property;
  2550. zip_object_handlers.write_property = php_zip_write_property;
  2551. zip_class_entry = register_class_ZipArchive(zend_ce_countable);
  2552. zip_class_entry->create_object = php_zip_object_new;
  2553. zend_hash_init(&zip_prop_handlers, 0, NULL, php_zip_free_prop_handler, 1);
  2554. php_zip_register_prop_handler(&zip_prop_handlers, "lastId", php_zip_last_id, NULL, IS_LONG);
  2555. php_zip_register_prop_handler(&zip_prop_handlers, "status", php_zip_status, NULL, IS_LONG);
  2556. php_zip_register_prop_handler(&zip_prop_handlers, "statusSys", php_zip_status_sys, NULL, IS_LONG);
  2557. php_zip_register_prop_handler(&zip_prop_handlers, "numFiles", php_zip_get_num_files, NULL, IS_LONG);
  2558. php_zip_register_prop_handler(&zip_prop_handlers, "filename", NULL, php_zipobj_get_filename, IS_STRING);
  2559. php_zip_register_prop_handler(&zip_prop_handlers, "comment", NULL, php_zipobj_get_zip_comment, IS_STRING);
  2560. REGISTER_ZIP_CLASS_CONST_LONG("CREATE", ZIP_CREATE);
  2561. REGISTER_ZIP_CLASS_CONST_LONG("EXCL", ZIP_EXCL);
  2562. REGISTER_ZIP_CLASS_CONST_LONG("CHECKCONS", ZIP_CHECKCONS);
  2563. REGISTER_ZIP_CLASS_CONST_LONG("OVERWRITE", ZIP_OVERWRITE);
  2564. #ifdef ZIP_RDONLY
  2565. REGISTER_ZIP_CLASS_CONST_LONG("RDONLY", ZIP_RDONLY);
  2566. #endif
  2567. REGISTER_ZIP_CLASS_CONST_LONG("FL_NOCASE", ZIP_FL_NOCASE);
  2568. REGISTER_ZIP_CLASS_CONST_LONG("FL_NODIR", ZIP_FL_NODIR);
  2569. REGISTER_ZIP_CLASS_CONST_LONG("FL_COMPRESSED", ZIP_FL_COMPRESSED);
  2570. REGISTER_ZIP_CLASS_CONST_LONG("FL_UNCHANGED", ZIP_FL_UNCHANGED);
  2571. REGISTER_ZIP_CLASS_CONST_LONG("FL_RECOMPRESS", ZIP_FL_RECOMPRESS);
  2572. REGISTER_ZIP_CLASS_CONST_LONG("FL_ENCRYPTED", ZIP_FL_ENCRYPTED);
  2573. REGISTER_ZIP_CLASS_CONST_LONG("FL_OVERWRITE", ZIP_FL_OVERWRITE);
  2574. REGISTER_ZIP_CLASS_CONST_LONG("FL_LOCAL", ZIP_FL_LOCAL);
  2575. REGISTER_ZIP_CLASS_CONST_LONG("FL_CENTRAL", ZIP_FL_CENTRAL);
  2576. /* Default filename encoding policy. */
  2577. REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_GUESS", ZIP_FL_ENC_GUESS);
  2578. REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_RAW", ZIP_FL_ENC_RAW);
  2579. REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_STRICT", ZIP_FL_ENC_STRICT);
  2580. REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_UTF_8", ZIP_FL_ENC_UTF_8);
  2581. REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_CP437", ZIP_FL_ENC_CP437);
  2582. REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFAULT", ZIP_CM_DEFAULT);
  2583. REGISTER_ZIP_CLASS_CONST_LONG("CM_STORE", ZIP_CM_STORE);
  2584. REGISTER_ZIP_CLASS_CONST_LONG("CM_SHRINK", ZIP_CM_SHRINK);
  2585. REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_1", ZIP_CM_REDUCE_1);
  2586. REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_2", ZIP_CM_REDUCE_2);
  2587. REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_3", ZIP_CM_REDUCE_3);
  2588. REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_4", ZIP_CM_REDUCE_4);
  2589. REGISTER_ZIP_CLASS_CONST_LONG("CM_IMPLODE", ZIP_CM_IMPLODE);
  2590. REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE", ZIP_CM_DEFLATE);
  2591. REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE64", ZIP_CM_DEFLATE64);
  2592. REGISTER_ZIP_CLASS_CONST_LONG("CM_PKWARE_IMPLODE", ZIP_CM_PKWARE_IMPLODE);
  2593. REGISTER_ZIP_CLASS_CONST_LONG("CM_BZIP2", ZIP_CM_BZIP2);
  2594. REGISTER_ZIP_CLASS_CONST_LONG("CM_LZMA", ZIP_CM_LZMA);
  2595. #ifdef ZIP_CM_LZMA2
  2596. REGISTER_ZIP_CLASS_CONST_LONG("CM_LZMA2", ZIP_CM_LZMA2);
  2597. #endif
  2598. #ifdef ZIP_CM_ZSTD
  2599. REGISTER_ZIP_CLASS_CONST_LONG("CM_ZSTD", ZIP_CM_ZSTD);
  2600. #endif
  2601. #ifdef ZIP_CM_XZ
  2602. REGISTER_ZIP_CLASS_CONST_LONG("CM_XZ", ZIP_CM_XZ);
  2603. #endif
  2604. REGISTER_ZIP_CLASS_CONST_LONG("CM_TERSE", ZIP_CM_TERSE);
  2605. REGISTER_ZIP_CLASS_CONST_LONG("CM_LZ77", ZIP_CM_LZ77);
  2606. REGISTER_ZIP_CLASS_CONST_LONG("CM_WAVPACK", ZIP_CM_WAVPACK);
  2607. REGISTER_ZIP_CLASS_CONST_LONG("CM_PPMD", ZIP_CM_PPMD);
  2608. /* Error code */
  2609. REGISTER_ZIP_CLASS_CONST_LONG("ER_OK", ZIP_ER_OK); /* N No error */
  2610. REGISTER_ZIP_CLASS_CONST_LONG("ER_MULTIDISK", ZIP_ER_MULTIDISK); /* N Multi-disk zip archives not supported */
  2611. REGISTER_ZIP_CLASS_CONST_LONG("ER_RENAME", ZIP_ER_RENAME); /* S Renaming temporary file failed */
  2612. REGISTER_ZIP_CLASS_CONST_LONG("ER_CLOSE", ZIP_ER_CLOSE); /* S Closing zip archive failed */
  2613. REGISTER_ZIP_CLASS_CONST_LONG("ER_SEEK", ZIP_ER_SEEK); /* S Seek error */
  2614. REGISTER_ZIP_CLASS_CONST_LONG("ER_READ", ZIP_ER_READ); /* S Read error */
  2615. REGISTER_ZIP_CLASS_CONST_LONG("ER_WRITE", ZIP_ER_WRITE); /* S Write error */
  2616. REGISTER_ZIP_CLASS_CONST_LONG("ER_CRC", ZIP_ER_CRC); /* N CRC error */
  2617. REGISTER_ZIP_CLASS_CONST_LONG("ER_ZIPCLOSED", ZIP_ER_ZIPCLOSED); /* N Containing zip archive was closed */
  2618. REGISTER_ZIP_CLASS_CONST_LONG("ER_NOENT", ZIP_ER_NOENT); /* N No such file */
  2619. REGISTER_ZIP_CLASS_CONST_LONG("ER_EXISTS", ZIP_ER_EXISTS); /* N File already exists */
  2620. REGISTER_ZIP_CLASS_CONST_LONG("ER_OPEN", ZIP_ER_OPEN); /* S Can't open file */
  2621. REGISTER_ZIP_CLASS_CONST_LONG("ER_TMPOPEN", ZIP_ER_TMPOPEN); /* S Failure to create temporary file */
  2622. REGISTER_ZIP_CLASS_CONST_LONG("ER_ZLIB", ZIP_ER_ZLIB); /* Z Zlib error */
  2623. REGISTER_ZIP_CLASS_CONST_LONG("ER_MEMORY", ZIP_ER_MEMORY); /* N Malloc failure */
  2624. REGISTER_ZIP_CLASS_CONST_LONG("ER_CHANGED", ZIP_ER_CHANGED); /* N Entry has been changed */
  2625. REGISTER_ZIP_CLASS_CONST_LONG("ER_COMPNOTSUPP", ZIP_ER_COMPNOTSUPP);/* N Compression method not supported */
  2626. REGISTER_ZIP_CLASS_CONST_LONG("ER_EOF", ZIP_ER_EOF); /* N Premature EOF */
  2627. REGISTER_ZIP_CLASS_CONST_LONG("ER_INVAL", ZIP_ER_INVAL); /* N Invalid argument */
  2628. REGISTER_ZIP_CLASS_CONST_LONG("ER_NOZIP", ZIP_ER_NOZIP); /* N Not a zip archive */
  2629. REGISTER_ZIP_CLASS_CONST_LONG("ER_INTERNAL", ZIP_ER_INTERNAL); /* N Internal error */
  2630. REGISTER_ZIP_CLASS_CONST_LONG("ER_INCONS", ZIP_ER_INCONS); /* N Zip archive inconsistent */
  2631. REGISTER_ZIP_CLASS_CONST_LONG("ER_REMOVE", ZIP_ER_REMOVE); /* S Can't remove file */
  2632. REGISTER_ZIP_CLASS_CONST_LONG("ER_DELETED", ZIP_ER_DELETED); /* N Entry has been deleted */
  2633. REGISTER_ZIP_CLASS_CONST_LONG("ER_ENCRNOTSUPP", ZIP_ER_ENCRNOTSUPP);/* N Encryption method not supported */
  2634. REGISTER_ZIP_CLASS_CONST_LONG("ER_RDONLY", ZIP_ER_RDONLY); /* N Read-only archive */
  2635. REGISTER_ZIP_CLASS_CONST_LONG("ER_NOPASSWD", ZIP_ER_NOPASSWD); /* N Entry has been deleted */
  2636. REGISTER_ZIP_CLASS_CONST_LONG("ER_WRONGPASSWD", ZIP_ER_WRONGPASSWD);/* N Wrong password provided */
  2637. /* since 1.0.0 */
  2638. #ifdef ZIP_ER_OPNOTSUPP
  2639. REGISTER_ZIP_CLASS_CONST_LONG("ER_OPNOTSUPP", ZIP_ER_OPNOTSUPP); /* N Operation not supported */
  2640. #endif
  2641. #ifdef ZIP_ER_INUSE
  2642. REGISTER_ZIP_CLASS_CONST_LONG("ER_INUSE", ZIP_ER_INUSE); /* N Resource still in use */
  2643. #endif
  2644. #ifdef ZIP_ER_TELL
  2645. REGISTER_ZIP_CLASS_CONST_LONG("ER_TELL", ZIP_ER_TELL); /* S Tell error */
  2646. #endif
  2647. /* since 1.6.0 */
  2648. #ifdef ZIP_ER_COMPRESSED_DATA
  2649. REGISTER_ZIP_CLASS_CONST_LONG("ER_COMPRESSED_DATA", ZIP_ER_COMPRESSED_DATA);/* N Compressed data invalid */
  2650. #endif
  2651. #ifdef ZIP_ER_CANCELLED
  2652. REGISTER_ZIP_CLASS_CONST_LONG("ER_CANCELLED", ZIP_ER_CANCELLED); /* N Operation cancelled */
  2653. #endif
  2654. #ifdef ZIP_OPSYS_DEFAULT
  2655. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_DOS", ZIP_OPSYS_DOS);
  2656. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_AMIGA", ZIP_OPSYS_AMIGA);
  2657. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OPENVMS", ZIP_OPSYS_OPENVMS);
  2658. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_UNIX", ZIP_OPSYS_UNIX);
  2659. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_VM_CMS", ZIP_OPSYS_VM_CMS);
  2660. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_ATARI_ST", ZIP_OPSYS_ATARI_ST);
  2661. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OS_2", ZIP_OPSYS_OS_2);
  2662. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_MACINTOSH", ZIP_OPSYS_MACINTOSH);
  2663. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_Z_SYSTEM", ZIP_OPSYS_Z_SYSTEM);
  2664. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_CPM", ZIP_OPSYS_CPM);
  2665. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_WINDOWS_NTFS", ZIP_OPSYS_WINDOWS_NTFS);
  2666. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_MVS", ZIP_OPSYS_MVS);
  2667. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_VSE", ZIP_OPSYS_VSE);
  2668. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_ACORN_RISC", ZIP_OPSYS_ACORN_RISC);
  2669. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_VFAT", ZIP_OPSYS_VFAT);
  2670. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_ALTERNATE_MVS", ZIP_OPSYS_ALTERNATE_MVS);
  2671. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_BEOS", ZIP_OPSYS_BEOS);
  2672. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_TANDEM", ZIP_OPSYS_TANDEM);
  2673. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OS_400", ZIP_OPSYS_OS_400);
  2674. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OS_X", ZIP_OPSYS_OS_X);
  2675. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_DEFAULT", ZIP_OPSYS_DEFAULT);
  2676. #endif /* ifdef ZIP_OPSYS_DEFAULT */
  2677. REGISTER_ZIP_CLASS_CONST_LONG("EM_NONE", ZIP_EM_NONE);
  2678. REGISTER_ZIP_CLASS_CONST_LONG("EM_TRAD_PKWARE", ZIP_EM_TRAD_PKWARE);
  2679. #ifdef HAVE_ENCRYPTION
  2680. REGISTER_ZIP_CLASS_CONST_LONG("EM_AES_128", ZIP_EM_AES_128);
  2681. REGISTER_ZIP_CLASS_CONST_LONG("EM_AES_192", ZIP_EM_AES_192);
  2682. REGISTER_ZIP_CLASS_CONST_LONG("EM_AES_256", ZIP_EM_AES_256);
  2683. #endif
  2684. REGISTER_ZIP_CLASS_CONST_LONG("EM_UNKNOWN", ZIP_EM_UNKNOWN);
  2685. #ifdef HAVE_LIBZIP_VERSION
  2686. zend_declare_class_constant_string(zip_class_entry, "LIBZIP_VERSION", sizeof("LIBZIP_VERSION")-1, zip_libzip_version());
  2687. #else
  2688. zend_declare_class_constant_string(zip_class_entry, "LIBZIP_VERSION", sizeof("LIBZIP_VERSION")-1, LIBZIP_VERSION);
  2689. #endif
  2690. php_register_url_stream_wrapper("zip", &php_stream_zip_wrapper);
  2691. le_zip_dir = zend_register_list_destructors_ex(php_zip_free_dir, NULL, le_zip_dir_name, module_number);
  2692. le_zip_entry = zend_register_list_destructors_ex(php_zip_free_entry, NULL, le_zip_entry_name, module_number);
  2693. return SUCCESS;
  2694. }
  2695. /* }}} */
  2696. /* {{{ PHP_MSHUTDOWN_FUNCTION */
  2697. static PHP_MSHUTDOWN_FUNCTION(zip)
  2698. {
  2699. zend_hash_destroy(&zip_prop_handlers);
  2700. php_unregister_url_stream_wrapper("zip");
  2701. return SUCCESS;
  2702. }
  2703. /* }}} */
  2704. /* {{{ PHP_MINFO_FUNCTION */
  2705. static PHP_MINFO_FUNCTION(zip)
  2706. {
  2707. php_info_print_table_start();
  2708. php_info_print_table_row(2, "Zip", "enabled");
  2709. php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION);
  2710. #ifdef HAVE_LIBZIP_VERSION
  2711. if (strcmp(LIBZIP_VERSION, zip_libzip_version())) {
  2712. php_info_print_table_row(2, "Libzip headers version", LIBZIP_VERSION);
  2713. php_info_print_table_row(2, "Libzip library version", zip_libzip_version());
  2714. } else
  2715. #endif
  2716. {
  2717. php_info_print_table_row(2, "Libzip version", LIBZIP_VERSION);
  2718. }
  2719. #ifdef HAVE_METHOD_SUPPORTED
  2720. php_info_print_table_row(2, "BZIP2 compression",
  2721. zip_compression_method_supported(ZIP_CM_BZIP2, 1) ? "Yes" : "No");
  2722. php_info_print_table_row(2, "XZ compression",
  2723. zip_compression_method_supported(ZIP_CM_XZ, 1) ? "Yes" : "No");
  2724. #ifdef ZIP_CM_ZSTD
  2725. php_info_print_table_row(2, "ZSTD compression",
  2726. zip_compression_method_supported(ZIP_CM_ZSTD, 1) ? "Yes" : "No");
  2727. #else
  2728. php_info_print_table_row(2, "ZSTD compression", "No");
  2729. #endif
  2730. php_info_print_table_row(2, "AES-128 encryption",
  2731. zip_encryption_method_supported(ZIP_EM_AES_128, 1) ? "Yes" : "No");
  2732. php_info_print_table_row(2, "AES-192 encryption",
  2733. zip_encryption_method_supported(ZIP_EM_AES_128, 1) ? "Yes" : "No");
  2734. php_info_print_table_row(2, "AES-256 encryption",
  2735. zip_encryption_method_supported(ZIP_EM_AES_128, 1) ? "Yes" : "No");
  2736. #endif
  2737. php_info_print_table_end();
  2738. }
  2739. /* }}} */