Commit:    2139d2702d26e62f220f24e268d8ea1e09a9ee64
Author:    Joey Smith <joeysm...@gmail.com>         Thu, 13 Sep 2012 12:37:48 
-0600
Committer: Stanislav Malyshev <s...@php.net>      Sat, 24 Aug 2013 20:45:14 
-0700
Parents:   bdccf0a61d9a3979136930aef4b5ba4f601aa03d
Branches:  PHP-5.5 master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=2139d2702d26e62f220f24e268d8ea1e09a9ee64

Log:
Expose fputcsv's escape_char to userland

Allows users to assert that something other than the backslash
should be considered an escape char; also follows the RFC 4180
recommendation that fields containing a " be enclosed.

Changed paths:
  M  NEWS
  M  UPGRADING
  M  ext/standard/file.c
  M  ext/standard/tests/file/fputcsv_error.phpt
  A  ext/standard/tests/file/fputcsv_variation15.phpt


Diff:
diff --git a/NEWS b/NEWS
index d0843d6..d5c5b8e 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ PHP                                                             
           NEWS
 ?? ??? 2013, PHP 5.5.4
 
 - Core:
+  . Improved fputcsv() to allow specifying escape character.
   . Fixed bug #65490 (Duplicate calls to get lineno & filename for 
     DTRACE_FUNCTION_*). (Chris Jones)
   . Fixed bug #65483 (quoted-printable encode stream filter incorrectly 
encoding
diff --git a/UPGRADING b/UPGRADING
index eb3bf99..39fe2d7 100755
--- a/UPGRADING
+++ b/UPGRADING
@@ -186,6 +186,9 @@ PHP 5.5 UPGRADE NOTES
   DOMDocument::schemaValidate() accept flag parameter. Only flag 
   available now is LIBXML_SCHEMA_CREATE. Default is 0.
 
+- Since 5.5.4, fputcsv() has fifth parameter escape_char, allowing to
+  specify escape char.
+
 ========================================
 5. New Functions
 ========================================
diff --git a/ext/standard/file.c b/ext/standard/file.c
index 106f5c1..ad6bdad 100644
--- a/ext/standard/file.c
+++ b/ext/standard/file.c
@@ -818,7 +818,7 @@ PHP_FUNCTION(tempnam)
        if (p_len > 64) {
                p[63] = '\0';
        }
-       
+
        RETVAL_FALSE;
 
        if ((fd = php_open_temporary_fd_ex(dir, p, &opened_path, 1 TSRMLS_CC)) 
>= 0) {
@@ -1380,13 +1380,13 @@ PHP_FUNCTION(umask)
 {
        long arg1 = 0;
        int oldumask;
-       
+
        oldumask = umask(077);
 
        if (BG(umask) == -1) {
                BG(umask) = oldumask;
        }
-       
+
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &arg1) == 
FAILURE) {
                RETURN_FALSE;
        }
@@ -1799,22 +1799,23 @@ quit_loop:
 
 #define FPUTCSV_FLD_CHK(c) memchr(Z_STRVAL(field), c, Z_STRLEN(field))
 
-/* {{{ proto int fputcsv(resource fp, array fields [, string delimiter [, 
string enclosure]])
+/* {{{ proto int fputcsv(resource fp, array fields [, string delimiter [, 
string enclosure [, string escape_char]]])
    Format line as CSV and write to file pointer */
 PHP_FUNCTION(fputcsv)
 {
-       char delimiter = ',';   /* allow this to be set as parameter */
-       char enclosure = '"';   /* allow this to be set as parameter */
-       const char escape_char = '\\';
+       char delimiter = ',';    /* allow this to be set as parameter */
+       char enclosure = '"';    /* allow this to be set as parameter */
+       char escape_char = '\\'; /* allow this to be set as parameter */
        php_stream *stream;
        zval *fp = NULL, *fields = NULL;
        int ret;
-       char *delimiter_str = NULL, *enclosure_str = NULL;
-       int delimiter_str_len = 0, enclosure_str_len = 0;
+       char *delimiter_str = NULL, *enclosure_str = NULL, *escape_str = NULL;
+       int delimiter_str_len = 0, enclosure_str_len = 0, escape_str_len = 0;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ra|ss",
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ra|sss",
                        &fp, &fields, &delimiter_str, &delimiter_str_len,
-                       &enclosure_str, &enclosure_str_len) == FAILURE) {
+                       &enclosure_str, &enclosure_str_len,
+                       &escape_str, &escape_str_len) == FAILURE) {
                return;
        }
 
@@ -1842,6 +1843,17 @@ PHP_FUNCTION(fputcsv)
                enclosure = *enclosure_str;
        }
 
+       if (escape_str != NULL) {
+               if (escape_str_len < 1) {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "escape 
must be a character");
+                       RETURN_FALSE;
+               } else if (escape_str_len > 1) {
+                       php_error_docref(NULL TSRMLS_CC, E_NOTICE, "escape must 
be a single character");
+               }
+               /* use first character from string */
+               escape_char = *escape_str;
+       }
+
        PHP_STREAM_TO_ZVAL(stream, &fp);
 
        ret = php_fputcsv(stream, fields, delimiter, enclosure, escape_char 
TSRMLS_CC);
diff --git a/ext/standard/tests/file/fputcsv_error.phpt 
b/ext/standard/tests/file/fputcsv_error.phpt
index 9403cf4..ebffd45 100644
--- a/ext/standard/tests/file/fputcsv_error.phpt
+++ b/ext/standard/tests/file/fputcsv_error.phpt
@@ -48,7 +48,7 @@ Warning: fputcsv() expects at least 2 parameters, 0 given in 
%s on line %d
 NULL
 -- Testing fputcsv() with more than expected number of arguments --
 
-Warning: fputcsv() expects at most 4 parameters, 5 given in %s on line %d
+Warning: fputcsv() expects parameter 5 to be string, resource given in %s on 
line %d
 NULL
 -- Testing fputcsv() with invalid arguments --
 -- Iteration 1 --
diff --git a/ext/standard/tests/file/fputcsv_variation15.phpt 
b/ext/standard/tests/file/fputcsv_variation15.phpt
new file mode 100755
index 0000000..dc4a9e2
--- /dev/null
+++ b/ext/standard/tests/file/fputcsv_variation15.phpt
@@ -0,0 +1,107 @@
+--TEST--
+various fputcsv() functionality tests
+--CREDITS--
+Lee Leathers <leeleath...@gmail.com>
+--FILE--
+<?php
+
+$list = array (
+  0 => 'aaa,bbb',
+  1 => 'aaa,"bbb"',
+  2 => '"aaa","bbb"',
+  3 => 'aaa,bbb',
+  4 => '"aaa",bbb',
+  5 => '"aaa",   "bbb"',
+  6 => ',',
+  7 => 'aaa,',
+  8 => ',"aaa"',
+  9 => '"",""',
+  10 => '"""""",',
+  11 => '""""",aaa',
+  12 => 'aaa,bbb   ',
+  13 => 'aaa,"bbb   "',
+  14 => 'aaa"aaa","bbb"bbb',
+  15 => 'aaa"aaa""",bbb',
+  16 => 'aaa,"/"bbb,ccc',
+  17 => 'aaa"/"a","bbb"',
+  18 => '"/"","aaa"',
+  19 => '"/""",aaa',
+);
+
+$file = dirname(__FILE__) . 'fgetcsv.csv';
+@unlink($file);
+
+$fp = fopen($file, "w");
+foreach ($list as $v) {
+       fputcsv($fp, explode(',', $v), ',', '"', '/');
+}
+fclose($fp);
+
+$res = file($file);
+foreach($res as &$val)
+{
+       $val = substr($val, 0, -1);
+}
+echo '$list = ';var_export($res);echo ";\n";
+
+$fp = fopen($file, "r");
+$res = array();
+while($l=fgetcsv($fp, 0, ',', '"', '/'))
+{
+       $res[] = join(',',$l);
+}
+fclose($fp);
+
+echo '$list = ';var_export($res);echo ";\n";
+
+@unlink($file);
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+$list = array (
+  0 => 'aaa,bbb',
+  1 => 'aaa,"""bbb"""',
+  2 => '"""aaa""","""bbb"""',
+  3 => 'aaa,bbb',
+  4 => '"""aaa""",bbb',
+  5 => '"""aaa""","   ""bbb"""',
+  6 => ',',
+  7 => 'aaa,',
+  8 => ',"""aaa"""',
+  9 => '"""""",""""""',
+  10 => '"""""""""""""",',
+  11 => '"""""""""""",aaa',
+  12 => 'aaa,"bbb   "',
+  13 => 'aaa,"""bbb   """',
+  14 => '"aaa""aaa""","""bbb""bbb"',
+  15 => '"aaa""aaa""""""",bbb',
+  16 => 'aaa,"""/"bbb",ccc',
+  17 => '"aaa""/"a""","""bbb"""',
+  18 => '"""/"""","""aaa"""',
+  19 => '"""/"""""",aaa',
+);
+$list = array (
+  0 => 'aaa,bbb',
+  1 => 'aaa,"bbb"',
+  2 => '"aaa","bbb"',
+  3 => 'aaa,bbb',
+  4 => '"aaa",bbb',
+  5 => '"aaa",   "bbb"',
+  6 => ',',
+  7 => 'aaa,',
+  8 => ',"aaa"',
+  9 => '"",""',
+  10 => '"""""",',
+  11 => '""""",aaa',
+  12 => 'aaa,bbb   ',
+  13 => 'aaa,"bbb   "',
+  14 => 'aaa"aaa","bbb"bbb',
+  15 => 'aaa"aaa""",bbb',
+  16 => 'aaa,"/"bbb,ccc',
+  17 => 'aaa"/"a","bbb"',
+  18 => '"/"","aaa"',
+  19 => '"/""",aaa',
+);
+===DONE===


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to