dsp Wed Oct 3 10:44:32 2007 UTC Added files: (Branch: PHP_5_3) /php-src/ext/standard/tests/file bug40501.csv bug40501.phpt
Modified files: /php-src NEWS /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: MFH: Add an escape parameter to fgetcsv to satisfy rfc4180 and bug #40501. [DOC] 5th parameter available since PHP 5.3+
http://cvs.php.net/viewvc.cgi/php-src/NEWS?r1=1.2027.2.547.2.965.2.20&r2=1.2027.2.547.2.965.2.21&diff_format=u Index: php-src/NEWS diff -u php-src/NEWS:1.2027.2.547.2.965.2.20 php-src/NEWS:1.2027.2.547.2.965.2.21 --- php-src/NEWS:1.2027.2.547.2.965.2.20 Wed Oct 3 10:33:01 2007 +++ php-src/NEWS Wed Oct 3 10:44:32 2007 @@ -1,6 +1,7 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 20??, PHP 5.3.0 +- Added optional escape character parameter to fgetcsv. (David Soria Parra) - Added xsl->setProfiling() for profiling stylesheets. (Christian) - Added long-option feature to getopt() and made getopt() available also on win32 systems by adding a common getopt implementation into core. http://cvs.php.net/viewvc.cgi/php-src/ext/spl/spl_directory.c?r1=1.45.2.27.2.23.2.1&r2=1.45.2.27.2.23.2.2&diff_format=u Index: php-src/ext/spl/spl_directory.c diff -u php-src/ext/spl/spl_directory.c:1.45.2.27.2.23.2.1 php-src/ext/spl/spl_directory.c:1.45.2.27.2.23.2.2 --- php-src/ext/spl/spl_directory.c:1.45.2.27.2.23.2.1 Thu Sep 27 18:00:44 2007 +++ php-src/ext/spl/spl_directory.c Wed Oct 3 10:44:32 2007 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: spl_directory.c,v 1.45.2.27.2.23.2.1 2007/09/27 18:00:44 dmitry Exp $ */ +/* $Id: spl_directory.c,v 1.45.2.27.2.23.2.2 2007/10/03 10:44:32 dsp Exp $ */ #ifdef HAVE_CONFIG_H # include "config.h" @@ -1589,7 +1589,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; @@ -1606,7 +1606,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); @@ -1632,7 +1632,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); } @@ -1943,18 +1943,25 @@ } /* }}} */ -/* {{{ proto array SplFileObject::fgetcsv([string delimiter [, string enclosure]]) +/* {{{ proto array SplFileObject::fgetcsv([string delimiter [, string enclosure [, escape = '\\']]]) Return current line as csv */ 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]; + /* no break */ case 2: if (e_len != 1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character"); @@ -1972,23 +1979,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"); @@ -2008,6 +2022,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.12.2.5.2.4&r2=1.12.2.5.2.4.2.1&diff_format=u Index: php-src/ext/spl/spl_directory.h diff -u php-src/ext/spl/spl_directory.h:1.12.2.5.2.4 php-src/ext/spl/spl_directory.h:1.12.2.5.2.4.2.1 --- php-src/ext/spl/spl_directory.h:1.12.2.5.2.4 Mon Jan 1 09:36:07 2007 +++ php-src/ext/spl/spl_directory.h Wed Oct 3 10:44:32 2007 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: spl_directory.h,v 1.12.2.5.2.4 2007/01/01 09:36:07 sebastian Exp $ */ +/* $Id: spl_directory.h,v 1.12.2.5.2.4.2.1 2007/10/03 10:44:32 dsp Exp $ */ #ifndef SPL_DIRECTORY_H #define SPL_DIRECTORY_H @@ -84,6 +84,7 @@ zend_function *func_getCurr; char delimiter; char enclosure; + char escape; } file; } u; }; http://cvs.php.net/viewvc.cgi/php-src/ext/standard/file.c?r1=1.409.2.6.2.28&r2=1.409.2.6.2.28.2.1&diff_format=u Index: php-src/ext/standard/file.c diff -u php-src/ext/standard/file.c:1.409.2.6.2.28 php-src/ext/standard/file.c:1.409.2.6.2.28.2.1 --- php-src/ext/standard/file.c:1.409.2.6.2.28 Tue Sep 4 12:51:49 2007 +++ php-src/ext/standard/file.c Wed Oct 3 10:44:32 2007 @@ -21,7 +21,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: file.c,v 1.409.2.6.2.28 2007/09/04 12:51:49 iliaa Exp $ */ +/* $Id: file.c,v 1.409.2.6.2.28.2.1 2007/10/03 10:44:32 dsp Exp $ */ /* Synced with php 3.0 revision 1.218 1999-06-16 [ssb] */ @@ -2013,12 +2013,14 @@ } /* }}} */ -/* {{{ proto array fgetcsv(resource fp [,int length [, string delimiter [, string enclosure]]]) +/* {{{ proto array fgetcsv(resource fp [,int length [, string delimiter [, string enclosure [, string escape]]]]) Get line from file pointer and parse for CSV fields */ PHP_FUNCTION(fgetcsv) { char delimiter = ','; /* allow this to be set as parameter */ char enclosure = '"'; /* allow this to be set as parameter */ + char escape = '\\'; + /* first section exactly as php_fgetss */ long len = 0; @@ -2032,10 +2034,13 @@ int delimiter_str_len = 0; char *enclosure_str = NULL; int enclosure_str_len = 0; + char *escape_str = NULL; + int escape_str_len = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|Zss", - &fd, &len_zv, &delimiter_str, &delimiter_str_len, - &enclosure_str, &enclosure_str_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|Zsss", + &fd, &len_zv, &delimiter_str, &delimiter_str_len, + &enclosure_str, &enclosure_str_len, + &escape_str, &escape_str_len) == FAILURE) { return; } @@ -2064,6 +2069,17 @@ enclosure = enclosure_str[0]; } + if (escape_str != NULL) { + if (escape_str_len < 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "escape must be character"); + RETURN_FALSE; + } else if (escape_str_len > 1) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "escape must be a single character"); + } + + escape = escape_str[0]; + } + if (len_zv != NULL && Z_TYPE_PP(len_zv) != IS_NULL) { convert_to_long_ex(len_zv); len = Z_LVAL_PP(len_zv); @@ -2092,14 +2108,13 @@ } } - php_fgetcsv(stream, delimiter, enclosure, buf_len, buf, return_value TSRMLS_CC); + php_fgetcsv(stream, delimiter, enclosure, escape, buf_len, buf, return_value TSRMLS_CC); } /* }}} */ -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_char, size_t buf_len, char *buf, zval *return_value TSRMLS_DC) /* {{{ */ { char *temp, *tptr, *bptr, *line_end, *limit; - const char escape_char = '\\'; size_t temp_len, line_end_len; int inc_len; @@ -2250,7 +2265,8 @@ state = 0; break; default: - if (*bptr == escape_char) { + if ((escape_char == enclosure && *bptr == escape_char && *(bptr+1) == escape_char) + || (escape_char != enclosure && *bptr == escape_char)) { state = 1; } else if (*bptr == enclosure) { state = 2; http://cvs.php.net/viewvc.cgi/php-src/ext/standard/file.h?r1=1.94.2.2.2.5&r2=1.94.2.2.2.5.2.1&diff_format=u Index: php-src/ext/standard/file.h diff -u php-src/ext/standard/file.h:1.94.2.2.2.5 php-src/ext/standard/file.h:1.94.2.2.2.5.2.1 --- php-src/ext/standard/file.h:1.94.2.2.2.5 Wed Jan 10 14:40:06 2007 +++ php-src/ext/standard/file.h Wed Oct 3 10:44:32 2007 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: file.h,v 1.94.2.2.2.5 2007/01/10 14:40:06 bjori Exp $ */ +/* $Id: file.h,v 1.94.2.2.2.5.2.1 2007/10/03 10:44:32 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_char, size_t buf_len, char *buf, zval *return_value TSRMLS_DC); #define META_DEF_BUFSIZE 8192 http://cvs.php.net/viewvc.cgi/php-src/ext/standard/tests/file/fgetcsv_error.phpt?r1=1.1.2.1&r2=1.1.2.1.2.1&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.1.2.1 php-src/ext/standard/tests/file/fgetcsv_error.phpt:1.1.2.1.2.1 --- php-src/ext/standard/tests/file/fgetcsv_error.phpt:1.1.2.1 Wed Aug 8 13:13:18 2007 +++ php-src/ext/standard/tests/file/fgetcsv_error.phpt Wed Oct 3 10:44:32 2007 @@ -3,7 +3,7 @@ --FILE-- <?php /* - Prototype: array fgetcsv ( resource $handle [, int $length [, string $delimiter [, string $enclosure]]] ); + Prototype: array fgetcsv ( resource $handle [, int $length [, string $delimiter [, string $enclosure [, string $escape]]]] ); Description: Gets line from file pointer and parse for CSV fields */ @@ -18,7 +18,8 @@ $len = 1024; $delim = ";"; $enclosure ="\""; -var_dump( fgetcsv($fp, $len, $delim, $enclosure, $fp) ); +$escape = '"'; +var_dump( fgetcsv($fp, $len, $delim, $enclosure, $escape, $fp) ); fclose($fp); // test invalid arguments : non-resources @@ -35,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"; @@ -47,7 +48,7 @@ NULL -- Testing fgetcsv() with more than expected number of arguments -- -Warning: fgetcsv() expects at most 4 parameters, 5 given in %s on line %d +Warning: fgetcsv() expects at most 5 parameters, 6 given in %s on line %d NULL -- Testing fgetcsv() with invalid arguments -- -- Iteration 1 -- 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