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 - ext/standard - php_fopen_wrapper.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 130 179 72.6 %
Date: 2014-10-22 Functions: 7 10 70.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2014 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@php.net>                             |
      16             :    |          Jim Winstead <jimw@php.net>                                 |
      17             :    |          Hartmut Holzgraefe <hholzgra@php.net>                       |
      18             :    +----------------------------------------------------------------------+
      19             :  */
      20             : /* $Id$ */
      21             : 
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #if HAVE_UNISTD_H
      25             : #include <unistd.h>
      26             : #endif
      27             : 
      28             : #include "php.h"
      29             : #include "php_globals.h"
      30             : #include "php_standard.h"
      31             : #include "php_fopen_wrappers.h"
      32             : #include "SAPI.h"
      33             : 
      34           8 : static size_t php_stream_output_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) /* {{{ */
      35             : {
      36           8 :         PHPWRITE(buf, count);
      37           8 :         return count;
      38             : }
      39             : /* }}} */
      40             : 
      41           0 : static size_t php_stream_output_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) /* {{{ */
      42             : {
      43           0 :         stream->eof = 1;
      44           0 :         return 0;
      45             : }
      46             : /* }}} */
      47             : 
      48           1 : static int php_stream_output_close(php_stream *stream, int close_handle TSRMLS_DC) /* {{{ */
      49             : {
      50           1 :         return 0;
      51             : }
      52             : /* }}} */
      53             : 
      54             : php_stream_ops php_stream_output_ops = {
      55             :         php_stream_output_write,
      56             :         php_stream_output_read,
      57             :         php_stream_output_close,
      58             :         NULL, /* flush */
      59             :         "Output",
      60             :         NULL, /* seek */
      61             :         NULL, /* cast */
      62             :         NULL, /* stat */
      63             :         NULL  /* set_option */
      64             : };
      65             : 
      66             : typedef struct php_stream_input { /* {{{ */
      67             :         php_stream *body;
      68             :         zend_off_t position;
      69             : } php_stream_input_t;
      70             : /* }}} */
      71             : 
      72           0 : static size_t php_stream_input_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) /* {{{ */
      73             : {
      74           0 :         return -1;
      75             : }
      76             : /* }}} */
      77             : 
      78          34 : static size_t php_stream_input_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) /* {{{ */
      79             : {
      80          34 :         php_stream_input_t *input = stream->abstract;
      81             :         size_t read;
      82             : 
      83          34 :         if (!SG(post_read) && SG(read_post_bytes) < input->position + count) {
      84             :                 /* read requested data from SAPI */
      85           7 :                 int read_bytes = sapi_read_post_block(buf, count TSRMLS_CC);
      86             : 
      87           7 :                 if (read_bytes > 0) {
      88           7 :                         php_stream_seek(input->body, 0, SEEK_END);
      89           7 :                         php_stream_write(input->body, buf, read_bytes);
      90             :                 }
      91             :         }
      92             : 
      93          34 :         php_stream_seek(input->body, input->position, SEEK_SET);
      94          34 :         read = php_stream_read(input->body, buf, count);
      95             : 
      96          50 :         if (!read || read == (size_t) -1) {
      97          16 :                 stream->eof = 1;
      98             :         } else {
      99          18 :                 input->position += read;
     100             :         }
     101             : 
     102          34 :         return read;
     103             : }
     104             : /* }}} */
     105             : 
     106          17 : static int php_stream_input_close(php_stream *stream, int close_handle TSRMLS_DC) /* {{{ */
     107             : {
     108          17 :         efree(stream->abstract);
     109          17 :         stream->abstract = NULL;
     110             : 
     111          17 :         return 0;
     112             : }
     113             : /* }}} */
     114             : 
     115          17 : static int php_stream_input_flush(php_stream *stream TSRMLS_DC) /* {{{ */
     116             : {
     117          17 :         return -1;
     118             : }
     119             : /* }}} */
     120             : 
     121           0 : static int php_stream_input_seek(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffset TSRMLS_DC) /* {{{ */
     122             : {
     123           0 :         php_stream_input_t *input = stream->abstract;
     124             : 
     125           0 :         if (input->body) {
     126           0 :                 int sought = php_stream_seek(input->body, offset, whence);
     127           0 :                 *newoffset = (input->body)->position;
     128           0 :                 return sought;
     129             :         }
     130             : 
     131           0 :         return -1;
     132             : }
     133             : /* }}} */
     134             : 
     135             : php_stream_ops php_stream_input_ops = {
     136             :         php_stream_input_write,
     137             :         php_stream_input_read,
     138             :         php_stream_input_close,
     139             :         php_stream_input_flush,
     140             :         "Input",
     141             :         php_stream_input_seek,
     142             :         NULL, /* cast */
     143             :         NULL, /* stat */
     144             :         NULL  /* set_option */
     145             : };
     146             : 
     147           1 : static void php_stream_apply_filter_list(php_stream *stream, char *filterlist, int read_chain, int write_chain TSRMLS_DC) /* {{{ */
     148             : {
     149             :         char *p, *token;
     150             :         php_stream_filter *temp_filter;
     151             : 
     152           1 :         p = php_strtok_r(filterlist, "|", &token);
     153           6 :         while (p) {
     154           4 :                 php_url_decode(p, strlen(p));
     155           4 :                 if (read_chain) {
     156           4 :                         if ((temp_filter = php_stream_filter_create(p, NULL, php_stream_is_persistent(stream) TSRMLS_CC))) {
     157           4 :                                 php_stream_filter_append(&stream->readfilters, temp_filter);
     158             :                         } else {
     159           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create filter (%s)", p);
     160             :                         }
     161             :                 }
     162           4 :                 if (write_chain) {
     163           0 :                         if ((temp_filter = php_stream_filter_create(p, NULL, php_stream_is_persistent(stream) TSRMLS_CC))) {
     164           0 :                                 php_stream_filter_append(&stream->writefilters, temp_filter);
     165             :                         } else {
     166           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create filter (%s)", p);
     167             :                         }
     168             :                 }
     169           4 :                 p = php_strtok_r(NULL, "|", &token);
     170             :         }
     171           1 : }
     172             : /* }}} */
     173             : 
     174       59945 : php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *path, const char *mode, int options,
     175             :                                                                          char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */
     176             : {
     177       59945 :         int fd = -1;
     178       59945 :         int mode_rw = 0;
     179       59945 :         php_stream * stream = NULL;
     180             :         char *p, *token, *pathdup;
     181             :         zend_long max_memory;
     182       59945 :         FILE *file = NULL;
     183             : 
     184       59945 :         if (!strncasecmp(path, "php://", 6)) {
     185       59945 :                 path += 6;
     186             :         }
     187             : 
     188       59945 :         if (!strncasecmp(path, "temp", 4)) {
     189          24 :                 path += 4;
     190          24 :                 max_memory = PHP_STREAM_MAX_MEM;
     191          24 :                 if (!strncasecmp(path, "/maxmemory:", 11)) {
     192           1 :                         path += 11;
     193           1 :                         max_memory = ZEND_STRTOL(path, NULL, 10);
     194           1 :                         if (max_memory < 0) {
     195           0 :                                 php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Max memory must be >= 0");
     196           0 :                                 return NULL;
     197             :                         }
     198             :                 }
     199          24 :                 if (strpbrk(mode, "wa+")) {
     200          22 :                         mode_rw = TEMP_STREAM_DEFAULT;
     201             :                 } else {
     202           2 :                         mode_rw = TEMP_STREAM_READONLY;
     203             :                 }
     204          24 :                 return php_stream_temp_create(mode_rw, max_memory);
     205             :         }
     206             : 
     207       59921 :         if (!strcasecmp(path, "memory")) {
     208          33 :                 if (strpbrk(mode, "wa+")) {
     209          31 :                         mode_rw = TEMP_STREAM_DEFAULT;
     210             :                 } else {
     211           2 :                         mode_rw = TEMP_STREAM_READONLY;
     212             :                 }
     213          33 :                 return php_stream_memory_create(mode_rw);
     214             :         }
     215             : 
     216       59888 :         if (!strcasecmp(path, "output")) {
     217           1 :                 return php_stream_alloc(&php_stream_output_ops, NULL, 0, "wb");
     218             :         }
     219             : 
     220       59887 :         if (!strcasecmp(path, "input")) {
     221             :                 php_stream_input_t *input;
     222             : 
     223          17 :                 if ((options & STREAM_OPEN_FOR_INCLUDE) && !PG(allow_url_include) ) {
     224           0 :                         if (options & REPORT_ERRORS) {
     225           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "URL file-access is disabled in the server configuration");
     226             :                         }
     227           0 :                         return NULL;
     228             :                 }
     229             : 
     230          17 :                 input = ecalloc(1, sizeof(*input));
     231          17 :                 if ((input->body = SG(request_info).request_body)) {
     232          10 :                         php_stream_rewind(input->body);
     233             :                 } else {
     234           7 :                         input->body = php_stream_temp_create_ex(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE, PG(upload_tmp_dir));
     235           7 :                         SG(request_info).request_body = input->body;
     236             :                 }
     237             : 
     238          17 :                 return php_stream_alloc(&php_stream_input_ops, input, 0, "rb");
     239             :         }
     240             : 
     241       59870 :         if (!strcasecmp(path, "stdin")) {
     242       19955 :                 if ((options & STREAM_OPEN_FOR_INCLUDE) && !PG(allow_url_include) ) {
     243           0 :                         if (options & REPORT_ERRORS) {
     244           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "URL file-access is disabled in the server configuration");
     245             :                         }
     246           0 :                         return NULL;
     247             :                 }
     248       19955 :                 if (!strcmp(sapi_module.name, "cli")) {
     249             :                         static int cli_in = 0;
     250       19955 :                         fd = STDIN_FILENO;
     251       19955 :                         if (cli_in) {
     252           5 :                                 fd = dup(fd);
     253             :                         } else {
     254       19950 :                                 cli_in = 1;
     255       19950 :                                 file = stdin;
     256             :                         }
     257             :                 } else {
     258           0 :                         fd = dup(STDIN_FILENO);
     259             :                 }
     260       39915 :         } else if (!strcasecmp(path, "stdout")) {
     261       19957 :                 if (!strcmp(sapi_module.name, "cli")) {
     262             :                         static int cli_out = 0;
     263       19957 :                         fd = STDOUT_FILENO;
     264       19957 :                         if (cli_out++) {
     265           7 :                                 fd = dup(fd);
     266             :                         } else {
     267       19950 :                                 cli_out = 1;
     268       19950 :                                 file = stdout;
     269             :                         }
     270             :                 } else {
     271           0 :                         fd = dup(STDOUT_FILENO);
     272             :                 }
     273       19958 :         } else if (!strcasecmp(path, "stderr")) {
     274       19950 :                 if (!strcmp(sapi_module.name, "cli")) {
     275             :                         static int cli_err = 0;
     276       19950 :                         fd = STDERR_FILENO;
     277       19950 :                         if (cli_err++) {
     278           0 :                                 fd = dup(fd);
     279             :                         } else {
     280       19950 :                                 cli_err = 1;
     281       19950 :                                 file = stderr;
     282             :                         }
     283             :                 } else {
     284           0 :                         fd = dup(STDERR_FILENO);
     285             :                 }
     286           8 :         } else if (!strncasecmp(path, "fd/", 3)) {
     287             :                 const char *start;
     288             :                 char       *end;
     289             :                 zend_long  fildes_ori;
     290             :                 int                dtablesize;
     291             : 
     292           6 :                 if (strcmp(sapi_module.name, "cli")) {
     293           0 :                         if (options & REPORT_ERRORS) {
     294           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Direct access to file descriptors is only available from command-line PHP");
     295             :                         }
     296           0 :                         return NULL;
     297             :                 }
     298             : 
     299           6 :                 if ((options & STREAM_OPEN_FOR_INCLUDE) && !PG(allow_url_include) ) {
     300           0 :                         if (options & REPORT_ERRORS) {
     301           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "URL file-access is disabled in the server configuration");
     302             :                         }
     303           0 :                         return NULL;
     304             :                 }
     305             : 
     306           6 :                 start = &path[3];
     307           6 :                 fildes_ori = ZEND_STRTOL(start, &end, 10);
     308           6 :                 if (end == start || *end != '\0') {
     309           2 :                         php_stream_wrapper_log_error(wrapper, options TSRMLS_CC,
     310             :                                 "php://fd/ stream must be specified in the form php://fd/<orig fd>");
     311           2 :                         return NULL;
     312             :                 }
     313             : 
     314             : #if HAVE_UNISTD_H
     315           4 :                 dtablesize = getdtablesize();
     316             : #else
     317             :                 dtablesize = INT_MAX;
     318             : #endif
     319             : 
     320           4 :                 if (fildes_ori < 0 || fildes_ori >= dtablesize) {
     321           1 :                         php_stream_wrapper_log_error(wrapper, options TSRMLS_CC,
     322             :                                 "The file descriptors must be non-negative numbers smaller than %d", dtablesize);
     323           1 :                         return NULL;
     324             :                 }
     325             :                 
     326           3 :                 fd = dup(fildes_ori);
     327           3 :                 if (fd == -1) {
     328           1 :                         php_stream_wrapper_log_error(wrapper, options TSRMLS_CC,
     329             :                                 "Error duping file descriptor " ZEND_LONG_FMT "; possibly it doesn't exist: "
     330             :                                 "[%d]: %s", fildes_ori, errno, strerror(errno));
     331           1 :                         return NULL;
     332             :                 }
     333           2 :         } else if (!strncasecmp(path, "filter/", 7)) {
     334             :                 /* Save time/memory when chain isn't specified */
     335           1 :                 if (strchr(mode, 'r') || strchr(mode, '+')) {
     336           1 :                         mode_rw |= PHP_STREAM_FILTER_READ;
     337             :                 }
     338           1 :                 if (strchr(mode, 'w') || strchr(mode, '+') || strchr(mode, 'a')) {
     339           0 :                         mode_rw |= PHP_STREAM_FILTER_WRITE;
     340             :                 }
     341           1 :                 pathdup = estrndup(path + 6, strlen(path + 6));
     342           1 :                 p = strstr(pathdup, "/resource=");
     343           1 :                 if (!p) {
     344           0 :                         php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "No URL resource specified");
     345           0 :                         efree(pathdup);
     346           0 :                         return NULL;
     347             :                 }
     348           1 :                 if (!(stream = php_stream_open_wrapper(p + 10, mode, options, opened_path))) {
     349           0 :                         efree(pathdup);
     350           0 :                         return NULL;
     351             :                 }
     352             : 
     353           1 :                 *p = '\0';
     354             : 
     355           1 :                 p = php_strtok_r(pathdup + 1, "/", &token);
     356           3 :                 while (p) {
     357           1 :                         if (!strncasecmp(p, "read=", 5)) {
     358           1 :                                 php_stream_apply_filter_list(stream, p + 5, 1, 0 TSRMLS_CC);
     359           0 :                         } else if (!strncasecmp(p, "write=", 6)) {
     360           0 :                                 php_stream_apply_filter_list(stream, p + 6, 0, 1 TSRMLS_CC);
     361             :                         } else {
     362           0 :                                 php_stream_apply_filter_list(stream, p, mode_rw & PHP_STREAM_FILTER_READ, mode_rw & PHP_STREAM_FILTER_WRITE TSRMLS_CC);
     363             :                         }
     364           1 :                         p = php_strtok_r(NULL, "/", &token);
     365             :                 }
     366           1 :                 efree(pathdup);
     367             : 
     368           1 :                 return stream;
     369             :         } else {
     370             :                 /* invalid php://thingy */
     371           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid php:// URL specified");
     372           1 :                 return NULL;
     373             :         }
     374             : 
     375             :         /* must be stdin, stderr or stdout */
     376       59864 :         if (fd == -1)   {
     377             :                 /* failed to dup */
     378           0 :                 return NULL;
     379             :         }
     380             : 
     381             : #if defined(S_IFSOCK) && !defined(WIN32) && !defined(__BEOS__)
     382             :         do {
     383             :                 zend_stat_t st;
     384       59864 :                 memset(&st, 0, sizeof(st));
     385       59864 :                 if (zend_fstat(fd, &st) == 0 && (st.st_mode & S_IFMT) == S_IFSOCK) {
     386           0 :                         stream = php_stream_sock_open_from_socket(fd, NULL);
     387           0 :                         if (stream) {
     388           0 :                                 stream->ops = &php_stream_socket_ops;
     389           0 :                                 return stream;
     390             :                         }
     391             :                 }
     392             :         } while (0);
     393             : #endif
     394             : 
     395       59864 :         if (file) {
     396       59850 :                 stream = php_stream_fopen_from_file(file, mode);
     397             :         } else {
     398          14 :                 stream = php_stream_fopen_from_fd(fd, mode, NULL);
     399          14 :                 if (stream == NULL) {
     400           0 :                         close(fd);
     401             :                 }
     402             :         }
     403             : 
     404       59864 :         return stream;
     405             : }
     406             : /* }}} */
     407             : 
     408             : static php_stream_wrapper_ops php_stdio_wops = {
     409             :         php_stream_url_wrap_php,
     410             :         NULL, /* close */
     411             :         NULL, /* fstat */
     412             :         NULL, /* stat */
     413             :         NULL, /* opendir */
     414             :         "PHP",
     415             :         NULL, /* unlink */
     416             :         NULL, /* rename */
     417             :         NULL, /* mkdir */
     418             :         NULL  /* rmdir */
     419             : };
     420             : 
     421             : php_stream_wrapper php_stream_php_wrapper =     {
     422             :         &php_stdio_wops,
     423             :         NULL,
     424             :         0, /* is_url */
     425             : };
     426             : 
     427             : 
     428             : /*
     429             :  * Local variables:
     430             :  * tab-width: 4
     431             :  * c-basic-offset: 4
     432             :  * End:
     433             :  * vim600: sw=4 ts=4 fdm=marker
     434             :  * vim<600: sw=4 ts=4
     435             :  */

Generated by: LCOV version 1.10

Generated at Wed, 22 Oct 2014 07:24:59 +0000 (6 hours ago)

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