PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - main - fopen_wrappers.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 249 339 73.5 %
Date: 2015-08-29 Functions: 12 12 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2015 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: Rasmus Lerdorf <rasmus@lerdorf.on.ca>                       |
      16             :    |          Jim Winstead <jimw@php.net>                                 |
      17             :    +----------------------------------------------------------------------+
      18             :  */
      19             : 
      20             : /* $Id$ */
      21             : 
      22             : /* {{{ includes
      23             :  */
      24             : #include "php.h"
      25             : #include "php_globals.h"
      26             : #include "SAPI.h"
      27             : 
      28             : #include <stdio.h>
      29             : #include <stdlib.h>
      30             : #include <errno.h>
      31             : #include <sys/types.h>
      32             : #include <sys/stat.h>
      33             : #include <fcntl.h>
      34             : 
      35             : #ifdef PHP_WIN32
      36             : #define O_RDONLY _O_RDONLY
      37             : #include "win32/param.h"
      38             : #else
      39             : #include <sys/param.h>
      40             : #endif
      41             : 
      42             : #include "ext/standard/head.h"
      43             : #include "ext/standard/php_standard.h"
      44             : #include "zend_compile.h"
      45             : #include "php_network.h"
      46             : 
      47             : #if HAVE_PWD_H
      48             : #include <pwd.h>
      49             : #endif
      50             : 
      51             : #include <sys/types.h>
      52             : #if HAVE_SYS_SOCKET_H
      53             : #include <sys/socket.h>
      54             : #endif
      55             : 
      56             : #ifdef PHP_WIN32
      57             : #include <winsock2.h>
      58             : #elif defined(NETWARE) && defined(USE_WINSOCK)
      59             : #include <novsock2.h>
      60             : #else
      61             : #include <netinet/in.h>
      62             : #include <netdb.h>
      63             : #if HAVE_ARPA_INET_H
      64             : #include <arpa/inet.h>
      65             : #endif
      66             : #endif
      67             : 
      68             : #if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
      69             : #undef AF_UNIX
      70             : #endif
      71             : 
      72             : #if defined(AF_UNIX)
      73             : #include <sys/un.h>
      74             : #endif
      75             : /* }}} */
      76             : 
      77             : /* {{{ OnUpdateBaseDir
      78             : Allows any change to open_basedir setting in during Startup and Shutdown events,
      79             : or a tightening during activation/runtime/deactivation */
      80       21308 : PHPAPI ZEND_INI_MH(OnUpdateBaseDir)
      81             : {
      82             :         char **p, *pathbuf, *ptr, *end;
      83             : #ifndef ZTS
      84       21308 :         char *base = (char *) mh_arg2;
      85             : #else
      86             :         char *base = (char *) ts_resource(*((int *) mh_arg2));
      87             : #endif
      88             : 
      89       21308 :         p = (char **) (base + (size_t) mh_arg1);
      90             : 
      91       21308 :         if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN || stage == PHP_INI_STAGE_ACTIVATE || stage == PHP_INI_STAGE_DEACTIVATE) {
      92             :                 /* We're in a PHP_INI_SYSTEM context, no restrictions */
      93       21299 :                 *p = new_value ? ZSTR_VAL(new_value) : NULL;
      94       21299 :                 return SUCCESS;
      95             :         }
      96             : 
      97             :         /* Otherwise we're in runtime */
      98           9 :         if (!*p || !**p) {
      99             :                 /* open_basedir not set yet, go ahead and give it a value */
     100           7 :                 *p = ZSTR_VAL(new_value);
     101           7 :                 return SUCCESS;
     102             :         }
     103             : 
     104             :         /* Shortcut: When we have a open_basedir and someone tries to unset, we know it'll fail */
     105           2 :         if (!new_value || !*ZSTR_VAL(new_value)) {
     106           0 :                 return FAILURE;
     107             :         }
     108             : 
     109             :         /* Is the proposed open_basedir at least as restrictive as the current setting? */
     110           2 :         ptr = pathbuf = estrdup(ZSTR_VAL(new_value));
     111           5 :         while (ptr && *ptr) {
     112           2 :                 end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
     113           2 :                 if (end != NULL) {
     114           0 :                         *end = '\0';
     115           0 :                         end++;
     116             :                 }
     117           2 :                 if (php_check_open_basedir_ex(ptr, 0) != 0) {
     118             :                         /* At least one portion of this open_basedir is less restrictive than the prior one, FAIL */
     119           1 :                         efree(pathbuf);
     120           1 :                         return FAILURE;
     121             :                 }
     122           1 :                 ptr = end;
     123             :         }
     124           1 :         efree(pathbuf);
     125             : 
     126             :         /* Everything checks out, set it */
     127           1 :         *p = ZSTR_VAL(new_value);
     128             : 
     129           1 :         return SUCCESS;
     130             : }
     131             : /* }}} */
     132             : 
     133             : /* {{{ php_check_specific_open_basedir
     134             :         When open_basedir is not NULL, check if the given filename is located in
     135             :         open_basedir. Returns -1 if error or not in the open_basedir, else 0.
     136             :         When open_basedir is NULL, always return 0.
     137             : */
     138        1090 : PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path)
     139             : {
     140             :         char resolved_name[MAXPATHLEN];
     141             :         char resolved_basedir[MAXPATHLEN];
     142             :         char local_open_basedir[MAXPATHLEN];
     143             :         char path_tmp[MAXPATHLEN];
     144             :         char *path_file;
     145             :         int resolved_basedir_len;
     146             :         int resolved_name_len;
     147             :         int path_len;
     148        1090 :         int nesting_level = 0;
     149             : 
     150             :         /* Special case basedir==".": Use script-directory */
     151        1090 :         if (strcmp(basedir, ".") || !VCWD_GETCWD(local_open_basedir, MAXPATHLEN)) {
     152             :                 /* Else use the unmodified path */
     153          23 :                 strlcpy(local_open_basedir, basedir, sizeof(local_open_basedir));
     154             :         }
     155             : 
     156        1090 :         path_len = (int)strlen(path);
     157        1090 :         if (path_len > (MAXPATHLEN - 1)) {
     158             :                 /* empty and too long paths are invalid */
     159           0 :                 return -1;
     160             :         }
     161             : 
     162             :         /* normalize and expand path */
     163        1090 :         if (expand_filepath(path, resolved_name) == NULL) {
     164           1 :                 return -1;
     165             :         }
     166             : 
     167        1089 :         path_len = (int)strlen(resolved_name);
     168        1089 :         memcpy(path_tmp, resolved_name, path_len + 1); /* safe */
     169             : 
     170        2538 :         while (VCWD_REALPATH(path_tmp, resolved_name) == NULL) {
     171             : #if defined(PHP_WIN32) || defined(HAVE_SYMLINK)
     172         360 :                 if (nesting_level == 0) {
     173             :                         int ret;
     174             :                         char buf[MAXPATHLEN];
     175             : 
     176         357 :                         ret = php_sys_readlink(path_tmp, buf, MAXPATHLEN - 1);
     177         357 :                         if (ret < 0) {
     178             :                                 /* not a broken symlink, move along.. */
     179             :                         } else {
     180             :                                 /* put the real path into the path buffer */
     181           0 :                                 memcpy(path_tmp, buf, ret);
     182           0 :                                 path_tmp[ret] = '\0';
     183             :                         }
     184             :                 }
     185             : #endif
     186             : 
     187             : #if defined(PHP_WIN32) || defined(NETWARE)
     188             :                 path_file = strrchr(path_tmp, DEFAULT_SLASH);
     189             :                 if (!path_file) {
     190             :                         path_file = strrchr(path_tmp, '/');
     191             :                 }
     192             : #else
     193         360 :                 path_file = strrchr(path_tmp, DEFAULT_SLASH);
     194             : #endif
     195         360 :                 if (!path_file) {
     196             :                         /* none of the path components exist. definitely not in open_basedir.. */
     197           0 :                         return -1;
     198             :                 } else {
     199         360 :                         path_len = path_file - path_tmp + 1;
     200             : #if defined(PHP_WIN32) || defined(NETWARE)
     201             :                         if (path_len > 1 && path_tmp[path_len - 2] == ':') {
     202             :                                 if (path_len != 3) {
     203             :                                         return -1;
     204             :                                 }
     205             :                                 /* this is c:\ */
     206             :                                 path_tmp[path_len] = '\0';
     207             :                         } else {
     208             :                                 path_tmp[path_len - 1] = '\0';
     209             :                         }
     210             : #else
     211         360 :                         path_tmp[path_len - 1] = '\0';
     212             : #endif
     213             :                 }
     214         360 :                 nesting_level++;
     215             :         }
     216             : 
     217             :         /* Resolve open_basedir to resolved_basedir */
     218        1089 :         if (expand_filepath(local_open_basedir, resolved_basedir) != NULL) {
     219        1089 :                 int basedir_len = (int)strlen(basedir);
     220             :                 /* Handler for basedirs that end with a / */
     221        1089 :                 resolved_basedir_len = (int)strlen(resolved_basedir);
     222             : #if defined(PHP_WIN32) || defined(NETWARE)
     223             :                 if (basedir[basedir_len - 1] == PHP_DIR_SEPARATOR || basedir[basedir_len - 1] == '/') {
     224             : #else
     225        1089 :                 if (basedir[basedir_len - 1] == PHP_DIR_SEPARATOR) {
     226             : #endif
     227           3 :                         if (resolved_basedir[resolved_basedir_len - 1] != PHP_DIR_SEPARATOR) {
     228           0 :                                 resolved_basedir[resolved_basedir_len] = PHP_DIR_SEPARATOR;
     229           0 :                                 resolved_basedir[++resolved_basedir_len] = '\0';
     230             :                         }
     231             :                 } else {
     232        1086 :                                 resolved_basedir[resolved_basedir_len++] = PHP_DIR_SEPARATOR;
     233        1086 :                                 resolved_basedir[resolved_basedir_len] = '\0';
     234             :                 }
     235             : 
     236        1089 :                 resolved_name_len = (int)strlen(resolved_name);
     237        1089 :                 if (path_tmp[path_len - 1] == PHP_DIR_SEPARATOR) {
     238          69 :                         if (resolved_name[resolved_name_len - 1] != PHP_DIR_SEPARATOR) {
     239          37 :                                 resolved_name[resolved_name_len] = PHP_DIR_SEPARATOR;
     240          37 :                                 resolved_name[++resolved_name_len] = '\0';
     241             :                         }
     242             :                 }
     243             : 
     244             :                 /* Check the path */
     245             : #if defined(PHP_WIN32) || defined(NETWARE)
     246             :                 if (strncasecmp(resolved_basedir, resolved_name, resolved_basedir_len) == 0) {
     247             : #else
     248        1089 :                 if (strncmp(resolved_basedir, resolved_name, resolved_basedir_len) == 0) {
     249             : #endif
     250        1001 :                         if (resolved_name_len > resolved_basedir_len &&
     251         499 :                                 resolved_name[resolved_basedir_len - 1] != PHP_DIR_SEPARATOR) {
     252           0 :                                 return -1;
     253             :                         } else {
     254             :                                 /* File is in the right directory */
     255         502 :                                 return 0;
     256             :                         }
     257             :                 } else {
     258             :                         /* /openbasedir/ and /openbasedir are the same directory */
     259         587 :                         if (resolved_basedir_len == (resolved_name_len + 1) && resolved_basedir[resolved_basedir_len - 1] == PHP_DIR_SEPARATOR) {
     260             : #if defined(PHP_WIN32) || defined(NETWARE)
     261             :                                 if (strncasecmp(resolved_basedir, resolved_name, resolved_name_len) == 0) {
     262             : #else
     263         247 :                                 if (strncmp(resolved_basedir, resolved_name, resolved_name_len) == 0) {
     264             : #endif
     265         246 :                                         return 0;
     266             :                                 }
     267             :                         }
     268         341 :                         return -1;
     269             :                 }
     270             :         } else {
     271             :                 /* Unable to resolve the real path, return -1 */
     272           0 :                 return -1;
     273             :         }
     274             : }
     275             : /* }}} */
     276             : 
     277      421259 : PHPAPI int php_check_open_basedir(const char *path)
     278             : {
     279      421259 :         return php_check_open_basedir_ex(path, 1);
     280             : }
     281             : 
     282             : /* {{{ php_check_open_basedir
     283             :  */
     284      479359 : PHPAPI int php_check_open_basedir_ex(const char *path, int warn)
     285             : {
     286             :         /* Only check when open_basedir is available */
     287      479359 :         if (PG(open_basedir) && *PG(open_basedir)) {
     288             :                 char *pathbuf;
     289             :                 char *ptr;
     290             :                 char *end;
     291             : 
     292             :                 /* Check if the path is too long so we can give a more useful error
     293             :                 * message. */
     294        1091 :                 if (strlen(path) > (MAXPATHLEN - 1)) {
     295           1 :                         php_error_docref(NULL, E_WARNING, "File name is longer than the maximum allowed path length on this platform (%d): %s", MAXPATHLEN, path);
     296           1 :                         errno = EINVAL;
     297           1 :                         return -1;
     298             :                 }
     299             : 
     300        1090 :                 pathbuf = estrdup(PG(open_basedir));
     301             : 
     302        1090 :                 ptr = pathbuf;
     303             : 
     304        2522 :                 while (ptr && *ptr) {
     305        1090 :                         end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
     306        1090 :                         if (end != NULL) {
     307           0 :                                 *end = '\0';
     308           0 :                                 end++;
     309             :                         }
     310             : 
     311        1090 :                         if (php_check_specific_open_basedir(ptr, path) == 0) {
     312         748 :                                 efree(pathbuf);
     313         748 :                                 return 0;
     314             :                         }
     315             : 
     316         342 :                         ptr = end;
     317             :                 }
     318         342 :                 if (warn) {
     319         315 :                         php_error_docref(NULL, E_WARNING, "open_basedir restriction in effect. File(%s) is not within the allowed path(s): (%s)", path, PG(open_basedir));
     320             :                 }
     321         342 :                 efree(pathbuf);
     322         342 :                 errno = EPERM; /* we deny permission to open it */
     323         342 :                 return -1;
     324             :         }
     325             : 
     326             :         /* Nothing to check... */
     327      478268 :         return 0;
     328             : }
     329             : /* }}} */
     330             : 
     331             : /* {{{ php_fopen_and_set_opened_path
     332             :  */
     333         164 : static FILE *php_fopen_and_set_opened_path(const char *path, const char *mode, zend_string **opened_path)
     334             : {
     335             :         FILE *fp;
     336             : 
     337         164 :         if (php_check_open_basedir((char *)path)) {
     338           0 :                 return NULL;
     339             :         }
     340         164 :         fp = VCWD_FOPEN(path, mode);
     341         164 :         if (fp && opened_path) {
     342             :                 //TODO :avoid reallocation
     343           0 :                 char *tmp = expand_filepath_with_mode(path, NULL, NULL, 0, CWD_EXPAND);
     344           0 :                 if (tmp) {
     345           0 :                         *opened_path = zend_string_init(tmp, strlen(tmp), 0);
     346           0 :                         efree(tmp);
     347             :                 }
     348             :         }
     349         164 :         return fp;
     350             : }
     351             : /* }}} */
     352             : 
     353             : /* {{{ php_fopen_primary_script
     354             :  */
     355         403 : PHPAPI int php_fopen_primary_script(zend_file_handle *file_handle)
     356             : {
     357             :         char *path_info;
     358         403 :         char *filename = NULL;
     359         403 :         zend_string *resolved_path = NULL;
     360             :         int length;
     361             :         zend_bool orig_display_errors;
     362             : 
     363         403 :         path_info = SG(request_info).request_uri;
     364             : #if HAVE_PWD_H
     365         403 :         if (PG(user_dir) && *PG(user_dir) && path_info && '/' == path_info[0] && '~' == path_info[1]) {
     366           0 :                 char *s = strchr(path_info + 2, '/');
     367             : 
     368           0 :                 if (s) {                        /* if there is no path name after the file, do not bother */
     369             :                         char user[32];                  /* to try open the directory */
     370             :                         struct passwd *pw;
     371             : #if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
     372             :                         struct passwd pwstruc;
     373             :                         long pwbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
     374             :                         char *pwbuf;
     375             : 
     376             :                         if (pwbuflen < 1) {
     377             :                                 return FAILURE;
     378             :                         }
     379             : 
     380             :                         pwbuf = emalloc(pwbuflen);
     381             : #endif
     382           0 :                         length = s - (path_info + 2);
     383           0 :                         if (length > (int)sizeof(user) - 1) {
     384           0 :                                 length = sizeof(user) - 1;
     385             :                         }
     386           0 :                         memcpy(user, path_info + 2, length);
     387           0 :                         user[length] = '\0';
     388             : #if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
     389             :                         if (getpwnam_r(user, &pwstruc, pwbuf, pwbuflen, &pw)) {
     390             :                                 efree(pwbuf);
     391             :                                 return FAILURE;
     392             :                         }
     393             : #else
     394           0 :                         pw = getpwnam(user);
     395             : #endif
     396           0 :                         if (pw && pw->pw_dir) {
     397           0 :                                 spprintf(&filename, 0, "%s%c%s%c%s", pw->pw_dir, PHP_DIR_SEPARATOR, PG(user_dir), PHP_DIR_SEPARATOR, s + 1); /* Safe */
     398             :                         } else {
     399           0 :                                 filename = SG(request_info).path_translated;
     400             :                         }
     401             : #if defined(ZTS) && defined(HAVE_GETPWNAM_R) && defined(_SC_GETPW_R_SIZE_MAX)
     402             :                         efree(pwbuf);
     403             : #endif
     404             :                 }
     405             :         } else
     406             : #endif
     407         403 :         if (PG(doc_root) && path_info && (length = (int)strlen(PG(doc_root))) &&
     408           0 :                 IS_ABSOLUTE_PATH(PG(doc_root), length)) {
     409           0 :                 int path_len = (int)strlen(path_info);
     410           0 :                 filename = emalloc(length + path_len + 2);
     411           0 :                 if (filename) {
     412           0 :                         memcpy(filename, PG(doc_root), length);
     413           0 :                         if (!IS_SLASH(filename[length - 1])) {  /* length is never 0 */
     414           0 :                                 filename[length++] = PHP_DIR_SEPARATOR;
     415             :                         }
     416           0 :                         if (IS_SLASH(path_info[0])) {
     417           0 :                                 length--;
     418             :                         }
     419           0 :                         strncpy(filename + length, path_info, path_len + 1);
     420             :                 }
     421             :         } else {
     422         403 :                 filename = SG(request_info).path_translated;
     423             :         }
     424             : 
     425             : 
     426         403 :         if (filename) {
     427         403 :                 resolved_path = zend_resolve_path(filename, (int)strlen(filename));
     428             :         }
     429             : 
     430         403 :         if (!resolved_path) {
     431           7 :                 if (SG(request_info).path_translated != filename) {
     432           0 :                         if (filename) {
     433           0 :                                 efree(filename);
     434             :                         }
     435             :                 }
     436             :                 /* we have to free SG(request_info).path_translated here because
     437             :                  * php_destroy_request_info assumes that it will get
     438             :                  * freed when the include_names hash is emptied, but
     439             :                  * we're not adding it in this case */
     440           7 :                 if (SG(request_info).path_translated) {
     441           7 :                         efree(SG(request_info).path_translated);
     442           7 :                         SG(request_info).path_translated = NULL;
     443             :                 }
     444           7 :                 return FAILURE;
     445             :         }
     446             :         zend_string_release(resolved_path);
     447             : 
     448         396 :         orig_display_errors = PG(display_errors);
     449         396 :         PG(display_errors) = 0;
     450         396 :         if (zend_stream_open(filename, file_handle) == FAILURE) {
     451           0 :                 PG(display_errors) = orig_display_errors;
     452           0 :                 if (SG(request_info).path_translated != filename) {
     453           0 :                         if (filename) {
     454           0 :                                 efree(filename);
     455             :                         }
     456             :                 }
     457           0 :                 if (SG(request_info).path_translated) {
     458           0 :                         efree(SG(request_info).path_translated);
     459           0 :                         SG(request_info).path_translated = NULL;
     460             :                 }
     461           0 :                 return FAILURE;
     462             :         }
     463         396 :         PG(display_errors) = orig_display_errors;
     464             : 
     465         396 :         if (SG(request_info).path_translated != filename) {
     466           0 :                 if (SG(request_info).path_translated) {
     467           0 :                         efree(SG(request_info).path_translated);
     468             :                 }
     469           0 :                 SG(request_info).path_translated = filename;
     470             :         }
     471             : 
     472         396 :         return SUCCESS;
     473             : }
     474             : /* }}} */
     475             : 
     476             : /* {{{ php_resolve_path
     477             :  * Returns the realpath for given filename according to include path
     478             :  */
     479       14973 : PHPAPI zend_string *php_resolve_path(const char *filename, int filename_length, const char *path)
     480             : {
     481             :         char resolved_path[MAXPATHLEN];
     482             :         char trypath[MAXPATHLEN];
     483             :         const char *ptr, *end, *p;
     484             :         const char *actual_path;
     485             :         php_stream_wrapper *wrapper;
     486             :         zend_string *exec_filename;
     487             : 
     488       14973 :         if (!filename || CHECK_NULL_PATH(filename, filename_length)) {
     489           0 :                 return NULL;
     490             :         }
     491             : 
     492             :         /* Don't resolve paths which contain protocol (except of file://) */
     493       14973 :         for (p = filename; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++);
     494       14973 :         if ((*p == ':') && (p - filename > 1) && (p[1] == '/') && (p[2] == '/')) {
     495         292 :                 wrapper = php_stream_locate_url_wrapper(filename, &actual_path, STREAM_OPEN_FOR_INCLUDE);
     496         292 :                 if (wrapper == &php_plain_files_wrapper) {
     497           4 :                         if (tsrm_realpath(actual_path, resolved_path)) {
     498           4 :                                 return zend_string_init(resolved_path, strlen(resolved_path), 0);
     499             :                         }
     500             :                 }
     501         290 :                 return NULL;
     502             :         }
     503             : 
     504       35404 :         if ((*filename == '.' &&
     505           4 :              (IS_SLASH(filename[1]) ||
     506           0 :               ((filename[1] == '.') && IS_SLASH(filename[2])))) ||
     507       14677 :             IS_ABSOLUTE_PATH(filename, filename_length) ||
     508             :             !path ||
     509        6042 :             !*path) {
     510        8639 :                 if (tsrm_realpath(filename, resolved_path)) {
     511       17256 :                         return zend_string_init(resolved_path, strlen(resolved_path), 0);
     512             :                 } else {
     513          11 :                         return NULL;
     514             :                 }
     515             :         }
     516             : 
     517        6042 :         ptr = path;
     518       23999 :         while (ptr && *ptr) {
     519             :                 /* Check for stream wrapper */
     520       12031 :                 int is_stream_wrapper = 0;
     521             : 
     522       12031 :                 for (p = ptr; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++);
     523       12031 :                 if ((*p == ':') && (p - ptr > 1) && (p[1] == '/') && (p[2] == '/')) {
     524             :                         /* .:// or ..:// is not a stream wrapper */
     525          45 :                         if (p[-1] != '.' || p[-2] != '.' || p - 2 != ptr) {
     526          45 :                                 p += 3;
     527          45 :                                 is_stream_wrapper = 1;
     528             :                         }
     529             :                 }
     530       12031 :                 end = strchr(p, DEFAULT_DIR_SEPARATOR);
     531       12031 :                 if (end) {
     532        6100 :                         if ((end-ptr) + 1 + filename_length + 1 >= MAXPATHLEN) {
     533           0 :                                 ptr = end + 1;
     534           0 :                                 continue;
     535             :                         }
     536        6100 :                         memcpy(trypath, ptr, end-ptr);
     537        6100 :                         trypath[end-ptr] = '/';
     538        6100 :                         memcpy(trypath+(end-ptr)+1, filename, filename_length+1);
     539        6100 :                         ptr = end+1;
     540             :                 } else {
     541        5931 :                         int len = (int)strlen(ptr);
     542             : 
     543        5931 :                         if (len + 1 + filename_length + 1 >= MAXPATHLEN) {
     544           0 :                                 break;
     545             :                         }
     546        5931 :                         memcpy(trypath, ptr, len);
     547        5931 :                         trypath[len] = '/';
     548        5931 :                         memcpy(trypath+len+1, filename, filename_length+1);
     549        5931 :                         ptr = NULL;
     550             :                 }
     551       12031 :                 actual_path = trypath;
     552       12031 :                 if (is_stream_wrapper) {
     553          45 :                         wrapper = php_stream_locate_url_wrapper(trypath, &actual_path, STREAM_OPEN_FOR_INCLUDE);
     554          45 :                         if (!wrapper) {
     555           0 :                                 continue;
     556          45 :                         } else if (wrapper != &php_plain_files_wrapper) {
     557          45 :                                 if (wrapper->wops->url_stat) {
     558             :                                         php_stream_statbuf ssb;
     559             : 
     560          45 :                                         if (SUCCESS == wrapper->wops->url_stat(wrapper, trypath, 0, &ssb, NULL)) {
     561          66 :                                                 return zend_string_init(trypath, strlen(trypath), 0);
     562             :                                         }
     563             :                                 }
     564          12 :                                 continue;
     565             :                         }
     566             :                 }
     567       11986 :                 if (tsrm_realpath(actual_path, resolved_path)) {
     568         166 :                         return zend_string_init(resolved_path, strlen(resolved_path), 0);
     569             :                 }
     570             :         } /* end provided path */
     571             : 
     572             :         /* check in calling scripts' current working directory as a fall back case
     573             :          */
     574       11845 :         if (zend_is_executing() &&
     575        5919 :             (exec_filename = zend_get_executed_filename_ex()) != NULL) {
     576        5919 :                 const char *exec_fname = ZSTR_VAL(exec_filename);
     577        5919 :                 size_t exec_fname_length = ZSTR_LEN(exec_filename);
     578             : 
     579      144309 :                 while ((--exec_fname_length < SIZE_MAX) && !IS_SLASH(exec_fname[exec_fname_length]));
     580       11838 :                 if (exec_fname_length > 0 &&
     581        5919 :                     exec_fname_length + 1 + filename_length + 1 < MAXPATHLEN) {
     582        5919 :                         memcpy(trypath, exec_fname, exec_fname_length + 1);
     583        5919 :                         memcpy(trypath+exec_fname_length + 1, filename, filename_length+1);
     584        5919 :                         actual_path = trypath;
     585             : 
     586             :                         /* Check for stream wrapper */
     587        5919 :                         for (p = trypath; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++);
     588        5919 :                         if ((*p == ':') && (p - trypath > 1) && (p[1] == '/') && (p[2] == '/')) {
     589           4 :                                 wrapper = php_stream_locate_url_wrapper(trypath, &actual_path, STREAM_OPEN_FOR_INCLUDE);
     590           4 :                                 if (!wrapper) {
     591           0 :                                         return NULL;
     592           4 :                                 } else if (wrapper != &php_plain_files_wrapper) {
     593           4 :                                         if (wrapper->wops->url_stat) {
     594             :                                                 php_stream_statbuf ssb;
     595             : 
     596           4 :                                                 if (SUCCESS == wrapper->wops->url_stat(wrapper, trypath, 0, &ssb, NULL)) {
     597           4 :                                                         return zend_string_init(trypath, strlen(trypath), 0);
     598             :                                                 }
     599             :                                         }
     600           2 :                                         return NULL;
     601             :                                 }
     602             :                         }
     603             : 
     604        5915 :                         if (tsrm_realpath(actual_path, resolved_path)) {
     605       11686 :                                 return zend_string_init(resolved_path, strlen(resolved_path), 0);
     606             :                         }
     607             :                 }
     608             :         }
     609             : 
     610          79 :         return NULL;
     611             : }
     612             : /* }}} */
     613             : 
     614             : /* {{{ php_fopen_with_path
     615             :  * Tries to open a file with a PATH-style list of directories.
     616             :  * If the filename starts with "." or "/", the path is ignored.
     617             :  */
     618          82 : PHPAPI FILE *php_fopen_with_path(const char *filename, const char *mode, const char *path, zend_string **opened_path)
     619             : {
     620             :         char *pathbuf, *ptr, *end;
     621             :         char trypath[MAXPATHLEN];
     622             :         FILE *fp;
     623             :         int filename_length;
     624             :         zend_string *exec_filename;
     625             : 
     626          82 :         if (opened_path) {
     627          82 :                 *opened_path = NULL;
     628             :         }
     629             : 
     630          82 :         if (!filename) {
     631           0 :                 return NULL;
     632             :         }
     633             : 
     634          82 :         filename_length = (int)strlen(filename);
     635             : #ifndef PHP_WIN32
     636             :         (void) filename_length;
     637             : #endif
     638             : 
     639             :         /* Relative path open */
     640         246 :         if ((*filename == '.')
     641             :         /* Absolute path open */
     642          82 :          || IS_ABSOLUTE_PATH(filename, filename_length)
     643          82 :          || (!path || (path && !*path))
     644             :         ) {
     645           0 :                 return php_fopen_and_set_opened_path(filename, mode, opened_path);
     646             :         }
     647             : 
     648             :         /* check in provided path */
     649             :         /* append the calling scripts' current working directory
     650             :          * as a fall back case
     651             :          */
     652          82 :         if (zend_is_executing() &&
     653           0 :             (exec_filename = zend_get_executed_filename_ex()) != NULL) {
     654           0 :                 const char *exec_fname = ZSTR_VAL(exec_filename);
     655           0 :                 size_t exec_fname_length = ZSTR_LEN(exec_filename);
     656             : 
     657           0 :                 while ((--exec_fname_length < SIZE_MAX) && !IS_SLASH(exec_fname[exec_fname_length]));
     658           0 :                 if ((exec_fname && exec_fname[0] == '[') || exec_fname_length <= 0) {
     659             :                         /* [no active file] or no path */
     660           0 :                         pathbuf = estrdup(path);
     661             :                 } else {
     662           0 :                         size_t path_length = strlen(path);
     663             : 
     664           0 :                         pathbuf = (char *) emalloc(exec_fname_length + path_length + 1 + 1);
     665           0 :                         memcpy(pathbuf, path, path_length);
     666           0 :                         pathbuf[path_length] = DEFAULT_DIR_SEPARATOR;
     667           0 :                         memcpy(pathbuf + path_length + 1, exec_fname, exec_fname_length);
     668           0 :                         pathbuf[path_length + exec_fname_length + 1] = '\0';
     669             :                 }
     670             :         } else {
     671          82 :                 pathbuf = estrdup(path);
     672             :         }
     673             : 
     674          82 :         ptr = pathbuf;
     675             : 
     676         328 :         while (ptr && *ptr) {
     677         164 :                 end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
     678         164 :                 if (end != NULL) {
     679          82 :                         *end = '\0';
     680          82 :                         end++;
     681             :                 }
     682         164 :                 if (snprintf(trypath, MAXPATHLEN, "%s/%s", ptr, filename) >= MAXPATHLEN) {
     683           0 :                         php_error_docref(NULL, E_NOTICE, "%s/%s path was truncated to %d", ptr, filename, MAXPATHLEN);
     684             :                 }
     685         164 :                 fp = php_fopen_and_set_opened_path(trypath, mode, opened_path);
     686         164 :                 if (fp) {
     687           0 :                         efree(pathbuf);
     688           0 :                         return fp;
     689             :                 }
     690         164 :                 ptr = end;
     691             :         } /* end provided path */
     692             : 
     693          82 :         efree(pathbuf);
     694          82 :         return NULL;
     695             : }
     696             : /* }}} */
     697             : 
     698             : /* {{{ php_strip_url_passwd
     699             :  */
     700         558 : PHPAPI char *php_strip_url_passwd(char *url)
     701             : {
     702             :         register char *p, *url_start;
     703             : 
     704         558 :         if (url == NULL) {
     705           0 :                 return "";
     706             :         }
     707             : 
     708         558 :         p = url;
     709             : 
     710       18308 :         while (*p) {
     711       17353 :                 if (*p == ':' && *(p + 1) == '/' && *(p + 2) == '/') {
     712             :                         /* found protocol */
     713         161 :                         url_start = p = p + 3;
     714             : 
     715        7402 :                         while (*p) {
     716        7082 :                                 if (*p == '@') {
     717             :                                         int i;
     718             : 
     719           8 :                                         for (i = 0; i < 3 && url_start < p; i++, url_start++) {
     720           6 :                                                 *url_start = '.';
     721             :                                         }
     722          24 :                                         for (; *p; p++) {
     723          22 :                                                 *url_start++ = *p;
     724             :                                         }
     725           2 :                                         *url_start=0;
     726           2 :                                         break;
     727             :                                 }
     728        7080 :                                 p++;
     729             :                         }
     730         161 :                         return url;
     731             :                 }
     732       17192 :                 p++;
     733             :         }
     734         397 :         return url;
     735             : }
     736             : /* }}} */
     737             : 
     738             : /* {{{ expand_filepath
     739             :  */
     740      117603 : PHPAPI char *expand_filepath(const char *filepath, char *real_path)
     741             : {
     742      117603 :         return expand_filepath_ex(filepath, real_path, NULL, 0);
     743             : }
     744             : /* }}} */
     745             : 
     746             : /* {{{ expand_filepath_ex
     747             :  */
     748      117771 : PHPAPI char *expand_filepath_ex(const char *filepath, char *real_path, const char *relative_to, size_t relative_to_len)
     749             : {
     750      117771 :         return expand_filepath_with_mode(filepath, real_path, relative_to, relative_to_len, CWD_FILEPATH);
     751             : }
     752             : /* }}} */
     753             : 
     754             : /* {{{ expand_filepath_use_realpath
     755             :  */
     756      118367 : PHPAPI char *expand_filepath_with_mode(const char *filepath, char *real_path, const char *relative_to, size_t relative_to_len, int realpath_mode)
     757             : {
     758             :         cwd_state new_state;
     759             :         char cwd[MAXPATHLEN];
     760             :         int copy_len;
     761             :         int path_len;
     762             : 
     763      118367 :         if (!filepath[0]) {
     764           2 :                 return NULL;
     765             :         }
     766             : 
     767      118365 :         path_len = (int)strlen(filepath);
     768             : 
     769      118365 :         if (IS_ABSOLUTE_PATH(filepath, path_len)) {
     770      117095 :                 cwd[0] = '\0';
     771             :         } else {
     772        1270 :                 const char *iam = SG(request_info).path_translated;
     773             :                 const char *result;
     774        1270 :                 if (relative_to) {
     775          32 :                         if (relative_to_len > MAXPATHLEN-1U) {
     776           0 :                                 return NULL;
     777             :                         }
     778          32 :                         result = relative_to;
     779          32 :                         memcpy(cwd, relative_to, relative_to_len+1U);
     780             :                 } else {
     781        1238 :                         result = VCWD_GETCWD(cwd, MAXPATHLEN);
     782             :                 }
     783             : 
     784        1270 :                 if (!result && (iam != filepath)) {
     785           0 :                         int fdtest = -1;
     786             : 
     787           0 :                         fdtest = VCWD_OPEN(filepath, O_RDONLY);
     788           0 :                         if (fdtest != -1) {
     789             :                                 /* return a relative file path if for any reason
     790             :                                  * we cannot cannot getcwd() and the requested,
     791             :                                  * relatively referenced file is accessible */
     792           0 :                                 copy_len = path_len > MAXPATHLEN - 1 ? MAXPATHLEN - 1 : path_len;
     793           0 :                                 if (real_path) {
     794           0 :                                         memcpy(real_path, filepath, copy_len);
     795           0 :                                         real_path[copy_len] = '\0';
     796             :                                 } else {
     797           0 :                                         real_path = estrndup(filepath, copy_len);
     798             :                                 }
     799           0 :                                 close(fdtest);
     800           0 :                                 return real_path;
     801             :                         } else {
     802           0 :                                 cwd[0] = '\0';
     803             :                         }
     804        1270 :                 } else if (!result) {
     805           0 :                         cwd[0] = '\0';
     806             :                 }
     807             :         }
     808             : 
     809      118365 :         new_state.cwd = estrdup(cwd);
     810      118365 :         new_state.cwd_length = (int)strlen(cwd);
     811             : 
     812      118365 :         if (virtual_file_ex(&new_state, filepath, NULL, realpath_mode)) {
     813           3 :                 efree(new_state.cwd);
     814           3 :                 return NULL;
     815             :         }
     816             : 
     817      118362 :         if (real_path) {
     818       94844 :                 copy_len = new_state.cwd_length > MAXPATHLEN - 1 ? MAXPATHLEN - 1 : new_state.cwd_length;
     819       94844 :                 memcpy(real_path, new_state.cwd, copy_len);
     820       94844 :                 real_path[copy_len] = '\0';
     821             :         } else {
     822       23518 :                 real_path = estrndup(new_state.cwd, new_state.cwd_length);
     823             :         }
     824      118362 :         efree(new_state.cwd);
     825             : 
     826      118362 :         return real_path;
     827             : }
     828             : /* }}} */
     829             : 
     830             : /*
     831             :  * Local variables:
     832             :  * tab-width: 4
     833             :  * c-basic-offset: 4
     834             :  * End:
     835             :  * vim600: sw=4 ts=4 fdm=marker
     836             :  * vim<600: sw=4 ts=4
     837             :  */

Generated by: LCOV version 1.10

Generated at Sat, 29 Aug 2015 10:22:29 +0000 (19 hours ago)

Copyright © 2005-2015 The PHP Group
All rights reserved.