dsp Wed Oct 3 10:31:04 2007 UTC Added files: /php-src/ext/standard/tests/file bug40501.csv bug40501.phpt
Modified files: /php-src/ext/spl spl_directory.c spl_directory.h /php-src/ext/standard file.c file.h /php-src/ext/standard/tests/file fgetcsv_error.phpt Log: - Add an escape parameter to fgetcsv to satisfy rfc4180 and bug #40501.
http://cvs.php.net/viewvc.cgi/php-src/ext/spl/spl_directory.c?r1=1.136&r2=1.137&diff_format=u Index: php-src/ext/spl/spl_directory.c diff -u php-src/ext/spl/spl_directory.c:1.136 php-src/ext/spl/spl_directory.c:1.137 --- php-src/ext/spl/spl_directory.c:1.136 Thu Sep 27 18:28:42 2007 +++ php-src/ext/spl/spl_directory.c Wed Oct 3 10:31:03 2007 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: spl_directory.c,v 1.136 2007/09/27 18:28:42 dmitry Exp $ */ +/* $Id: spl_directory.c,v 1.137 2007/10/03 10:31:03 dsp Exp $ */ #ifdef HAVE_CONFIG_H # include "config.h" @@ -1771,7 +1771,7 @@ spl_filesystem_file_call(intern, func_ptr, pass_num_args, return_value, arg2 TSRMLS_CC); \ } -static int spl_filesystem_file_read_csv(spl_filesystem_object *intern, char delimiter, char enclosure, zval *return_value TSRMLS_DC) /* {{{ */ +static int spl_filesystem_file_read_csv(spl_filesystem_object *intern, char delimiter, char enclosure, char escape, zval *return_value TSRMLS_DC) /* {{{ */ { int ret = SUCCESS; @@ -1788,7 +1788,7 @@ } ALLOC_INIT_ZVAL(intern->u.file.current_zval); - php_fgetcsv(intern->u.file.stream, delimiter, enclosure, buf_len, buf, intern->u.file.current_zval TSRMLS_CC); + php_fgetcsv(intern->u.file.stream, delimiter, enclosure, escape, buf_len, buf, intern->u.file.current_zval TSRMLS_CC); if (return_value) { if (Z_TYPE_P(return_value) != IS_NULL) { zval_dtor(return_value); @@ -1814,7 +1814,7 @@ return FAILURE; } if (intern->flags & SPL_FILE_OBJECT_READ_CSV) { - return spl_filesystem_file_read_csv(intern, intern->u.file.delimiter, intern->u.file.enclosure, NULL TSRMLS_CC); + return spl_filesystem_file_read_csv(intern, intern->u.file.delimiter, intern->u.file.enclosure, intern->u.file.escape, NULL TSRMLS_CC); } else { zend_call_method_with_0_params(&this_ptr, Z_OBJCE_P(getThis()), &intern->u.file.func_getCurr, "getCurrentLine", &retval); } @@ -2149,13 +2149,20 @@ SPL_METHOD(SplFileObject, fgetcsv) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure; - char *delim, *enclo; - int d_len, e_len; + char delimiter = intern->u.file.delimiter, enclosure = intern->u.file.enclosure, escape = intern->u.file.escape; + char *delim, *enclo, *esc; + int d_len, e_len, esc_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ss", &delim, &d_len, &enclo, &e_len) == SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) { switch(ZEND_NUM_ARGS()) { + case 3: + if (esc_len != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "escape must be a character"); + RETURN_FALSE; + } + escape = esc[0]; + case 2: if (e_len != 1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character"); @@ -2173,23 +2180,30 @@ case 0: break; } - spl_filesystem_file_read_csv(intern, delimiter, enclosure, return_value TSRMLS_CC); + spl_filesystem_file_read_csv(intern, delimiter, enclosure, escape, return_value TSRMLS_CC); } } /* }}} */ -/* {{{ proto void SplFileObject::setCsvControl([string delimiter = ',' [, string enclosure = '"']]) +/* {{{ proto void SplFileObject::setCsvControl([string delimiter = ',' [, string enclosure = '"' [, string escape = '\\']]]) Set the delimiter and enclosure character used in fgetcsv */ SPL_METHOD(SplFileObject, setCsvControl) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - char delimiter = ',', enclosure = '"'; - char *delim, *enclo; - int d_len, e_len; + char delimiter = ',', enclosure = '"', escape='\\'; + char *delim, *enclo, *esc; + int d_len, e_len, esc_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ss", &delim, &d_len, &enclo, &e_len) == SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sss", &delim, &d_len, &enclo, &e_len, &esc, &esc_len) == SUCCESS) { switch(ZEND_NUM_ARGS()) { + case 3: + if (esc_len != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "escape must be a character"); + RETURN_FALSE; + } + escape = esc[0]; + /* no break */ case 2: if (e_len != 1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character"); @@ -2209,6 +2223,7 @@ } intern->u.file.delimiter = delimiter; intern->u.file.enclosure = enclosure; + intern->u.file.escape = escape; } } /* }}} */ http://cvs.php.net/viewvc.cgi/php-src/ext/spl/spl_directory.h?r1=1.34&r2=1.35&diff_format=u Index: php-src/ext/spl/spl_directory.h diff -u php-src/ext/spl/spl_directory.h:1.34 php-src/ext/spl/spl_directory.h:1.35 --- php-src/ext/spl/spl_directory.h:1.34 Sun Mar 4 00:42:30 2007 +++ php-src/ext/spl/spl_directory.h Wed Oct 3 10:31:03 2007 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: spl_directory.h,v 1.34 2007/03/04 00:42:30 helly Exp $ */ +/* $Id: spl_directory.h,v 1.35 2007/10/03 10:31:03 dsp Exp $ */ #ifndef SPL_DIRECTORY_H #define SPL_DIRECTORY_H @@ -93,6 +93,7 @@ zend_function *func_getCurr; char delimiter; char enclosure; + char escape; } file; } u; spl_filesystem_iterator it; http://cvs.php.net/viewvc.cgi/php-src/ext/standard/file.c?r1=1.500&r2=1.501&diff_format=u Index: php-src/ext/standard/file.c diff -u php-src/ext/standard/file.c:1.500 php-src/ext/standard/file.c:1.501 --- php-src/ext/standard/file.c:1.500 Wed Sep 5 12:55:36 2007 +++ php-src/ext/standard/file.c Wed Oct 3 10:31:04 2007 @@ -21,7 +21,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: file.c,v 1.500 2007/09/05 12:55:36 iliaa Exp $ */ +/* $Id: file.c,v 1.501 2007/10/03 10:31:04 dsp Exp $ */ /* Synced with php 3.0 revision 1.218 1999-06-16 [ssb] */ @@ -2260,12 +2260,12 @@ /* }}} */ PHPAPI void php_fgetcsv(php_stream *stream, /* {{{ */ - char delimiter, char enclosure, - size_t buf_len, char *buf, - zval *return_value TSRMLS_DC) + char delimiter, char enclosure, char escape, + size_t buf_len, char *buf, + zval *return_value TSRMLS_DC) { - char *delim = &delimiter, *enc = &enclosure, *buffer = buf; - int delim_len = 1, enc_len = 1, buffer_len = buf_len; + char *delim = &delimiter, *enc = &enclosure, *buffer = buf, *esc; + int delim_len = 1, enc_len = 1, esc_len = 1, buffer_len = buf_len; zend_uchar type = IS_STRING; if (stream) { @@ -2285,22 +2285,30 @@ INIT_PZVAL(return_value); return; } + if (FAILURE == zend_string_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), (UChar**)&esc, &esc_len, &escape, 1 TSRMLS_CC)) { + efree(delim); + efree(enc); + INIT_PZVAL(return_value); + return; + } if (FAILURE == zend_string_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), (UChar**)&buffer, &buffer_len, buf, buf_len TSRMLS_CC)) { efree(delim); efree(enc); + efree(esc); INIT_PZVAL(return_value); return; } - php_u_fgetcsv(stream, (UChar*)delim, delim_len, (UChar*)enc, enc_len, &esc, 1, + php_u_fgetcsv(stream, (UChar*)delim, delim_len, (UChar*)enc, enc_len, (UChar*)esc, esc_len, (UChar*)buffer, buffer_len, return_value TSRMLS_CC); /* Types converted, free storage */ efree(delim); efree(enc); + efree(esc); } else { /* Binary stream with binary delimiter/enclosures/prefetch */ - php_fgetcsv_ex(stream, delim, delim_len, enc, enc_len, "\\", 1, buffer, buffer_len, return_value TSRMLS_CC); + php_fgetcsv_ex(stream, delim, delim_len, enc, enc_len, esc, esc_len, buffer, buffer_len, return_value TSRMLS_CC); } } @@ -2365,8 +2373,12 @@ } /* Is it an escape character? */ - if (PHP_FGETCSV_BIN_CHECK(p, e, escape, escape_len)) { - /* Skip escape sequence and let next char be treated as literal */ + if ((PHP_FGETCSV_BIN_CHECK(p, e, escape, escape_len) && escape != enclosure) + || (PHP_FGETCSV_BIN_CHECK(p, e, escape, escape_len) + && PHP_FGETCSV_BIN_CHECK(p+1, e, escape, escape_len) && escape == enclosure)) { + /* Skip escape sequence and let next char be treated as literal + If enclosure is the same character as esacpe, it is considered as esacped + if it appears twice */ p += escape_len; /* FALL THROUGH */ } @@ -2569,8 +2581,12 @@ } /* Is it an escape character? */ - if (PHP_FGETCSV_UNI_CHECK(p, e, escape, escape_len)) { - /* Skip escape sequence and let next char be treated as literal */ + if ((PHP_FGETCSV_UNI_CHECK(p, e, escape, escape_len) && escape != enclosure) + || (PHP_FGETCSV_UNI_CHECK(p, e, escape, escape_len) + && PHP_FGETCSV_UNI_CHECK(p+1, e, escape, escape_len) && escape == enclosure)) { + /* Skip escape sequence and let next char be treated as literal + If enclosure is the same character as esacpe, it is considered as esacped + if it appears twice */ p += escape_len; /* FALL THROUGH */ } http://cvs.php.net/viewvc.cgi/php-src/ext/standard/file.h?r1=1.104&r2=1.105&diff_format=u Index: php-src/ext/standard/file.h diff -u php-src/ext/standard/file.h:1.104 php-src/ext/standard/file.h:1.105 --- php-src/ext/standard/file.h:1.104 Wed Jan 10 15:06:58 2007 +++ php-src/ext/standard/file.h Wed Oct 3 10:31:04 2007 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: file.h,v 1.104 2007/01/10 15:06:58 bjori Exp $ */ +/* $Id: file.h,v 1.105 2007/10/03 10:31:04 dsp Exp $ */ /* Synced with php 3.0 revision 1.30 1999-06-16 [ssb] */ @@ -78,7 +78,7 @@ PHPAPI int php_copy_file_ex(char *src, char *dest, int src_chk TSRMLS_DC); PHPAPI int php_mkdir_ex(char *dir, long mode, int options TSRMLS_DC); PHPAPI int php_mkdir(char *dir, long mode TSRMLS_DC); -PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, size_t buf_len, char *buf, zval *return_value TSRMLS_DC); +PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, char escape, size_t buf_len, char *buf, zval *return_value TSRMLS_DC); PHPAPI void php_fgetcsv_ex(php_stream *stream, char *delimiter, int delimiter_len, char *enclosure, int enclosure_len, char *escape, int escape_len, char *buffer, int buffer_len, zval *return_value TSRMLS_DC); PHPAPI void php_u_fgetcsv(php_stream *stream, UChar *delimiter, int delimiter_len, UChar *enclosure, int enclosure_len, UChar *escape, int escape_len, http://cvs.php.net/viewvc.cgi/php-src/ext/standard/tests/file/fgetcsv_error.phpt?r1=1.2&r2=1.3&diff_format=u Index: php-src/ext/standard/tests/file/fgetcsv_error.phpt diff -u php-src/ext/standard/tests/file/fgetcsv_error.phpt:1.2 php-src/ext/standard/tests/file/fgetcsv_error.phpt:1.3 --- php-src/ext/standard/tests/file/fgetcsv_error.phpt:1.2 Wed Aug 8 13:15:01 2007 +++ php-src/ext/standard/tests/file/fgetcsv_error.phpt Wed Oct 3 10:31:04 2007 @@ -36,7 +36,7 @@ for($loop_counter = 1; $loop_counter <= count($invalid_args); $loop_counter++) { echo "-- Iteration $loop_counter --\n"; var_dump( fgetcsv($invalid_args[$loop_counter - 1]) ); // with default args - var_dump( fgetcsv($invalid_args[$loop_counter - 1], $len, $delim, $enclosure) ); // all args specified + var_dump( fgetcsv($invalid_args[$loop_counter - 1], $len, $delim, $enclosure, $escape) ); // all args specified } echo "Done\n"; http://cvs.php.net/viewvc.cgi/php-src/ext/standard/tests/file/bug40501.csv?view=markup&rev=1.1 Index: php-src/ext/standard/tests/file/bug40501.csv +++ php-src/ext/standard/tests/file/bug40501.csv "this element contains the delimiter, and ends with an odd number of backslashes (ex: 1)\",and it isn't the last element$ http://cvs.php.net/viewvc.cgi/php-src/ext/standard/tests/file/bug40501.phpt?view=markup&rev=1.1 Index: php-src/ext/standard/tests/file/bug40501.phpt +++ php-src/ext/standard/tests/file/bug40501.phpt --TEST-- Bug #40501 (fgetcsv() can't handle trailing odd number of backslashes) --FILE-- <?php $file = dirname(__FILE__).'/bug40501.csv'; $h = fopen($file, 'r'); $data = fgetcsv($h, NULL, ',', '"', '"'); fclose($h); var_dump($data); ?> --EXPECT-- array(2) { [0]=> string(88) "this element contains the delimiter, and ends with an odd number of backslashes (ex: 1)\" [1]=> string(30) "and it isn't the last element$" }
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php