2003-02-16 22:19:28 +00:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2004-01-08 08:18:22 +00:00
| PHP Version 5 |
2003-02-16 22:19:28 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 13:10:10 +00:00
| Copyright ( c ) 1997 - 2006 The PHP Group |
2003-02-16 22:19:28 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 13:10:10 +00:00
| This source file is subject to version 3.01 of the PHP license , |
2003-02-16 22:19:28 +00:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-10 20:04:29 +00:00
| available through the world - wide - web at the following url : |
2006-01-01 13:10:10 +00:00
| http : //www.php.net/license/3_01.txt |
2003-02-16 22:19:28 +00: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 08:40:19 +00:00
| Authors : Wez Furlong < wez @ thebrainroom . com > |
2003-02-16 22:19:28 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
/* $Id$ */
# include "php.h"
# include "php_globals.h"
# include "php_network.h"
# include "php_open_temporary_file.h"
# include "ext/standard/file.h"
# include <stddef.h>
# include <fcntl.h>
# include "php_streams_int.h"
2004-06-21 21:08:05 +00:00
/* Global filter hash, copied to FG(stream_filters) on registration of volatile filter */
2003-02-16 22:19:28 +00:00
static HashTable stream_filters_hash ;
2004-06-21 21:08:05 +00:00
/* Should only be used during core initialization */
PHPAPI HashTable * php_get_stream_filters_hash_global ( )
2003-02-16 22:19:28 +00:00
{
return & stream_filters_hash ;
}
2004-06-21 21:08:05 +00:00
/* Normal hash selection/retrieval call */
PHPAPI HashTable * _php_get_stream_filters_hash ( TSRMLS_D )
{
return ( FG ( stream_filters ) ? FG ( stream_filters ) : & stream_filters_hash ) ;
}
/* API for registering GLOBAL filters */
2003-02-16 22:19:28 +00:00
PHPAPI int php_stream_filter_register_factory ( const char * filterpattern , php_stream_filter_factory * factory TSRMLS_DC )
{
return zend_hash_add ( & stream_filters_hash , ( char * ) filterpattern , strlen ( filterpattern ) , factory , sizeof ( * factory ) , NULL ) ;
}
PHPAPI int php_stream_filter_unregister_factory ( const char * filterpattern TSRMLS_DC )
{
return zend_hash_del ( & stream_filters_hash , ( char * ) filterpattern , strlen ( filterpattern ) ) ;
}
2004-06-21 21:08:05 +00:00
/* API for registering VOLATILE wrappers */
PHPAPI int php_stream_filter_register_factory_volatile ( const char * filterpattern , php_stream_filter_factory * factory TSRMLS_DC )
{
if ( ! FG ( stream_filters ) ) {
php_stream_filter_factory tmpfactory ;
2004-09-13 21:07:22 +00:00
ALLOC_HASHTABLE ( FG ( stream_filters ) ) ;
2004-06-21 21:08:05 +00:00
zend_hash_init ( FG ( stream_filters ) , 0 , NULL , NULL , 1 ) ;
zend_hash_copy ( FG ( stream_filters ) , & stream_filters_hash , NULL , & tmpfactory , sizeof ( php_stream_filter_factory ) ) ;
}
return zend_hash_add ( FG ( stream_filters ) , ( char * ) filterpattern , strlen ( filterpattern ) , factory , sizeof ( * factory ) , NULL ) ;
}
2003-02-18 01:22:21 +00:00
/* Buckets */
PHPAPI php_stream_bucket * php_stream_bucket_new ( php_stream * stream , char * buf , size_t buflen , int own_buf , int buf_persistent TSRMLS_DC )
{
int is_persistent = php_stream_is_persistent ( stream ) ;
php_stream_bucket * bucket ;
bucket = ( php_stream_bucket * ) pemalloc ( sizeof ( php_stream_bucket ) , is_persistent ) ;
if ( bucket = = NULL ) {
return NULL ;
}
bucket - > next = bucket - > prev = NULL ;
if ( is_persistent & & ! buf_persistent ) {
/* all data in a persistent bucket must also be persistent */
2006-03-13 04:40:11 +00:00
bucket - > buf . s = pemalloc ( buflen , 1 ) ;
2003-02-18 01:22:21 +00:00
2006-03-13 04:40:11 +00:00
if ( bucket - > buf . s = = NULL ) {
2003-02-18 01:22:21 +00:00
pefree ( bucket , 1 ) ;
return NULL ;
}
2006-03-13 04:40:11 +00:00
memcpy ( bucket - > buf . s , buf , buflen ) ;
bucket - > buflen = buflen ;
2003-02-18 01:22:21 +00:00
bucket - > own_buf = 1 ;
} else {
2006-03-13 04:40:11 +00:00
bucket - > buf . s = buf ;
bucket - > buflen = buflen ;
2003-02-18 01:22:21 +00:00
bucket - > own_buf = own_buf ;
}
2006-03-13 04:40:11 +00:00
bucket - > buf_type = IS_STRING ;
2005-08-11 23:36:07 +00:00
bucket - > is_persistent = is_persistent ;
bucket - > refcount = 1 ;
return bucket ;
}
PHPAPI php_stream_bucket * php_stream_bucket_new_unicode ( php_stream * stream , UChar * buf , int32_t buflen , int own_buf , int buf_persistent TSRMLS_DC )
{
int is_persistent = php_stream_is_persistent ( stream ) ;
php_stream_bucket * bucket ;
bucket = ( php_stream_bucket * ) pemalloc ( sizeof ( php_stream_bucket ) , is_persistent ) ;
if ( bucket = = NULL ) {
return NULL ;
}
bucket - > next = bucket - > prev = NULL ;
if ( is_persistent & & ! buf_persistent ) {
/* all data in a persistent bucket must also be persistent */
2006-03-13 04:40:11 +00:00
bucket - > buf . u = safe_pemalloc ( sizeof ( UChar ) , buflen , 0 , 1 ) ;
2005-08-11 23:36:07 +00:00
2006-03-13 04:40:11 +00:00
if ( bucket - > buf . u = = NULL ) {
2005-08-11 23:36:07 +00:00
pefree ( bucket , 1 ) ;
return NULL ;
}
2006-03-13 04:40:11 +00:00
memcpy ( bucket - > buf . u , buf , buflen ) ;
bucket - > buflen = buflen ;
2005-08-11 23:36:07 +00:00
bucket - > own_buf = 1 ;
} else {
2006-03-13 04:40:11 +00:00
bucket - > buf . u = buf ;
bucket - > buflen = buflen ;
2005-08-11 23:36:07 +00:00
bucket - > own_buf = own_buf ;
}
2006-03-13 04:40:11 +00:00
bucket - > buf_type = IS_UNICODE ;
2003-02-18 01:22:21 +00:00
bucket - > is_persistent = is_persistent ;
bucket - > refcount = 1 ;
return bucket ;
}
/* Given a bucket, returns a version of that bucket with a writeable buffer.
* If the original bucket has a refcount of 1 and owns its buffer , then it
* is returned unchanged .
* Otherwise , a copy of the buffer is made .
* In both cases , the original bucket is unlinked from its brigade .
* If a copy is made , the original bucket is delref ' d .
* */
PHPAPI php_stream_bucket * php_stream_bucket_make_writeable ( php_stream_bucket * bucket TSRMLS_DC )
{
php_stream_bucket * retval ;
php_stream_bucket_unlink ( bucket TSRMLS_CC ) ;
if ( bucket - > refcount = = 1 & & bucket - > own_buf ) {
return bucket ;
}
retval = ( php_stream_bucket * ) pemalloc ( sizeof ( php_stream_bucket ) , bucket - > is_persistent ) ;
memcpy ( retval , bucket , sizeof ( * retval ) ) ;
2006-03-13 04:40:11 +00:00
if ( bucket - > buf_type = = IS_UNICODE ) {
retval - > buf . u = safe_pemalloc ( sizeof ( UChar ) , retval - > buflen , 0 , retval - > is_persistent ) ;
memcpy ( retval - > buf . u , bucket - > buf . u , UBYTES ( retval - > buflen ) ) ;
2005-08-11 23:36:07 +00:00
} else {
2006-03-13 04:40:11 +00:00
retval - > buf . s = pemalloc ( retval - > buflen , retval - > is_persistent ) ;
memcpy ( retval - > buf . s , bucket - > buf . s , retval - > buflen ) ;
2005-08-11 23:36:07 +00:00
}
2003-02-18 01:22:21 +00:00
retval - > refcount = 1 ;
retval - > own_buf = 1 ;
2003-02-18 01:39:26 +00:00
php_stream_bucket_delref ( bucket TSRMLS_CC ) ;
2003-02-18 01:22:21 +00:00
return retval ;
}
PHPAPI int php_stream_bucket_split ( php_stream_bucket * in , php_stream_bucket * * left , php_stream_bucket * * right , size_t length TSRMLS_DC )
{
* left = ( php_stream_bucket * ) pecalloc ( 1 , sizeof ( php_stream_bucket ) , in - > is_persistent ) ;
* right = ( php_stream_bucket * ) pecalloc ( 1 , sizeof ( php_stream_bucket ) , in - > is_persistent ) ;
if ( * left = = NULL | | * right = = NULL ) {
goto exit_fail ;
}
2006-03-13 04:40:11 +00:00
if ( in - > buf_type = = IS_UNICODE ) {
( * left ) - > buf . u = safe_pemalloc ( sizeof ( UChar ) , length , 0 , in - > is_persistent ) ;
( * left ) - > buflen = length ;
memcpy ( ( * left ) - > buf . u , in - > buf . u , UBYTES ( length ) ) ;
2005-08-11 23:36:07 +00:00
2006-03-13 04:40:11 +00:00
( * right ) - > buflen = in - > buflen - length ;
( * right ) - > buf . u = pemalloc ( UBYTES ( ( * right ) - > buflen ) , in - > is_persistent ) ;
memcpy ( ( * right ) - > buf . u , in - > buf . u + length , UBYTES ( ( * right ) - > buflen ) ) ;
2005-08-11 23:36:07 +00:00
} else {
2006-03-13 04:40:11 +00:00
( * left ) - > buf . s = pemalloc ( length , in - > is_persistent ) ;
( * left ) - > buflen = length ;
memcpy ( ( * left ) - > buf . s , in - > buf . s , length ) ;
2005-08-11 23:36:07 +00:00
2006-03-13 04:40:11 +00:00
( * right ) - > buflen = in - > buflen - length ;
( * right ) - > buf . s = pemalloc ( ( * right ) - > buflen , in - > is_persistent ) ;
memcpy ( ( * right ) - > buf . s , in - > buf . s + length , ( * right ) - > buflen ) ;
2005-08-11 23:36:07 +00:00
}
2003-02-18 01:22:21 +00:00
( * left ) - > refcount = 1 ;
( * left ) - > own_buf = 1 ;
( * left ) - > is_persistent = in - > is_persistent ;
2006-03-13 04:40:11 +00:00
( * left ) - > buf_type = in - > buf_type ;
2005-08-11 23:36:07 +00:00
2003-02-18 01:22:21 +00:00
( * right ) - > refcount = 1 ;
( * right ) - > own_buf = 1 ;
( * right ) - > is_persistent = in - > is_persistent ;
2006-03-13 04:40:11 +00:00
( * right ) - > buf_type = in - > buf_type ;
2003-02-18 01:22:21 +00:00
return SUCCESS ;
exit_fail :
if ( * right ) {
2006-03-13 04:40:11 +00:00
if ( ( * right ) - > buf . v ) {
pefree ( ( * right ) - > buf . v , in - > is_persistent ) ;
2003-02-18 01:22:21 +00:00
}
pefree ( * right , in - > is_persistent ) ;
}
if ( * left ) {
2006-03-13 04:40:11 +00:00
if ( ( * left ) - > buf . v ) {
pefree ( ( * left ) - > buf . v , in - > is_persistent ) ;
2003-02-18 01:22:21 +00:00
}
pefree ( * left , in - > is_persistent ) ;
}
return FAILURE ;
}
PHPAPI void php_stream_bucket_delref ( php_stream_bucket * bucket TSRMLS_DC )
{
if ( - - bucket - > refcount = = 0 ) {
if ( bucket - > own_buf ) {
2006-03-13 04:40:11 +00:00
pefree ( bucket - > buf . v , bucket - > is_persistent ) ;
2003-02-18 01:22:21 +00:00
}
pefree ( bucket , bucket - > is_persistent ) ;
}
}
PHPAPI void php_stream_bucket_prepend ( php_stream_bucket_brigade * brigade , php_stream_bucket * bucket TSRMLS_DC )
{
bucket - > next = brigade - > head ;
bucket - > prev = NULL ;
if ( brigade - > head ) {
brigade - > head - > prev = bucket ;
} else {
brigade - > tail = bucket ;
}
brigade - > head = bucket ;
bucket - > brigade = brigade ;
}
PHPAPI void php_stream_bucket_append ( php_stream_bucket_brigade * brigade , php_stream_bucket * bucket TSRMLS_DC )
{
2006-01-10 16:14:45 +00:00
if ( brigade - > tail = = bucket ) {
return ;
}
2003-02-18 01:22:21 +00:00
bucket - > prev = brigade - > tail ;
bucket - > next = NULL ;
if ( brigade - > tail ) {
brigade - > tail - > next = bucket ;
} else {
brigade - > head = bucket ;
}
brigade - > tail = bucket ;
bucket - > brigade = brigade ;
}
PHPAPI void php_stream_bucket_unlink ( php_stream_bucket * bucket TSRMLS_DC )
{
if ( bucket - > prev ) {
bucket - > prev - > next = bucket - > next ;
} else {
bucket - > brigade - > head = bucket - > next ;
}
if ( bucket - > next ) {
bucket - > next - > prev = bucket - > prev ;
} else {
bucket - > brigade - > tail = bucket - > prev ;
}
bucket - > brigade = NULL ;
bucket - > next = bucket - > prev = NULL ;
}
2003-02-16 22:19:28 +00:00
/* We allow very simple pattern matching for filter factories:
2003-10-28 21:52:59 +00:00
* if " convert.charset.utf-8/sjis " is requested , we search first for an exact
* match . If that fails , we try " convert.charset.* " , then " convert.* "
2003-02-16 22:19:28 +00:00
* This means that we don ' t need to clog up the hashtable with a zillion
* charsets ( for example ) but still be able to provide them all as filters */
2003-04-16 14:30:25 +00:00
PHPAPI php_stream_filter * php_stream_filter_create ( const char * filtername , zval * filterparams , int persistent TSRMLS_DC )
2003-02-16 22:19:28 +00:00
{
2004-06-21 21:08:05 +00:00
HashTable * filter_hash = ( FG ( stream_filters ) ? FG ( stream_filters ) : & stream_filters_hash ) ;
2003-02-16 22:19:28 +00:00
php_stream_filter_factory * factory ;
php_stream_filter * filter = NULL ;
int n ;
char * period ;
n = strlen ( filtername ) ;
2004-06-21 21:08:05 +00:00
if ( SUCCESS = = zend_hash_find ( filter_hash , ( char * ) filtername , n , ( void * * ) & factory ) ) {
2003-04-16 14:30:25 +00:00
filter = factory - > create_filter ( filtername , filterparams , persistent TSRMLS_CC ) ;
2003-10-28 21:52:59 +00:00
} else if ( ( period = strrchr ( filtername , ' . ' ) ) ) {
2003-02-16 22:19:28 +00:00
/* try a wildcard */
2003-10-28 21:52:59 +00:00
char * wildname ;
wildname = estrdup ( filtername ) ;
period = wildname + ( period - filtername ) ;
2003-10-28 23:29:16 +00:00
while ( period & & ! filter ) {
2003-10-28 21:52:59 +00:00
* period = ' \0 ' ;
strcat ( wildname , " .* " ) ;
2004-06-21 21:08:05 +00:00
if ( SUCCESS = = zend_hash_find ( filter_hash , wildname , strlen ( wildname ) , ( void * * ) & factory ) ) {
2003-10-28 21:52:59 +00:00
filter = factory - > create_filter ( filtername , filterparams , persistent TSRMLS_CC ) ;
}
* period = ' \0 ' ;
period = strrchr ( wildname , ' . ' ) ;
2003-02-16 22:19:28 +00:00
}
2003-10-28 21:52:59 +00:00
efree ( wildname ) ;
2003-02-16 22:19:28 +00:00
}
if ( filter = = NULL ) {
/* TODO: these need correct docrefs */
if ( factory = = NULL )
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " unable to locate filter \" %s \" " , filtername ) ;
else
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " unable to create or locate filter \" %s \" " , filtername ) ;
}
return filter ;
}
PHPAPI php_stream_filter * _php_stream_filter_alloc ( php_stream_filter_ops * fops , void * abstract , int persistent STREAMS_DC TSRMLS_DC )
{
php_stream_filter * filter ;
filter = ( php_stream_filter * ) pemalloc_rel_orig ( sizeof ( php_stream_filter ) , persistent ) ;
memset ( filter , 0 , sizeof ( php_stream_filter ) ) ;
filter - > fops = fops ;
filter - > abstract = abstract ;
filter - > is_persistent = persistent ;
return filter ;
}
PHPAPI void php_stream_filter_free ( php_stream_filter * filter TSRMLS_DC )
{
if ( filter - > fops - > dtor )
filter - > fops - > dtor ( filter TSRMLS_CC ) ;
pefree ( filter , filter - > is_persistent ) ;
}
2004-05-26 21:19:21 +00:00
PHPAPI void _php_stream_filter_prepend ( php_stream_filter_chain * chain , php_stream_filter * filter TSRMLS_DC )
2003-02-16 22:19:28 +00:00
{
2003-02-18 01:22:21 +00:00
filter - > next = chain - > head ;
2003-02-16 22:19:28 +00:00
filter - > prev = NULL ;
2003-02-18 01:22:21 +00:00
if ( chain - > head ) {
chain - > head - > prev = filter ;
2003-02-16 22:19:28 +00:00
} else {
2003-02-18 01:22:21 +00:00
chain - > tail = filter ;
2003-02-16 22:19:28 +00:00
}
2003-02-18 01:22:21 +00:00
chain - > head = filter ;
filter - > chain = chain ;
2003-02-16 22:19:28 +00:00
}
2004-05-26 21:19:21 +00:00
PHPAPI void _php_stream_filter_append ( php_stream_filter_chain * chain , php_stream_filter * filter TSRMLS_DC )
2003-02-16 22:19:28 +00:00
{
2004-03-31 23:48:59 +00:00
php_stream * stream = chain - > stream ;
2003-02-18 01:22:21 +00:00
filter - > prev = chain - > tail ;
2003-02-16 22:19:28 +00:00
filter - > next = NULL ;
2003-02-18 01:22:21 +00:00
if ( chain - > tail ) {
chain - > tail - > next = filter ;
2003-02-16 22:19:28 +00:00
} else {
2003-02-18 01:22:21 +00:00
chain - > head = filter ;
2003-02-16 22:19:28 +00:00
}
2003-02-18 01:22:21 +00:00
chain - > tail = filter ;
filter - > chain = chain ;
2004-03-31 23:48:59 +00:00
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
if ( & ( stream - > readfilters ) = = chain ) {
2004-03-31 23:48:59 +00:00
/* Let's going ahead and wind anything in the buffer through this filter */
2006-03-13 04:40:11 +00:00
php_stream_bucket_brigade brig_in = { NULL , NULL } , brig_out = { NULL , NULL } ;
php_stream_bucket_brigade * brig_inp = & brig_in , * brig_outp = & brig_out ;
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
php_stream_filter_status_t status = PSFS_FEED_ME ;
2004-03-31 23:48:59 +00:00
php_stream_bucket * bucket ;
2006-03-13 04:40:11 +00:00
size_t consumed = 0 ;
2004-03-31 23:48:59 +00:00
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
if ( ( stream - > writepos - stream - > readpos ) > 0 ) {
if ( stream - > readbuf_type = = IS_UNICODE ) {
bucket = php_stream_bucket_new_unicode ( stream , stream - > readbuf . u + stream - > readpos , stream - > writepos - stream - > readpos , 0 , 0 TSRMLS_CC ) ;
} else {
bucket = php_stream_bucket_new ( stream , stream - > readbuf . s + stream - > readpos , stream - > writepos - stream - > readpos , 0 , 0 TSRMLS_CC ) ;
}
php_stream_bucket_append ( brig_inp , bucket TSRMLS_CC ) ;
status = filter - > fops - > filter ( stream , filter , brig_inp , brig_outp , & consumed , PSFS_FLAG_NORMAL TSRMLS_CC ) ;
2004-03-31 23:48:59 +00:00
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
if ( stream - > readpos + consumed > stream - > writepos | | consumed < 0 ) {
/* No behaving filter should cause this. */
status = PSFS_ERR_FATAL ;
}
2006-03-13 04:40:11 +00:00
}
2005-08-11 23:36:07 +00:00
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
if ( status = = PSFS_ERR_FATAL ) {
/* If this first cycle simply fails then there's something wrong with the filter.
Pull the filter off the chain and leave the read buffer alone . */
if ( chain - > head = = filter ) {
chain - > head = NULL ;
chain - > tail = NULL ;
} else {
filter - > prev - > next = NULL ;
chain - > tail = filter - > prev ;
}
php_stream_bucket_unlink ( bucket TSRMLS_CC ) ;
php_stream_bucket_delref ( bucket TSRMLS_CC ) ;
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Filter failed to process pre-buffered data. Not adding to filterchain. " ) ;
} else {
/* This filter addition may change the readbuffer type.
Since all the previously held data is in the bucket brigade ,
we can reappropriate the buffer that already exists ( if one does ) */
if ( stream - > readbuf_type = = IS_UNICODE & & ( filter - > fops - > flags & PSFO_FLAG_OUTPUTS_UNICODE ) = = 0 ) {
/* Buffer is currently based on unicode characters, but filter only outputs STRING adjust counting */
stream - > readbuf_type = IS_STRING ;
stream - > readbuflen * = UBYTES ( 1 ) ;
} else if ( stream - > readbuf_type = = IS_STRING & & ( filter - > fops - > flags & PSFO_FLAG_OUTPUTS_STRING ) = = 0 ) {
/* Buffer is currently based on binary characters, but filter only outputs UNICODE adjust counting */
stream - > readbuf_type = IS_UNICODE ;
stream - > readbuflen / = UBYTES ( 1 ) ;
}
if ( status = = PSFS_FEED_ME ) {
2004-03-31 23:48:59 +00:00
/* We don't actually need data yet,
leave this filter in a feed me state until data is needed .
Reset stream ' s internal read buffer since the filter is " holding " it . */
2006-03-13 04:40:11 +00:00
stream - > readpos = 0 ;
stream - > writepos = 0 ;
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
} else if ( status = = PSFS_PASS_ON ) {
2006-03-13 04:40:11 +00:00
/* Put any filtered data onto the readbuffer stack.
Previously read data has been at least partially consumed . */
stream - > readpos + = consumed ;
if ( stream - > writepos = = stream - > readpos ) {
/* Entirely consumed */
stream - > writepos = 0 ;
stream - > readpos = 0 ;
}
while ( brig_outp - > head ) {
bucket = brig_outp - > head ;
/* Convert for stream type */
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
if ( bucket - > buf_type ! = stream - > readbuf_type ) {
/* Stream expects different type than bucket contains, convert slopily */
php_stream_bucket_convert_notranscode ( bucket , stream - > readbuf_type ) ;
2006-03-13 04:40:11 +00:00
}
/* Grow buffer to hold this bucket if need be.
TODO : See warning in main / stream / streams . c : : php_stream_fill_read_buffer */
if ( stream - > readbuflen - stream - > writepos < bucket - > buflen ) {
stream - > readbuflen + = bucket - > buflen ;
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
stream - > readbuf . v = perealloc ( stream - > readbuf . v , PS_ULEN ( stream - > readbuf_type = = IS_UNICODE , stream - > readbuflen ) , stream - > is_persistent ) ;
2006-03-13 04:40:11 +00:00
}
/* Append to readbuf */
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
if ( stream - > readbuf_type = = IS_UNICODE ) {
2006-03-13 04:40:11 +00:00
memcpy ( stream - > readbuf . u + stream - > writepos , bucket - > buf . u , UBYTES ( bucket - > buflen ) ) ;
} else {
memcpy ( stream - > readbuf . s + stream - > writepos , bucket - > buf . s , bucket - > buflen ) ;
}
stream - > writepos + = bucket - > buflen ;
php_stream_bucket_unlink ( bucket TSRMLS_CC ) ;
php_stream_bucket_delref ( bucket TSRMLS_CC ) ;
}
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
}
2005-08-11 23:36:07 +00:00
}
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
} /* end of readfilters specific code */
2005-08-11 23:36:07 +00:00
}
2004-03-31 23:48:59 +00:00
2005-08-11 23:36:07 +00:00
PHPAPI int _php_stream_filter_check_chain ( php_stream_filter_chain * chain TSRMLS_DC )
{
php_stream_filter * filter ;
long last_output = PSFO_FLAG_OUTPUTS_ANY ;
2004-03-31 23:48:59 +00:00
2005-08-11 23:36:07 +00:00
for ( filter = chain - > head ; filter ; filter = filter - > next ) {
if ( ( ( ( filter - > fops - > flags & PSFO_FLAG_ACCEPT_MASK ) < < PSFO_FLAG_ACCEPT_SHIFT ) & last_output ) = = 0 ) {
/* Nothing which the last filter outputs is accepted by this filter */
return FAILURE ;
}
if ( filter - > fops - > flags & PSFO_FLAG_OUTPUTS_SAME ) {
continue ;
}
if ( filter - > fops - > flags & PSFO_FLAG_OUTPUTS_OPPOSITE ) {
last_output = ( ( last_output & PSFO_FLAG_OUTPUTS_STRING ) ? PSFO_FLAG_OUTPUTS_UNICODE : 0 ) |
( ( last_output & PSFO_FLAG_OUTPUTS_UNICODE ) ? PSFO_FLAG_OUTPUTS_STRING : 0 ) ;
continue ;
}
last_output = filter - > fops - > flags & PSFO_FLAG_OUTPUTS_ANY ;
}
return SUCCESS ;
}
PHPAPI int _php_stream_filter_output_prefer_unicode ( php_stream_filter * filter TSRMLS_DC )
{
php_stream_filter_chain * chain = filter - > chain ;
php_stream_filter * f ;
int inverted = 0 ;
2006-01-12 19:21:36 +00:00
int preferred = ( chain = = & chain - > stream - > readfilters ? 1 : 0 ) ;
2005-08-11 23:36:07 +00:00
for ( f = filter - > next ; f ; f = f - > next ) {
if ( ( f - > fops - > flags & PSFO_FLAG_ACCEPTS_STRING ) = = 0 ) {
return inverted ^ = 1 ;
}
if ( ( f - > fops - > flags & PSFO_FLAG_ACCEPTS_UNICODE ) = = 0 ) {
return inverted ;
}
if ( ( ( f - > fops - > flags & PSFO_FLAG_OUTPUTS_SAME ) = = 0 ) & &
( ( f - > fops - > flags & PSFO_FLAG_OUTPUTS_OPPOSITE ) = = 0 ) ) {
/* Input type for next filter won't effect output -- Might as well go for unicode */
return inverted ^ 1 ;
}
if ( f - > fops - > flags & PSFO_FLAG_OUTPUTS_SAME ) {
continue ;
}
if ( f - > fops - > flags & PSFO_FLAG_OUTPUTS_OPPOSITE ) {
inverted ^ = 1 ;
continue ;
2004-03-31 23:48:59 +00:00
}
}
2005-08-11 23:36:07 +00:00
return preferred ^ inverted ;
2003-02-16 22:19:28 +00:00
}
2004-09-14 03:48:17 +00:00
PHPAPI int _php_stream_filter_flush ( php_stream_filter * filter , int finish TSRMLS_DC )
{
php_stream_bucket_brigade brig_a = { NULL , NULL } , brig_b = { NULL , NULL } , * inp = & brig_a , * outp = & brig_b , * brig_temp ;
php_stream_bucket * bucket ;
php_stream_filter_chain * chain ;
php_stream_filter * current ;
php_stream * stream ;
size_t flushed_size = 0 ;
long flags = ( finish ? PSFS_FLAG_FLUSH_CLOSE : PSFS_FLAG_FLUSH_INC ) ;
if ( ! filter - > chain | | ! filter - > chain - > stream ) {
/* Filter is not attached to a chain, or chain is somehow not part of a stream */
return FAILURE ;
}
chain = filter - > chain ;
stream = chain - > stream ;
for ( current = filter ; current ; current = current - > next ) {
php_stream_filter_status_t status ;
status = filter - > fops - > filter ( stream , filter , inp , outp , NULL , flags TSRMLS_CC ) ;
if ( status = = PSFS_FEED_ME ) {
/* We've flushed the data far enough */
return SUCCESS ;
}
if ( status = = PSFS_ERR_FATAL ) {
return FAILURE ;
}
/* Otherwise we have data available to PASS_ON
Swap the brigades and continue */
brig_temp = inp ;
inp = outp ;
outp = brig_temp ;
outp - > head = NULL ;
outp - > tail = NULL ;
flags = PSFS_FLAG_NORMAL ;
}
/* Last filter returned data via PSFS_PASS_ON
Do something with it */
for ( bucket = inp - > head ; bucket ; bucket = bucket - > next ) {
2006-03-13 04:40:11 +00:00
flushed_size + = bucket - > buflen ;
2004-09-14 03:48:17 +00:00
}
if ( flushed_size = = 0 ) {
/* Unlikely, but possible */
return SUCCESS ;
}
if ( chain = = & ( stream - > readfilters ) ) {
2006-03-13 04:40:11 +00:00
/* Dump any newly flushed data to the read buffer */
if ( stream - > readpos > stream - > chunk_size ) {
/* Back the buffer up */
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
memcpy ( stream - > readbuf . s , stream - > readbuf . s + PS_ULEN ( stream - > readbuf_type = = IS_UNICODE , stream - > readpos ) , PS_ULEN ( stream - > readbuf_type = = IS_UNICODE , stream - > writepos - stream - > readpos ) ) ;
2006-03-13 04:40:11 +00:00
stream - > writepos - = stream - > readpos ;
stream - > readpos = 0 ;
}
if ( flushed_size > ( stream - > readbuflen - stream - > writepos ) ) {
/* Grow the buffer */
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
stream - > readbuf . v = perealloc ( stream - > readbuf . v , PS_ULEN ( stream - > readbuf_type = = IS_UNICODE , stream - > writepos + flushed_size + stream - > chunk_size ) , stream - > is_persistent ) ;
2006-03-13 04:40:11 +00:00
}
while ( ( bucket = inp - > head ) ) {
/* Convert if necessary */
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
if ( bucket - > buf_type ! = stream - > readbuf_type ) {
/* Stream expects different type than what's in bucket, convert slopily */
php_stream_bucket_convert_notranscode ( bucket , stream - > readbuf_type ) ;
2005-08-11 23:36:07 +00:00
}
2006-03-13 04:40:11 +00:00
/* Append to readbuf */
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
if ( stream - > readbuf_type = = IS_UNICODE ) {
2006-03-13 04:40:11 +00:00
memcpy ( stream - > readbuf . u + stream - > writepos , bucket - > buf . u , UBYTES ( bucket - > buflen ) ) ;
} else {
memcpy ( stream - > readbuf . s + stream - > writepos , bucket - > buf . s , bucket - > buflen ) ;
}
stream - > writepos + = bucket - > buflen ;
php_stream_bucket_unlink ( bucket TSRMLS_CC ) ;
php_stream_bucket_delref ( bucket TSRMLS_CC ) ;
2004-09-14 03:48:17 +00:00
}
2006-03-13 04:40:11 +00:00
2004-09-14 03:48:17 +00:00
} else if ( chain = = & ( stream - > writefilters ) ) {
/* Send flushed data to the stream */
while ( ( bucket = inp - > head ) ) {
2006-03-13 04:40:11 +00:00
/* Convert if necessary */
if ( bucket - > buf_type = = IS_UNICODE ) {
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
/* Force data to binary, adjusting buflen */
php_stream_bucket_convert_notranscode ( bucket , IS_STRING ) ;
2005-08-11 23:36:07 +00:00
}
2006-03-13 04:40:11 +00:00
/* Must be binary by this point */
stream - > ops - > write ( stream , bucket - > buf . s , bucket - > buflen TSRMLS_CC ) ;
2004-09-14 03:48:17 +00:00
php_stream_bucket_unlink ( bucket TSRMLS_CC ) ;
php_stream_bucket_delref ( bucket TSRMLS_CC ) ;
}
}
return SUCCESS ;
}
2003-02-18 01:22:21 +00:00
PHPAPI php_stream_filter * php_stream_filter_remove ( php_stream_filter * filter , int call_dtor TSRMLS_DC )
2003-02-16 22:19:28 +00:00
{
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
/* UTODO: Figure out a sane way to "defilter" so that unicode converters can be swapped around
For now , at least fopen ( , ' b ' ) + stream_encoding ( $ fp , ' charset ' ) works since there ' s nothing to remove */
2003-02-16 22:19:28 +00:00
if ( filter - > prev ) {
filter - > prev - > next = filter - > next ;
} else {
2003-02-18 01:22:21 +00:00
filter - > chain - > head = filter - > next ;
2003-02-16 22:19:28 +00:00
}
if ( filter - > next ) {
filter - > next - > prev = filter - > prev ;
} else {
2003-02-18 01:22:21 +00:00
filter - > chain - > tail = filter - > prev ;
2003-02-16 22:19:28 +00:00
}
2005-03-29 04:02:03 +00:00
if ( filter - > rsrc_id > 0 ) {
zend_list_delete ( filter - > rsrc_id ) ;
}
2003-02-16 22:19:28 +00:00
if ( call_dtor ) {
php_stream_filter_free ( filter TSRMLS_CC ) ;
return NULL ;
}
return filter ;
}
2006-03-13 04:40:11 +00:00
PHPAPI int _php_stream_bucket_convert ( php_stream_bucket * bucket , unsigned char type , UConverter * conv TSRMLS_DC )
2005-08-11 23:36:07 +00:00
{
2006-03-13 04:40:11 +00:00
if ( bucket - > buf_type = = type ) {
2005-08-11 23:36:07 +00:00
return SUCCESS ;
}
2006-03-13 04:40:11 +00:00
if ( conv ) {
/* transcode current type using provided converter */
if ( type = = IS_UNICODE ) {
UErrorCode status = U_ZERO_ERROR ;
UChar * dest ;
int destlen ;
2005-08-11 23:36:07 +00:00
2006-03-13 04:40:11 +00:00
zend_convert_to_unicode ( conv , & dest , & destlen , bucket - > buf . s , bucket - > buflen , & status ) ;
2005-08-11 23:36:07 +00:00
2006-03-13 04:40:11 +00:00
if ( bucket - > own_buf ) {
pefree ( bucket - > buf . s , bucket - > is_persistent ) ;
}
2005-08-11 23:36:07 +00:00
2006-03-13 04:40:11 +00:00
/* Might be dangerous, double check this (or, better, get a persistent version of zend_convert_to_unicode() */
bucket - > is_persistent = 0 ;
2005-08-11 23:36:07 +00:00
2006-03-13 04:40:11 +00:00
bucket - > buf_type = IS_UNICODE ;
bucket - > buf . u = dest ;
bucket - > buflen = destlen ;
bucket - > own_buf = 1 ;
return SUCCESS ;
} else {
UErrorCode status = U_ZERO_ERROR ;
char * dest ;
2006-03-24 20:21:48 +00:00
int destlen , num_conv ;
num_conv = zend_convert_from_unicode ( conv , & dest , & destlen , bucket - > buf . u , bucket - > buflen , & status ) ;
if ( U_FAILURE ( status ) ) {
2006-03-26 06:19:24 +00:00
int32_t offset = u_countChar32 ( bucket - > buf . u , num_conv ) ;
2005-08-11 23:36:07 +00:00
2006-03-26 06:19:24 +00:00
zend_raise_conversion_error_ex ( " Could not convert Unicode string to binary string " , conv , ZEND_FROM_UNICODE , offset , ( UG ( from_error_mode ) & ZEND_CONV_ERROR_EXCEPTION ) TSRMLS_CC ) ;
2006-03-24 20:21:48 +00:00
}
2005-08-11 23:36:07 +00:00
2006-03-13 04:40:11 +00:00
if ( bucket - > own_buf ) {
pefree ( bucket - > buf . u , bucket - > is_persistent ) ;
}
2005-08-11 23:36:07 +00:00
2006-03-13 04:40:11 +00:00
/* See above */
bucket - > is_persistent = 0 ;
2005-08-11 23:36:07 +00:00
2006-03-13 04:40:11 +00:00
bucket - > buf_type = IS_STRING ;
bucket - > buf . s = dest ;
bucket - > buflen = destlen ;
bucket - > own_buf = 1 ;
return SUCCESS ;
}
} else {
/* Convert without transcode, usually a bad idea as it creates ugly data,
When binary streams receive unicode data ( because of filters or writing unicode strings )
this is the only option */
if ( type = = IS_UNICODE ) {
if ( bucket - > buflen = = 0 ) {
/* Shortcut conversion for empty buckets */
if ( bucket - > own_buf ) {
pefree ( bucket - > buf . s , bucket - > is_persistent ) ;
}
2006-03-24 21:25:44 +00:00
bucket - > buf_type = IS_UNICODE ;
bucket - > buf . u = EMPTY_STR ;
2006-03-13 04:40:11 +00:00
bucket - > own_buf = 0 ;
bucket - > buflen = 0 ;
return SUCCESS ;
}
2005-08-11 23:36:07 +00:00
2006-03-13 04:40:11 +00:00
if ( bucket - > own_buf ) {
/* one UChar padding for partial units, one more for terminating NULL */
bucket - > buf . s = perealloc ( bucket - > buf . s , bucket - > buflen + UBYTES ( 2 ) , bucket - > is_persistent ) ;
} else {
int destlen = ceil ( bucket - > buflen / sizeof ( UChar ) ) ;
UChar * dest = pemalloc ( UBYTES ( destlen + 2 ) , bucket - > is_persistent ) ;
memcpy ( dest , bucket - > buf . s , bucket - > buflen ) ;
bucket - > buf . u = dest ;
bucket - > own_buf = 1 ;
}
memset ( bucket - > buf . s + bucket - > buflen , 0 , UBYTES ( 2 ) ) ;
bucket - > buf_type = IS_UNICODE ;
bucket - > buflen = ceil ( bucket - > buflen / sizeof ( UChar ) ) ;
return SUCCESS ;
} else { /* IS_STRING */
bucket - > buf_type = IS_STRING ;
bucket - > buflen * = 2 ;
return SUCCESS ;
}
2005-08-11 23:36:07 +00:00
}
2006-03-13 04:40:11 +00:00
/* Never reached */
return FAILURE ;
2005-08-11 23:36:07 +00:00
}
Another (and hopefully last) major streams commit.
This moves unicode conversion to the filter layer
(rather than at the lower streams layer)
unicode_filter.c has been moved from ext/unicode to main/streams
as it's an integral part of the streams unicode conversion process.
There are now three ways to set encoding on a stream:
(1) By context
$ctx = stream_context_create(NULL,array('encoding'=>'latin1'));
$fp = fopen('somefile', 'r+t', false, $ctx);
(2) By stream_encoding()
$fp = fopen('somefile', 'r+');
stream_encoding($fp, 'latin1');
(3) By filter
$fp = fopen('somefile', 'r+');
stream_filter_append($fp, 'unicode.from.latin1', STREAM_FILTER_READ);
stream_filter_append($fp, 'unicode.to.latin1', STREAM_FILTER_WRITE);
Note: Methods 1 and 2 are convenience wrappers around method 3.
2006-03-29 01:20:43 +00:00
PHPAPI int _php_stream_encoding_apply ( php_stream * stream , int writechain , const char * encoding , uint16_t error_mode , UChar * subst TSRMLS_DC )
{
int encoding_len = strlen ( encoding ) ;
int buflen = sizeof ( " unicode.from. " ) + encoding_len - 1 ; /* might be "to", but "from" is long enough for both */
char * buf = emalloc ( buflen + 1 ) ;
php_stream_filter * filter ;
zval * filterparams ;
if ( writechain ) {
memcpy ( buf , " unicode.to. " , sizeof ( " unicode.to. " ) - 1 ) ;
memcpy ( buf + sizeof ( " unicode.to. " ) - 1 , encoding , encoding_len + 1 ) ;
} else {
memcpy ( buf , " unicode.from. " , sizeof ( " unicode.from. " ) - 1 ) ;
memcpy ( buf + sizeof ( " unicode.from. " ) - 1 , encoding , encoding_len + 1 ) ;
}
ALLOC_INIT_ZVAL ( filterparams ) ;
array_init ( filterparams ) ;
add_assoc_long ( filterparams , " error_mode " , error_mode ) ;
if ( subst ) {
add_assoc_unicode ( filterparams , " subst_char " , subst , 1 ) ;
}
filter = php_stream_filter_create ( buf , filterparams , php_stream_is_persistent ( stream ) TSRMLS_CC ) ;
efree ( buf ) ;
zval_ptr_dtor ( & filterparams ) ;
if ( ! filter ) {
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Unable to apply encoding for charset: %s \n " , encoding ) ;
return FAILURE ;
}
php_stream_filter_append ( writechain ? & stream - > writefilters : & stream - > readfilters , filter ) ;
return SUCCESS ;
}
2003-02-16 22:19:28 +00:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
* vim600 : noet sw = 4 ts = 4 fdm = marker
* vim < 600 : noet sw = 4 ts = 4
*/