func_interceptors.c 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145
  1. /*
  2. +----------------------------------------------------------------------+
  3. | phar php single-file executable PHP extension |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | https://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Gregory Beaver <cellog@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #include "phar_internal.h"
  19. #define PHAR_FUNC(name) \
  20. static PHP_NAMED_FUNCTION(name)
  21. PHAR_FUNC(phar_opendir) /* {{{ */
  22. {
  23. char *filename;
  24. size_t filename_len;
  25. zval *zcontext = NULL;
  26. if (!PHAR_G(intercepted)) {
  27. goto skip_phar;
  28. }
  29. if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
  30. && !HT_IS_INITIALIZED(&cached_phars)) {
  31. goto skip_phar;
  32. }
  33. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|r!", &filename, &filename_len, &zcontext) == FAILURE) {
  34. RETURN_THROWS();
  35. }
  36. if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
  37. char *arch, *entry, *fname;
  38. size_t arch_len, entry_len, fname_len;
  39. fname = (char*)zend_get_executed_filename();
  40. /* we are checking for existence of a file within the relative path. Chances are good that this is
  41. retrieving something from within the phar archive */
  42. if (strncasecmp(fname, "phar://", 7)) {
  43. goto skip_phar;
  44. }
  45. fname_len = strlen(fname);
  46. if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
  47. php_stream_context *context = NULL;
  48. php_stream *stream;
  49. char *name;
  50. efree(entry);
  51. entry = estrndup(filename, filename_len);
  52. /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
  53. entry_len = filename_len;
  54. /* retrieving a file within the current directory, so use this if possible */
  55. entry = phar_fix_filepath(entry, &entry_len, 1);
  56. if (entry[0] == '/') {
  57. spprintf(&name, 4096, "phar://%s%s", arch, entry);
  58. } else {
  59. spprintf(&name, 4096, "phar://%s/%s", arch, entry);
  60. }
  61. efree(entry);
  62. efree(arch);
  63. if (zcontext) {
  64. context = php_stream_context_from_zval(zcontext, 0);
  65. }
  66. stream = php_stream_opendir(name, REPORT_ERRORS, context);
  67. efree(name);
  68. if (!stream) {
  69. RETURN_FALSE;
  70. }
  71. php_stream_to_zval(stream, return_value);
  72. return;
  73. }
  74. }
  75. skip_phar:
  76. PHAR_G(orig_opendir)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  77. return;
  78. }
  79. /* }}} */
  80. PHAR_FUNC(phar_file_get_contents) /* {{{ */
  81. {
  82. char *filename;
  83. size_t filename_len;
  84. zend_string *contents;
  85. bool use_include_path = 0;
  86. php_stream *stream;
  87. zend_long offset = -1;
  88. zend_long maxlen;
  89. bool maxlen_is_null = 1;
  90. zval *zcontext = NULL;
  91. if (!PHAR_G(intercepted)) {
  92. goto skip_phar;
  93. }
  94. if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
  95. && !HT_IS_INITIALIZED(&cached_phars)) {
  96. goto skip_phar;
  97. }
  98. /* Parse arguments */
  99. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p|br!ll!", &filename, &filename_len, &use_include_path, &zcontext, &offset, &maxlen, &maxlen_is_null) == FAILURE) {
  100. goto skip_phar;
  101. }
  102. if (maxlen_is_null) {
  103. maxlen = (ssize_t) PHP_STREAM_COPY_ALL;
  104. }
  105. if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
  106. char *arch, *entry, *fname;
  107. zend_string *entry_str = NULL;
  108. size_t arch_len, entry_len, fname_len;
  109. php_stream_context *context = NULL;
  110. fname = (char*)zend_get_executed_filename();
  111. if (strncasecmp(fname, "phar://", 7)) {
  112. goto skip_phar;
  113. }
  114. fname_len = strlen(fname);
  115. if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
  116. char *name;
  117. phar_archive_data *phar;
  118. efree(entry);
  119. entry = filename;
  120. /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
  121. entry_len = filename_len;
  122. if (!maxlen_is_null && maxlen < 0) {
  123. efree(arch);
  124. zend_argument_value_error(5, "must be greater than or equal to 0");
  125. RETURN_THROWS();
  126. }
  127. /* retrieving a file defaults to within the current directory, so use this if possible */
  128. if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
  129. efree(arch);
  130. goto skip_phar;
  131. }
  132. if (use_include_path) {
  133. if ((entry_str = phar_find_in_include_path(entry, entry_len, NULL))) {
  134. name = ZSTR_VAL(entry_str);
  135. goto phar_it;
  136. } else {
  137. /* this file is not in the phar, use the original path */
  138. efree(arch);
  139. goto skip_phar;
  140. }
  141. } else {
  142. entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
  143. if (entry[0] == '/') {
  144. if (!zend_hash_str_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
  145. /* this file is not in the phar, use the original path */
  146. notfound:
  147. efree(arch);
  148. efree(entry);
  149. goto skip_phar;
  150. }
  151. } else {
  152. if (!zend_hash_str_exists(&(phar->manifest), entry, entry_len)) {
  153. goto notfound;
  154. }
  155. }
  156. /* auto-convert to phar:// */
  157. if (entry[0] == '/') {
  158. spprintf(&name, 4096, "phar://%s%s", arch, entry);
  159. } else {
  160. spprintf(&name, 4096, "phar://%s/%s", arch, entry);
  161. }
  162. if (entry != filename) {
  163. efree(entry);
  164. }
  165. }
  166. phar_it:
  167. efree(arch);
  168. if (zcontext) {
  169. context = php_stream_context_from_zval(zcontext, 0);
  170. }
  171. stream = php_stream_open_wrapper_ex(name, "rb", 0 | REPORT_ERRORS, NULL, context);
  172. if (entry_str) {
  173. zend_string_release_ex(entry_str, 0);
  174. } else {
  175. efree(name);
  176. }
  177. if (!stream) {
  178. RETURN_FALSE;
  179. }
  180. if (offset > 0 && php_stream_seek(stream, offset, SEEK_SET) < 0) {
  181. php_error_docref(NULL, E_WARNING, "Failed to seek to position " ZEND_LONG_FMT " in the stream", offset);
  182. php_stream_close(stream);
  183. RETURN_FALSE;
  184. }
  185. /* uses mmap if possible */
  186. contents = php_stream_copy_to_mem(stream, maxlen, 0);
  187. if (contents && ZSTR_LEN(contents) > 0) {
  188. RETVAL_STR(contents);
  189. } else if (contents) {
  190. zend_string_release_ex(contents, 0);
  191. RETVAL_EMPTY_STRING();
  192. } else {
  193. RETVAL_FALSE;
  194. }
  195. php_stream_close(stream);
  196. return;
  197. }
  198. }
  199. skip_phar:
  200. PHAR_G(orig_file_get_contents)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  201. return;
  202. }
  203. /* }}} */
  204. PHAR_FUNC(phar_readfile) /* {{{ */
  205. {
  206. char *filename;
  207. size_t filename_len;
  208. int size = 0;
  209. bool use_include_path = 0;
  210. zval *zcontext = NULL;
  211. php_stream *stream;
  212. if (!PHAR_G(intercepted)) {
  213. goto skip_phar;
  214. }
  215. if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
  216. && !HT_IS_INITIALIZED(&cached_phars)) {
  217. goto skip_phar;
  218. }
  219. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) {
  220. goto skip_phar;
  221. }
  222. if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
  223. char *arch, *entry, *fname;
  224. zend_string *entry_str = NULL;
  225. size_t arch_len, entry_len, fname_len;
  226. php_stream_context *context = NULL;
  227. char *name;
  228. phar_archive_data *phar;
  229. fname = (char*)zend_get_executed_filename();
  230. if (strncasecmp(fname, "phar://", 7)) {
  231. goto skip_phar;
  232. }
  233. fname_len = strlen(fname);
  234. if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
  235. goto skip_phar;
  236. }
  237. efree(entry);
  238. entry = filename;
  239. /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
  240. entry_len = filename_len;
  241. /* retrieving a file defaults to within the current directory, so use this if possible */
  242. if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
  243. efree(arch);
  244. goto skip_phar;
  245. }
  246. if (use_include_path) {
  247. if (!(entry_str = phar_find_in_include_path(entry, entry_len, NULL))) {
  248. /* this file is not in the phar, use the original path */
  249. efree(arch);
  250. goto skip_phar;
  251. } else {
  252. name = ZSTR_VAL(entry_str);
  253. }
  254. } else {
  255. entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
  256. if (entry[0] == '/') {
  257. if (!zend_hash_str_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
  258. /* this file is not in the phar, use the original path */
  259. notfound:
  260. efree(entry);
  261. efree(arch);
  262. goto skip_phar;
  263. }
  264. } else {
  265. if (!zend_hash_str_exists(&(phar->manifest), entry, entry_len)) {
  266. goto notfound;
  267. }
  268. }
  269. /* auto-convert to phar:// */
  270. if (entry[0] == '/') {
  271. spprintf(&name, 4096, "phar://%s%s", arch, entry);
  272. } else {
  273. spprintf(&name, 4096, "phar://%s/%s", arch, entry);
  274. }
  275. efree(entry);
  276. }
  277. efree(arch);
  278. context = php_stream_context_from_zval(zcontext, 0);
  279. stream = php_stream_open_wrapper_ex(name, "rb", 0 | REPORT_ERRORS, NULL, context);
  280. if (entry_str) {
  281. zend_string_release_ex(entry_str, 0);
  282. } else {
  283. efree(name);
  284. }
  285. if (stream == NULL) {
  286. RETURN_FALSE;
  287. }
  288. size = php_stream_passthru(stream);
  289. php_stream_close(stream);
  290. RETURN_LONG(size);
  291. }
  292. skip_phar:
  293. PHAR_G(orig_readfile)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  294. return;
  295. }
  296. /* }}} */
  297. PHAR_FUNC(phar_fopen) /* {{{ */
  298. {
  299. char *filename, *mode;
  300. size_t filename_len, mode_len;
  301. bool use_include_path = 0;
  302. zval *zcontext = NULL;
  303. php_stream *stream;
  304. if (!PHAR_G(intercepted)) {
  305. goto skip_phar;
  306. }
  307. if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
  308. && !HT_IS_INITIALIZED(&cached_phars)) {
  309. /* no need to check, include_path not even specified in fopen/ no active phars */
  310. goto skip_phar;
  311. }
  312. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "ps|br!", &filename, &filename_len, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) {
  313. goto skip_phar;
  314. }
  315. if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
  316. char *arch, *entry, *fname;
  317. zend_string *entry_str = NULL;
  318. size_t arch_len, entry_len, fname_len;
  319. php_stream_context *context = NULL;
  320. char *name;
  321. phar_archive_data *phar;
  322. fname = (char*)zend_get_executed_filename();
  323. if (strncasecmp(fname, "phar://", 7)) {
  324. goto skip_phar;
  325. }
  326. fname_len = strlen(fname);
  327. if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
  328. goto skip_phar;
  329. }
  330. efree(entry);
  331. entry = filename;
  332. /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
  333. entry_len = filename_len;
  334. /* retrieving a file defaults to within the current directory, so use this if possible */
  335. if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
  336. efree(arch);
  337. goto skip_phar;
  338. }
  339. if (use_include_path) {
  340. if (!(entry_str = phar_find_in_include_path(entry, entry_len, NULL))) {
  341. /* this file is not in the phar, use the original path */
  342. efree(arch);
  343. goto skip_phar;
  344. } else {
  345. name = ZSTR_VAL(entry_str);
  346. }
  347. } else {
  348. entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
  349. if (entry[0] == '/') {
  350. if (!zend_hash_str_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
  351. /* this file is not in the phar, use the original path */
  352. notfound:
  353. efree(entry);
  354. efree(arch);
  355. goto skip_phar;
  356. }
  357. } else {
  358. if (!zend_hash_str_exists(&(phar->manifest), entry, entry_len)) {
  359. /* this file is not in the phar, use the original path */
  360. goto notfound;
  361. }
  362. }
  363. /* auto-convert to phar:// */
  364. if (entry[0] == '/') {
  365. spprintf(&name, 4096, "phar://%s%s", arch, entry);
  366. } else {
  367. spprintf(&name, 4096, "phar://%s/%s", arch, entry);
  368. }
  369. efree(entry);
  370. }
  371. efree(arch);
  372. context = php_stream_context_from_zval(zcontext, 0);
  373. stream = php_stream_open_wrapper_ex(name, mode, 0 | REPORT_ERRORS, NULL, context);
  374. if (entry_str) {
  375. zend_string_release_ex(entry_str, 0);
  376. } else {
  377. efree(name);
  378. }
  379. if (stream == NULL) {
  380. RETURN_FALSE;
  381. }
  382. php_stream_to_zval(stream, return_value);
  383. if (zcontext) {
  384. Z_ADDREF_P(zcontext);
  385. }
  386. return;
  387. }
  388. skip_phar:
  389. PHAR_G(orig_fopen)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  390. return;
  391. }
  392. /* }}} */
  393. #define IS_LINK_OPERATION(__t) ((__t) == FS_TYPE || (__t) == FS_IS_LINK || (__t) == FS_LSTAT)
  394. #define IS_EXISTS_CHECK(__t) ((__t) == FS_EXISTS || (__t) == FS_IS_W || (__t) == FS_IS_R || (__t) == FS_IS_X || (__t) == FS_IS_FILE || (__t) == FS_IS_DIR || (__t) == FS_IS_LINK)
  395. #define IS_ABLE_CHECK(__t) ((__t) == FS_IS_R || (__t) == FS_IS_W || (__t) == FS_IS_X)
  396. #define IS_ACCESS_CHECK(__t) (IS_ABLE_CHECK(type) || (__t) == FS_EXISTS)
  397. /* {{{ php_stat */
  398. static void phar_fancy_stat(zend_stat_t *stat_sb, int type, zval *return_value)
  399. {
  400. zval stat_dev, stat_ino, stat_mode, stat_nlink, stat_uid, stat_gid, stat_rdev,
  401. stat_size, stat_atime, stat_mtime, stat_ctime, stat_blksize, stat_blocks;
  402. int rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */
  403. char *stat_sb_names[13] = {
  404. "dev", "ino", "mode", "nlink", "uid", "gid", "rdev",
  405. "size", "atime", "mtime", "ctime", "blksize", "blocks"
  406. };
  407. if (type >= FS_IS_W && type <= FS_IS_X) {
  408. if(stat_sb->st_uid==getuid()) {
  409. rmask=S_IRUSR;
  410. wmask=S_IWUSR;
  411. xmask=S_IXUSR;
  412. } else if(stat_sb->st_gid==getgid()) {
  413. rmask=S_IRGRP;
  414. wmask=S_IWGRP;
  415. xmask=S_IXGRP;
  416. } else {
  417. int groups, n, i;
  418. gid_t *gids;
  419. groups = getgroups(0, NULL);
  420. if(groups > 0) {
  421. gids=(gid_t *)safe_emalloc(groups, sizeof(gid_t), 0);
  422. n=getgroups(groups, gids);
  423. for(i=0;i<n;++i){
  424. if(stat_sb->st_gid==gids[i]) {
  425. rmask=S_IRGRP;
  426. wmask=S_IWGRP;
  427. xmask=S_IXGRP;
  428. break;
  429. }
  430. }
  431. efree(gids);
  432. }
  433. }
  434. }
  435. switch (type) {
  436. case FS_PERMS:
  437. RETURN_LONG((zend_long)stat_sb->st_mode);
  438. case FS_INODE:
  439. RETURN_LONG((zend_long)stat_sb->st_ino);
  440. case FS_SIZE:
  441. RETURN_LONG((zend_long)stat_sb->st_size);
  442. case FS_OWNER:
  443. RETURN_LONG((zend_long)stat_sb->st_uid);
  444. case FS_GROUP:
  445. RETURN_LONG((zend_long)stat_sb->st_gid);
  446. case FS_ATIME:
  447. RETURN_LONG((zend_long)stat_sb->st_atime);
  448. case FS_MTIME:
  449. RETURN_LONG((zend_long)stat_sb->st_mtime);
  450. case FS_CTIME:
  451. RETURN_LONG((zend_long)stat_sb->st_ctime);
  452. case FS_TYPE:
  453. if (S_ISLNK(stat_sb->st_mode)) {
  454. RETURN_STRING("link");
  455. }
  456. switch(stat_sb->st_mode & S_IFMT) {
  457. case S_IFDIR: RETURN_STRING("dir");
  458. case S_IFREG: RETURN_STRING("file");
  459. }
  460. php_error_docref(NULL, E_NOTICE, "Unknown file type (%u)", stat_sb->st_mode & S_IFMT);
  461. RETURN_STRING("unknown");
  462. case FS_IS_W:
  463. RETURN_BOOL((stat_sb->st_mode & wmask) != 0);
  464. case FS_IS_R:
  465. RETURN_BOOL((stat_sb->st_mode&rmask)!=0);
  466. case FS_IS_X:
  467. RETURN_BOOL((stat_sb->st_mode&xmask)!=0 && !S_ISDIR(stat_sb->st_mode));
  468. case FS_IS_FILE:
  469. RETURN_BOOL(S_ISREG(stat_sb->st_mode));
  470. case FS_IS_DIR:
  471. RETURN_BOOL(S_ISDIR(stat_sb->st_mode));
  472. case FS_IS_LINK:
  473. RETURN_BOOL(S_ISLNK(stat_sb->st_mode));
  474. case FS_EXISTS:
  475. RETURN_TRUE; /* the false case was done earlier */
  476. case FS_LSTAT:
  477. /* FALLTHROUGH */
  478. case FS_STAT:
  479. array_init(return_value);
  480. ZVAL_LONG(&stat_dev, stat_sb->st_dev);
  481. ZVAL_LONG(&stat_ino, stat_sb->st_ino);
  482. ZVAL_LONG(&stat_mode, stat_sb->st_mode);
  483. ZVAL_LONG(&stat_nlink, stat_sb->st_nlink);
  484. ZVAL_LONG(&stat_uid, stat_sb->st_uid);
  485. ZVAL_LONG(&stat_gid, stat_sb->st_gid);
  486. #ifdef HAVE_STRUCT_STAT_ST_RDEV
  487. ZVAL_LONG(&stat_rdev, stat_sb->st_rdev);
  488. #else
  489. ZVAL_LONG(&stat_rdev, -1);
  490. #endif
  491. ZVAL_LONG(&stat_size, stat_sb->st_size);
  492. ZVAL_LONG(&stat_atime, stat_sb->st_atime);
  493. ZVAL_LONG(&stat_mtime, stat_sb->st_mtime);
  494. ZVAL_LONG(&stat_ctime, stat_sb->st_ctime);
  495. #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
  496. ZVAL_LONG(&stat_blksize, stat_sb->st_blksize);
  497. #else
  498. ZVAL_LONG(&stat_blksize,-1);
  499. #endif
  500. #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
  501. ZVAL_LONG(&stat_blocks, stat_sb->st_blocks);
  502. #else
  503. ZVAL_LONG(&stat_blocks,-1);
  504. #endif
  505. /* Store numeric indexes in proper order */
  506. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_dev);
  507. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_ino);
  508. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_mode);
  509. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_nlink);
  510. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_uid);
  511. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_gid);
  512. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_rdev);
  513. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_size);
  514. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_atime);
  515. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_mtime);
  516. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_ctime);
  517. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_blksize);
  518. zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_blocks);
  519. /* Store string indexes referencing the same zval*/
  520. zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[0], strlen(stat_sb_names[0]), &stat_dev);
  521. zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[1], strlen(stat_sb_names[1]), &stat_ino);
  522. zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[2], strlen(stat_sb_names[2]), &stat_mode);
  523. zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[3], strlen(stat_sb_names[3]), &stat_nlink);
  524. zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[4], strlen(stat_sb_names[4]), &stat_uid);
  525. zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[5], strlen(stat_sb_names[5]), &stat_gid);
  526. zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[6], strlen(stat_sb_names[6]), &stat_rdev);
  527. zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[7], strlen(stat_sb_names[7]), &stat_size);
  528. zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[8], strlen(stat_sb_names[8]), &stat_atime);
  529. zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[9], strlen(stat_sb_names[9]), &stat_mtime);
  530. zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[10], strlen(stat_sb_names[10]), &stat_ctime);
  531. zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[11], strlen(stat_sb_names[11]), &stat_blksize);
  532. zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[12], strlen(stat_sb_names[12]), &stat_blocks);
  533. return;
  534. }
  535. php_error_docref(NULL, E_WARNING, "Didn't understand stat call");
  536. RETURN_FALSE;
  537. }
  538. /* }}} */
  539. static void phar_file_stat(const char *filename, size_t filename_length, int type, zif_handler orig_stat_func, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
  540. {
  541. if (!filename_length) {
  542. RETURN_FALSE;
  543. }
  544. if (!IS_ABSOLUTE_PATH(filename, filename_length) && !strstr(filename, "://")) {
  545. char *arch, *entry, *fname;
  546. size_t arch_len, entry_len, fname_len;
  547. zend_stat_t sb = {0};
  548. phar_entry_info *data = NULL;
  549. phar_archive_data *phar;
  550. fname = (char*)zend_get_executed_filename();
  551. /* we are checking for existence of a file within the relative path. Chances are good that this is
  552. retrieving something from within the phar archive */
  553. if (strncasecmp(fname, "phar://", 7)) {
  554. goto skip_phar;
  555. }
  556. fname_len = strlen(fname);
  557. if (PHAR_G(last_phar) && fname_len - 7 >= PHAR_G(last_phar_name_len) && !memcmp(fname + 7, PHAR_G(last_phar_name), PHAR_G(last_phar_name_len))) {
  558. arch = estrndup(PHAR_G(last_phar_name), PHAR_G(last_phar_name_len));
  559. arch_len = PHAR_G(last_phar_name_len);
  560. entry = estrndup(filename, filename_length);
  561. /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
  562. entry_len = filename_length;
  563. phar = PHAR_G(last_phar);
  564. goto splitted;
  565. }
  566. if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
  567. efree(entry);
  568. entry = estrndup(filename, filename_length);
  569. /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
  570. entry_len = filename_length;
  571. if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
  572. efree(arch);
  573. efree(entry);
  574. goto skip_phar;
  575. }
  576. splitted:
  577. entry = phar_fix_filepath(entry, &entry_len, 1);
  578. if (entry[0] == '/') {
  579. if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
  580. efree(entry);
  581. goto stat_entry;
  582. }
  583. goto notfound;
  584. }
  585. if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
  586. efree(entry);
  587. goto stat_entry;
  588. }
  589. if (zend_hash_str_exists(&(phar->virtual_dirs), entry, entry_len)) {
  590. efree(entry);
  591. efree(arch);
  592. if (IS_EXISTS_CHECK(type)) {
  593. RETURN_TRUE;
  594. }
  595. sb.st_size = 0;
  596. sb.st_mode = 0777;
  597. sb.st_mode |= S_IFDIR; /* regular directory */
  598. sb.st_mtime = phar->max_timestamp;
  599. sb.st_atime = phar->max_timestamp;
  600. sb.st_ctime = phar->max_timestamp;
  601. goto statme_baby;
  602. } else {
  603. char *save;
  604. size_t save_len;
  605. notfound:
  606. efree(entry);
  607. save = PHAR_G(cwd);
  608. save_len = PHAR_G(cwd_len);
  609. /* this file is not in the current directory, use the original path */
  610. entry = estrndup(filename, filename_length);
  611. entry_len = filename_length;
  612. PHAR_G(cwd) = "/";
  613. PHAR_G(cwd_len) = 0;
  614. /* clean path without cwd */
  615. entry = phar_fix_filepath(entry, &entry_len, 1);
  616. if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
  617. PHAR_G(cwd) = save;
  618. PHAR_G(cwd_len) = save_len;
  619. efree(entry);
  620. if (IS_EXISTS_CHECK(type)) {
  621. efree(arch);
  622. RETURN_TRUE;
  623. }
  624. goto stat_entry;
  625. }
  626. if (zend_hash_str_exists(&(phar->virtual_dirs), entry + 1, entry_len - 1)) {
  627. PHAR_G(cwd) = save;
  628. PHAR_G(cwd_len) = save_len;
  629. efree(entry);
  630. efree(arch);
  631. if (IS_EXISTS_CHECK(type)) {
  632. RETURN_TRUE;
  633. }
  634. sb.st_size = 0;
  635. sb.st_mode = 0777;
  636. sb.st_mode |= S_IFDIR; /* regular directory */
  637. sb.st_mtime = phar->max_timestamp;
  638. sb.st_atime = phar->max_timestamp;
  639. sb.st_ctime = phar->max_timestamp;
  640. goto statme_baby;
  641. }
  642. PHAR_G(cwd) = save;
  643. PHAR_G(cwd_len) = save_len;
  644. efree(entry);
  645. efree(arch);
  646. /* Error Occurred */
  647. if (!IS_EXISTS_CHECK(type)) {
  648. php_error_docref(NULL, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename);
  649. }
  650. RETURN_FALSE;
  651. }
  652. stat_entry:
  653. efree(arch);
  654. if (!data->is_dir) {
  655. sb.st_size = data->uncompressed_filesize;
  656. sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
  657. if (data->link) {
  658. sb.st_mode |= S_IFREG|S_IFLNK; /* regular file */
  659. } else {
  660. sb.st_mode |= S_IFREG; /* regular file */
  661. }
  662. /* timestamp is just the timestamp when this was added to the phar */
  663. sb.st_mtime = data->timestamp;
  664. sb.st_atime = data->timestamp;
  665. sb.st_ctime = data->timestamp;
  666. } else {
  667. sb.st_size = 0;
  668. sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
  669. sb.st_mode |= S_IFDIR; /* regular directory */
  670. if (data->link) {
  671. sb.st_mode |= S_IFLNK;
  672. }
  673. /* timestamp is just the timestamp when this was added to the phar */
  674. sb.st_mtime = data->timestamp;
  675. sb.st_atime = data->timestamp;
  676. sb.st_ctime = data->timestamp;
  677. }
  678. statme_baby:
  679. if (!phar->is_writeable) {
  680. sb.st_mode = (sb.st_mode & 0555) | (sb.st_mode & ~0777);
  681. }
  682. sb.st_nlink = 1;
  683. sb.st_rdev = -1;
  684. /* this is only for APC, so use /dev/null device - no chance of conflict there! */
  685. sb.st_dev = 0xc;
  686. /* generate unique inode number for alias/filename, so no phars will conflict */
  687. if (data) {
  688. sb.st_ino = data->inode;
  689. }
  690. #ifndef PHP_WIN32
  691. sb.st_blksize = -1;
  692. sb.st_blocks = -1;
  693. #endif
  694. phar_fancy_stat(&sb, type, return_value);
  695. return;
  696. }
  697. }
  698. skip_phar:
  699. orig_stat_func(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  700. return;
  701. }
  702. /* }}} */
  703. #define PharFileFunction(fname, funcnum, orig) \
  704. ZEND_NAMED_FUNCTION(fname) { \
  705. if (!PHAR_G(intercepted)) { \
  706. PHAR_G(orig)(INTERNAL_FUNCTION_PARAM_PASSTHRU); \
  707. } else { \
  708. char *filename; \
  709. size_t filename_len; \
  710. \
  711. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) { \
  712. RETURN_THROWS(); \
  713. } \
  714. \
  715. phar_file_stat(filename, filename_len, funcnum, PHAR_G(orig), INTERNAL_FUNCTION_PARAM_PASSTHRU); \
  716. } \
  717. }
  718. /* }}} */
  719. /* {{{ Get file permissions */
  720. PharFileFunction(phar_fileperms, FS_PERMS, orig_fileperms)
  721. /* }}} */
  722. /* {{{ Get file inode */
  723. PharFileFunction(phar_fileinode, FS_INODE, orig_fileinode)
  724. /* }}} */
  725. /* {{{ Get file size */
  726. PharFileFunction(phar_filesize, FS_SIZE, orig_filesize)
  727. /* }}} */
  728. /* {{{ Get file owner */
  729. PharFileFunction(phar_fileowner, FS_OWNER, orig_fileowner)
  730. /* }}} */
  731. /* {{{ Get file group */
  732. PharFileFunction(phar_filegroup, FS_GROUP, orig_filegroup)
  733. /* }}} */
  734. /* {{{ Get last access time of file */
  735. PharFileFunction(phar_fileatime, FS_ATIME, orig_fileatime)
  736. /* }}} */
  737. /* {{{ Get last modification time of file */
  738. PharFileFunction(phar_filemtime, FS_MTIME, orig_filemtime)
  739. /* }}} */
  740. /* {{{ Get inode modification time of file */
  741. PharFileFunction(phar_filectime, FS_CTIME, orig_filectime)
  742. /* }}} */
  743. /* {{{ Get file type */
  744. PharFileFunction(phar_filetype, FS_TYPE, orig_filetype)
  745. /* }}} */
  746. /* {{{ Returns true if file can be written */
  747. PharFileFunction(phar_is_writable, FS_IS_W, orig_is_writable)
  748. /* }}} */
  749. /* {{{ Returns true if file can be read */
  750. PharFileFunction(phar_is_readable, FS_IS_R, orig_is_readable)
  751. /* }}} */
  752. /* {{{ Returns true if file is executable */
  753. PharFileFunction(phar_is_executable, FS_IS_X, orig_is_executable)
  754. /* }}} */
  755. /* {{{ Returns true if filename exists */
  756. PharFileFunction(phar_file_exists, FS_EXISTS, orig_file_exists)
  757. /* }}} */
  758. /* {{{ Returns true if file is directory */
  759. PharFileFunction(phar_is_dir, FS_IS_DIR, orig_is_dir)
  760. /* }}} */
  761. PHAR_FUNC(phar_is_file) /* {{{ */
  762. {
  763. char *filename;
  764. size_t filename_len;
  765. if (!PHAR_G(intercepted)) {
  766. goto skip_phar;
  767. }
  768. if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
  769. && !HT_IS_INITIALIZED(&cached_phars)) {
  770. goto skip_phar;
  771. }
  772. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) {
  773. goto skip_phar;
  774. }
  775. if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
  776. char *arch, *entry, *fname;
  777. size_t arch_len, entry_len, fname_len;
  778. fname = (char*)zend_get_executed_filename();
  779. /* we are checking for existence of a file within the relative path. Chances are good that this is
  780. retrieving something from within the phar archive */
  781. if (strncasecmp(fname, "phar://", 7)) {
  782. goto skip_phar;
  783. }
  784. fname_len = strlen(fname);
  785. if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
  786. phar_archive_data *phar;
  787. efree(entry);
  788. entry = filename;
  789. /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
  790. entry_len = filename_len;
  791. /* retrieving a file within the current directory, so use this if possible */
  792. if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
  793. phar_entry_info *etemp;
  794. entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
  795. if (entry[0] == '/') {
  796. if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
  797. /* this file is not in the current directory, use the original path */
  798. found_it:
  799. efree(entry);
  800. efree(arch);
  801. RETURN_BOOL(!etemp->is_dir);
  802. }
  803. } else {
  804. if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
  805. goto found_it;
  806. }
  807. }
  808. }
  809. if (entry != filename) {
  810. efree(entry);
  811. }
  812. efree(arch);
  813. RETURN_FALSE;
  814. }
  815. }
  816. skip_phar:
  817. PHAR_G(orig_is_file)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  818. return;
  819. }
  820. /* }}} */
  821. PHAR_FUNC(phar_is_link) /* {{{ */
  822. {
  823. char *filename;
  824. size_t filename_len;
  825. if (!PHAR_G(intercepted)) {
  826. goto skip_phar;
  827. }
  828. if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
  829. && !HT_IS_INITIALIZED(&cached_phars)) {
  830. goto skip_phar;
  831. }
  832. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) {
  833. goto skip_phar;
  834. }
  835. if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
  836. char *arch, *entry, *fname;
  837. size_t arch_len, entry_len, fname_len;
  838. fname = (char*)zend_get_executed_filename();
  839. /* we are checking for existence of a file within the relative path. Chances are good that this is
  840. retrieving something from within the phar archive */
  841. if (strncasecmp(fname, "phar://", 7)) {
  842. goto skip_phar;
  843. }
  844. fname_len = strlen(fname);
  845. if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
  846. phar_archive_data *phar;
  847. efree(entry);
  848. entry = filename;
  849. /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
  850. entry_len = filename_len;
  851. /* retrieving a file within the current directory, so use this if possible */
  852. if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
  853. phar_entry_info *etemp;
  854. entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
  855. if (entry[0] == '/') {
  856. if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
  857. /* this file is not in the current directory, use the original path */
  858. found_it:
  859. efree(entry);
  860. efree(arch);
  861. RETURN_BOOL(etemp->link);
  862. }
  863. } else {
  864. if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
  865. goto found_it;
  866. }
  867. }
  868. }
  869. efree(entry);
  870. efree(arch);
  871. RETURN_FALSE;
  872. }
  873. }
  874. skip_phar:
  875. PHAR_G(orig_is_link)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  876. return;
  877. }
  878. /* }}} */
  879. /* {{{ Give information about a file or symbolic link */
  880. PharFileFunction(phar_lstat, FS_LSTAT, orig_lstat)
  881. /* }}} */
  882. /* {{{ Give information about a file */
  883. PharFileFunction(phar_stat, FS_STAT, orig_stat)
  884. /* }}} */
  885. /* {{{ void phar_intercept_functions(void) */
  886. void phar_intercept_functions(void)
  887. {
  888. if (!PHAR_G(request_init)) {
  889. PHAR_G(cwd) = NULL;
  890. PHAR_G(cwd_len) = 0;
  891. }
  892. PHAR_G(intercepted) = 1;
  893. }
  894. /* }}} */
  895. /* {{{ void phar_release_functions(void) */
  896. void phar_release_functions(void)
  897. {
  898. PHAR_G(intercepted) = 0;
  899. }
  900. /* }}} */
  901. /* {{{ void phar_intercept_functions_init(void) */
  902. #define PHAR_INTERCEPT(func) \
  903. PHAR_G(orig_##func) = NULL; \
  904. if (NULL != (orig = zend_hash_str_find_ptr(CG(function_table), #func, sizeof(#func)-1))) { \
  905. PHAR_G(orig_##func) = orig->internal_function.handler; \
  906. orig->internal_function.handler = phar_##func; \
  907. }
  908. void phar_intercept_functions_init(void)
  909. {
  910. zend_function *orig;
  911. PHAR_INTERCEPT(fopen);
  912. PHAR_INTERCEPT(file_get_contents);
  913. PHAR_INTERCEPT(is_file);
  914. PHAR_INTERCEPT(is_link);
  915. PHAR_INTERCEPT(is_dir);
  916. PHAR_INTERCEPT(opendir);
  917. PHAR_INTERCEPT(file_exists);
  918. PHAR_INTERCEPT(fileperms);
  919. PHAR_INTERCEPT(fileinode);
  920. PHAR_INTERCEPT(filesize);
  921. PHAR_INTERCEPT(fileowner);
  922. PHAR_INTERCEPT(filegroup);
  923. PHAR_INTERCEPT(fileatime);
  924. PHAR_INTERCEPT(filemtime);
  925. PHAR_INTERCEPT(filectime);
  926. PHAR_INTERCEPT(filetype);
  927. PHAR_INTERCEPT(is_writable);
  928. PHAR_INTERCEPT(is_readable);
  929. PHAR_INTERCEPT(is_executable);
  930. PHAR_INTERCEPT(lstat);
  931. PHAR_INTERCEPT(stat);
  932. PHAR_INTERCEPT(readfile);
  933. PHAR_G(intercepted) = 0;
  934. }
  935. /* }}} */
  936. /* {{{ void phar_intercept_functions_shutdown(void) */
  937. #define PHAR_RELEASE(func) \
  938. if (PHAR_G(orig_##func) && NULL != (orig = zend_hash_str_find_ptr(CG(function_table), #func, sizeof(#func)-1))) { \
  939. orig->internal_function.handler = PHAR_G(orig_##func); \
  940. } \
  941. PHAR_G(orig_##func) = NULL;
  942. void phar_intercept_functions_shutdown(void)
  943. {
  944. zend_function *orig;
  945. PHAR_RELEASE(fopen);
  946. PHAR_RELEASE(file_get_contents);
  947. PHAR_RELEASE(is_file);
  948. PHAR_RELEASE(is_dir);
  949. PHAR_RELEASE(opendir);
  950. PHAR_RELEASE(file_exists);
  951. PHAR_RELEASE(fileperms);
  952. PHAR_RELEASE(fileinode);
  953. PHAR_RELEASE(filesize);
  954. PHAR_RELEASE(fileowner);
  955. PHAR_RELEASE(filegroup);
  956. PHAR_RELEASE(fileatime);
  957. PHAR_RELEASE(filemtime);
  958. PHAR_RELEASE(filectime);
  959. PHAR_RELEASE(filetype);
  960. PHAR_RELEASE(is_writable);
  961. PHAR_RELEASE(is_readable);
  962. PHAR_RELEASE(is_executable);
  963. PHAR_RELEASE(lstat);
  964. PHAR_RELEASE(stat);
  965. PHAR_RELEASE(readfile);
  966. PHAR_G(intercepted) = 0;
  967. }
  968. /* }}} */
  969. static struct _phar_orig_functions {
  970. zif_handler orig_fopen;
  971. zif_handler orig_file_get_contents;
  972. zif_handler orig_is_file;
  973. zif_handler orig_is_link;
  974. zif_handler orig_is_dir;
  975. zif_handler orig_opendir;
  976. zif_handler orig_file_exists;
  977. zif_handler orig_fileperms;
  978. zif_handler orig_fileinode;
  979. zif_handler orig_filesize;
  980. zif_handler orig_fileowner;
  981. zif_handler orig_filegroup;
  982. zif_handler orig_fileatime;
  983. zif_handler orig_filemtime;
  984. zif_handler orig_filectime;
  985. zif_handler orig_filetype;
  986. zif_handler orig_is_writable;
  987. zif_handler orig_is_readable;
  988. zif_handler orig_is_executable;
  989. zif_handler orig_lstat;
  990. zif_handler orig_readfile;
  991. zif_handler orig_stat;
  992. } phar_orig_functions = {0};
  993. void phar_save_orig_functions(void) /* {{{ */
  994. {
  995. phar_orig_functions.orig_fopen = PHAR_G(orig_fopen);
  996. phar_orig_functions.orig_file_get_contents = PHAR_G(orig_file_get_contents);
  997. phar_orig_functions.orig_is_file = PHAR_G(orig_is_file);
  998. phar_orig_functions.orig_is_link = PHAR_G(orig_is_link);
  999. phar_orig_functions.orig_is_dir = PHAR_G(orig_is_dir);
  1000. phar_orig_functions.orig_opendir = PHAR_G(orig_opendir);
  1001. phar_orig_functions.orig_file_exists = PHAR_G(orig_file_exists);
  1002. phar_orig_functions.orig_fileperms = PHAR_G(orig_fileperms);
  1003. phar_orig_functions.orig_fileinode = PHAR_G(orig_fileinode);
  1004. phar_orig_functions.orig_filesize = PHAR_G(orig_filesize);
  1005. phar_orig_functions.orig_fileowner = PHAR_G(orig_fileowner);
  1006. phar_orig_functions.orig_filegroup = PHAR_G(orig_filegroup);
  1007. phar_orig_functions.orig_fileatime = PHAR_G(orig_fileatime);
  1008. phar_orig_functions.orig_filemtime = PHAR_G(orig_filemtime);
  1009. phar_orig_functions.orig_filectime = PHAR_G(orig_filectime);
  1010. phar_orig_functions.orig_filetype = PHAR_G(orig_filetype);
  1011. phar_orig_functions.orig_is_writable = PHAR_G(orig_is_writable);
  1012. phar_orig_functions.orig_is_readable = PHAR_G(orig_is_readable);
  1013. phar_orig_functions.orig_is_executable = PHAR_G(orig_is_executable);
  1014. phar_orig_functions.orig_lstat = PHAR_G(orig_lstat);
  1015. phar_orig_functions.orig_readfile = PHAR_G(orig_readfile);
  1016. phar_orig_functions.orig_stat = PHAR_G(orig_stat);
  1017. }
  1018. /* }}} */
  1019. void phar_restore_orig_functions(void) /* {{{ */
  1020. {
  1021. PHAR_G(orig_fopen) = phar_orig_functions.orig_fopen;
  1022. PHAR_G(orig_file_get_contents) = phar_orig_functions.orig_file_get_contents;
  1023. PHAR_G(orig_is_file) = phar_orig_functions.orig_is_file;
  1024. PHAR_G(orig_is_link) = phar_orig_functions.orig_is_link;
  1025. PHAR_G(orig_is_dir) = phar_orig_functions.orig_is_dir;
  1026. PHAR_G(orig_opendir) = phar_orig_functions.orig_opendir;
  1027. PHAR_G(orig_file_exists) = phar_orig_functions.orig_file_exists;
  1028. PHAR_G(orig_fileperms) = phar_orig_functions.orig_fileperms;
  1029. PHAR_G(orig_fileinode) = phar_orig_functions.orig_fileinode;
  1030. PHAR_G(orig_filesize) = phar_orig_functions.orig_filesize;
  1031. PHAR_G(orig_fileowner) = phar_orig_functions.orig_fileowner;
  1032. PHAR_G(orig_filegroup) = phar_orig_functions.orig_filegroup;
  1033. PHAR_G(orig_fileatime) = phar_orig_functions.orig_fileatime;
  1034. PHAR_G(orig_filemtime) = phar_orig_functions.orig_filemtime;
  1035. PHAR_G(orig_filectime) = phar_orig_functions.orig_filectime;
  1036. PHAR_G(orig_filetype) = phar_orig_functions.orig_filetype;
  1037. PHAR_G(orig_is_writable) = phar_orig_functions.orig_is_writable;
  1038. PHAR_G(orig_is_readable) = phar_orig_functions.orig_is_readable;
  1039. PHAR_G(orig_is_executable) = phar_orig_functions.orig_is_executable;
  1040. PHAR_G(orig_lstat) = phar_orig_functions.orig_lstat;
  1041. PHAR_G(orig_readfile) = phar_orig_functions.orig_readfile;
  1042. PHAR_G(orig_stat) = phar_orig_functions.orig_stat;
  1043. }
  1044. /* }}} */