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/streams - memory.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 245 321 76.3 %
Date: 2014-08-04 Functions: 20 23 87.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       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             :    | Author: Marcus Boerger <helly@php.net>                               |
      16             :    +----------------------------------------------------------------------+
      17             :  */
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : #define _GNU_SOURCE
      22             : #include "php.h"
      23             : 
      24             : PHPAPI int php_url_decode(char *str, int len);
      25             : PHPAPI unsigned char *php_base64_decode(const unsigned char *str, int length, int *ret_length);
      26             : 
      27             : /* Memory streams use a dynamic memory buffer to emulate a stream.
      28             :  * You can use php_stream_memory_open to create a readonly stream
      29             :  * from an existing memory buffer.
      30             :  */
      31             : 
      32             : /* Temp streams are streams that uses memory streams as long their
      33             :  * size is less than a given memory amount. When a write operation
      34             :  * exceeds that limit the content is written to a temporary file.
      35             :  */
      36             : 
      37             : /* {{{ ------- MEMORY stream implementation -------*/
      38             : 
      39             : typedef struct {
      40             :         char        *data;
      41             :         size_t      fpos;
      42             :         size_t      fsize;
      43             :         size_t      smax;
      44             :         int                     mode;
      45             : } php_stream_memory_data;
      46             : 
      47             : 
      48             : /* {{{ */
      49        2187 : static size_t php_stream_memory_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
      50             : {
      51        2187 :         php_stream_memory_data *ms = (php_stream_memory_data*)stream->abstract;
      52             :         assert(ms != NULL);
      53             : 
      54        2187 :         if (ms->mode & TEMP_STREAM_READONLY) {
      55           2 :                 return 0;
      56             :         }
      57        2185 :         if (ms->fpos + count > ms->fsize) {
      58             :                 char *tmp;
      59             : 
      60        2185 :                 if (!ms->data) {
      61         134 :                         tmp = emalloc(ms->fpos + count);
      62             :                 } else {
      63        2051 :                         tmp = erealloc(ms->data, ms->fpos + count);
      64             :                 }
      65        2185 :                 if (!tmp) {
      66           0 :                         count = ms->fsize - ms->fpos + 1;
      67             :                 } else {
      68        2185 :                         ms->data = tmp;
      69        2185 :                         ms->fsize = ms->fpos + count;
      70             :                 }
      71             :         }
      72        2185 :         if (!ms->data)
      73           0 :                 count = 0;
      74        2185 :         if (count) {
      75             :                 assert(buf!= NULL);
      76        2185 :                 memcpy(ms->data+ms->fpos, (char*)buf, count);
      77        2185 :                 ms->fpos += count;
      78             :         }
      79        2185 :         return count;
      80             : }
      81             : /* }}} */
      82             : 
      83             : 
      84             : /* {{{ */
      85         242 : static size_t php_stream_memory_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
      86             : {
      87         242 :         php_stream_memory_data *ms = (php_stream_memory_data*)stream->abstract;
      88             :         assert(ms != NULL);
      89             : 
      90         242 :         if (ms->fpos + count >= ms->fsize) {
      91         232 :                 count = ms->fsize - ms->fpos;
      92         232 :                 stream->eof = 1;
      93             :         }
      94         242 :         if (count) {
      95             :                 assert(ms->data!= NULL);
      96             :                 assert(buf!= NULL);
      97         173 :                 memcpy(buf, ms->data+ms->fpos, count);
      98         173 :                 ms->fpos += count;
      99             :         }
     100         242 :         return count;
     101             : }
     102             : /* }}} */
     103             : 
     104             : 
     105             : /* {{{ */
     106         196 : static int php_stream_memory_close(php_stream *stream, int close_handle TSRMLS_DC)
     107             : {
     108         196 :         php_stream_memory_data *ms = (php_stream_memory_data*)stream->abstract;
     109             :         assert(ms != NULL);
     110             : 
     111         196 :         if (ms->data && close_handle && ms->mode != TEMP_STREAM_READONLY) {
     112         135 :                 efree(ms->data);
     113             :         }
     114         196 :         efree(ms);
     115         196 :         return 0;
     116             : }
     117             : /* }}} */
     118             : 
     119             : 
     120             : /* {{{ */
     121         354 : static int php_stream_memory_flush(php_stream *stream TSRMLS_DC)
     122             : {
     123             :         /* nothing to do here */
     124         354 :         return 0;
     125             : }
     126             : /* }}} */
     127             : 
     128             : 
     129             : /* {{{ */
     130         274 : static int php_stream_memory_seek(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC)
     131             : {
     132         274 :         php_stream_memory_data *ms = (php_stream_memory_data*)stream->abstract;
     133             :         assert(ms != NULL);
     134             : 
     135         274 :         switch(whence) {
     136             :                 case SEEK_CUR:
     137           8 :                         if (offset < 0) {
     138           0 :                                 if (ms->fpos < (size_t)(-offset)) {
     139           0 :                                         ms->fpos = 0;
     140           0 :                                         *newoffs = -1;
     141           0 :                                         return -1;
     142             :                                 } else {
     143           0 :                                         ms->fpos = ms->fpos + offset;
     144           0 :                                         *newoffs = ms->fpos;
     145           0 :                                         stream->eof = 0;
     146           0 :                                         return 0;
     147             :                                 }
     148             :                         } else {
     149           8 :                                 if (ms->fpos + (size_t)(offset) > ms->fsize) {
     150           0 :                                         ms->fpos = ms->fsize;
     151           0 :                                         *newoffs = -1;
     152           0 :                                         return -1;
     153             :                                 } else {
     154           8 :                                         ms->fpos = ms->fpos + offset;
     155           8 :                                         *newoffs = ms->fpos;
     156           8 :                                         stream->eof = 0;
     157           8 :                                         return 0;
     158             :                                 }
     159             :                         }
     160             :                 case SEEK_SET:
     161         256 :                         if (ms->fsize < (size_t)(offset)) {
     162           4 :                                 ms->fpos = ms->fsize;
     163           4 :                                 *newoffs = -1;
     164           4 :                                 return -1;
     165             :                         } else {
     166         252 :                                 ms->fpos = offset;
     167         252 :                                 *newoffs = ms->fpos;
     168         252 :                                 stream->eof = 0;
     169         252 :                                 return 0;
     170             :                         }
     171             :                 case SEEK_END:
     172          10 :                         if (offset > 0) {
     173           1 :                                 ms->fpos = ms->fsize;
     174           1 :                                 *newoffs = -1;
     175           1 :                                 return -1;
     176           9 :                         } else if (ms->fsize < (size_t)(-offset)) {
     177           0 :                                 ms->fpos = 0;
     178           0 :                                 *newoffs = -1;
     179           0 :                                 return -1;
     180             :                         } else {
     181           9 :                                 ms->fpos = ms->fsize + offset;
     182           9 :                                 *newoffs = ms->fpos;
     183           9 :                                 stream->eof = 0;
     184           9 :                                 return 0;
     185             :                         }
     186             :                 default:
     187           0 :                         *newoffs = ms->fpos;
     188           0 :                         return -1;
     189             :         }
     190             : }
     191             : /* }}} */
     192             : 
     193             : /* {{{ */
     194           0 : static int php_stream_memory_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
     195             : {
     196           0 :         return FAILURE;
     197             : }
     198             : /* }}} */
     199             : 
     200          87 : static int php_stream_memory_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC) /* {{{ */
     201             : {
     202          87 :         time_t timestamp = 0;
     203          87 :         php_stream_memory_data *ms = (php_stream_memory_data*)stream->abstract;
     204             :         assert(ms != NULL);
     205             : 
     206          87 :         memset(ssb, 0, sizeof(php_stream_statbuf));
     207             :         /* read-only across the board */
     208             :         
     209          87 :         ssb->sb.st_mode = ms->mode & TEMP_STREAM_READONLY ? 0444 : 0666;
     210             : 
     211          87 :         ssb->sb.st_size = ms->fsize;
     212          87 :         ssb->sb.st_mode |= S_IFREG; /* regular file */
     213             : 
     214             : #ifdef NETWARE
     215             :         ssb->sb.st_mtime.tv_sec = timestamp;
     216             :         ssb->sb.st_atime.tv_sec = timestamp;
     217             :         ssb->sb.st_ctime.tv_sec = timestamp;
     218             : #else
     219          87 :         ssb->sb.st_mtime = timestamp;
     220          87 :         ssb->sb.st_atime = timestamp;
     221          87 :         ssb->sb.st_ctime = timestamp;
     222             : #endif
     223             : 
     224          87 :         ssb->sb.st_nlink = 1;
     225          87 :         ssb->sb.st_rdev = -1;
     226             :         /* this is only for APC, so use /dev/null device - no chance of conflict there! */
     227          87 :         ssb->sb.st_dev = 0xC;
     228             :         /* generate unique inode number for alias/filename, so no phars will conflict */
     229          87 :         ssb->sb.st_ino = 0;
     230             : 
     231             : #ifndef PHP_WIN32
     232          87 :         ssb->sb.st_blksize = -1;
     233             : #endif
     234             : 
     235             : #if !defined(PHP_WIN32) && !defined(__BEOS__)
     236          87 :         ssb->sb.st_blocks = -1;
     237             : #endif
     238             : 
     239          87 :         return 0;
     240             : }
     241             : /* }}} */
     242             : 
     243          64 : static int php_stream_memory_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC) /* {{{ */
     244             : {
     245          64 :         php_stream_memory_data *ms = (php_stream_memory_data*)stream->abstract;
     246             :         size_t newsize;
     247             :         
     248          64 :         switch(option) {
     249             :                 case PHP_STREAM_OPTION_TRUNCATE_API:
     250           0 :                         switch (value) {
     251             :                                 case PHP_STREAM_TRUNCATE_SUPPORTED:
     252           0 :                                         return PHP_STREAM_OPTION_RETURN_OK;
     253             : 
     254             :                                 case PHP_STREAM_TRUNCATE_SET_SIZE:
     255           0 :                                         if (ms->mode & TEMP_STREAM_READONLY) {
     256           0 :                                                 return PHP_STREAM_OPTION_RETURN_ERR;
     257             :                                         }
     258           0 :                                         newsize = *(size_t*)ptrparam;
     259           0 :                                         if (newsize <= ms->fsize) {
     260           0 :                                                 if (newsize < ms->fpos) {
     261           0 :                                                         ms->fpos = newsize;
     262             :                                                 }
     263             :                                         } else {
     264           0 :                                                 ms->data = erealloc(ms->data, newsize);
     265           0 :                                                 memset(ms->data+ms->fsize, 0, newsize - ms->fsize);
     266           0 :                                                 ms->fsize = newsize;
     267             :                                         }
     268           0 :                                         ms->fsize = newsize;
     269           0 :                                         return PHP_STREAM_OPTION_RETURN_OK;
     270             :                         }
     271             :                 default:
     272          64 :                         return PHP_STREAM_OPTION_RETURN_NOTIMPL;
     273             :         }
     274             : }
     275             : /* }}} */
     276             :         
     277             : PHPAPI php_stream_ops   php_stream_memory_ops = {
     278             :         php_stream_memory_write, php_stream_memory_read,
     279             :         php_stream_memory_close, php_stream_memory_flush,
     280             :         "MEMORY",
     281             :         php_stream_memory_seek,
     282             :         php_stream_memory_cast,
     283             :         php_stream_memory_stat,
     284             :         php_stream_memory_set_option
     285             : };
     286             : 
     287             : 
     288             : /* {{{ */
     289         196 : PHPAPI php_stream *_php_stream_memory_create(int mode STREAMS_DC TSRMLS_DC)
     290             : {
     291             :         php_stream_memory_data *self;
     292             :         php_stream *stream;
     293             : 
     294         196 :         self = emalloc(sizeof(*self));
     295         196 :         self->data = NULL;
     296         196 :         self->fpos = 0;
     297         196 :         self->fsize = 0;
     298         196 :         self->smax = ~0u;
     299         196 :         self->mode = mode;
     300             :         
     301         196 :         stream = php_stream_alloc_rel(&php_stream_memory_ops, self, 0, mode & TEMP_STREAM_READONLY ? "rb" : "w+b");
     302         196 :         stream->flags |= PHP_STREAM_FLAG_NO_BUFFER;
     303         196 :         return stream;
     304             : }
     305             : /* }}} */
     306             : 
     307             : 
     308             : /* {{{ */
     309           6 : PHPAPI php_stream *_php_stream_memory_open(int mode, char *buf, size_t length STREAMS_DC TSRMLS_DC)
     310             : {
     311             :         php_stream *stream;
     312             :         php_stream_memory_data *ms;
     313             : 
     314           6 :         if ((stream = php_stream_memory_create_rel(mode)) != NULL) {
     315           6 :                 ms = (php_stream_memory_data*)stream->abstract;
     316             :                 
     317          12 :                 if (mode == TEMP_STREAM_READONLY || mode == TEMP_STREAM_TAKE_BUFFER) {
     318             :                         /* use the buffer directly */
     319           6 :                         ms->data = buf;
     320           6 :                         ms->fsize = length;
     321             :                 } else {
     322           0 :                         if (length) {
     323             :                                 assert(buf != NULL);
     324           0 :                                 php_stream_write(stream, buf, length);
     325             :                         }
     326             :                 }
     327             :         }
     328           6 :         return stream;
     329             : }
     330             : /* }}} */
     331             : 
     332             : 
     333             : /* {{{ */
     334        2166 : PHPAPI char *_php_stream_memory_get_buffer(php_stream *stream, size_t *length STREAMS_DC TSRMLS_DC)
     335             : {
     336        2166 :         php_stream_memory_data *ms = (php_stream_memory_data*)stream->abstract;
     337             : 
     338             :         assert(ms != NULL);
     339             :         assert(length != 0);
     340             : 
     341        2166 :         *length = ms->fsize;
     342        2166 :         return ms->data;
     343             : }
     344             : /* }}} */
     345             : 
     346             : /* }}} */
     347             : 
     348             : /* {{{ ------- TEMP stream implementation -------*/
     349             : 
     350             : typedef struct {
     351             :         php_stream  *innerstream;
     352             :         size_t      smax;
     353             :         int                     mode;
     354             :         zval*       meta;
     355             :         char*           tmpdir;
     356             : } php_stream_temp_data;
     357             : 
     358             : 
     359             : /* {{{ */
     360        5118 : static size_t php_stream_temp_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
     361             : {
     362        5118 :         php_stream_temp_data *ts = (php_stream_temp_data*)stream->abstract;
     363             :         assert(ts != NULL);
     364             : 
     365        5118 :         if (!ts->innerstream) {
     366           0 :                 return -1;
     367             :         }
     368        5118 :         if (php_stream_is(ts->innerstream, PHP_STREAM_IS_MEMORY)) {
     369             :                 size_t memsize;
     370        2166 :                 char *membuf = php_stream_memory_get_buffer(ts->innerstream, &memsize);
     371             : 
     372        2166 :                 if (memsize + count >= ts->smax) {
     373           1 :                         php_stream *file = php_stream_fopen_temporary_file(ts->tmpdir, "php", NULL);
     374           1 :                         php_stream_write(file, membuf, memsize);
     375           1 :                         php_stream_free_enclosed(ts->innerstream, PHP_STREAM_FREE_CLOSE);
     376           1 :                         ts->innerstream = file;
     377           1 :                         php_stream_encloses(stream, ts->innerstream);
     378             :                 }
     379             :         }
     380        5118 :         return php_stream_write(ts->innerstream, buf, count);
     381             : }
     382             : /* }}} */
     383             : 
     384             : 
     385             : /* {{{ */
     386         200 : static size_t php_stream_temp_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
     387             : {
     388         200 :         php_stream_temp_data *ts = (php_stream_temp_data*)stream->abstract;
     389             :         size_t got;
     390             : 
     391             :         assert(ts != NULL);
     392             : 
     393         200 :         if (!ts->innerstream) {
     394           0 :                 return -1;
     395             :         }
     396             :         
     397         200 :         got = php_stream_read(ts->innerstream, buf, count);
     398             :         
     399         200 :         stream->eof = ts->innerstream->eof;
     400             :         
     401         200 :         return got;
     402             : }
     403             : /* }}} */
     404             : 
     405             : 
     406             : /* {{{ */
     407         153 : static int php_stream_temp_close(php_stream *stream, int close_handle TSRMLS_DC)
     408             : {
     409         153 :         php_stream_temp_data *ts = (php_stream_temp_data*)stream->abstract;
     410             :         int ret;
     411             : 
     412             :         assert(ts != NULL);
     413             : 
     414         153 :         if (ts->innerstream) {
     415         153 :                 ret = php_stream_free_enclosed(ts->innerstream, PHP_STREAM_FREE_CLOSE | (close_handle ? 0 : PHP_STREAM_FREE_PRESERVE_HANDLE));
     416             :         } else {
     417           0 :                 ret = 0;
     418             :         }
     419             :         
     420         153 :         if (ts->meta) {
     421          47 :                 zval_ptr_dtor(&ts->meta);
     422             :         }
     423             : 
     424         153 :         if (ts->tmpdir) {
     425           0 :                 efree(ts->tmpdir);
     426             :         }
     427             : 
     428         153 :         efree(ts);
     429             : 
     430         153 :         return ret;
     431             : }
     432             : /* }}} */
     433             : 
     434             : 
     435             : /* {{{ */
     436         160 : static int php_stream_temp_flush(php_stream *stream TSRMLS_DC)
     437             : {
     438         160 :         php_stream_temp_data *ts = (php_stream_temp_data*)stream->abstract;
     439             :         assert(ts != NULL);
     440             : 
     441         160 :         return ts->innerstream ? php_stream_flush(ts->innerstream) : -1;
     442             : }
     443             : /* }}} */
     444             : 
     445             : 
     446             : /* {{{ */
     447         236 : static int php_stream_temp_seek(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC)
     448             : {
     449         236 :         php_stream_temp_data *ts = (php_stream_temp_data*)stream->abstract;
     450             :         int ret;
     451             : 
     452             :         assert(ts != NULL);
     453             : 
     454         236 :         if (!ts->innerstream) {
     455           0 :                 *newoffs = -1;
     456           0 :                 return -1;
     457             :         }
     458         236 :         ret = php_stream_seek(ts->innerstream, offset, whence);
     459         236 :         *newoffs = php_stream_tell(ts->innerstream);
     460         236 :         stream->eof = ts->innerstream->eof;
     461             :         
     462         236 :         return ret;
     463             : }
     464             : /* }}} */
     465             : 
     466             : /* {{{ */
     467           0 : static int php_stream_temp_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
     468             : {
     469           0 :         php_stream_temp_data *ts = (php_stream_temp_data*)stream->abstract;
     470             :         php_stream *file;
     471             :         size_t memsize;
     472             :         char *membuf;
     473             :         off_t pos;
     474             : 
     475             :         assert(ts != NULL);
     476             : 
     477           0 :         if (!ts->innerstream) {
     478           0 :                 return FAILURE;
     479             :         }
     480           0 :         if (php_stream_is(ts->innerstream, PHP_STREAM_IS_STDIO)) {
     481           0 :                 return php_stream_cast(ts->innerstream, castas, ret, 0);
     482             :         }
     483             : 
     484             :         /* we are still using a memory based backing. If they are if we can be
     485             :          * a FILE*, say yes because we can perform the conversion.
     486             :          * If they actually want to perform the conversion, we need to switch
     487             :          * the memory stream to a tmpfile stream */
     488             : 
     489           0 :         if (ret == NULL && castas == PHP_STREAM_AS_STDIO) {
     490           0 :                 return SUCCESS;
     491             :         }
     492             : 
     493             :         /* say "no" to other stream forms */
     494           0 :         if (ret == NULL) {
     495           0 :                 return FAILURE;
     496             :         }
     497             : 
     498             :         /* perform the conversion and then pass the request on to the innerstream */
     499           0 :         membuf = php_stream_memory_get_buffer(ts->innerstream, &memsize);
     500           0 :         file = php_stream_fopen_tmpfile();
     501           0 :         php_stream_write(file, membuf, memsize);
     502           0 :         pos = php_stream_tell(ts->innerstream);
     503             :         
     504           0 :         php_stream_free_enclosed(ts->innerstream, PHP_STREAM_FREE_CLOSE);
     505           0 :         ts->innerstream = file;
     506           0 :         php_stream_encloses(stream, ts->innerstream);
     507           0 :         php_stream_seek(ts->innerstream, pos, SEEK_SET);
     508             : 
     509           0 :         return php_stream_cast(ts->innerstream, castas, ret, 1);
     510             : }
     511             : /* }}} */
     512             : 
     513          67 : static int php_stream_temp_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC) /* {{{ */
     514             : {
     515          67 :         php_stream_temp_data *ts = (php_stream_temp_data*)stream->abstract;
     516             : 
     517          67 :         if (!ts || !ts->innerstream) {
     518           0 :                 return -1;
     519             :         }
     520          67 :         return php_stream_stat(ts->innerstream, ssb);
     521             : }
     522             : /* }}} */
     523             : 
     524          69 : static int php_stream_temp_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC) /* {{{ */
     525             : {
     526          69 :         php_stream_temp_data *ts = (php_stream_temp_data*)stream->abstract;
     527             :         
     528          69 :         switch(option) {
     529             :                 case PHP_STREAM_OPTION_META_DATA_API:
     530           6 :                         if (ts->meta) {
     531           6 :                                 zend_hash_copy(Z_ARRVAL_P((zval*)ptrparam), Z_ARRVAL_P(ts->meta), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval*));
     532             :                         }
     533           6 :                         return PHP_STREAM_OPTION_RETURN_OK;
     534             :                 default:
     535          63 :                         if (ts->innerstream) {
     536          63 :                                 return php_stream_set_option(ts->innerstream, option, value, ptrparam);
     537             :                         }
     538           0 :                         return PHP_STREAM_OPTION_RETURN_NOTIMPL;
     539             :         }
     540             : }
     541             : /* }}} */
     542             : 
     543             : PHPAPI php_stream_ops   php_stream_temp_ops = {
     544             :         php_stream_temp_write, php_stream_temp_read,
     545             :         php_stream_temp_close, php_stream_temp_flush,
     546             :         "TEMP",
     547             :         php_stream_temp_seek,
     548             :         php_stream_temp_cast,
     549             :         php_stream_temp_stat,
     550             :         php_stream_temp_set_option
     551             : };
     552             : 
     553             : /* }}} */
     554             : 
     555             : /* {{{ _php_stream_temp_create_ex */
     556         153 : PHPAPI php_stream *_php_stream_temp_create_ex(int mode, size_t max_memory_usage, const char *tmpdir STREAMS_DC TSRMLS_DC)
     557             : {
     558             :         php_stream_temp_data *self;
     559             :         php_stream *stream;
     560             : 
     561         153 :         self = ecalloc(1, sizeof(*self));
     562         153 :         self->smax = max_memory_usage;
     563         153 :         self->mode = mode;
     564         153 :         if (tmpdir) {
     565           0 :                 self->tmpdir = estrdup(tmpdir);
     566             :         }
     567         153 :         stream = php_stream_alloc_rel(&php_stream_temp_ops, self, 0, mode & TEMP_STREAM_READONLY ? "rb" : "w+b");
     568         153 :         stream->flags |= PHP_STREAM_FLAG_NO_BUFFER;
     569         153 :         self->innerstream = php_stream_memory_create_rel(mode);
     570         153 :         php_stream_encloses(stream, self->innerstream);
     571             : 
     572         153 :         return stream;
     573             : }
     574             : /* }}} */
     575             : 
     576             : /* {{{ _php_stream_temp_create */
     577         111 : PHPAPI php_stream *_php_stream_temp_create(int mode, size_t max_memory_usage STREAMS_DC TSRMLS_DC)
     578             : {
     579         111 :         return php_stream_temp_create_ex(mode, max_memory_usage, NULL);
     580             : }
     581             : /* }}} */
     582             : 
     583             : /* {{{ _php_stream_temp_open */
     584           0 : PHPAPI php_stream *_php_stream_temp_open(int mode, size_t max_memory_usage, char *buf, size_t length STREAMS_DC TSRMLS_DC)
     585             : {
     586             :         php_stream *stream;
     587             :         php_stream_temp_data *ts;
     588             :         off_t newoffs;
     589             : 
     590           0 :         if ((stream = php_stream_temp_create_rel(mode, max_memory_usage)) != NULL) {
     591           0 :                 if (length) {
     592             :                         assert(buf != NULL);
     593           0 :                         php_stream_temp_write(stream, buf, length TSRMLS_CC);
     594           0 :                         php_stream_temp_seek(stream, 0, SEEK_SET, &newoffs TSRMLS_CC);
     595             :                 }
     596           0 :                 ts = (php_stream_temp_data*)stream->abstract;
     597             :                 assert(ts != NULL);
     598           0 :                 ts->mode = mode;
     599             :         }
     600           0 :         return stream;
     601             : }
     602             : /* }}} */
     603             : 
     604             : PHPAPI php_stream_ops php_stream_rfc2397_ops = {
     605             :         php_stream_temp_write, php_stream_temp_read,
     606             :         php_stream_temp_close, php_stream_temp_flush,
     607             :         "RFC2397",
     608             :         php_stream_temp_seek,
     609             :         php_stream_temp_cast,
     610             :         php_stream_temp_stat,
     611             :         php_stream_temp_set_option
     612             : };
     613             : 
     614          57 : static php_stream * php_stream_url_wrap_rfc2397(php_stream_wrapper *wrapper, const char *path,
     615             :                                                                                                 const char *mode, int options, char **opened_path,
     616             :                                                                                                 php_stream_context *context STREAMS_DC TSRMLS_DC) /* {{{ */
     617             : {
     618             :         php_stream *stream;
     619             :         php_stream_temp_data *ts;
     620             :         char *comma, *semi, *sep, *key;
     621             :         size_t mlen, dlen, plen, vlen;
     622             :         off_t newoffs;
     623          57 :         zval *meta = NULL;
     624          57 :         int base64 = 0, ilen;
     625             : 
     626          57 :         if (memcmp(path, "data:", 5)) {
     627           0 :                 return NULL;
     628             :         }
     629             : 
     630          57 :         path += 5;
     631          57 :         dlen = strlen(path);
     632             : 
     633          57 :         if (dlen >= 2 && path[0] == '/' && path[1] == '/') {
     634          41 :                 dlen -= 2;
     635          41 :                 path += 2;
     636             :         }
     637             : 
     638          57 :         if ((comma = memchr(path, ',', dlen)) == NULL) {
     639           3 :                 php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "rfc2397: no comma in URL");
     640           3 :                 return NULL;
     641             :         }
     642             : 
     643          54 :         if (comma != path) {
     644             :                 /* meta info */
     645          41 :                 mlen = comma - path;
     646          41 :                 dlen -= mlen;
     647          41 :                 semi = memchr(path, ';', mlen);
     648          41 :                 sep = memchr(path, '/', mlen);
     649             :                 
     650          41 :                 if (!semi && !sep) {
     651           2 :                         php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "rfc2397: illegal media type");
     652           2 :                         return NULL;
     653             :                 }
     654             : 
     655          39 :                 MAKE_STD_ZVAL(meta);
     656          39 :                 array_init(meta);
     657          39 :                 if (!semi) { /* there is only a mime type */
     658          20 :                         add_assoc_stringl(meta, "mediatype", (char *) path, mlen, 1);
     659          20 :                         mlen = 0;
     660          31 :                 } else if (sep && sep < semi) { /* there is a mime type */
     661          12 :                         plen = semi - path;
     662          12 :                         add_assoc_stringl(meta, "mediatype", (char *) path, plen, 1);
     663          12 :                         mlen -= plen;
     664          12 :                         path += plen;
     665           7 :                 } else if (semi != path || mlen != sizeof(";base64")-1 || memcmp(path, ";base64", sizeof(";base64")-1)) { /* must be error since parameters are only allowed after mediatype */
     666           2 :                         zval_ptr_dtor(&meta);
     667           2 :                         php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "rfc2397: illegal media type");
     668           2 :                         return NULL;
     669             :                 }
     670             :                 /* get parameters and potentially ';base64' */
     671          83 :                 while(semi && (semi == path)) {
     672          20 :                         path++;
     673          20 :                         mlen--;
     674          20 :                         sep = memchr(path, '=', mlen);
     675          20 :                         semi = memchr(path, ';', mlen);
     676          20 :                         if (!sep || (semi && semi < sep)) { /* must be ';base64' or failure */
     677          11 :                                 if (mlen != sizeof("base64")-1 || memcmp(path, "base64", sizeof("base64")-1)) {
     678             :                                         /* must be error since parameters are only allowed after mediatype and we have no '=' sign */
     679           2 :                                         zval_ptr_dtor(&meta);
     680           2 :                                         php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "rfc2397: illegal parameter");
     681           2 :                                         return NULL;
     682             :                                 }
     683           9 :                                 base64 = 1;
     684           9 :                                 mlen -= sizeof("base64") - 1;
     685           9 :                                 path += sizeof("base64") - 1;
     686           9 :                                 break;
     687             :                         }
     688             :                         /* found parameter ... the heart of cs ppl lies in +1/-1 or was it +2 this time? */
     689           9 :                         plen = sep - path;
     690           9 :                         vlen = (semi ? semi - sep : mlen - plen) - 1 /* '=' */;
     691           9 :                         key = estrndup(path, plen);
     692           9 :                         add_assoc_stringl_ex(meta, key, plen + 1, sep + 1, vlen, 1);
     693           9 :                         efree(key);
     694           9 :                         plen += vlen + 1;
     695           9 :                         mlen -= plen;
     696           9 :                         path += plen;
     697             :                 }
     698          35 :                 if (mlen) {
     699           0 :                         zval_ptr_dtor(&meta);
     700           0 :                         php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "rfc2397: illegal URL");
     701           0 :                         return NULL;
     702             :                 }
     703             :         } else {
     704          13 :                 MAKE_STD_ZVAL(meta);
     705          13 :                 array_init(meta);
     706             :         }
     707          48 :         add_assoc_bool(meta, "base64", base64);
     708             : 
     709             :         /* skip ',' */
     710          48 :         comma++;
     711          48 :         dlen--;
     712             : 
     713          48 :         if (base64) {
     714           9 :                 comma = (char*)php_base64_decode((const unsigned char *)comma, dlen, &ilen);
     715           9 :                 if (!comma) {
     716           1 :                         zval_ptr_dtor(&meta);
     717           1 :                         php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "rfc2397: unable to decode");
     718           1 :                         return NULL;
     719             :                 }
     720             :         } else {
     721          39 :                 comma = estrndup(comma, dlen);
     722          39 :                 ilen = dlen = php_url_decode(comma, dlen);
     723             :         }
     724             : 
     725          47 :         if ((stream = php_stream_temp_create_rel(0, ~0u)) != NULL) {
     726             :                 /* store data */
     727          47 :                 php_stream_temp_write(stream, comma, ilen TSRMLS_CC);
     728          47 :                 php_stream_temp_seek(stream, 0, SEEK_SET, &newoffs TSRMLS_CC);
     729             :                 /* set special stream stuff (enforce exact mode) */
     730          47 :                 vlen = strlen(mode);
     731          47 :                 if (vlen >= sizeof(stream->mode)) {
     732           0 :                         vlen = sizeof(stream->mode) - 1;
     733             :                 }
     734          47 :                 memcpy(stream->mode, mode, vlen);
     735          47 :                 stream->mode[vlen] = '\0';
     736          47 :                 stream->ops = &php_stream_rfc2397_ops;
     737          47 :                 ts = (php_stream_temp_data*)stream->abstract;
     738             :                 assert(ts != NULL);
     739          47 :                 ts->mode = mode && mode[0] == 'r' && mode[1] != '+' ? TEMP_STREAM_READONLY : 0;
     740          47 :                 ts->meta = meta;
     741             :         }
     742          47 :         efree(comma);
     743             : 
     744          47 :         return stream;
     745             : }
     746             : 
     747             : PHPAPI php_stream_wrapper_ops php_stream_rfc2397_wops = {
     748             :         php_stream_url_wrap_rfc2397,
     749             :         NULL, /* close */
     750             :         NULL, /* fstat */
     751             :         NULL, /* stat */
     752             :         NULL, /* opendir */
     753             :         "RFC2397",
     754             :         NULL, /* unlink */
     755             :         NULL, /* rename */
     756             :         NULL, /* mkdir */
     757             :         NULL  /* rmdir */
     758             : };
     759             : 
     760             : PHPAPI php_stream_wrapper php_stream_rfc2397_wrapper =  {
     761             :         &php_stream_rfc2397_wops,
     762             :         NULL,
     763             :         1, /* is_url */
     764             : };
     765             : 
     766             : /*
     767             :  * Local variables:
     768             :  * tab-width: 4
     769             :  * c-basic-offset: 4
     770             :  * End:
     771             :  * vim600: noet sw=4 ts=4 fdm=marker
     772             :  * vim<600: noet sw=4 ts=4
     773             :  */

Generated by: LCOV version 1.10

Generated at Mon, 04 Aug 2014 15:49:19 +0000 (29 days ago)

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