LTP GCOV extension - code coverage report
Current view: directory - main/streams - memory.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 317
Code covered: 0.0 % Executed lines: 0
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5