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 317 77.3 %
Date: 2014-07-27 Functions: 19 22 86.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 27 Jul 2014 12:58:42 +0000 (4 days ago)

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