func_interceptors.c 36 KB

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