2002-03-17 04:11:06 +08:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2014-09-20 00:33:14 +08:00
| PHP Version 7 |
2002-03-17 04:11:06 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2019-01-30 17:03:12 +08:00
| Copyright ( c ) The PHP Group |
2002-03-17 04:11:06 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 20:51:34 +08:00
| This source file is subject to version 3.01 of the PHP license , |
2002-03-17 04:11:06 +08:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-11 04:04:29 +08:00
| available through the world - wide - web at the following url : |
2006-01-01 20:51:34 +08:00
| http : //www.php.net/license/3_01.txt |
2002-03-17 04:11:06 +08:00
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2003-02-19 16:40:19 +08:00
| Author : Marcus Boerger < helly @ php . net > |
2002-03-17 04:11:06 +08:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
# define _GNU_SOURCE
# include "php.h"
2014-03-04 20:08:06 +08:00
# include "ext/standard/base64.h"
2002-03-18 12:57:06 +08:00
2016-02-22 09:02:55 +08:00
PHPAPI size_t php_url_decode ( char * str , size_t len ) ;
2006-05-14 09:42:03 +08:00
2002-03-18 12:57:06 +08:00
/* Memory streams use a dynamic memory buffer to emulate a stream.
* You can use php_stream_memory_open to create a readonly stream
* from an existing memory buffer .
*/
/* Temp streams are streams that uses memory streams as long their
* size is less than a given memory amount . When a write operation
* exceeds that limit the content is written to a temporary file .
*/
2002-03-17 04:11:06 +08:00
/* {{{ ------- MEMORY stream implementation -------*/
typedef struct {
2002-03-18 07:50:31 +08:00
char * data ;
size_t fpos ;
size_t fsize ;
size_t smax ;
int mode ;
2002-03-18 12:57:06 +08:00
} php_stream_memory_data ;
2002-03-17 04:11:06 +08:00
2002-03-20 03:15:40 +08:00
/* {{{ */
2019-07-18 21:25:59 +08:00
static ssize_t php_stream_memory_write ( php_stream * stream , const char * buf , size_t count )
2002-03-20 03:15:40 +08:00
{
2006-05-14 01:58:58 +08:00
php_stream_memory_data * ms = ( php_stream_memory_data * ) stream - > abstract ;
2002-03-17 04:11:06 +08:00
assert ( ms ! = NULL ) ;
2002-03-18 07:50:31 +08:00
2002-03-18 12:57:06 +08:00
if ( ms - > mode & TEMP_STREAM_READONLY ) {
2019-07-18 21:25:59 +08:00
return ( ssize_t ) - 1 ;
2017-08-04 13:59:22 +08:00
} else if ( ms - > mode & TEMP_STREAM_APPEND ) {
ms - > fpos = ms - > fsize ;
2002-03-18 07:50:31 +08:00
}
2002-03-18 12:57:06 +08:00
if ( ms - > fpos + count > ms - > fsize ) {
2002-03-17 04:11:06 +08:00
char * tmp ;
2002-03-18 12:57:06 +08:00
if ( ! ms - > data ) {
tmp = emalloc ( ms - > fpos + count ) ;
2002-03-17 04:11:06 +08:00
} else {
2002-03-18 12:57:06 +08:00
tmp = erealloc ( ms - > data , ms - > fpos + count ) ;
2002-03-17 04:11:06 +08:00
}
2017-03-16 16:27:57 +08:00
ms - > data = tmp ;
ms - > fsize = ms - > fpos + count ;
2002-03-17 04:11:06 +08:00
}
2002-03-18 12:57:06 +08:00
if ( ! ms - > data )
count = 0 ;
if ( count ) {
2002-03-17 04:11:06 +08:00
assert ( buf ! = NULL ) ;
2002-03-18 12:57:06 +08:00
memcpy ( ms - > data + ms - > fpos , ( char * ) buf , count ) ;
2002-03-17 04:11:06 +08:00
ms - > fpos + = count ;
}
return count ;
2002-03-20 03:15:40 +08:00
}
/* }}} */
2002-03-17 04:11:06 +08:00
2002-03-20 03:15:40 +08:00
/* {{{ */
2019-07-18 21:25:59 +08:00
static ssize_t php_stream_memory_read ( php_stream * stream , char * buf , size_t count )
2002-03-22 04:37:04 +08:00
{
2006-05-14 01:58:58 +08:00
php_stream_memory_data * ms = ( php_stream_memory_data * ) stream - > abstract ;
2002-03-17 04:11:06 +08:00
assert ( ms ! = NULL ) ;
2014-12-05 00:36:44 +08:00
if ( ms - > fpos = = ms - > fsize ) {
2006-05-24 06:31:25 +08:00
stream - > eof = 1 ;
2014-12-05 00:36:44 +08:00
count = 0 ;
} else {
if ( ms - > fpos + count > = ms - > fsize ) {
count = ms - > fsize - ms - > fpos ;
}
if ( count ) {
assert ( ms - > data ! = NULL ) ;
assert ( buf ! = NULL ) ;
memcpy ( buf , ms - > data + ms - > fpos , count ) ;
ms - > fpos + = count ;
}
2002-03-17 04:11:06 +08:00
}
return count ;
2002-03-20 03:15:40 +08:00
}
/* }}} */
2002-03-17 04:11:06 +08:00
2002-03-20 03:15:40 +08:00
/* {{{ */
2014-12-14 06:06:14 +08:00
static int php_stream_memory_close ( php_stream * stream , int close_handle )
2002-03-22 04:37:04 +08:00
{
2006-05-14 01:58:58 +08:00
php_stream_memory_data * ms = ( php_stream_memory_data * ) stream - > abstract ;
2002-03-17 04:11:06 +08:00
assert ( ms ! = NULL ) ;
2002-03-18 07:50:31 +08:00
2002-04-03 00:46:33 +08:00
if ( ms - > data & & close_handle & & ms - > mode ! = TEMP_STREAM_READONLY ) {
2002-03-17 04:11:06 +08:00
efree ( ms - > data ) ;
}
2002-03-22 04:37:04 +08:00
efree ( ms ) ;
2002-03-18 07:50:31 +08:00
return 0 ;
2002-03-20 03:15:40 +08:00
}
/* }}} */
2002-03-17 04:11:06 +08:00
2002-03-20 03:15:40 +08:00
/* {{{ */
2014-12-14 06:06:14 +08:00
static int php_stream_memory_flush ( php_stream * stream )
2002-10-21 07:05:34 +08:00
{
2002-03-18 12:57:06 +08:00
/* nothing to do here */
2002-03-17 04:11:06 +08:00
return 0 ;
2002-03-20 03:15:40 +08:00
}
/* }}} */
2002-03-17 04:11:06 +08:00
2002-03-20 03:15:40 +08:00
/* {{{ */
2014-12-14 06:06:14 +08:00
static int php_stream_memory_seek ( php_stream * stream , zend_off_t offset , int whence , zend_off_t * newoffs )
2002-03-20 03:15:40 +08:00
{
2006-05-14 01:58:58 +08:00
php_stream_memory_data * ms = ( php_stream_memory_data * ) stream - > abstract ;
2002-03-17 04:11:06 +08:00
assert ( ms ! = NULL ) ;
2002-03-18 07:50:31 +08:00
2002-03-18 12:57:06 +08:00
switch ( whence ) {
2002-03-17 04:11:06 +08:00
case SEEK_CUR :
2002-03-18 12:57:06 +08:00
if ( offset < 0 ) {
2002-03-21 03:13:03 +08:00
if ( ms - > fpos < ( size_t ) ( - offset ) ) {
2002-03-17 04:11:06 +08:00
ms - > fpos = 0 ;
2006-01-06 06:03:07 +08:00
* newoffs = - 1 ;
return - 1 ;
2002-03-17 04:11:06 +08:00
} else {
ms - > fpos = ms - > fpos + offset ;
2006-01-06 06:03:07 +08:00
* newoffs = ms - > fpos ;
2006-05-24 06:31:25 +08:00
stream - > eof = 0 ;
2006-01-06 06:03:07 +08:00
return 0 ;
2002-03-17 04:11:06 +08:00
}
} else {
2006-03-19 03:57:00 +08:00
if ( ms - > fpos + ( size_t ) ( offset ) > ms - > fsize ) {
2002-03-17 04:11:06 +08:00
ms - > fpos = ms - > fsize ;
2006-01-06 06:03:07 +08:00
* newoffs = - 1 ;
return - 1 ;
2002-03-17 04:11:06 +08:00
} else {
ms - > fpos = ms - > fpos + offset ;
2006-01-06 06:03:07 +08:00
* newoffs = ms - > fpos ;
2006-05-24 06:31:25 +08:00
stream - > eof = 0 ;
2006-01-06 06:03:07 +08:00
return 0 ;
2002-03-17 04:11:06 +08:00
}
}
case SEEK_SET :
2002-03-21 03:13:03 +08:00
if ( ms - > fsize < ( size_t ) ( offset ) ) {
2002-03-17 04:11:06 +08:00
ms - > fpos = ms - > fsize ;
2006-01-06 06:03:07 +08:00
* newoffs = - 1 ;
return - 1 ;
2002-03-17 04:11:06 +08:00
} else {
ms - > fpos = offset ;
2006-01-06 06:03:07 +08:00
* newoffs = ms - > fpos ;
2006-05-24 06:31:25 +08:00
stream - > eof = 0 ;
2006-01-06 06:03:07 +08:00
return 0 ;
2002-03-17 04:11:06 +08:00
}
case SEEK_END :
2002-03-18 12:57:06 +08:00
if ( offset > 0 ) {
2002-03-17 04:11:06 +08:00
ms - > fpos = ms - > fsize ;
2006-01-06 06:03:07 +08:00
* newoffs = - 1 ;
return - 1 ;
} else if ( ms - > fsize < ( size_t ) ( - offset ) ) {
2002-03-17 04:11:06 +08:00
ms - > fpos = 0 ;
2006-01-06 06:03:07 +08:00
* newoffs = - 1 ;
return - 1 ;
2002-03-17 04:11:06 +08:00
} else {
ms - > fpos = ms - > fsize + offset ;
2006-01-06 06:03:07 +08:00
* newoffs = ms - > fpos ;
2006-05-24 06:31:25 +08:00
stream - > eof = 0 ;
2006-01-06 06:03:07 +08:00
return 0 ;
2002-03-17 04:11:06 +08:00
}
default :
2006-01-06 06:03:07 +08:00
* newoffs = ms - > fpos ;
return - 1 ;
2002-03-18 07:50:31 +08:00
}
2002-03-20 03:15:40 +08:00
}
/* }}} */
2002-03-18 07:50:31 +08:00
2002-03-20 03:15:40 +08:00
/* {{{ */
2014-12-14 06:06:14 +08:00
static int php_stream_memory_cast ( php_stream * stream , int castas , void * * ret )
2002-03-22 04:37:04 +08:00
{
2002-03-18 07:50:31 +08:00
return FAILURE ;
2002-03-20 03:15:40 +08:00
}
/* }}} */
2014-12-14 06:06:14 +08:00
static int php_stream_memory_stat ( php_stream * stream , php_stream_statbuf * ssb ) /* { { { */
2006-05-14 01:58:58 +08:00
{
time_t timestamp = 0 ;
php_stream_memory_data * ms = ( php_stream_memory_data * ) stream - > abstract ;
assert ( ms ! = NULL ) ;
memset ( ssb , 0 , sizeof ( php_stream_statbuf ) ) ;
/* read-only across the board */
2015-01-03 17:22:58 +08:00
2006-05-14 01:58:58 +08:00
ssb - > sb . st_mode = ms - > mode & TEMP_STREAM_READONLY ? 0444 : 0666 ;
ssb - > sb . st_size = ms - > fsize ;
ssb - > sb . st_mode | = S_IFREG ; /* regular file */
ssb - > sb . st_mtime = timestamp ;
ssb - > sb . st_atime = timestamp ;
ssb - > sb . st_ctime = timestamp ;
ssb - > sb . st_nlink = 1 ;
ssb - > sb . st_rdev = - 1 ;
/* this is only for APC, so use /dev/null device - no chance of conflict there! */
ssb - > sb . st_dev = 0xC ;
/* generate unique inode number for alias/filename, so no phars will conflict */
ssb - > sb . st_ino = 0 ;
# ifndef PHP_WIN32
ssb - > sb . st_blksize = - 1 ;
ssb - > sb . st_blocks = - 1 ;
# endif
return 0 ;
}
/* }}} */
2002-03-17 04:11:06 +08:00
2014-12-14 06:06:14 +08:00
static int php_stream_memory_set_option ( php_stream * stream , int option , int value , void * ptrparam ) /* { { { */
2007-01-28 04:25:11 +08:00
{
php_stream_memory_data * ms = ( php_stream_memory_data * ) stream - > abstract ;
size_t newsize ;
2015-01-03 17:22:58 +08:00
2007-01-28 04:25:11 +08:00
switch ( option ) {
case PHP_STREAM_OPTION_TRUNCATE_API :
switch ( value ) {
case PHP_STREAM_TRUNCATE_SUPPORTED :
return PHP_STREAM_OPTION_RETURN_OK ;
case PHP_STREAM_TRUNCATE_SET_SIZE :
2007-02-04 00:40:05 +08:00
if ( ms - > mode & TEMP_STREAM_READONLY ) {
return PHP_STREAM_OPTION_RETURN_ERR ;
}
2007-01-28 04:25:11 +08:00
newsize = * ( size_t * ) ptrparam ;
if ( newsize < = ms - > fsize ) {
if ( newsize < ms - > fpos ) {
ms - > fpos = newsize ;
}
2007-02-23 07:26:03 +08:00
} else {
ms - > data = erealloc ( ms - > data , newsize ) ;
memset ( ms - > data + ms - > fsize , 0 , newsize - ms - > fsize ) ;
2007-01-28 04:25:11 +08:00
ms - > fsize = newsize ;
}
2007-02-23 07:26:03 +08:00
ms - > fsize = newsize ;
return PHP_STREAM_OPTION_RETURN_OK ;
2007-01-28 04:25:11 +08:00
}
default :
return PHP_STREAM_OPTION_RETURN_NOTIMPL ;
}
}
/* }}} */
2015-01-03 17:22:58 +08:00
2017-12-15 03:14:36 +08:00
PHPAPI const php_stream_ops php_stream_memory_ops = {
2002-03-18 07:50:31 +08:00
php_stream_memory_write , php_stream_memory_read ,
php_stream_memory_close , php_stream_memory_flush ,
2002-03-28 08:49:00 +08:00
" MEMORY " ,
2002-03-18 07:50:31 +08:00
php_stream_memory_seek ,
php_stream_memory_cast ,
2006-05-14 01:58:58 +08:00
php_stream_memory_stat ,
2007-02-08 04:59:59 +08:00
php_stream_memory_set_option
2002-03-17 04:11:06 +08:00
} ;
2017-08-04 13:59:22 +08:00
/* {{{ */
PHPAPI int php_stream_mode_from_str ( const char * mode )
{
if ( strpbrk ( mode , " a " ) ) {
return TEMP_STREAM_APPEND ;
} else if ( strpbrk ( mode , " w+ " ) ) {
return TEMP_STREAM_DEFAULT ;
}
return TEMP_STREAM_READONLY ;
}
/* }}} */
/* {{{ */
PHPAPI const char * _php_stream_mode_to_str ( int mode )
{
if ( mode = = TEMP_STREAM_READONLY ) {
return " rb " ;
} else if ( mode = = TEMP_STREAM_APPEND ) {
return " a+b " ;
}
return " w+b " ;
}
/* }}} */
2002-03-20 03:15:40 +08:00
/* {{{ */
2014-12-14 06:06:14 +08:00
PHPAPI php_stream * _php_stream_memory_create ( int mode STREAMS_DC )
2002-03-20 03:15:40 +08:00
{
2002-03-18 12:57:06 +08:00
php_stream_memory_data * self ;
2002-09-23 21:22:10 +08:00
php_stream * stream ;
2002-03-17 04:11:06 +08:00
self = emalloc ( sizeof ( * self ) ) ;
self - > data = NULL ;
self - > fpos = 0 ;
self - > fsize = 0 ;
2006-05-14 01:58:58 +08:00
self - > smax = ~ 0u ;
2002-03-18 07:50:31 +08:00
self - > mode = mode ;
2015-01-03 17:22:58 +08:00
2017-08-04 13:59:22 +08:00
stream = php_stream_alloc_rel ( & php_stream_memory_ops , self , 0 , _php_stream_mode_to_str ( mode ) ) ;
2002-09-23 21:22:10 +08:00
stream - > flags | = PHP_STREAM_FLAG_NO_BUFFER ;
return stream ;
2002-03-20 03:15:40 +08:00
}
/* }}} */
2002-03-18 07:50:31 +08:00
2002-03-20 03:15:40 +08:00
/* {{{ */
2014-12-14 06:06:14 +08:00
PHPAPI php_stream * _php_stream_memory_open ( int mode , char * buf , size_t length STREAMS_DC )
2002-10-21 07:05:34 +08:00
{
php_stream * stream ;
2002-03-18 12:57:06 +08:00
php_stream_memory_data * ms ;
2002-03-18 07:50:31 +08:00
2002-04-03 00:46:33 +08:00
if ( ( stream = php_stream_memory_create_rel ( mode ) ) ! = NULL ) {
2006-05-14 01:58:58 +08:00
ms = ( php_stream_memory_data * ) stream - > abstract ;
2015-01-03 17:22:58 +08:00
2005-02-07 05:41:36 +08:00
if ( mode = = TEMP_STREAM_READONLY | | mode = = TEMP_STREAM_TAKE_BUFFER ) {
2002-04-03 00:46:33 +08:00
/* use the buffer directly */
ms - > data = buf ;
ms - > fsize = length ;
} else {
if ( length ) {
assert ( buf ! = NULL ) ;
php_stream_write ( stream , buf , length ) ;
}
}
2002-03-18 07:50:31 +08:00
}
return stream ;
2002-03-20 03:15:40 +08:00
}
/* }}} */
2002-03-18 07:50:31 +08:00
2002-03-20 03:15:40 +08:00
/* {{{ */
2014-12-14 06:06:14 +08:00
PHPAPI char * _php_stream_memory_get_buffer ( php_stream * stream , size_t * length STREAMS_DC )
2002-03-22 04:37:04 +08:00
{
2006-05-14 01:58:58 +08:00
php_stream_memory_data * ms = ( php_stream_memory_data * ) stream - > abstract ;
2002-03-18 07:50:31 +08:00
assert ( ms ! = NULL ) ;
assert ( length ! = 0 ) ;
* length = ms - > fsize ;
return ms - > data ;
2002-03-20 03:15:40 +08:00
}
2002-03-18 12:57:06 +08:00
/* }}} */
2002-03-20 07:29:37 +08:00
/* }}} */
2002-03-20 03:15:40 +08:00
2002-03-18 07:50:31 +08:00
/* {{{ ------- TEMP stream implementation -------*/
2002-03-18 12:57:06 +08:00
typedef struct {
php_stream * innerstream ;
size_t smax ;
int mode ;
2014-02-10 14:04:30 +08:00
zval meta ;
2014-07-02 18:22:14 +08:00
char * tmpdir ;
2002-03-18 12:57:06 +08:00
} php_stream_temp_data ;
2002-03-18 07:50:31 +08:00
2002-03-20 03:15:40 +08:00
/* {{{ */
2019-07-18 21:25:59 +08:00
static ssize_t php_stream_temp_write ( php_stream * stream , const char * buf , size_t count )
2002-03-22 04:37:04 +08:00
{
2006-05-14 01:58:58 +08:00
php_stream_temp_data * ts = ( php_stream_temp_data * ) stream - > abstract ;
2002-03-18 12:57:06 +08:00
assert ( ts ! = NULL ) ;
2006-01-06 06:03:07 +08:00
if ( ! ts - > innerstream ) {
return - 1 ;
}
2002-03-18 12:57:06 +08:00
if ( php_stream_is ( ts - > innerstream , PHP_STREAM_IS_MEMORY ) ) {
size_t memsize ;
2002-03-18 19:18:07 +08:00
char * membuf = php_stream_memory_get_buffer ( ts - > innerstream , & memsize ) ;
2002-03-18 12:57:06 +08:00
if ( memsize + count > = ts - > smax ) {
2014-07-02 18:22:14 +08:00
php_stream * file = php_stream_fopen_temporary_file ( ts - > tmpdir , " php " , NULL ) ;
2015-02-05 12:26:29 +08:00
if ( file = = NULL ) {
2015-03-08 19:24:50 +08:00
php_error_docref ( NULL , E_WARNING , " Unable to create temporary file, Check permissions in temporary files directory. " ) ;
2015-02-05 16:26:38 +08:00
return 0 ;
2015-02-05 12:26:29 +08:00
}
2002-03-18 12:57:06 +08:00
php_stream_write ( file , membuf , memsize ) ;
2010-11-15 11:05:32 +08:00
php_stream_free_enclosed ( ts - > innerstream , PHP_STREAM_FREE_CLOSE ) ;
2002-03-18 12:57:06 +08:00
ts - > innerstream = file ;
2010-11-15 11:05:32 +08:00
php_stream_encloses ( stream , ts - > innerstream ) ;
2002-03-18 07:50:31 +08:00
}
}
2002-03-18 12:57:06 +08:00
return php_stream_write ( ts - > innerstream , buf , count ) ;
2002-03-20 03:15:40 +08:00
}
/* }}} */
2002-03-18 07:50:31 +08:00
2002-03-20 03:15:40 +08:00
/* {{{ */
2019-07-18 21:25:59 +08:00
static ssize_t php_stream_temp_read ( php_stream * stream , char * buf , size_t count )
2002-03-22 04:37:04 +08:00
{
2006-05-14 01:58:58 +08:00
php_stream_temp_data * ts = ( php_stream_temp_data * ) stream - > abstract ;
2005-10-07 15:38:59 +08:00
size_t got ;
2002-03-18 07:50:31 +08:00
2002-03-18 12:57:06 +08:00
assert ( ts ! = NULL ) ;
2002-03-18 07:50:31 +08:00
2006-01-06 06:03:07 +08:00
if ( ! ts - > innerstream ) {
return - 1 ;
}
2015-01-03 17:22:58 +08:00
2005-10-07 15:38:59 +08:00
got = php_stream_read ( ts - > innerstream , buf , count ) ;
2015-01-03 17:22:58 +08:00
2006-05-24 06:31:25 +08:00
stream - > eof = ts - > innerstream - > eof ;
2015-01-03 17:22:58 +08:00
2005-10-07 05:31:25 +08:00
return got ;
2002-03-20 03:15:40 +08:00
}
/* }}} */
2002-03-18 07:50:31 +08:00
2002-03-20 03:15:40 +08:00
/* {{{ */
2014-12-14 06:06:14 +08:00
static int php_stream_temp_close ( php_stream * stream , int close_handle )
2002-03-20 03:15:40 +08:00
{
2006-05-14 01:58:58 +08:00
php_stream_temp_data * ts = ( php_stream_temp_data * ) stream - > abstract ;
2002-03-20 07:29:37 +08:00
int ret ;
2002-03-18 07:50:31 +08:00
2002-03-18 12:57:06 +08:00
assert ( ts ! = NULL ) ;
2002-03-18 07:50:31 +08:00
2006-01-06 06:03:07 +08:00
if ( ts - > innerstream ) {
2010-11-15 11:05:32 +08:00
ret = php_stream_free_enclosed ( ts - > innerstream , PHP_STREAM_FREE_CLOSE | ( close_handle ? 0 : PHP_STREAM_FREE_PRESERVE_HANDLE ) ) ;
2006-01-06 06:03:07 +08:00
} else {
ret = 0 ;
}
2015-01-03 17:22:58 +08:00
2014-02-10 14:04:30 +08:00
zval_ptr_dtor ( & ts - > meta ) ;
2002-03-20 07:29:37 +08:00
2014-07-02 18:22:14 +08:00
if ( ts - > tmpdir ) {
efree ( ts - > tmpdir ) ;
}
2002-03-20 07:29:37 +08:00
efree ( ts ) ;
2002-03-22 04:37:04 +08:00
2002-03-20 07:29:37 +08:00
return ret ;
2002-03-20 03:15:40 +08:00
}
/* }}} */
2002-03-18 07:50:31 +08:00
2002-03-20 03:15:40 +08:00
/* {{{ */
2014-12-14 06:06:14 +08:00
static int php_stream_temp_flush ( php_stream * stream )
2002-03-22 04:37:04 +08:00
{
2006-05-14 01:58:58 +08:00
php_stream_temp_data * ts = ( php_stream_temp_data * ) stream - > abstract ;
2002-03-18 12:57:06 +08:00
assert ( ts ! = NULL ) ;
2002-03-18 07:50:31 +08:00
2006-01-06 06:03:07 +08:00
return ts - > innerstream ? php_stream_flush ( ts - > innerstream ) : - 1 ;
2002-03-20 03:15:40 +08:00
}
/* }}} */
2002-03-18 07:50:31 +08:00
2002-03-20 03:15:40 +08:00
/* {{{ */
2014-12-14 06:06:14 +08:00
static int php_stream_temp_seek ( php_stream * stream , zend_off_t offset , int whence , zend_off_t * newoffs )
2002-03-22 04:37:04 +08:00
{
2006-05-14 01:58:58 +08:00
php_stream_temp_data * ts = ( php_stream_temp_data * ) stream - > abstract ;
2002-09-23 09:47:04 +08:00
int ret ;
2002-03-18 07:50:31 +08:00
2002-03-18 12:57:06 +08:00
assert ( ts ! = NULL ) ;
2002-03-18 07:50:31 +08:00
2006-01-06 06:03:07 +08:00
if ( ! ts - > innerstream ) {
* newoffs = - 1 ;
return - 1 ;
}
2002-09-23 09:47:04 +08:00
ret = php_stream_seek ( ts - > innerstream , offset , whence ) ;
* newoffs = php_stream_tell ( ts - > innerstream ) ;
2006-05-24 06:31:25 +08:00
stream - > eof = ts - > innerstream - > eof ;
2015-01-03 17:22:58 +08:00
2002-09-23 09:47:04 +08:00
return ret ;
2002-03-20 03:15:40 +08:00
}
/* }}} */
2002-03-18 07:50:31 +08:00
2002-03-20 03:15:40 +08:00
/* {{{ */
2014-12-14 06:06:14 +08:00
static int php_stream_temp_cast ( php_stream * stream , int castas , void * * ret )
2002-03-22 04:37:04 +08:00
{
2006-05-14 01:58:58 +08:00
php_stream_temp_data * ts = ( php_stream_temp_data * ) stream - > abstract ;
2002-03-20 07:29:37 +08:00
php_stream * file ;
size_t memsize ;
char * membuf ;
2014-08-16 17:16:11 +08:00
zend_off_t pos ;
2002-03-18 07:50:31 +08:00
2002-03-18 12:57:06 +08:00
assert ( ts ! = NULL ) ;
2002-03-18 07:50:31 +08:00
2006-01-06 06:03:07 +08:00
if ( ! ts - > innerstream ) {
return FAILURE ;
}
2002-03-20 07:29:37 +08:00
if ( php_stream_is ( ts - > innerstream , PHP_STREAM_IS_STDIO ) ) {
return php_stream_cast ( ts - > innerstream , castas , ret , 0 ) ;
}
/* we are still using a memory based backing. If they are if we can be
* a FILE * , say yes because we can perform the conversion .
* If they actually want to perform the conversion , we need to switch
* the memory stream to a tmpfile stream */
if ( ret = = NULL & & castas = = PHP_STREAM_AS_STDIO ) {
return SUCCESS ;
}
/* say "no" to other stream forms */
if ( ret = = NULL ) {
return FAILURE ;
}
2002-03-22 04:37:04 +08:00
2017-04-14 16:26:13 +08:00
file = php_stream_fopen_tmpfile ( ) ;
if ( file = = NULL ) {
php_error_docref ( NULL , E_WARNING , " Unable to create temporary file. " ) ;
return FAILURE ;
}
2002-03-20 07:29:37 +08:00
/* perform the conversion and then pass the request on to the innerstream */
membuf = php_stream_memory_get_buffer ( ts - > innerstream , & memsize ) ;
php_stream_write ( file , membuf , memsize ) ;
pos = php_stream_tell ( ts - > innerstream ) ;
2015-01-03 17:22:58 +08:00
2010-11-15 11:05:32 +08:00
php_stream_free_enclosed ( ts - > innerstream , PHP_STREAM_FREE_CLOSE ) ;
2002-03-20 07:29:37 +08:00
ts - > innerstream = file ;
2010-11-15 11:05:32 +08:00
php_stream_encloses ( stream , ts - > innerstream ) ;
2002-03-20 07:29:37 +08:00
php_stream_seek ( ts - > innerstream , pos , SEEK_SET ) ;
2002-03-22 04:37:04 +08:00
2002-03-20 07:29:37 +08:00
return php_stream_cast ( ts - > innerstream , castas , ret , 1 ) ;
2002-03-20 03:15:40 +08:00
}
/* }}} */
2002-03-18 07:50:31 +08:00
2014-12-14 06:06:14 +08:00
static int php_stream_temp_stat ( php_stream * stream , php_stream_statbuf * ssb ) /* { { { */
2006-05-14 01:58:58 +08:00
{
php_stream_temp_data * ts = ( php_stream_temp_data * ) stream - > abstract ;
if ( ! ts | | ! ts - > innerstream ) {
return - 1 ;
}
return php_stream_stat ( ts - > innerstream , ssb ) ;
}
/* }}} */
2014-12-14 06:06:14 +08:00
static int php_stream_temp_set_option ( php_stream * stream , int option , int value , void * ptrparam ) /* { { { */
2006-05-14 01:58:58 +08:00
{
php_stream_temp_data * ts = ( php_stream_temp_data * ) stream - > abstract ;
2015-01-03 17:22:58 +08:00
2006-05-14 01:58:58 +08:00
switch ( option ) {
case PHP_STREAM_OPTION_META_DATA_API :
2014-02-10 14:04:30 +08:00
if ( Z_TYPE ( ts - > meta ) ! = IS_UNDEF ) {
zend_hash_copy ( Z_ARRVAL_P ( ( zval * ) ptrparam ) , Z_ARRVAL ( ts - > meta ) , zval_add_ref ) ;
2006-05-14 01:58:58 +08:00
}
return PHP_STREAM_OPTION_RETURN_OK ;
default :
2007-01-28 04:25:11 +08:00
if ( ts - > innerstream ) {
return php_stream_set_option ( ts - > innerstream , option , value , ptrparam ) ;
}
2006-05-14 01:58:58 +08:00
return PHP_STREAM_OPTION_RETURN_NOTIMPL ;
}
}
/* }}} */
2017-12-15 03:14:36 +08:00
PHPAPI const php_stream_ops php_stream_temp_ops = {
2002-03-18 07:50:31 +08:00
php_stream_temp_write , php_stream_temp_read ,
php_stream_temp_close , php_stream_temp_flush ,
2002-03-28 08:49:00 +08:00
" TEMP " ,
2002-03-18 07:50:31 +08:00
php_stream_temp_seek ,
php_stream_temp_cast ,
2006-05-14 01:58:58 +08:00
php_stream_temp_stat ,
php_stream_temp_set_option
2002-03-18 07:50:31 +08:00
} ;
2003-03-01 23:20:42 +08:00
/* }}} */
2002-03-20 03:15:40 +08:00
2014-07-02 18:22:14 +08:00
/* {{{ _php_stream_temp_create_ex */
2014-12-14 06:06:14 +08:00
PHPAPI php_stream * _php_stream_temp_create_ex ( int mode , size_t max_memory_usage , const char * tmpdir STREAMS_DC )
2002-03-22 04:37:04 +08:00
{
2002-03-18 07:50:31 +08:00
php_stream_temp_data * self ;
php_stream * stream ;
2002-03-20 07:29:37 +08:00
self = ecalloc ( 1 , sizeof ( * self ) ) ;
2002-03-18 07:50:31 +08:00
self - > smax = max_memory_usage ;
self - > mode = mode ;
2014-02-10 14:04:30 +08:00
ZVAL_UNDEF ( & self - > meta ) ;
2014-07-02 18:22:14 +08:00
if ( tmpdir ) {
self - > tmpdir = estrdup ( tmpdir ) ;
}
2017-08-04 13:59:22 +08:00
stream = php_stream_alloc_rel ( & php_stream_temp_ops , self , 0 , _php_stream_mode_to_str ( mode ) ) ;
2002-09-23 21:22:10 +08:00
stream - > flags | = PHP_STREAM_FLAG_NO_BUFFER ;
2007-01-28 04:25:11 +08:00
self - > innerstream = php_stream_memory_create_rel ( mode ) ;
2010-11-15 11:05:32 +08:00
php_stream_encloses ( stream , self - > innerstream ) ;
2002-09-23 21:22:10 +08:00
2002-03-18 07:50:31 +08:00
return stream ;
2002-03-20 03:15:40 +08:00
}
/* }}} */
2002-03-18 07:50:31 +08:00
2014-07-02 21:41:59 +08:00
/* {{{ _php_stream_temp_create */
2014-12-14 06:06:14 +08:00
PHPAPI php_stream * _php_stream_temp_create ( int mode , size_t max_memory_usage STREAMS_DC )
2014-07-02 21:41:59 +08:00
{
return php_stream_temp_create_ex ( mode , max_memory_usage , NULL ) ;
}
/* }}} */
2002-03-20 03:15:40 +08:00
2003-03-01 23:20:42 +08:00
/* {{{ _php_stream_temp_open */
2014-12-14 06:06:14 +08:00
PHPAPI php_stream * _php_stream_temp_open ( int mode , size_t max_memory_usage , char * buf , size_t length STREAMS_DC )
2002-03-22 04:37:04 +08:00
{
2002-03-18 07:50:31 +08:00
php_stream * stream ;
2006-05-14 01:58:58 +08:00
php_stream_temp_data * ts ;
2014-08-16 17:16:11 +08:00
zend_off_t newoffs ;
2002-03-18 07:50:31 +08:00
2005-12-14 08:06:09 +08:00
if ( ( stream = php_stream_temp_create_rel ( mode , max_memory_usage ) ) ! = NULL ) {
2002-03-18 12:57:06 +08:00
if ( length ) {
2002-03-18 07:50:31 +08:00
assert ( buf ! = NULL ) ;
2014-12-14 06:06:14 +08:00
php_stream_temp_write ( stream , buf , length ) ;
php_stream_temp_seek ( stream , 0 , SEEK_SET , & newoffs ) ;
2002-03-18 07:50:31 +08:00
}
2006-05-14 01:58:58 +08:00
ts = ( php_stream_temp_data * ) stream - > abstract ;
assert ( ts ! = NULL ) ;
ts - > mode = mode ;
2002-03-18 07:50:31 +08:00
}
return stream ;
2002-03-20 03:15:40 +08:00
}
/* }}} */
2002-03-18 07:50:31 +08:00
2017-12-15 03:14:36 +08:00
PHPAPI const php_stream_ops php_stream_rfc2397_ops = {
2006-05-14 01:58:58 +08:00
php_stream_temp_write , php_stream_temp_read ,
php_stream_temp_close , php_stream_temp_flush ,
" RFC2397 " ,
php_stream_temp_seek ,
php_stream_temp_cast ,
php_stream_temp_stat ,
php_stream_temp_set_option
} ;
2013-07-30 18:49:36 +08:00
static php_stream * php_stream_url_wrap_rfc2397 ( php_stream_wrapper * wrapper , const char * path ,
2015-03-04 07:05:28 +08:00
const char * mode , int options , zend_string * * opened_path ,
2014-12-14 06:06:14 +08:00
php_stream_context * context STREAMS_DC ) /* {{{ */
2006-05-14 01:58:58 +08:00
{
php_stream * stream ;
php_stream_temp_data * ts ;
2017-12-01 04:29:21 +08:00
char * comma , * semi , * sep ;
2017-07-09 21:10:42 +08:00
size_t mlen , dlen , plen , vlen , ilen ;
2014-08-16 17:16:11 +08:00
zend_off_t newoffs ;
2014-02-10 14:04:30 +08:00
zval meta ;
2017-07-09 21:10:42 +08:00
int base64 = 0 ;
2014-03-04 20:08:06 +08:00
zend_string * base64_comma = NULL ;
2006-05-14 01:58:58 +08:00
2014-02-10 14:04:30 +08:00
ZVAL_NULL ( & meta ) ;
2006-05-14 01:58:58 +08:00
if ( memcmp ( path , " data: " , 5 ) ) {
return NULL ;
}
path + = 5 ;
dlen = strlen ( path ) ;
if ( dlen > = 2 & & path [ 0 ] = = ' / ' & & path [ 1 ] = = ' / ' ) {
dlen - = 2 ;
path + = 2 ;
}
if ( ( comma = memchr ( path , ' , ' , dlen ) ) = = NULL ) {
2014-12-14 06:06:14 +08:00
php_stream_wrapper_log_error ( wrapper , options , " rfc2397: no comma in URL " ) ;
2006-05-14 01:58:58 +08:00
return NULL ;
}
2006-05-14 09:06:09 +08:00
if ( comma ! = path ) {
/* meta info */
mlen = comma - path ;
dlen - = mlen ;
semi = memchr ( path , ' ; ' , mlen ) ;
sep = memchr ( path , ' / ' , mlen ) ;
2015-01-03 17:22:58 +08:00
2006-05-14 09:06:09 +08:00
if ( ! semi & & ! sep ) {
2014-12-14 06:06:14 +08:00
php_stream_wrapper_log_error ( wrapper , options , " rfc2397: illegal media type " ) ;
2006-05-14 09:06:09 +08:00
return NULL ;
}
2014-02-10 14:04:30 +08:00
array_init ( & meta ) ;
2006-05-14 09:06:09 +08:00
if ( ! semi ) { /* there is only a mime type */
2014-04-15 19:40:40 +08:00
add_assoc_stringl ( & meta , " mediatype " , ( char * ) path , mlen ) ;
2006-05-14 09:06:09 +08:00
mlen = 0 ;
} else if ( sep & & sep < semi ) { /* there is a mime type */
plen = semi - path ;
2014-04-15 19:40:40 +08:00
add_assoc_stringl ( & meta , " mediatype " , ( char * ) path , plen ) ;
2006-05-14 09:06:09 +08:00
mlen - = plen ;
path + = plen ;
} else if ( semi ! = path | | mlen ! = sizeof ( " ;base64 " ) - 1 | | memcmp ( path , " ;base64 " , sizeof ( " ;base64 " ) - 1 ) ) { /* must be error since parameters are only allowed after mediatype */
zval_ptr_dtor ( & meta ) ;
2014-12-14 06:06:14 +08:00
php_stream_wrapper_log_error ( wrapper , options , " rfc2397: illegal media type " ) ;
2006-05-14 09:06:09 +08:00
return NULL ;
}
/* get parameters and potentially ';base64' */
while ( semi & & ( semi = = path ) ) {
path + + ;
mlen - - ;
sep = memchr ( path , ' = ' , mlen ) ;
2006-05-14 01:58:58 +08:00
semi = memchr ( path , ' ; ' , mlen ) ;
2006-05-14 09:06:09 +08:00
if ( ! sep | | ( semi & & semi < sep ) ) { /* must be ';base64' or failure */
if ( mlen ! = sizeof ( " base64 " ) - 1 | | memcmp ( path , " base64 " , sizeof ( " base64 " ) - 1 ) ) {
/* must be error since parameters are only allowed after mediatype and we have no '=' sign */
zval_ptr_dtor ( & meta ) ;
2014-12-14 06:06:14 +08:00
php_stream_wrapper_log_error ( wrapper , options , " rfc2397: illegal parameter " ) ;
2006-05-14 09:06:09 +08:00
return NULL ;
}
base64 = 1 ;
mlen - = sizeof ( " base64 " ) - 1 ;
path + = sizeof ( " base64 " ) - 1 ;
break ;
}
/* found parameter ... the heart of cs ppl lies in +1/-1 or was it +2 this time? */
plen = sep - path ;
2016-06-22 01:12:29 +08:00
vlen = ( semi ? ( size_t ) ( semi - sep ) : ( mlen - plen ) ) - 1 /* '=' */ ;
2017-12-01 04:29:21 +08:00
if ( plen ! = sizeof ( " mediatype " ) - 1 | | memcmp ( path , " mediatype " , sizeof ( " mediatype " ) - 1 ) ) {
add_assoc_stringl_ex ( & meta , path , plen , sep + 1 , vlen ) ;
2016-01-17 14:10:54 +08:00
}
2006-05-14 09:06:09 +08:00
plen + = vlen + 1 ;
mlen - = plen ;
path + = plen ;
2006-05-14 01:58:58 +08:00
}
2006-05-14 09:06:09 +08:00
if ( mlen ) {
zval_ptr_dtor ( & meta ) ;
2014-12-14 06:06:14 +08:00
php_stream_wrapper_log_error ( wrapper , options , " rfc2397: illegal URL " ) ;
2006-05-14 09:06:09 +08:00
return NULL ;
}
} else {
2014-02-10 14:04:30 +08:00
array_init ( & meta ) ;
2006-05-14 09:06:09 +08:00
}
2014-02-10 14:04:30 +08:00
add_assoc_bool ( & meta , " base64 " , base64 ) ;
2006-05-14 09:06:09 +08:00
2006-05-21 21:37:19 +08:00
/* skip ',' */
comma + + ;
dlen - - ;
if ( base64 ) {
2016-07-11 17:40:03 +08:00
base64_comma = php_base64_decode_ex ( ( const unsigned char * ) comma , dlen , 1 ) ;
2014-03-04 20:08:06 +08:00
if ( ! base64_comma ) {
2006-06-06 22:09:12 +08:00
zval_ptr_dtor ( & meta ) ;
2014-12-14 06:06:14 +08:00
php_stream_wrapper_log_error ( wrapper , options , " rfc2397: unable to decode " ) ;
2006-05-21 21:37:19 +08:00
return NULL ;
}
2015-06-30 18:59:27 +08:00
comma = ZSTR_VAL ( base64_comma ) ;
2017-07-09 21:10:42 +08:00
ilen = ZSTR_LEN ( base64_comma ) ;
2006-05-21 21:37:19 +08:00
} else {
comma = estrndup ( comma , dlen ) ;
2016-02-22 09:02:55 +08:00
dlen = php_url_decode ( comma , dlen ) ;
2017-07-09 21:10:42 +08:00
ilen = dlen ;
2006-05-21 21:37:19 +08:00
}
2006-05-14 09:06:09 +08:00
if ( ( stream = php_stream_temp_create_rel ( 0 , ~ 0u ) ) ! = NULL ) {
2006-05-14 01:58:58 +08:00
/* store data */
2014-12-14 06:06:14 +08:00
php_stream_temp_write ( stream , comma , ilen ) ;
php_stream_temp_seek ( stream , 0 , SEEK_SET , & newoffs ) ;
2006-05-14 09:06:09 +08:00
/* set special stream stuff (enforce exact mode) */
vlen = strlen ( mode ) ;
if ( vlen > = sizeof ( stream - > mode ) ) {
vlen = sizeof ( stream - > mode ) - 1 ;
}
memcpy ( stream - > mode , mode , vlen ) ;
stream - > mode [ vlen ] = ' \0 ' ;
stream - > ops = & php_stream_rfc2397_ops ;
2006-05-14 01:58:58 +08:00
ts = ( php_stream_temp_data * ) stream - > abstract ;
assert ( ts ! = NULL ) ;
2007-01-28 04:25:11 +08:00
ts - > mode = mode & & mode [ 0 ] = = ' r ' & & mode [ 1 ] ! = ' + ' ? TEMP_STREAM_READONLY : 0 ;
2014-02-10 14:04:30 +08:00
ZVAL_COPY_VALUE ( & ts - > meta , & meta ) ;
2006-05-14 01:58:58 +08:00
}
2014-03-04 20:08:06 +08:00
if ( base64_comma ) {
2014-08-26 01:24:55 +08:00
zend_string_free ( base64_comma ) ;
2014-03-04 20:08:06 +08:00
} else {
efree ( comma ) ;
}
2006-05-14 01:58:58 +08:00
return stream ;
}
2017-12-15 03:14:36 +08:00
PHPAPI const php_stream_wrapper_ops php_stream_rfc2397_wops = {
2006-05-14 01:58:58 +08:00
php_stream_url_wrap_rfc2397 ,
NULL , /* close */
NULL , /* fstat */
NULL , /* stat */
NULL , /* opendir */
" RFC2397 " ,
NULL , /* unlink */
NULL , /* rename */
NULL , /* mkdir */
2016-06-22 01:12:29 +08:00
NULL , /* rmdir */
NULL , /* stream_metadata */
2006-05-14 01:58:58 +08:00
} ;
2017-12-15 03:46:22 +08:00
PHPAPI const php_stream_wrapper php_stream_rfc2397_wrapper = {
2006-05-14 01:58:58 +08:00
& php_stream_rfc2397_wops ,
NULL ,
2006-11-05 04:43:28 +08:00
1 , /* is_url */
2006-05-14 01:58:58 +08:00
} ;