12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145 |
- /*
- +----------------------------------------------------------------------+
- | phar php single-file executable PHP extension |
- +----------------------------------------------------------------------+
- | Copyright (c) The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | https://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: Gregory Beaver <cellog@php.net> |
- +----------------------------------------------------------------------+
- */
- #include "phar_internal.h"
- #define PHAR_FUNC(name) \
- static PHP_NAMED_FUNCTION(name)
- PHAR_FUNC(phar_opendir) /* {{{ */
- {
- char *filename;
- size_t filename_len;
- zval *zcontext = NULL;
- if (!PHAR_G(intercepted)) {
- goto skip_phar;
- }
- if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
- && !HT_IS_INITIALIZED(&cached_phars)) {
- goto skip_phar;
- }
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|r!", &filename, &filename_len, &zcontext) == FAILURE) {
- RETURN_THROWS();
- }
- if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
- char *arch, *entry, *fname;
- size_t arch_len, entry_len, fname_len;
- fname = (char*)zend_get_executed_filename();
- /* we are checking for existence of a file within the relative path. Chances are good that this is
- retrieving something from within the phar archive */
- if (strncasecmp(fname, "phar://", 7)) {
- goto skip_phar;
- }
- fname_len = strlen(fname);
- if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
- php_stream_context *context = NULL;
- php_stream *stream;
- char *name;
- efree(entry);
- entry = estrndup(filename, filename_len);
- /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
- entry_len = filename_len;
- /* retrieving a file within the current directory, so use this if possible */
- entry = phar_fix_filepath(entry, &entry_len, 1);
- if (entry[0] == '/') {
- spprintf(&name, 4096, "phar://%s%s", arch, entry);
- } else {
- spprintf(&name, 4096, "phar://%s/%s", arch, entry);
- }
- efree(entry);
- efree(arch);
- if (zcontext) {
- context = php_stream_context_from_zval(zcontext, 0);
- }
- stream = php_stream_opendir(name, REPORT_ERRORS, context);
- efree(name);
- if (!stream) {
- RETURN_FALSE;
- }
- php_stream_to_zval(stream, return_value);
- return;
- }
- }
- skip_phar:
- PHAR_G(orig_opendir)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
- return;
- }
- /* }}} */
- PHAR_FUNC(phar_file_get_contents) /* {{{ */
- {
- char *filename;
- size_t filename_len;
- zend_string *contents;
- bool use_include_path = 0;
- php_stream *stream;
- zend_long offset = -1;
- zend_long maxlen;
- bool maxlen_is_null = 1;
- zval *zcontext = NULL;
- if (!PHAR_G(intercepted)) {
- goto skip_phar;
- }
- if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
- && !HT_IS_INITIALIZED(&cached_phars)) {
- goto skip_phar;
- }
- /* Parse arguments */
- 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) {
- goto skip_phar;
- }
- if (maxlen_is_null) {
- maxlen = (ssize_t) PHP_STREAM_COPY_ALL;
- }
- if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
- char *arch, *entry, *fname;
- zend_string *entry_str = NULL;
- size_t arch_len, entry_len, fname_len;
- php_stream_context *context = NULL;
- fname = (char*)zend_get_executed_filename();
- if (strncasecmp(fname, "phar://", 7)) {
- goto skip_phar;
- }
- fname_len = strlen(fname);
- if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
- char *name;
- phar_archive_data *phar;
- efree(entry);
- entry = filename;
- /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
- entry_len = filename_len;
- if (!maxlen_is_null && maxlen < 0) {
- efree(arch);
- zend_argument_value_error(5, "must be greater than or equal to 0");
- RETURN_THROWS();
- }
- /* retrieving a file defaults to within the current directory, so use this if possible */
- if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
- efree(arch);
- goto skip_phar;
- }
- if (use_include_path) {
- if ((entry_str = phar_find_in_include_path(entry, entry_len, NULL))) {
- name = ZSTR_VAL(entry_str);
- goto phar_it;
- } else {
- /* this file is not in the phar, use the original path */
- efree(arch);
- goto skip_phar;
- }
- } else {
- entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
- if (entry[0] == '/') {
- if (!zend_hash_str_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
- /* this file is not in the phar, use the original path */
- notfound:
- efree(arch);
- efree(entry);
- goto skip_phar;
- }
- } else {
- if (!zend_hash_str_exists(&(phar->manifest), entry, entry_len)) {
- goto notfound;
- }
- }
- /* auto-convert to phar:// */
- if (entry[0] == '/') {
- spprintf(&name, 4096, "phar://%s%s", arch, entry);
- } else {
- spprintf(&name, 4096, "phar://%s/%s", arch, entry);
- }
- if (entry != filename) {
- efree(entry);
- }
- }
- phar_it:
- efree(arch);
- if (zcontext) {
- context = php_stream_context_from_zval(zcontext, 0);
- }
- stream = php_stream_open_wrapper_ex(name, "rb", 0 | REPORT_ERRORS, NULL, context);
- if (entry_str) {
- zend_string_release_ex(entry_str, 0);
- } else {
- efree(name);
- }
- if (!stream) {
- RETURN_FALSE;
- }
- if (offset > 0 && php_stream_seek(stream, offset, SEEK_SET) < 0) {
- php_error_docref(NULL, E_WARNING, "Failed to seek to position " ZEND_LONG_FMT " in the stream", offset);
- php_stream_close(stream);
- RETURN_FALSE;
- }
- /* uses mmap if possible */
- contents = php_stream_copy_to_mem(stream, maxlen, 0);
- if (contents && ZSTR_LEN(contents) > 0) {
- RETVAL_STR(contents);
- } else if (contents) {
- zend_string_release_ex(contents, 0);
- RETVAL_EMPTY_STRING();
- } else {
- RETVAL_FALSE;
- }
- php_stream_close(stream);
- return;
- }
- }
- skip_phar:
- PHAR_G(orig_file_get_contents)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
- return;
- }
- /* }}} */
- PHAR_FUNC(phar_readfile) /* {{{ */
- {
- char *filename;
- size_t filename_len;
- int size = 0;
- bool use_include_path = 0;
- zval *zcontext = NULL;
- php_stream *stream;
- if (!PHAR_G(intercepted)) {
- goto skip_phar;
- }
- if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
- && !HT_IS_INITIALIZED(&cached_phars)) {
- goto skip_phar;
- }
- if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) {
- goto skip_phar;
- }
- if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
- char *arch, *entry, *fname;
- zend_string *entry_str = NULL;
- size_t arch_len, entry_len, fname_len;
- php_stream_context *context = NULL;
- char *name;
- phar_archive_data *phar;
- fname = (char*)zend_get_executed_filename();
- if (strncasecmp(fname, "phar://", 7)) {
- goto skip_phar;
- }
- fname_len = strlen(fname);
- if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
- goto skip_phar;
- }
- efree(entry);
- entry = filename;
- /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
- entry_len = filename_len;
- /* retrieving a file defaults to within the current directory, so use this if possible */
- if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
- efree(arch);
- goto skip_phar;
- }
- if (use_include_path) {
- if (!(entry_str = phar_find_in_include_path(entry, entry_len, NULL))) {
- /* this file is not in the phar, use the original path */
- efree(arch);
- goto skip_phar;
- } else {
- name = ZSTR_VAL(entry_str);
- }
- } else {
- entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
- if (entry[0] == '/') {
- if (!zend_hash_str_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
- /* this file is not in the phar, use the original path */
- notfound:
- efree(entry);
- efree(arch);
- goto skip_phar;
- }
- } else {
- if (!zend_hash_str_exists(&(phar->manifest), entry, entry_len)) {
- goto notfound;
- }
- }
- /* auto-convert to phar:// */
- if (entry[0] == '/') {
- spprintf(&name, 4096, "phar://%s%s", arch, entry);
- } else {
- spprintf(&name, 4096, "phar://%s/%s", arch, entry);
- }
- efree(entry);
- }
- efree(arch);
- context = php_stream_context_from_zval(zcontext, 0);
- stream = php_stream_open_wrapper_ex(name, "rb", 0 | REPORT_ERRORS, NULL, context);
- if (entry_str) {
- zend_string_release_ex(entry_str, 0);
- } else {
- efree(name);
- }
- if (stream == NULL) {
- RETURN_FALSE;
- }
- size = php_stream_passthru(stream);
- php_stream_close(stream);
- RETURN_LONG(size);
- }
- skip_phar:
- PHAR_G(orig_readfile)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
- return;
- }
- /* }}} */
- PHAR_FUNC(phar_fopen) /* {{{ */
- {
- char *filename, *mode;
- size_t filename_len, mode_len;
- bool use_include_path = 0;
- zval *zcontext = NULL;
- php_stream *stream;
- if (!PHAR_G(intercepted)) {
- goto skip_phar;
- }
- if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
- && !HT_IS_INITIALIZED(&cached_phars)) {
- /* no need to check, include_path not even specified in fopen/ no active phars */
- goto skip_phar;
- }
- 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) {
- goto skip_phar;
- }
- if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
- char *arch, *entry, *fname;
- zend_string *entry_str = NULL;
- size_t arch_len, entry_len, fname_len;
- php_stream_context *context = NULL;
- char *name;
- phar_archive_data *phar;
- fname = (char*)zend_get_executed_filename();
- if (strncasecmp(fname, "phar://", 7)) {
- goto skip_phar;
- }
- fname_len = strlen(fname);
- if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
- goto skip_phar;
- }
- efree(entry);
- entry = filename;
- /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
- entry_len = filename_len;
- /* retrieving a file defaults to within the current directory, so use this if possible */
- if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
- efree(arch);
- goto skip_phar;
- }
- if (use_include_path) {
- if (!(entry_str = phar_find_in_include_path(entry, entry_len, NULL))) {
- /* this file is not in the phar, use the original path */
- efree(arch);
- goto skip_phar;
- } else {
- name = ZSTR_VAL(entry_str);
- }
- } else {
- entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
- if (entry[0] == '/') {
- if (!zend_hash_str_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
- /* this file is not in the phar, use the original path */
- notfound:
- efree(entry);
- efree(arch);
- goto skip_phar;
- }
- } else {
- if (!zend_hash_str_exists(&(phar->manifest), entry, entry_len)) {
- /* this file is not in the phar, use the original path */
- goto notfound;
- }
- }
- /* auto-convert to phar:// */
- if (entry[0] == '/') {
- spprintf(&name, 4096, "phar://%s%s", arch, entry);
- } else {
- spprintf(&name, 4096, "phar://%s/%s", arch, entry);
- }
- efree(entry);
- }
- efree(arch);
- context = php_stream_context_from_zval(zcontext, 0);
- stream = php_stream_open_wrapper_ex(name, mode, 0 | REPORT_ERRORS, NULL, context);
- if (entry_str) {
- zend_string_release_ex(entry_str, 0);
- } else {
- efree(name);
- }
- if (stream == NULL) {
- RETURN_FALSE;
- }
- php_stream_to_zval(stream, return_value);
- if (zcontext) {
- Z_ADDREF_P(zcontext);
- }
- return;
- }
- skip_phar:
- PHAR_G(orig_fopen)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
- return;
- }
- /* }}} */
- #define IS_LINK_OPERATION(__t) ((__t) == FS_TYPE || (__t) == FS_IS_LINK || (__t) == FS_LSTAT)
- #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)
- #define IS_ABLE_CHECK(__t) ((__t) == FS_IS_R || (__t) == FS_IS_W || (__t) == FS_IS_X)
- #define IS_ACCESS_CHECK(__t) (IS_ABLE_CHECK(type) || (__t) == FS_EXISTS)
- /* {{{ php_stat */
- static void phar_fancy_stat(zend_stat_t *stat_sb, int type, zval *return_value)
- {
- zval stat_dev, stat_ino, stat_mode, stat_nlink, stat_uid, stat_gid, stat_rdev,
- stat_size, stat_atime, stat_mtime, stat_ctime, stat_blksize, stat_blocks;
- int rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */
- char *stat_sb_names[13] = {
- "dev", "ino", "mode", "nlink", "uid", "gid", "rdev",
- "size", "atime", "mtime", "ctime", "blksize", "blocks"
- };
- if (type >= FS_IS_W && type <= FS_IS_X) {
- if(stat_sb->st_uid==getuid()) {
- rmask=S_IRUSR;
- wmask=S_IWUSR;
- xmask=S_IXUSR;
- } else if(stat_sb->st_gid==getgid()) {
- rmask=S_IRGRP;
- wmask=S_IWGRP;
- xmask=S_IXGRP;
- } else {
- int groups, n, i;
- gid_t *gids;
- groups = getgroups(0, NULL);
- if(groups > 0) {
- gids=(gid_t *)safe_emalloc(groups, sizeof(gid_t), 0);
- n=getgroups(groups, gids);
- for(i=0;i<n;++i){
- if(stat_sb->st_gid==gids[i]) {
- rmask=S_IRGRP;
- wmask=S_IWGRP;
- xmask=S_IXGRP;
- break;
- }
- }
- efree(gids);
- }
- }
- }
- switch (type) {
- case FS_PERMS:
- RETURN_LONG((zend_long)stat_sb->st_mode);
- case FS_INODE:
- RETURN_LONG((zend_long)stat_sb->st_ino);
- case FS_SIZE:
- RETURN_LONG((zend_long)stat_sb->st_size);
- case FS_OWNER:
- RETURN_LONG((zend_long)stat_sb->st_uid);
- case FS_GROUP:
- RETURN_LONG((zend_long)stat_sb->st_gid);
- case FS_ATIME:
- RETURN_LONG((zend_long)stat_sb->st_atime);
- case FS_MTIME:
- RETURN_LONG((zend_long)stat_sb->st_mtime);
- case FS_CTIME:
- RETURN_LONG((zend_long)stat_sb->st_ctime);
- case FS_TYPE:
- if (S_ISLNK(stat_sb->st_mode)) {
- RETURN_STRING("link");
- }
- switch(stat_sb->st_mode & S_IFMT) {
- case S_IFDIR: RETURN_STRING("dir");
- case S_IFREG: RETURN_STRING("file");
- }
- php_error_docref(NULL, E_NOTICE, "Unknown file type (%u)", stat_sb->st_mode & S_IFMT);
- RETURN_STRING("unknown");
- case FS_IS_W:
- RETURN_BOOL((stat_sb->st_mode & wmask) != 0);
- case FS_IS_R:
- RETURN_BOOL((stat_sb->st_mode&rmask)!=0);
- case FS_IS_X:
- RETURN_BOOL((stat_sb->st_mode&xmask)!=0 && !S_ISDIR(stat_sb->st_mode));
- case FS_IS_FILE:
- RETURN_BOOL(S_ISREG(stat_sb->st_mode));
- case FS_IS_DIR:
- RETURN_BOOL(S_ISDIR(stat_sb->st_mode));
- case FS_IS_LINK:
- RETURN_BOOL(S_ISLNK(stat_sb->st_mode));
- case FS_EXISTS:
- RETURN_TRUE; /* the false case was done earlier */
- case FS_LSTAT:
- /* FALLTHROUGH */
- case FS_STAT:
- array_init(return_value);
- ZVAL_LONG(&stat_dev, stat_sb->st_dev);
- ZVAL_LONG(&stat_ino, stat_sb->st_ino);
- ZVAL_LONG(&stat_mode, stat_sb->st_mode);
- ZVAL_LONG(&stat_nlink, stat_sb->st_nlink);
- ZVAL_LONG(&stat_uid, stat_sb->st_uid);
- ZVAL_LONG(&stat_gid, stat_sb->st_gid);
- #ifdef HAVE_STRUCT_STAT_ST_RDEV
- ZVAL_LONG(&stat_rdev, stat_sb->st_rdev);
- #else
- ZVAL_LONG(&stat_rdev, -1);
- #endif
- ZVAL_LONG(&stat_size, stat_sb->st_size);
- ZVAL_LONG(&stat_atime, stat_sb->st_atime);
- ZVAL_LONG(&stat_mtime, stat_sb->st_mtime);
- ZVAL_LONG(&stat_ctime, stat_sb->st_ctime);
- #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
- ZVAL_LONG(&stat_blksize, stat_sb->st_blksize);
- #else
- ZVAL_LONG(&stat_blksize,-1);
- #endif
- #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
- ZVAL_LONG(&stat_blocks, stat_sb->st_blocks);
- #else
- ZVAL_LONG(&stat_blocks,-1);
- #endif
- /* Store numeric indexes in proper order */
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_dev);
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_ino);
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_mode);
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_nlink);
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_uid);
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_gid);
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_rdev);
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_size);
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_atime);
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_mtime);
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_ctime);
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_blksize);
- zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_blocks);
- /* Store string indexes referencing the same zval*/
- zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[0], strlen(stat_sb_names[0]), &stat_dev);
- zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[1], strlen(stat_sb_names[1]), &stat_ino);
- zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[2], strlen(stat_sb_names[2]), &stat_mode);
- zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[3], strlen(stat_sb_names[3]), &stat_nlink);
- zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[4], strlen(stat_sb_names[4]), &stat_uid);
- zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[5], strlen(stat_sb_names[5]), &stat_gid);
- zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[6], strlen(stat_sb_names[6]), &stat_rdev);
- zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[7], strlen(stat_sb_names[7]), &stat_size);
- zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[8], strlen(stat_sb_names[8]), &stat_atime);
- zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[9], strlen(stat_sb_names[9]), &stat_mtime);
- zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[10], strlen(stat_sb_names[10]), &stat_ctime);
- zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[11], strlen(stat_sb_names[11]), &stat_blksize);
- zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[12], strlen(stat_sb_names[12]), &stat_blocks);
- return;
- }
- php_error_docref(NULL, E_WARNING, "Didn't understand stat call");
- RETURN_FALSE;
- }
- /* }}} */
- static void phar_file_stat(const char *filename, size_t filename_length, int type, zif_handler orig_stat_func, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
- {
- if (!filename_length) {
- RETURN_FALSE;
- }
- if (!IS_ABSOLUTE_PATH(filename, filename_length) && !strstr(filename, "://")) {
- char *arch, *entry, *fname;
- size_t arch_len, entry_len, fname_len;
- zend_stat_t sb = {0};
- phar_entry_info *data = NULL;
- phar_archive_data *phar;
- fname = (char*)zend_get_executed_filename();
- /* we are checking for existence of a file within the relative path. Chances are good that this is
- retrieving something from within the phar archive */
- if (strncasecmp(fname, "phar://", 7)) {
- goto skip_phar;
- }
- fname_len = strlen(fname);
- 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))) {
- arch = estrndup(PHAR_G(last_phar_name), PHAR_G(last_phar_name_len));
- arch_len = PHAR_G(last_phar_name_len);
- entry = estrndup(filename, filename_length);
- /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
- entry_len = filename_length;
- phar = PHAR_G(last_phar);
- goto splitted;
- }
- if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
- efree(entry);
- entry = estrndup(filename, filename_length);
- /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
- entry_len = filename_length;
- if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
- efree(arch);
- efree(entry);
- goto skip_phar;
- }
- splitted:
- entry = phar_fix_filepath(entry, &entry_len, 1);
- if (entry[0] == '/') {
- if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
- efree(entry);
- goto stat_entry;
- }
- goto notfound;
- }
- if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
- efree(entry);
- goto stat_entry;
- }
- if (zend_hash_str_exists(&(phar->virtual_dirs), entry, entry_len)) {
- efree(entry);
- efree(arch);
- if (IS_EXISTS_CHECK(type)) {
- RETURN_TRUE;
- }
- sb.st_size = 0;
- sb.st_mode = 0777;
- sb.st_mode |= S_IFDIR; /* regular directory */
- sb.st_mtime = phar->max_timestamp;
- sb.st_atime = phar->max_timestamp;
- sb.st_ctime = phar->max_timestamp;
- goto statme_baby;
- } else {
- char *save;
- size_t save_len;
- notfound:
- efree(entry);
- save = PHAR_G(cwd);
- save_len = PHAR_G(cwd_len);
- /* this file is not in the current directory, use the original path */
- entry = estrndup(filename, filename_length);
- entry_len = filename_length;
- PHAR_G(cwd) = "/";
- PHAR_G(cwd_len) = 0;
- /* clean path without cwd */
- entry = phar_fix_filepath(entry, &entry_len, 1);
- if (NULL != (data = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
- PHAR_G(cwd) = save;
- PHAR_G(cwd_len) = save_len;
- efree(entry);
- if (IS_EXISTS_CHECK(type)) {
- efree(arch);
- RETURN_TRUE;
- }
- goto stat_entry;
- }
- if (zend_hash_str_exists(&(phar->virtual_dirs), entry + 1, entry_len - 1)) {
- PHAR_G(cwd) = save;
- PHAR_G(cwd_len) = save_len;
- efree(entry);
- efree(arch);
- if (IS_EXISTS_CHECK(type)) {
- RETURN_TRUE;
- }
- sb.st_size = 0;
- sb.st_mode = 0777;
- sb.st_mode |= S_IFDIR; /* regular directory */
- sb.st_mtime = phar->max_timestamp;
- sb.st_atime = phar->max_timestamp;
- sb.st_ctime = phar->max_timestamp;
- goto statme_baby;
- }
- PHAR_G(cwd) = save;
- PHAR_G(cwd_len) = save_len;
- efree(entry);
- efree(arch);
- /* Error Occurred */
- if (!IS_EXISTS_CHECK(type)) {
- php_error_docref(NULL, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename);
- }
- RETURN_FALSE;
- }
- stat_entry:
- efree(arch);
- if (!data->is_dir) {
- sb.st_size = data->uncompressed_filesize;
- sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
- if (data->link) {
- sb.st_mode |= S_IFREG|S_IFLNK; /* regular file */
- } else {
- sb.st_mode |= S_IFREG; /* regular file */
- }
- /* timestamp is just the timestamp when this was added to the phar */
- sb.st_mtime = data->timestamp;
- sb.st_atime = data->timestamp;
- sb.st_ctime = data->timestamp;
- } else {
- sb.st_size = 0;
- sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
- sb.st_mode |= S_IFDIR; /* regular directory */
- if (data->link) {
- sb.st_mode |= S_IFLNK;
- }
- /* timestamp is just the timestamp when this was added to the phar */
- sb.st_mtime = data->timestamp;
- sb.st_atime = data->timestamp;
- sb.st_ctime = data->timestamp;
- }
- statme_baby:
- if (!phar->is_writeable) {
- sb.st_mode = (sb.st_mode & 0555) | (sb.st_mode & ~0777);
- }
- sb.st_nlink = 1;
- sb.st_rdev = -1;
- /* this is only for APC, so use /dev/null device - no chance of conflict there! */
- sb.st_dev = 0xc;
- /* generate unique inode number for alias/filename, so no phars will conflict */
- if (data) {
- sb.st_ino = data->inode;
- }
- #ifndef PHP_WIN32
- sb.st_blksize = -1;
- sb.st_blocks = -1;
- #endif
- phar_fancy_stat(&sb, type, return_value);
- return;
- }
- }
- skip_phar:
- orig_stat_func(INTERNAL_FUNCTION_PARAM_PASSTHRU);
- return;
- }
- /* }}} */
- #define PharFileFunction(fname, funcnum, orig) \
- ZEND_NAMED_FUNCTION(fname) { \
- if (!PHAR_G(intercepted)) { \
- PHAR_G(orig)(INTERNAL_FUNCTION_PARAM_PASSTHRU); \
- } else { \
- char *filename; \
- size_t filename_len; \
- \
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) { \
- RETURN_THROWS(); \
- } \
- \
- phar_file_stat(filename, filename_len, funcnum, PHAR_G(orig), INTERNAL_FUNCTION_PARAM_PASSTHRU); \
- } \
- }
- /* }}} */
- /* {{{ Get file permissions */
- PharFileFunction(phar_fileperms, FS_PERMS, orig_fileperms)
- /* }}} */
- /* {{{ Get file inode */
- PharFileFunction(phar_fileinode, FS_INODE, orig_fileinode)
- /* }}} */
- /* {{{ Get file size */
- PharFileFunction(phar_filesize, FS_SIZE, orig_filesize)
- /* }}} */
- /* {{{ Get file owner */
- PharFileFunction(phar_fileowner, FS_OWNER, orig_fileowner)
- /* }}} */
- /* {{{ Get file group */
- PharFileFunction(phar_filegroup, FS_GROUP, orig_filegroup)
- /* }}} */
- /* {{{ Get last access time of file */
- PharFileFunction(phar_fileatime, FS_ATIME, orig_fileatime)
- /* }}} */
- /* {{{ Get last modification time of file */
- PharFileFunction(phar_filemtime, FS_MTIME, orig_filemtime)
- /* }}} */
- /* {{{ Get inode modification time of file */
- PharFileFunction(phar_filectime, FS_CTIME, orig_filectime)
- /* }}} */
- /* {{{ Get file type */
- PharFileFunction(phar_filetype, FS_TYPE, orig_filetype)
- /* }}} */
- /* {{{ Returns true if file can be written */
- PharFileFunction(phar_is_writable, FS_IS_W, orig_is_writable)
- /* }}} */
- /* {{{ Returns true if file can be read */
- PharFileFunction(phar_is_readable, FS_IS_R, orig_is_readable)
- /* }}} */
- /* {{{ Returns true if file is executable */
- PharFileFunction(phar_is_executable, FS_IS_X, orig_is_executable)
- /* }}} */
- /* {{{ Returns true if filename exists */
- PharFileFunction(phar_file_exists, FS_EXISTS, orig_file_exists)
- /* }}} */
- /* {{{ Returns true if file is directory */
- PharFileFunction(phar_is_dir, FS_IS_DIR, orig_is_dir)
- /* }}} */
- PHAR_FUNC(phar_is_file) /* {{{ */
- {
- char *filename;
- size_t filename_len;
- if (!PHAR_G(intercepted)) {
- goto skip_phar;
- }
- if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
- && !HT_IS_INITIALIZED(&cached_phars)) {
- goto skip_phar;
- }
- if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) {
- goto skip_phar;
- }
- if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
- char *arch, *entry, *fname;
- size_t arch_len, entry_len, fname_len;
- fname = (char*)zend_get_executed_filename();
- /* we are checking for existence of a file within the relative path. Chances are good that this is
- retrieving something from within the phar archive */
- if (strncasecmp(fname, "phar://", 7)) {
- goto skip_phar;
- }
- fname_len = strlen(fname);
- if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
- phar_archive_data *phar;
- efree(entry);
- entry = filename;
- /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
- entry_len = filename_len;
- /* retrieving a file within the current directory, so use this if possible */
- if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
- phar_entry_info *etemp;
- entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
- if (entry[0] == '/') {
- if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
- /* this file is not in the current directory, use the original path */
- found_it:
- efree(entry);
- efree(arch);
- RETURN_BOOL(!etemp->is_dir);
- }
- } else {
- if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
- goto found_it;
- }
- }
- }
- if (entry != filename) {
- efree(entry);
- }
- efree(arch);
- RETURN_FALSE;
- }
- }
- skip_phar:
- PHAR_G(orig_is_file)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
- return;
- }
- /* }}} */
- PHAR_FUNC(phar_is_link) /* {{{ */
- {
- char *filename;
- size_t filename_len;
- if (!PHAR_G(intercepted)) {
- goto skip_phar;
- }
- if ((HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && !zend_hash_num_elements(&(PHAR_G(phar_fname_map))))
- && !HT_IS_INITIALIZED(&cached_phars)) {
- goto skip_phar;
- }
- if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) {
- goto skip_phar;
- }
- if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
- char *arch, *entry, *fname;
- size_t arch_len, entry_len, fname_len;
- fname = (char*)zend_get_executed_filename();
- /* we are checking for existence of a file within the relative path. Chances are good that this is
- retrieving something from within the phar archive */
- if (strncasecmp(fname, "phar://", 7)) {
- goto skip_phar;
- }
- fname_len = strlen(fname);
- if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
- phar_archive_data *phar;
- efree(entry);
- entry = filename;
- /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
- entry_len = filename_len;
- /* retrieving a file within the current directory, so use this if possible */
- if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
- phar_entry_info *etemp;
- entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1);
- if (entry[0] == '/') {
- if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry + 1, entry_len - 1))) {
- /* this file is not in the current directory, use the original path */
- found_it:
- efree(entry);
- efree(arch);
- RETURN_BOOL(etemp->link);
- }
- } else {
- if (NULL != (etemp = zend_hash_str_find_ptr(&(phar->manifest), entry, entry_len))) {
- goto found_it;
- }
- }
- }
- efree(entry);
- efree(arch);
- RETURN_FALSE;
- }
- }
- skip_phar:
- PHAR_G(orig_is_link)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
- return;
- }
- /* }}} */
- /* {{{ Give information about a file or symbolic link */
- PharFileFunction(phar_lstat, FS_LSTAT, orig_lstat)
- /* }}} */
- /* {{{ Give information about a file */
- PharFileFunction(phar_stat, FS_STAT, orig_stat)
- /* }}} */
- /* {{{ void phar_intercept_functions(void) */
- void phar_intercept_functions(void)
- {
- if (!PHAR_G(request_init)) {
- PHAR_G(cwd) = NULL;
- PHAR_G(cwd_len) = 0;
- }
- PHAR_G(intercepted) = 1;
- }
- /* }}} */
- /* {{{ void phar_release_functions(void) */
- void phar_release_functions(void)
- {
- PHAR_G(intercepted) = 0;
- }
- /* }}} */
- /* {{{ void phar_intercept_functions_init(void) */
- #define PHAR_INTERCEPT(func) \
- PHAR_G(orig_##func) = NULL; \
- if (NULL != (orig = zend_hash_str_find_ptr(CG(function_table), #func, sizeof(#func)-1))) { \
- PHAR_G(orig_##func) = orig->internal_function.handler; \
- orig->internal_function.handler = phar_##func; \
- }
- void phar_intercept_functions_init(void)
- {
- zend_function *orig;
- PHAR_INTERCEPT(fopen);
- PHAR_INTERCEPT(file_get_contents);
- PHAR_INTERCEPT(is_file);
- PHAR_INTERCEPT(is_link);
- PHAR_INTERCEPT(is_dir);
- PHAR_INTERCEPT(opendir);
- PHAR_INTERCEPT(file_exists);
- PHAR_INTERCEPT(fileperms);
- PHAR_INTERCEPT(fileinode);
- PHAR_INTERCEPT(filesize);
- PHAR_INTERCEPT(fileowner);
- PHAR_INTERCEPT(filegroup);
- PHAR_INTERCEPT(fileatime);
- PHAR_INTERCEPT(filemtime);
- PHAR_INTERCEPT(filectime);
- PHAR_INTERCEPT(filetype);
- PHAR_INTERCEPT(is_writable);
- PHAR_INTERCEPT(is_readable);
- PHAR_INTERCEPT(is_executable);
- PHAR_INTERCEPT(lstat);
- PHAR_INTERCEPT(stat);
- PHAR_INTERCEPT(readfile);
- PHAR_G(intercepted) = 0;
- }
- /* }}} */
- /* {{{ void phar_intercept_functions_shutdown(void) */
- #define PHAR_RELEASE(func) \
- if (PHAR_G(orig_##func) && NULL != (orig = zend_hash_str_find_ptr(CG(function_table), #func, sizeof(#func)-1))) { \
- orig->internal_function.handler = PHAR_G(orig_##func); \
- } \
- PHAR_G(orig_##func) = NULL;
- void phar_intercept_functions_shutdown(void)
- {
- zend_function *orig;
- PHAR_RELEASE(fopen);
- PHAR_RELEASE(file_get_contents);
- PHAR_RELEASE(is_file);
- PHAR_RELEASE(is_dir);
- PHAR_RELEASE(opendir);
- PHAR_RELEASE(file_exists);
- PHAR_RELEASE(fileperms);
- PHAR_RELEASE(fileinode);
- PHAR_RELEASE(filesize);
- PHAR_RELEASE(fileowner);
- PHAR_RELEASE(filegroup);
- PHAR_RELEASE(fileatime);
- PHAR_RELEASE(filemtime);
- PHAR_RELEASE(filectime);
- PHAR_RELEASE(filetype);
- PHAR_RELEASE(is_writable);
- PHAR_RELEASE(is_readable);
- PHAR_RELEASE(is_executable);
- PHAR_RELEASE(lstat);
- PHAR_RELEASE(stat);
- PHAR_RELEASE(readfile);
- PHAR_G(intercepted) = 0;
- }
- /* }}} */
- static struct _phar_orig_functions {
- zif_handler orig_fopen;
- zif_handler orig_file_get_contents;
- zif_handler orig_is_file;
- zif_handler orig_is_link;
- zif_handler orig_is_dir;
- zif_handler orig_opendir;
- zif_handler orig_file_exists;
- zif_handler orig_fileperms;
- zif_handler orig_fileinode;
- zif_handler orig_filesize;
- zif_handler orig_fileowner;
- zif_handler orig_filegroup;
- zif_handler orig_fileatime;
- zif_handler orig_filemtime;
- zif_handler orig_filectime;
- zif_handler orig_filetype;
- zif_handler orig_is_writable;
- zif_handler orig_is_readable;
- zif_handler orig_is_executable;
- zif_handler orig_lstat;
- zif_handler orig_readfile;
- zif_handler orig_stat;
- } phar_orig_functions = {0};
- void phar_save_orig_functions(void) /* {{{ */
- {
- phar_orig_functions.orig_fopen = PHAR_G(orig_fopen);
- phar_orig_functions.orig_file_get_contents = PHAR_G(orig_file_get_contents);
- phar_orig_functions.orig_is_file = PHAR_G(orig_is_file);
- phar_orig_functions.orig_is_link = PHAR_G(orig_is_link);
- phar_orig_functions.orig_is_dir = PHAR_G(orig_is_dir);
- phar_orig_functions.orig_opendir = PHAR_G(orig_opendir);
- phar_orig_functions.orig_file_exists = PHAR_G(orig_file_exists);
- phar_orig_functions.orig_fileperms = PHAR_G(orig_fileperms);
- phar_orig_functions.orig_fileinode = PHAR_G(orig_fileinode);
- phar_orig_functions.orig_filesize = PHAR_G(orig_filesize);
- phar_orig_functions.orig_fileowner = PHAR_G(orig_fileowner);
- phar_orig_functions.orig_filegroup = PHAR_G(orig_filegroup);
- phar_orig_functions.orig_fileatime = PHAR_G(orig_fileatime);
- phar_orig_functions.orig_filemtime = PHAR_G(orig_filemtime);
- phar_orig_functions.orig_filectime = PHAR_G(orig_filectime);
- phar_orig_functions.orig_filetype = PHAR_G(orig_filetype);
- phar_orig_functions.orig_is_writable = PHAR_G(orig_is_writable);
- phar_orig_functions.orig_is_readable = PHAR_G(orig_is_readable);
- phar_orig_functions.orig_is_executable = PHAR_G(orig_is_executable);
- phar_orig_functions.orig_lstat = PHAR_G(orig_lstat);
- phar_orig_functions.orig_readfile = PHAR_G(orig_readfile);
- phar_orig_functions.orig_stat = PHAR_G(orig_stat);
- }
- /* }}} */
- void phar_restore_orig_functions(void) /* {{{ */
- {
- PHAR_G(orig_fopen) = phar_orig_functions.orig_fopen;
- PHAR_G(orig_file_get_contents) = phar_orig_functions.orig_file_get_contents;
- PHAR_G(orig_is_file) = phar_orig_functions.orig_is_file;
- PHAR_G(orig_is_link) = phar_orig_functions.orig_is_link;
- PHAR_G(orig_is_dir) = phar_orig_functions.orig_is_dir;
- PHAR_G(orig_opendir) = phar_orig_functions.orig_opendir;
- PHAR_G(orig_file_exists) = phar_orig_functions.orig_file_exists;
- PHAR_G(orig_fileperms) = phar_orig_functions.orig_fileperms;
- PHAR_G(orig_fileinode) = phar_orig_functions.orig_fileinode;
- PHAR_G(orig_filesize) = phar_orig_functions.orig_filesize;
- PHAR_G(orig_fileowner) = phar_orig_functions.orig_fileowner;
- PHAR_G(orig_filegroup) = phar_orig_functions.orig_filegroup;
- PHAR_G(orig_fileatime) = phar_orig_functions.orig_fileatime;
- PHAR_G(orig_filemtime) = phar_orig_functions.orig_filemtime;
- PHAR_G(orig_filectime) = phar_orig_functions.orig_filectime;
- PHAR_G(orig_filetype) = phar_orig_functions.orig_filetype;
- PHAR_G(orig_is_writable) = phar_orig_functions.orig_is_writable;
- PHAR_G(orig_is_readable) = phar_orig_functions.orig_is_readable;
- PHAR_G(orig_is_executable) = phar_orig_functions.orig_is_executable;
- PHAR_G(orig_lstat) = phar_orig_functions.orig_lstat;
- PHAR_G(orig_readfile) = phar_orig_functions.orig_readfile;
- PHAR_G(orig_stat) = phar_orig_functions.orig_stat;
- }
- /* }}} */
|