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

LTP GCOV extension - code coverage report
Current view: directory - var/php_gcov/PHP_5_2/main/streams - memory.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 317
Code covered: 75.7 % Executed lines: 240
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 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 288393 2009-09-17 02:45:25Z srinatar $ */
      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             157 : {
      52             157 :         php_stream_memory_data *ms = (php_stream_memory_data*)stream->abstract;
      53                 :         assert(ms != NULL);
      54                 : 
      55             157 :         if (ms->mode & TEMP_STREAM_READONLY) {
      56               2 :                 return 0;
      57                 :         }
      58             155 :         if (ms->fpos + count > ms->fsize) {
      59                 :                 char *tmp;
      60                 : 
      61             155 :                 if (!ms->data) {
      62              87 :                         tmp = emalloc(ms->fpos + count);
      63                 :                 } else {
      64              68 :                         tmp = erealloc(ms->data, ms->fpos + count);
      65                 :                 }
      66             155 :                 if (!tmp) {
      67               0 :                         count = ms->fsize - ms->fpos + 1;
      68                 :                 } else {
      69             155 :                         ms->data = tmp;
      70             155 :                         ms->fsize = ms->fpos + count;
      71                 :                 }
      72                 :         }
      73             155 :         if (!ms->data)
      74               0 :                 count = 0;
      75             155 :         if (count) {
      76                 :                 assert(buf!= NULL);
      77             155 :                 memcpy(ms->data+ms->fpos, (char*)buf, count);
      78             155 :                 ms->fpos += count;
      79                 :         }
      80             155 :         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             198 : {
      88             198 :         php_stream_memory_data *ms = (php_stream_memory_data*)stream->abstract;
      89                 :         assert(ms != NULL);
      90                 : 
      91             198 :         if (ms->fpos + count >= ms->fsize) {
      92             183 :                 count = ms->fsize - ms->fpos;
      93             183 :                 stream->eof = 1;
      94                 :         }
      95             198 :         if (count) {
      96                 :                 assert(ms->data!= NULL);
      97                 :                 assert(buf!= NULL);
      98             160 :                 memcpy(buf, ms->data+ms->fpos, count);
      99             160 :                 ms->fpos += count;
     100                 :         }
     101             198 :         return count;
     102                 : }
     103                 : /* }}} */
     104                 : 
     105                 : 
     106                 : /* {{{ */
     107                 : static int php_stream_memory_close(php_stream *stream, int close_handle TSRMLS_DC)
     108             141 : {
     109             141 :         php_stream_memory_data *ms = (php_stream_memory_data*)stream->abstract;
     110                 :         assert(ms != NULL);
     111                 : 
     112             141 :         if (ms->data && close_handle && ms->mode != TEMP_STREAM_READONLY) {
     113              88 :                 efree(ms->data);
     114                 :         }
     115             141 :         if (ms->owner_ptr) {
     116             105 :                 *ms->owner_ptr = NULL;
     117                 :         }
     118             141 :         efree(ms);
     119             141 :         return 0;
     120                 : }
     121                 : /* }}} */
     122                 : 
     123                 : 
     124                 : /* {{{ */
     125                 : static int php_stream_memory_flush(php_stream *stream TSRMLS_DC)
     126             247 : {
     127                 :         /* nothing to do here */
     128             247 :         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             266 : {
     136             266 :         php_stream_memory_data *ms = (php_stream_memory_data*)stream->abstract;
     137                 :         assert(ms != NULL);
     138                 : 
     139             266 :         switch(whence) {
     140                 :                 case SEEK_CUR:
     141               4 :                         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               4 :                                 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               4 :                                         ms->fpos = ms->fpos + offset;
     159               4 :                                         *newoffs = ms->fpos;
     160               4 :                                         stream->eof = 0;
     161               4 :                                         return 0;
     162                 :                                 }
     163                 :                         }
     164                 :                 case SEEK_SET:
     165             259 :                         if (ms->fsize < (size_t)(offset)) {
     166               2 :                                 ms->fpos = ms->fsize;
     167               2 :                                 *newoffs = -1;
     168               2 :                                 return -1;
     169                 :                         } else {
     170             257 :                                 ms->fpos = offset;
     171             257 :                                 *newoffs = ms->fpos;
     172             257 :                                 stream->eof = 0;
     173             257 :                                 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                 : 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              64 : {
     206              64 :         time_t timestamp = 0;
     207              64 :         php_stream_memory_data *ms = (php_stream_memory_data*)stream->abstract;
     208                 :         assert(ms != NULL);
     209                 : 
     210              64 :         memset(ssb, 0, sizeof(php_stream_statbuf));
     211                 :         /* read-only across the board */
     212                 :         
     213              64 :         ssb->sb.st_mode = ms->mode & TEMP_STREAM_READONLY ? 0444 : 0666;
     214                 : 
     215              64 :         ssb->sb.st_size = ms->fsize;
     216              64 :         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              64 :         ssb->sb.st_mtime = timestamp;
     224              64 :         ssb->sb.st_atime = timestamp;
     225              64 :         ssb->sb.st_ctime = timestamp;
     226                 : #endif
     227                 : 
     228              64 :         ssb->sb.st_nlink = 1;
     229              64 :         ssb->sb.st_rdev = -1;
     230                 :         /* this is only for APC, so use /dev/null device - no chance of conflict there! */
     231              64 :         ssb->sb.st_dev = 0xC;
     232                 :         /* generate unique inode number for alias/filename, so no phars will conflict */
     233              64 :         ssb->sb.st_ino = 0;
     234                 : 
     235                 : #ifndef PHP_WIN32
     236              64 :         ssb->sb.st_blksize = -1;
     237                 : #endif
     238                 : 
     239                 : #if !defined(PHP_WIN32) && !defined(__BEOS__)
     240              64 :         ssb->sb.st_blocks = -1;
     241                 : #endif
     242                 : 
     243              64 :         return 0;
     244                 : }
     245                 : /* }}} */
     246                 : 
     247                 : static int php_stream_memory_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC) /* {{{ */
     248              28 : {
     249              28 :         php_stream_memory_data *ms = (php_stream_memory_data*)stream->abstract;
     250                 :         size_t newsize;
     251                 :         
     252              28 :         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              28 :                         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                 : PHPAPI php_stream *_php_stream_memory_create(int mode STREAMS_DC TSRMLS_DC)
     294             141 : {
     295                 :         php_stream_memory_data *self;
     296                 :         php_stream *stream;
     297                 : 
     298             141 :         self = emalloc(sizeof(*self));
     299             141 :         self->data = NULL;
     300             141 :         self->fpos = 0;
     301             141 :         self->fsize = 0;
     302             141 :         self->smax = ~0u;
     303             141 :         self->mode = mode;
     304             141 :         self->owner_ptr = NULL;
     305                 :         
     306             141 :         stream = php_stream_alloc_rel(&php_stream_memory_ops, self, 0, mode & TEMP_STREAM_READONLY ? "rb" : "w+b");
     307             141 :         stream->flags |= PHP_STREAM_FLAG_NO_BUFFER;
     308             141 :         return stream;
     309                 : }
     310                 : /* }}} */
     311                 : 
     312                 : 
     313                 : /* {{{ */
     314                 : PHPAPI php_stream *_php_stream_memory_open(int mode, char *buf, size_t length STREAMS_DC TSRMLS_DC)
     315               5 : {
     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                 : PHPAPI char *_php_stream_memory_get_buffer(php_stream *stream, size_t *length STREAMS_DC TSRMLS_DC)
     340             139 : {
     341             139 :         php_stream_memory_data *ms = (php_stream_memory_data*)stream->abstract;
     342                 : 
     343                 :         assert(ms != NULL);
     344                 :         assert(length != 0);
     345                 : 
     346             139 :         *length = ms->fsize;
     347             139 :         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                 : static size_t php_stream_temp_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
     365             139 : {
     366             139 :         php_stream_temp_data *ts = (php_stream_temp_data*)stream->abstract;
     367                 :         assert(ts != NULL);
     368                 : 
     369             139 :         if (!ts->innerstream) {
     370               0 :                 return -1;
     371                 :         }
     372             139 :         if (php_stream_is(ts->innerstream, PHP_STREAM_IS_MEMORY)) {
     373                 :                 size_t memsize;
     374             139 :                 char *membuf = php_stream_memory_get_buffer(ts->innerstream, &memsize);
     375                 : 
     376             139 :                 if (memsize + count >= ts->smax) {
     377               0 :                         php_stream *file = php_stream_fopen_tmpfile();
     378               0 :                         php_stream_write(file, membuf, memsize);
     379               0 :                         php_stream_close(ts->innerstream);
     380               0 :                         ts->innerstream = file;
     381                 :                 }
     382                 :         }
     383             139 :         return php_stream_write(ts->innerstream, buf, count);
     384                 : }
     385                 : /* }}} */
     386                 : 
     387                 : 
     388                 : /* {{{ */
     389                 : static size_t php_stream_temp_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
     390             164 : {
     391             164 :         php_stream_temp_data *ts = (php_stream_temp_data*)stream->abstract;
     392                 :         size_t got;
     393                 : 
     394                 :         assert(ts != NULL);
     395                 : 
     396             164 :         if (!ts->innerstream) {
     397               0 :                 return -1;
     398                 :         }
     399                 :         
     400             164 :         got = php_stream_read(ts->innerstream, buf, count);
     401                 :         
     402             164 :         stream->eof = ts->innerstream->eof;
     403                 :         
     404             164 :         return got;
     405                 : }
     406                 : /* }}} */
     407                 : 
     408                 : 
     409                 : /* {{{ */
     410                 : static int php_stream_temp_close(php_stream *stream, int close_handle TSRMLS_DC)
     411             105 : {
     412             105 :         php_stream_temp_data *ts = (php_stream_temp_data*)stream->abstract;
     413                 :         int ret;
     414                 : 
     415                 :         assert(ts != NULL);
     416                 : 
     417             105 :         if (ts->innerstream) {
     418             105 :                 ret = php_stream_free(ts->innerstream, PHP_STREAM_FREE_CLOSE | (close_handle ? 0 : PHP_STREAM_FREE_PRESERVE_HANDLE));
     419                 :         } else {
     420               0 :                 ret = 0;
     421                 :         }
     422                 :         
     423             105 :         if (ts->meta) {
     424              35 :                 zval_ptr_dtor(&ts->meta);
     425                 :         }
     426                 : 
     427             105 :         efree(ts);
     428                 : 
     429             105 :         return ret;
     430                 : }
     431                 : /* }}} */
     432                 : 
     433                 : 
     434                 : /* {{{ */
     435                 : static int php_stream_temp_flush(php_stream *stream TSRMLS_DC)
     436             105 : {
     437             105 :         php_stream_temp_data *ts = (php_stream_temp_data*)stream->abstract;
     438                 :         assert(ts != NULL);
     439                 : 
     440             105 :         return ts->innerstream ? php_stream_flush(ts->innerstream) : -1;
     441                 : }
     442                 : /* }}} */
     443                 : 
     444                 : 
     445                 : /* {{{ */
     446                 : static int php_stream_temp_seek(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC)
     447             235 : {
     448             235 :         php_stream_temp_data *ts = (php_stream_temp_data*)stream->abstract;
     449                 :         int ret;
     450                 : 
     451                 :         assert(ts != NULL);
     452                 : 
     453             235 :         if (!ts->innerstream) {
     454               0 :                 *newoffs = -1;
     455               0 :                 return -1;
     456                 :         }
     457             235 :         ret = php_stream_seek(ts->innerstream, offset, whence);
     458             235 :         *newoffs = php_stream_tell(ts->innerstream);
     459             235 :         stream->eof = ts->innerstream->eof;
     460                 :         
     461             235 :         return ret;
     462                 : }
     463                 : /* }}} */
     464                 : 
     465                 : /* {{{ */
     466                 : static int php_stream_temp_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
     467               0 : {
     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                 : static int php_stream_temp_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC) /* {{{ */
     512              44 : {
     513              44 :         php_stream_temp_data *ts = (php_stream_temp_data*)stream->abstract;
     514                 : 
     515              44 :         if (!ts || !ts->innerstream) {
     516               0 :                 return -1;
     517                 :         }
     518              44 :         return php_stream_stat(ts->innerstream, ssb);
     519                 : }
     520                 : /* }}} */
     521                 : 
     522                 : static int php_stream_temp_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC) /* {{{ */
     523              34 : {
     524              34 :         php_stream_temp_data *ts = (php_stream_temp_data*)stream->abstract;
     525                 :         
     526              34 :         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              28 :                         if (ts->innerstream) {
     534              28 :                                 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                 : PHPAPI php_stream *_php_stream_temp_create(int mode, size_t max_memory_usage STREAMS_DC TSRMLS_DC)
     555             105 : {
     556                 :         php_stream_temp_data *self;
     557                 :         php_stream *stream;
     558                 : 
     559             105 :         self = ecalloc(1, sizeof(*self));
     560             105 :         self->smax = max_memory_usage;
     561             105 :         self->mode = mode;
     562             105 :         self->meta = NULL;
     563             105 :         stream = php_stream_alloc_rel(&php_stream_temp_ops, self, 0, mode & TEMP_STREAM_READONLY ? "rb" : "w+b");
     564             105 :         stream->flags |= PHP_STREAM_FLAG_NO_BUFFER;
     565             105 :         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             105 :         ((php_stream_memory_data*)self->innerstream->abstract)->owner_ptr = &self->innerstream;
     568                 : 
     569             105 :         return stream;
     570                 : }
     571                 : /* }}} */
     572                 : 
     573                 : 
     574                 : /* {{{ _php_stream_temp_open */
     575                 : PHPAPI php_stream *_php_stream_temp_open(int mode, size_t max_memory_usage, char *buf, size_t length STREAMS_DC TSRMLS_DC)
     576               0 : {
     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                 : 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              45 : {
     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              45 :         zval *meta = NULL;
     613              45 :         int base64 = 0, ilen;
     614                 : 
     615              45 :         if (memcmp(path, "data:", 5)) {
     616               0 :                 return NULL;
     617                 :         }
     618                 : 
     619              45 :         path += 5;
     620              45 :         dlen = strlen(path);
     621                 : 
     622              45 :         if (dlen >= 2 && path[0] == '/' && path[1] == '/') {
     623              30 :                 dlen -= 2;
     624              30 :                 path += 2;
     625                 :         }
     626                 : 
     627              45 :         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              42 :         if (comma != path) {
     633                 :                 /* meta info */
     634              32 :                 mlen = comma - path;
     635              32 :                 dlen -= mlen;
     636              32 :                 semi = memchr(path, ';', mlen);
     637              32 :                 sep = memchr(path, '/', mlen);
     638                 :                 
     639              32 :                 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              30 :                 MAKE_STD_ZVAL(meta);
     645              30 :                 array_init(meta);
     646              30 :                 if (!semi) { /* there is only a mime type */
     647              10 :                         add_assoc_stringl(meta, "mediatype", path, mlen, 1);
     648              10 :                         mlen = 0;
     649              31 :                 } else if (sep && sep < semi) { /* there is a mime type */
     650              11 :                         plen = semi - path;
     651              11 :                         add_assoc_stringl(meta, "mediatype", path, plen, 1);
     652              11 :                         mlen -= plen;
     653              11 :                         path += plen;
     654               9 :                 } 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              65 :                 while(semi && (semi == path)) {
     661              21 :                         path++;
     662              21 :                         mlen--;
     663              21 :                         sep = memchr(path, '=', mlen);
     664              21 :                         semi = memchr(path, ';', mlen);
     665              21 :                         if (!sep || (semi && semi < sep)) { /* must be ';base64' or failure */
     666              12 :                                 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              10 :                                 base64 = 1;
     673              10 :                                 mlen -= sizeof("base64") - 1;
     674              10 :                                 path += sizeof("base64") - 1;
     675              10 :                                 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              26 :                 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              10 :                 MAKE_STD_ZVAL(meta);
     694              10 :                 array_init(meta);
     695                 :         }
     696              36 :         add_assoc_bool(meta, "base64", base64);
     697                 : 
     698                 :         /* skip ',' */
     699              36 :         comma++;
     700              36 :         dlen--;
     701                 : 
     702              36 :         if (base64) {
     703              10 :                 comma = (char*)php_base64_decode((const unsigned char *)comma, dlen, &ilen);
     704              10 :                 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              26 :                 comma = estrndup(comma, dlen);
     711              26 :                 ilen = dlen = php_url_decode(comma, dlen);
     712                 :         }
     713                 : 
     714              35 :         if ((stream = php_stream_temp_create_rel(0, ~0u)) != NULL) {
     715                 :                 /* store data */
     716              35 :                 php_stream_temp_write(stream, comma, ilen TSRMLS_CC);
     717              35 :                 php_stream_temp_seek(stream, 0, SEEK_SET, &newoffs TSRMLS_CC);
     718                 :                 /* set special stream stuff (enforce exact mode) */
     719              35 :                 vlen = strlen(mode);
     720              35 :                 if (vlen >= sizeof(stream->mode)) {
     721               0 :                         vlen = sizeof(stream->mode) - 1;
     722                 :                 }
     723              35 :                 memcpy(stream->mode, mode, vlen);
     724              35 :                 stream->mode[vlen] = '\0';
     725              35 :                 stream->ops = &php_stream_rfc2397_ops;
     726              35 :                 ts = (php_stream_temp_data*)stream->abstract;
     727                 :                 assert(ts != NULL);
     728              35 :                 ts->mode = mode && mode[0] == 'r' && mode[1] != '+' ? TEMP_STREAM_READONLY : 0;
     729              35 :                 ts->meta = meta;
     730                 :         }
     731              35 :         efree(comma);
     732                 : 
     733              35 :         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: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:29 +0000 (5 days ago)

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