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