PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - standard - file.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 1358
Code covered: 87.9 % Executed lines: 1194
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 6                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 3.01 of the PHP license,      |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
      16                 :    |          Stig Bakken <ssb@php.net>                                   |
      17                 :    |          Andi Gutmans <andi@zend.com>                                |
      18                 :    |          Zeev Suraski <zeev@zend.com>                                |
      19                 :    | PHP 4.0 patches by Thies C. Arntzen (thies@thieso.net)               |
      20                 :    | PHP streams by Wez Furlong (wez@thebrainroom.com)                    |
      21                 :    +----------------------------------------------------------------------+
      22                 : */
      23                 : 
      24                 : /* $Id: file.c 290190 2009-11-03 21:21:34Z guenter $ */
      25                 : 
      26                 : /* Synced with php 3.0 revision 1.218 1999-06-16 [ssb] */
      27                 : 
      28                 : /* {{{ includes */
      29                 : 
      30                 : #include "php.h"
      31                 : #include "php_globals.h"
      32                 : #include "ext/standard/flock_compat.h"
      33                 : #include "ext/standard/exec.h"
      34                 : #include "ext/standard/php_filestat.h"
      35                 : #include "php_open_temporary_file.h"
      36                 : #include "ext/standard/basic_functions.h"
      37                 : #include "php_ini.h"
      38                 : #include "php_smart_str.h"
      39                 : 
      40                 : #include <stdio.h>
      41                 : #include <stdlib.h>
      42                 : #include <errno.h>
      43                 : #include <sys/types.h>
      44                 : #include <sys/stat.h>
      45                 : #include <fcntl.h>
      46                 : 
      47                 : #ifdef PHP_WIN32
      48                 : # include <io.h>
      49                 : # define O_RDONLY _O_RDONLY
      50                 : # include "win32/param.h"
      51                 : # include "win32/winutil.h"
      52                 : # include "win32/fnmatch.h"
      53                 : #else
      54                 : # if HAVE_SYS_PARAM_H
      55                 : #  include <sys/param.h>
      56                 : # endif
      57                 : # if HAVE_SYS_SELECT_H
      58                 : #  include <sys/select.h>
      59                 : # endif
      60                 : # if defined(NETWARE) && defined(USE_WINSOCK)
      61                 : #  include <novsock2.h>
      62                 : # else
      63                 : #  include <sys/socket.h>
      64                 : #  include <netinet/in.h>
      65                 : #  include <netdb.h>
      66                 : # endif
      67                 : # if HAVE_ARPA_INET_H
      68                 : #  include <arpa/inet.h>
      69                 : # endif
      70                 : #endif
      71                 : 
      72                 : #include "ext/standard/head.h"
      73                 : #include "php_string.h"
      74                 : #include "file.h"
      75                 : 
      76                 : #if HAVE_PWD_H
      77                 : # ifdef PHP_WIN32
      78                 : #  include "win32/pwd.h"
      79                 : # else
      80                 : #  include <pwd.h>
      81                 : # endif
      82                 : #endif
      83                 : 
      84                 : #ifdef HAVE_SYS_TIME_H
      85                 : # include <sys/time.h>
      86                 : #endif
      87                 : 
      88                 : #include "fsock.h"
      89                 : #include "fopen_wrappers.h"
      90                 : #include "streamsfuncs.h"
      91                 : #include "php_globals.h"
      92                 : 
      93                 : #ifdef HAVE_SYS_FILE_H
      94                 : # include <sys/file.h>
      95                 : #endif
      96                 : 
      97                 : #if MISSING_FCLOSE_DECL
      98                 : extern int fclose(FILE *);
      99                 : #endif
     100                 : 
     101                 : #ifdef HAVE_SYS_MMAN_H
     102                 : # include <sys/mman.h>
     103                 : #endif
     104                 : 
     105                 : #include "scanf.h"
     106                 : #include "zend_API.h"
     107                 : 
     108                 : #ifdef ZTS
     109                 : int file_globals_id;
     110                 : #else
     111                 : php_file_globals file_globals;
     112                 : #endif
     113                 : 
     114                 : #if defined(HAVE_FNMATCH) && !defined(PHP_WIN32)
     115                 : # ifndef _GNU_SOURCE
     116                 : #  define _GNU_SOURCE
     117                 : # endif
     118                 : # include <fnmatch.h>
     119                 : #endif
     120                 : 
     121                 : #ifdef HAVE_WCHAR_H
     122                 : # include <wchar.h>
     123                 : #endif
     124                 : 
     125                 : #ifndef S_ISDIR
     126                 : # define S_ISDIR(mode)  (((mode)&S_IFMT) == S_IFDIR)
     127                 : #endif
     128                 : /* }}} */
     129                 : 
     130                 : #define PHP_STREAM_TO_ZVAL(stream, arg) \
     131                 :         php_stream_from_zval_no_verify(stream, arg); \
     132                 :         if (stream == NULL) {   \
     133                 :                 RETURN_FALSE;   \
     134                 :         }
     135                 : 
     136                 : /* {{{ ZTS-stuff / Globals / Prototypes */
     137                 : 
     138                 : /* sharing globals is *evil* */
     139                 : static int le_stream_context = FAILURE;
     140                 : 
     141                 : PHPAPI int php_le_stream_context(void)
     142            3507 : {
     143            3507 :         return le_stream_context;
     144                 : }
     145                 : /* }}} */
     146                 : 
     147                 : /* {{{ Module-Stuff
     148                 : */
     149                 : static ZEND_RSRC_DTOR_FUNC(file_context_dtor)
     150            3095 : {
     151            3095 :         php_stream_context *context = (php_stream_context*)rsrc->ptr;
     152            3095 :         if (context->options) {
     153            3095 :                 zval_ptr_dtor(&context->options);
     154            3095 :                 context->options = NULL;
     155                 :         }
     156            3095 :         php_stream_context_free(context);
     157            3095 : }
     158                 : 
     159                 : static void file_globals_ctor(php_file_globals *file_globals_p TSRMLS_DC)
     160           17007 : {
     161           17007 :         FG(pclose_ret) = 0;
     162           17007 :         FG(user_stream_current_filename) = NULL;
     163           17007 :         FG(def_chunk_size) = PHP_SOCK_CHUNK_SIZE;
     164           17007 : }
     165                 : 
     166                 : static void file_globals_dtor(php_file_globals *file_globals_p TSRMLS_DC)
     167           17039 : {
     168           17039 : }
     169                 : 
     170                 : PHP_INI_BEGIN()
     171                 :         STD_PHP_INI_ENTRY("user_agent", NULL, PHP_INI_ALL, OnUpdateString, user_agent, php_file_globals, file_globals)
     172                 :         STD_PHP_INI_ENTRY("default_socket_timeout", "60", PHP_INI_ALL, OnUpdateLong, default_socket_timeout, php_file_globals, file_globals)
     173                 :         STD_PHP_INI_ENTRY("auto_detect_line_endings", "0", PHP_INI_ALL, OnUpdateLong, auto_detect_line_endings, php_file_globals, file_globals)
     174                 : PHP_INI_END()
     175                 : 
     176                 : PHP_MINIT_FUNCTION(file)
     177           17007 : {
     178           17007 :         le_stream_context = zend_register_list_destructors_ex(file_context_dtor, NULL, "stream-context", module_number);
     179                 : 
     180                 : #ifdef ZTS
     181                 :         ts_allocate_id(&file_globals_id, sizeof(php_file_globals), (ts_allocate_ctor) file_globals_ctor, (ts_allocate_dtor) file_globals_dtor);
     182                 : #else
     183           17007 :         file_globals_ctor(&file_globals TSRMLS_CC);
     184                 : #endif
     185                 : 
     186           17007 :         REGISTER_INI_ENTRIES();
     187                 : 
     188           17007 :         REGISTER_LONG_CONSTANT("SEEK_SET", SEEK_SET, CONST_CS | CONST_PERSISTENT);
     189           17007 :         REGISTER_LONG_CONSTANT("SEEK_CUR", SEEK_CUR, CONST_CS | CONST_PERSISTENT);
     190           17007 :         REGISTER_LONG_CONSTANT("SEEK_END", SEEK_END, CONST_CS | CONST_PERSISTENT);
     191           17007 :         REGISTER_LONG_CONSTANT("LOCK_SH", PHP_LOCK_SH, CONST_CS | CONST_PERSISTENT);
     192           17007 :         REGISTER_LONG_CONSTANT("LOCK_EX", PHP_LOCK_EX, CONST_CS | CONST_PERSISTENT);
     193           17007 :         REGISTER_LONG_CONSTANT("LOCK_UN", PHP_LOCK_UN, CONST_CS | CONST_PERSISTENT);
     194           17007 :         REGISTER_LONG_CONSTANT("LOCK_NB", PHP_LOCK_NB, CONST_CS | CONST_PERSISTENT);
     195                 : 
     196           17007 :         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_CONNECT",                       PHP_STREAM_NOTIFY_CONNECT,                      CONST_CS | CONST_PERSISTENT);
     197           17007 :         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_AUTH_REQUIRED", PHP_STREAM_NOTIFY_AUTH_REQUIRED,        CONST_CS | CONST_PERSISTENT);
     198           17007 :         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_AUTH_RESULT",           PHP_STREAM_NOTIFY_AUTH_RESULT,          CONST_CS | CONST_PERSISTENT);
     199           17007 :         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_MIME_TYPE_IS",  PHP_STREAM_NOTIFY_MIME_TYPE_IS,         CONST_CS | CONST_PERSISTENT);
     200           17007 :         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_FILE_SIZE_IS",  PHP_STREAM_NOTIFY_FILE_SIZE_IS,         CONST_CS | CONST_PERSISTENT);
     201           17007 :         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_REDIRECTED",            PHP_STREAM_NOTIFY_REDIRECTED,           CONST_CS | CONST_PERSISTENT);
     202           17007 :         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_PROGRESS",              PHP_STREAM_NOTIFY_PROGRESS,                     CONST_CS | CONST_PERSISTENT);
     203           17007 :         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_FAILURE",                       PHP_STREAM_NOTIFY_FAILURE,                      CONST_CS | CONST_PERSISTENT);
     204           17007 :         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_COMPLETED",             PHP_STREAM_NOTIFY_COMPLETED,            CONST_CS | CONST_PERSISTENT);
     205           17007 :         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_RESOLVE",                       PHP_STREAM_NOTIFY_RESOLVE,                      CONST_CS | CONST_PERSISTENT);
     206                 : 
     207           17007 :         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_SEVERITY_INFO", PHP_STREAM_NOTIFY_SEVERITY_INFO,        CONST_CS | CONST_PERSISTENT);
     208           17007 :         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_SEVERITY_WARN", PHP_STREAM_NOTIFY_SEVERITY_WARN,        CONST_CS | CONST_PERSISTENT);
     209           17007 :         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_SEVERITY_ERR",  PHP_STREAM_NOTIFY_SEVERITY_ERR,         CONST_CS | CONST_PERSISTENT);
     210                 : 
     211           17007 :         REGISTER_LONG_CONSTANT("STREAM_FILTER_READ",                  PHP_STREAM_FILTER_READ,                         CONST_CS | CONST_PERSISTENT);
     212           17007 :         REGISTER_LONG_CONSTANT("STREAM_FILTER_WRITE",                 PHP_STREAM_FILTER_WRITE,                        CONST_CS | CONST_PERSISTENT);
     213           17007 :         REGISTER_LONG_CONSTANT("STREAM_FILTER_ALL",                           PHP_STREAM_FILTER_ALL,                          CONST_CS | CONST_PERSISTENT);
     214                 : 
     215           17007 :         REGISTER_LONG_CONSTANT("STREAM_CLIENT_PERSISTENT",            PHP_STREAM_CLIENT_PERSISTENT,           CONST_CS | CONST_PERSISTENT);
     216           17007 :         REGISTER_LONG_CONSTANT("STREAM_CLIENT_ASYNC_CONNECT", PHP_STREAM_CLIENT_ASYNC_CONNECT,        CONST_CS | CONST_PERSISTENT);
     217           17007 :         REGISTER_LONG_CONSTANT("STREAM_CLIENT_CONNECT",                       PHP_STREAM_CLIENT_CONNECT,      CONST_CS | CONST_PERSISTENT);
     218                 : 
     219           17007 :         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv2_CLIENT",           STREAM_CRYPTO_METHOD_SSLv2_CLIENT,      CONST_CS|CONST_PERSISTENT);
     220           17007 :         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv3_CLIENT",           STREAM_CRYPTO_METHOD_SSLv3_CLIENT,      CONST_CS|CONST_PERSISTENT);
     221           17007 :         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv23_CLIENT",  STREAM_CRYPTO_METHOD_SSLv23_CLIENT,     CONST_CS|CONST_PERSISTENT);
     222           17007 :         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLS_CLIENT",             STREAM_CRYPTO_METHOD_TLS_CLIENT,        CONST_CS|CONST_PERSISTENT);
     223           17007 :         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv2_SERVER",           STREAM_CRYPTO_METHOD_SSLv2_SERVER,      CONST_CS|CONST_PERSISTENT);
     224           17007 :         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv3_SERVER",           STREAM_CRYPTO_METHOD_SSLv3_SERVER,      CONST_CS|CONST_PERSISTENT);
     225           17007 :         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv23_SERVER",  STREAM_CRYPTO_METHOD_SSLv23_SERVER,     CONST_CS|CONST_PERSISTENT);
     226           17007 :         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLS_SERVER",             STREAM_CRYPTO_METHOD_TLS_SERVER,        CONST_CS|CONST_PERSISTENT);
     227                 : 
     228           17007 :         REGISTER_LONG_CONSTANT("STREAM_SHUT_RD",      STREAM_SHUT_RD,         CONST_CS|CONST_PERSISTENT);
     229           17007 :         REGISTER_LONG_CONSTANT("STREAM_SHUT_WR",      STREAM_SHUT_WR,         CONST_CS|CONST_PERSISTENT);
     230           17007 :         REGISTER_LONG_CONSTANT("STREAM_SHUT_RDWR",    STREAM_SHUT_RDWR,       CONST_CS|CONST_PERSISTENT);
     231                 : 
     232                 : #ifdef PF_INET
     233           17007 :         REGISTER_LONG_CONSTANT("STREAM_PF_INET", PF_INET, CONST_CS|CONST_PERSISTENT);
     234                 : #elif defined(AF_INET)
     235                 :         REGISTER_LONG_CONSTANT("STREAM_PF_INET", AF_INET, CONST_CS|CONST_PERSISTENT);
     236                 : #endif
     237                 : 
     238                 : #ifdef PF_INET6
     239           17007 :         REGISTER_LONG_CONSTANT("STREAM_PF_INET6", PF_INET6, CONST_CS|CONST_PERSISTENT);
     240                 : #elif defined(AF_INET6)
     241                 :         REGISTER_LONG_CONSTANT("STREAM_PF_INET6", AF_INET6, CONST_CS|CONST_PERSISTENT);
     242                 : #endif
     243                 : 
     244                 : #ifdef PF_UNIX
     245           17007 :         REGISTER_LONG_CONSTANT("STREAM_PF_UNIX", PF_UNIX, CONST_CS|CONST_PERSISTENT);
     246                 : #elif defined(AF_UNIX)
     247                 :         REGISTER_LONG_CONSTANT("STREAM_PF_UNIX", AF_UNIX, CONST_CS|CONST_PERSISTENT);
     248                 : #endif
     249                 : 
     250                 : #ifdef IPPROTO_IP
     251                 :         /* most people will use this one when calling socket() or socketpair() */
     252           17007 :         REGISTER_LONG_CONSTANT("STREAM_IPPROTO_IP", IPPROTO_IP, CONST_CS|CONST_PERSISTENT);
     253                 : #endif
     254                 : 
     255                 : #ifdef IPPROTO_TCP
     256           17007 :         REGISTER_LONG_CONSTANT("STREAM_IPPROTO_TCP", IPPROTO_TCP, CONST_CS|CONST_PERSISTENT);
     257                 : #endif
     258                 : 
     259                 : #ifdef IPPROTO_UDP
     260           17007 :         REGISTER_LONG_CONSTANT("STREAM_IPPROTO_UDP", IPPROTO_UDP, CONST_CS|CONST_PERSISTENT);
     261                 : #endif
     262                 : 
     263                 : #ifdef IPPROTO_ICMP
     264           17007 :         REGISTER_LONG_CONSTANT("STREAM_IPPROTO_ICMP", IPPROTO_ICMP, CONST_CS|CONST_PERSISTENT);
     265                 : #endif
     266                 : 
     267                 : #ifdef IPPROTO_RAW
     268           17007 :         REGISTER_LONG_CONSTANT("STREAM_IPPROTO_RAW", IPPROTO_RAW, CONST_CS|CONST_PERSISTENT);
     269                 : #endif
     270                 : 
     271           17007 :         REGISTER_LONG_CONSTANT("STREAM_SOCK_STREAM", SOCK_STREAM, CONST_CS|CONST_PERSISTENT);
     272           17007 :         REGISTER_LONG_CONSTANT("STREAM_SOCK_DGRAM", SOCK_DGRAM, CONST_CS|CONST_PERSISTENT);
     273                 : 
     274                 : #ifdef SOCK_RAW
     275           17007 :         REGISTER_LONG_CONSTANT("STREAM_SOCK_RAW", SOCK_RAW, CONST_CS|CONST_PERSISTENT);
     276                 : #endif
     277                 : 
     278                 : #ifdef SOCK_SEQPACKET
     279           17007 :         REGISTER_LONG_CONSTANT("STREAM_SOCK_SEQPACKET", SOCK_SEQPACKET, CONST_CS|CONST_PERSISTENT);
     280                 : #endif
     281                 : 
     282                 : #ifdef SOCK_RDM
     283           17007 :         REGISTER_LONG_CONSTANT("STREAM_SOCK_RDM", SOCK_RDM, CONST_CS|CONST_PERSISTENT);
     284                 : #endif
     285                 : 
     286           17007 :         REGISTER_LONG_CONSTANT("STREAM_PEEK", STREAM_PEEK, CONST_CS | CONST_PERSISTENT);
     287           17007 :         REGISTER_LONG_CONSTANT("STREAM_OOB",  STREAM_OOB, CONST_CS | CONST_PERSISTENT);
     288                 : 
     289           17007 :         REGISTER_LONG_CONSTANT("STREAM_SERVER_BIND",                  STREAM_XPORT_BIND,                                      CONST_CS | CONST_PERSISTENT);
     290           17007 :         REGISTER_LONG_CONSTANT("STREAM_SERVER_LISTEN",                        STREAM_XPORT_LISTEN,                            CONST_CS | CONST_PERSISTENT);
     291                 : 
     292           17007 :         REGISTER_LONG_CONSTANT("FILE_USE_INCLUDE_PATH",                       PHP_FILE_USE_INCLUDE_PATH,                      CONST_CS | CONST_PERSISTENT);
     293           17007 :         REGISTER_LONG_CONSTANT("FILE_IGNORE_NEW_LINES",                       PHP_FILE_IGNORE_NEW_LINES,                      CONST_CS | CONST_PERSISTENT);
     294           17007 :         REGISTER_LONG_CONSTANT("FILE_SKIP_EMPTY_LINES",                       PHP_FILE_SKIP_EMPTY_LINES,                      CONST_CS | CONST_PERSISTENT);
     295           17007 :         REGISTER_LONG_CONSTANT("FILE_APPEND",                                 PHP_FILE_APPEND,                                        CONST_CS | CONST_PERSISTENT);
     296           17007 :         REGISTER_LONG_CONSTANT("FILE_NO_DEFAULT_CONTEXT",             PHP_FILE_NO_DEFAULT_CONTEXT,            CONST_CS | CONST_PERSISTENT);
     297           17007 :         REGISTER_LONG_CONSTANT("FILE_TEXT",                                           PHP_FILE_TEXT,                                          CONST_CS | CONST_PERSISTENT);
     298           17007 :         REGISTER_LONG_CONSTANT("FILE_BINARY",                                 PHP_FILE_BINARY,                                        CONST_CS | CONST_PERSISTENT);
     299                 : 
     300                 : #ifdef HAVE_FNMATCH
     301           17007 :         REGISTER_LONG_CONSTANT("FNM_NOESCAPE", FNM_NOESCAPE, CONST_CS | CONST_PERSISTENT);
     302           17007 :         REGISTER_LONG_CONSTANT("FNM_PATHNAME", FNM_PATHNAME, CONST_CS | CONST_PERSISTENT);
     303           17007 :         REGISTER_LONG_CONSTANT("FNM_PERIOD",   FNM_PERIOD,   CONST_CS | CONST_PERSISTENT);
     304                 : # ifdef FNM_CASEFOLD /* a GNU extension */ /* TODO emulate if not available */
     305           17007 :         REGISTER_LONG_CONSTANT("FNM_CASEFOLD", FNM_CASEFOLD, CONST_CS | CONST_PERSISTENT);
     306                 : # endif
     307                 : #endif
     308                 : 
     309           17007 :         return SUCCESS;
     310                 : }
     311                 : /* }}} */
     312                 : 
     313                 : PHP_MSHUTDOWN_FUNCTION(file) /* {{{ */
     314           17039 : {
     315                 : #ifndef ZTS
     316           17039 :         file_globals_dtor(&file_globals TSRMLS_CC);
     317                 : #endif
     318           17039 :         return SUCCESS;
     319                 : }
     320                 : /* }}} */
     321                 : 
     322                 : static int flock_values[] = { LOCK_SH, LOCK_EX, LOCK_UN };
     323                 : 
     324                 : /* {{{ proto bool flock(resource fp, int operation [, int &wouldblock]) U
     325                 :    Portable file locking */
     326                 : PHP_FUNCTION(flock)
     327             193 : {
     328             193 :         zval *arg1, *arg3 = NULL;
     329                 :         int act;
     330                 :         php_stream *stream;
     331             193 :         long operation = 0;
     332                 : 
     333             193 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|z", &arg1, &operation, &arg3) == FAILURE) {
     334              10 :                 return;
     335                 :         }
     336                 : 
     337             183 :         PHP_STREAM_TO_ZVAL(stream, &arg1);
     338                 : 
     339             181 :         act = operation & 3;
     340             181 :         if (act < 1 || act > 3) {
     341               6 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal operation argument");
     342               6 :                 RETURN_FALSE;
     343                 :         }
     344                 : 
     345             175 :         if (arg3 && PZVAL_IS_REF(arg3)) {
     346             144 :                 convert_to_long_ex(&arg3);
     347             144 :                 Z_LVAL_P(arg3) = 0;
     348                 :         }
     349                 : 
     350                 :         /* flock_values contains all possible actions if (operation & 4) we won't block on the lock */
     351             175 :         act = flock_values[act - 1] | (operation & PHP_LOCK_NB ? LOCK_NB : 0);
     352             175 :         if (php_stream_lock(stream, act)) {
     353              12 :                 if (operation && errno == EWOULDBLOCK && arg3 && PZVAL_IS_REF(arg3)) {
     354               0 :                         Z_LVAL_P(arg3) = 1;
     355                 :                 }
     356              12 :                 RETURN_FALSE;
     357                 :         }
     358             163 :         RETURN_TRUE;
     359                 : }
     360                 : /* }}} */
     361                 : 
     362                 : #define PHP_META_UNSAFE ".\\+*?[^]$() "
     363                 : 
     364                 : /* {{{ proto array get_meta_tags(string filename [, bool use_include_path]) U
     365                 :    Extracts all meta tag content attributes from a file and returns an array */
     366                 : PHP_FUNCTION(get_meta_tags)
     367               8 : {
     368                 :         zval **ppfilename;
     369                 :         char *filename;
     370                 :         int filename_len;
     371               8 :         zend_bool use_include_path = 0;
     372               8 :         int in_tag = 0, done = 0;
     373               8 :         int looking_for_val = 0, have_name = 0, have_content = 0;
     374               8 :         int saw_name = 0, saw_content = 0;
     375               8 :         char *name = NULL, *value = NULL, *temp = NULL;
     376                 :         php_meta_tags_token tok, tok_last;
     377                 :         php_meta_tags_data md;
     378                 : 
     379                 :         /* Initiailize our structure */
     380               8 :         memset(&md, 0, sizeof(md));
     381                 : 
     382                 :         /* Parse arguments */
     383               8 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|b", &ppfilename, &use_include_path) == FAILURE ||
     384                 :                 php_stream_path_param_encode(ppfilename, &filename, &filename_len, REPORT_ERRORS, FG(default_context)) == FAILURE) {
     385               0 :                 return;
     386                 :         }
     387                 : 
     388               8 :         md.stream = php_stream_open_wrapper(filename, "rt",
     389                 :                         (use_include_path ? USE_PATH : 0) | REPORT_ERRORS,
     390                 :                         NULL);
     391               8 :         if (!md.stream) {
     392               0 :                 RETURN_FALSE;
     393                 :         }
     394                 : 
     395               8 :         if (md.stream->readbuf_type == IS_UNICODE) {
     396                 :                 /* Either stream auto-applied encoding (which http:// wrapper does do)
     397                 :                  * Or the streams layer unicodified it for us */
     398                 :                 zval *filterparams;
     399                 :                 php_stream_filter *filter;
     400                 : 
     401                 :                 /* Be lazy and convert contents to utf8 again
     402                 :                  * This could be made more efficient by detecting if
     403                 :                  * it's being upconverted from utf8 and cancelling all conversion
     404                 :                  * rather than reconverting, but this is a silly function anyway */
     405                 : 
     406               8 :                 MAKE_STD_ZVAL(filterparams);
     407               8 :                 array_init(filterparams);
     408               8 :                 add_ascii_assoc_long(filterparams, "error_mode", UG(from_error_mode));
     409               8 :                 add_ascii_assoc_unicode(filterparams, "subst_char", UG(from_subst_char), 1);
     410               8 :                 filter = php_stream_filter_create("unicode.to.utf8", filterparams, 0 TSRMLS_CC);
     411               8 :                 zval_ptr_dtor(&filterparams);
     412                 : 
     413               8 :                 if (!filter) {
     414               0 :                         php_stream_close(md.stream);
     415               0 :                         RETURN_FALSE;
     416                 :                 }
     417               8 :                 php_stream_filter_append(&md.stream->readfilters, filter);
     418                 :         }
     419                 : 
     420               8 :         array_init(return_value);
     421                 : 
     422               8 :         tok_last = TOK_EOF;
     423                 : 
     424             220 :         while (!done && (tok = php_next_meta_token(&md TSRMLS_CC)) != TOK_EOF) {
     425             204 :                 if (tok == TOK_ID) {
     426              45 :                         if (tok_last == TOK_OPENTAG) {
     427              17 :                                 md.in_meta = !strcasecmp("meta", md.token_data);
     428              30 :                         } else if (tok_last == TOK_SLASH && in_tag) {
     429               2 :                                 if (strcasecmp("head", md.token_data) == 0) {
     430                 :                                         /* We are done here! */
     431               2 :                                         done = 1;
     432                 :                                 }
     433              26 :                         } else if (tok_last == TOK_EQUAL && looking_for_val) {
     434               0 :                                 if (saw_name) {
     435               0 :                                         STR_FREE(name);
     436                 :                                         /* Get the NAME attr (Single word attr, non-quoted) */
     437               0 :                                         temp = name = estrndup(md.token_data, md.token_len);
     438                 : 
     439               0 :                                         while (temp && *temp) {
     440               0 :                                                 if (strchr(PHP_META_UNSAFE, *temp)) {
     441               0 :                                                         *temp = '_';
     442                 :                                                 }
     443               0 :                                                 temp++;
     444                 :                                         }
     445                 : 
     446               0 :                                         have_name = 1;
     447               0 :                                 } else if (saw_content) {
     448               0 :                                         STR_FREE(value);
     449                 :                                         /* Get the CONTENT attr (Single word attr, non-quoted) */
     450               0 :                                         value = estrndup(md.token_data, md.token_len);
     451                 : 
     452               0 :                                         have_content = 1;
     453                 :                                 }
     454                 : 
     455               0 :                                 looking_for_val = 0;
     456                 :                         } else {
     457              26 :                                 if (md.in_meta) {
     458              26 :                                         if (strcasecmp("name", md.token_data) == 0) {
     459              13 :                                                 saw_name = 1;
     460              13 :                                                 saw_content = 0;
     461              13 :                                                 looking_for_val = 1;
     462              13 :                                         } else if (strcasecmp("content", md.token_data) == 0) {
     463              13 :                                                 saw_name = 0;
     464              13 :                                                 saw_content = 1;
     465              13 :                                                 looking_for_val = 1;
     466                 :                                         }
     467                 :                                 }
     468                 :                         }
     469             185 :                 } else if (tok == TOK_STRING && tok_last == TOK_EQUAL && looking_for_val) {
     470              26 :                         if (saw_name) {
     471              13 :                                 STR_FREE(name);
     472                 :                                 /* Get the NAME attr (Quoted single/double) */
     473              13 :                                 temp = name = estrndup(md.token_data, md.token_len);
     474                 : 
     475             136 :                                 while (temp && *temp) {
     476             110 :                                         if (strchr(PHP_META_UNSAFE, *temp)) {
     477               2 :                                                 *temp = '_';
     478                 :                                         }
     479             110 :                                         temp++;
     480                 :                                 }
     481                 : 
     482              13 :                                 have_name = 1;
     483              13 :                         } else if (saw_content) {
     484              13 :                                 STR_FREE(value);
     485                 :                                 /* Get the CONTENT attr (Single word attr, non-quoted) */
     486              13 :                                 value = estrndup(md.token_data, md.token_len);
     487                 : 
     488              13 :                                 have_content = 1;
     489                 :                         }
     490                 : 
     491              26 :                         looking_for_val = 0;
     492             133 :                 } else if (tok == TOK_OPENTAG) {
     493              25 :                         if (looking_for_val) {
     494               0 :                                 looking_for_val = 0;
     495               0 :                                 have_name = saw_name = 0;
     496               0 :                                 have_content = saw_content = 0;
     497                 :                         }
     498              25 :                         in_tag = 1;
     499             108 :                 } else if (tok == TOK_CLOSETAG) {
     500              13 :                         if (have_name) {
     501                 :                                 /* For BC */
     502              10 :                                 php_strtolower(name, strlen(name));
     503              10 :                                 if (have_content) {
     504              10 :                                         add_assoc_utf8_string(return_value, name, value, 1);
     505                 :                                 } else {
     506               0 :                                         add_assoc_utf8_string(return_value, name, "", 1);
     507                 :                                 }
     508                 : 
     509              10 :                                 efree(name);
     510              10 :                                 STR_FREE(value);
     511               3 :                         } else if (have_content) {
     512               0 :                                 efree(value);
     513                 :                         }
     514                 : 
     515              13 :                         name = value = NULL;
     516                 : 
     517                 :                         /* Reset all of our flags */
     518              13 :                         in_tag = looking_for_val = 0;
     519              13 :                         have_name = saw_name = 0;
     520              13 :                         have_content = saw_content = 0;
     521              13 :                         md.in_meta = 0;
     522                 :                 }
     523                 : 
     524             204 :                 tok_last = tok;
     525                 : 
     526             204 :                 if (md.token_data)
     527              71 :                         efree(md.token_data);
     528                 : 
     529             204 :                 md.token_data = NULL;
     530                 :         }
     531                 : 
     532               8 :         STR_FREE(value);
     533               8 :         STR_FREE(name);
     534               8 :         php_stream_close(md.stream);
     535                 : }
     536                 : /* }}} */
     537                 : 
     538                 : /* {{{ proto string file_get_contents(string filename [, long flags [, resource context [, long offset [, long maxlen]]]]) U
     539                 :    Read the entire file into a string */
     540                 : PHP_FUNCTION(file_get_contents)
     541            2281 : {
     542                 :         zval **ppfilename;
     543                 :         char *filename;
     544                 :         int filename_len;
     545            2281 :         void *contents = NULL;
     546            2281 :         long flags = 0;
     547                 :         php_stream *stream;
     548                 :         int len;
     549            2281 :         long offset = -1;
     550            2281 :         long maxlen = PHP_STREAM_COPY_ALL, real_maxlen;
     551            2281 :         zval *zcontext = NULL;
     552            2281 :         php_stream_context *context = NULL;
     553                 : 
     554                 :         /* Parse arguments */
     555            2281 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|lr!ll", &ppfilename, &flags, &zcontext, &offset, &maxlen) == FAILURE) {
     556              65 :                 return;
     557                 :         }
     558                 : 
     559            2216 :         if (ZEND_NUM_ARGS() == 5 && maxlen < 0) {
     560               5 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "length must be greater than or equal to zero");
     561               5 :                 RETURN_FALSE;
     562                 :         }
     563                 : 
     564            2211 :         context = php_stream_context_from_zval(zcontext, 0);
     565            2211 :         if (php_stream_path_param_encode(ppfilename, &filename, &filename_len, REPORT_ERRORS, context) == FAILURE) {
     566               0 :                 RETURN_FALSE;
     567                 :         }
     568                 : 
     569            2211 :         stream = php_stream_open_wrapper_ex(filename, (flags & PHP_FILE_TEXT) ? "rt" : "rb",
     570                 :                                 ((flags & PHP_FILE_USE_INCLUDE_PATH) ? USE_PATH : 0) | REPORT_ERRORS,
     571                 :                                 NULL, context);
     572            2211 :         if (!stream) {
     573              54 :                 RETURN_FALSE;
     574                 :         }
     575                 : 
     576            2157 :         if (offset > 0 && php_stream_seek(stream, offset, SEEK_SET) < 0) {
     577               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to seek to position %ld in the stream", offset);
     578               1 :                 php_stream_close(stream);
     579               1 :                 RETURN_FALSE;
     580                 :         }
     581                 : 
     582            4312 :         if (maxlen <= 0 || stream->readbuf_type == IS_STRING) {
     583            2156 :                 real_maxlen = maxlen;
     584                 :         } else {
     585                 :                 /* Allows worst case scenario of each input char being turned into two UChars
     586                 :                  * UTODO: Have this take converter into account, since many never generate surrogate pairs */
     587               0 :                 real_maxlen = maxlen * 2;
     588                 :         }
     589                 : 
     590                 :         /* uses mmap if possible */
     591            2156 :         len = php_stream_copy_to_mem_ex(stream, stream->readbuf_type, &contents, real_maxlen, maxlen, 0);
     592                 : 
     593            2156 :         if (stream->readbuf_type == IS_STRING) {
     594            2153 :                 if (len > 0) {
     595            1776 :                         RETVAL_STRINGL(contents, len, 0);
     596                 :                 } else {
     597             377 :                         if (contents) {
     598               0 :                                 efree(contents);
     599                 :                         }
     600             377 :                         RETVAL_EMPTY_STRING();
     601                 :                 }
     602                 :         } else {
     603               3 :                 if (len > 0) {
     604               3 :                         RETVAL_UNICODEL(contents, len, 0);
     605                 :                 } else {
     606               0 :                         if (contents) {
     607               0 :                                 efree(contents);
     608                 :                         }
     609               0 :                         RETVAL_EMPTY_UNICODE();
     610                 :                 }
     611                 :         }
     612                 : 
     613            2156 :         php_stream_close(stream);
     614                 : }
     615                 : /* }}} */
     616                 : 
     617                 : /* {{{ proto int file_put_contents(string file, mixed data [, int flags [, resource context]]) U
     618                 :    Write/Create a file with contents data and return the number of bytes written */
     619                 : PHP_FUNCTION(file_put_contents)
     620           24363 : {
     621           24363 :         int argc = ZEND_NUM_ARGS();
     622                 :         php_stream *stream;
     623                 :         zval **ppfilename;
     624                 :         char *filename;
     625                 :         int filename_len;
     626                 :         zval *data;
     627           24363 :         int numchars = 0;
     628           24363 :         long flags = (argc < 3) ? PHP_FILE_TEXT : 0;
     629           24363 :         zval *zcontext = NULL;
     630           24363 :         php_stream_context *context = NULL;
     631           24363 :         char mode[3] = { 'w', 0, 0 };
     632           24363 :         php_stream *srcstream = NULL;
     633                 : 
     634           24363 :         if (zend_parse_parameters(argc TSRMLS_CC, "Zz/|lr!", &ppfilename, &data, &flags, &zcontext) == FAILURE) {
     635              28 :                 return;
     636                 :         }
     637                 : 
     638           24335 :         if (Z_TYPE_P(data) == IS_RESOURCE) {
     639               1 :                 php_stream_from_zval(srcstream, &data);
     640                 :         }
     641                 : 
     642           24334 :         context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
     643           24334 :         if (php_stream_path_param_encode(ppfilename, &filename, &filename_len, REPORT_ERRORS, context) == FAILURE) {
     644               0 :                 RETURN_FALSE;
     645                 :         }
     646                 : 
     647           24334 :         if (flags & PHP_FILE_APPEND) {
     648               8 :                 mode[0] = 'a';
     649                 :         }
     650           44190 :         if (flags & PHP_FILE_BINARY || (Z_TYPE_P(data) == IS_STRING)) {
     651           19856 :                 mode[1] = 'b';
     652            4478 :         } else if (flags & PHP_FILE_TEXT) {
     653            4465 :                 mode[1] = 't';
     654                 :         }
     655                 : 
     656           24334 :         stream = php_stream_open_wrapper_ex(filename, mode,
     657                 :                         ((flags & PHP_FILE_USE_INCLUDE_PATH) ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
     658           24334 :         if (stream == NULL) {
     659              21 :                 RETURN_FALSE;
     660                 :         }
     661                 : 
     662           24313 :         if (flags & LOCK_EX && (!php_stream_supports_lock(stream) || php_stream_lock(stream, LOCK_EX))) {
     663               0 :                 php_stream_close(stream);
     664               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Exclusive locks are not supported for this stream");
     665               0 :                 RETURN_FALSE;
     666                 :         }
     667                 : 
     668           24313 :         switch (Z_TYPE_P(data)) {
     669                 :                 case IS_RESOURCE: {
     670                 :                         size_t len;
     671               0 :                         if (php_stream_copy_to_stream_ex(srcstream, stream, PHP_STREAM_COPY_ALL, &len) != SUCCESS) {
     672               0 :                                 numchars = -1;
     673                 :                         } else {
     674               0 :                                 numchars = len;
     675                 :                         }
     676               0 :                         break;
     677                 :                 }
     678                 :                 case IS_ARRAY:
     679               6 :                         if (zend_hash_num_elements(Z_ARRVAL_P(data))) {
     680                 :                                 zval **tmp;
     681                 :                                 HashPosition pos;
     682                 : 
     683               5 :                                 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(data), &pos);
     684              75 :                                 while (zend_hash_get_current_data_ex(Z_ARRVAL_P(data), (void **) &tmp, &pos) == SUCCESS) {
     685              65 :                                         if (Z_TYPE_PP(tmp) == IS_UNICODE) {
     686               3 :                                                 int ustrlen = u_countChar32(Z_USTRVAL_PP(tmp), Z_USTRLEN_PP(tmp));
     687               3 :                                                 int wrote_u16 = php_stream_write_unicode(stream, Z_USTRVAL_PP(tmp), Z_USTRLEN_PP(tmp));
     688               3 :                                                 if (wrote_u16 < 0) {
     689               0 :                                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write %d characters to %s", ustrlen, filename);
     690               0 :                                                         numchars = -1;
     691               0 :                                                         break;
     692               3 :                                                 } else if (wrote_u16 != Z_USTRLEN_PP(tmp)) {
     693               0 :                                                         int numchars = u_countChar32(Z_USTRVAL_PP(tmp), wrote_u16);
     694                 : 
     695               0 :                                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %d of %d characters written, possibly out of free disk space", numchars, ustrlen);
     696               0 :                                                         numchars = -1;
     697               0 :                                                         break;
     698                 :                                                 }
     699               3 :                                                 numchars += ustrlen;
     700                 :                                         } else { /* non-unicode */
     701              62 :                                                 int free_val = 0;
     702              62 :                                                 zval strval = **tmp;
     703                 :                                                 int wrote_bytes;
     704                 : 
     705              62 :                                                 if (Z_TYPE(strval) != IS_STRING) {
     706              12 :                                                         zval_copy_ctor(&strval);
     707              12 :                                                         convert_to_string(&strval);
     708              12 :                                                         free_val = 1;
     709                 :                                                 }
     710              62 :                                                 if (Z_STRLEN(strval)) {
     711              61 :                                                         numchars += Z_STRLEN(strval);
     712              61 :                                                         wrote_bytes = php_stream_write(stream, Z_STRVAL(strval), Z_STRLEN(strval));
     713              61 :                                                         if (wrote_bytes < 0) {
     714               0 :                                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write %d bytes to %s", Z_STRLEN(strval), filename);
     715               0 :                                                                 numchars = -1;
     716               0 :                                                                 break;
     717                 :                                                         }
     718              61 :                                                         if (wrote_bytes != Z_STRLEN(strval)) {
     719               0 :                                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %d of %d bytes written, possibly out of free disk space", wrote_bytes, Z_STRLEN(strval));
     720               0 :                                                                 numchars = -1;
     721               0 :                                                                 break;
     722                 :                                                         }
     723                 :                                                 }
     724              62 :                                                 if (free_val) {
     725              12 :                                                         zval_dtor(&strval);
     726                 :                                                 }
     727                 :                                         }
     728              65 :                                         zend_hash_move_forward_ex(Z_ARRVAL_P(data), &pos);
     729                 :                                 }
     730                 :                         }
     731               6 :                         break;
     732                 :                 case IS_OBJECT:
     733                 :                         /* TODO */
     734               3 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "2nd parameter must be non-object (for now)");
     735               3 :                         numchars = -1;
     736               3 :                         break;
     737                 :                 case IS_UNICODE:
     738            4425 :                         if (Z_USTRLEN_P(data)) {
     739             319 :                                 int ustrlen = u_countChar32(Z_USTRVAL_P(data), Z_USTRLEN_P(data));
     740             319 :                                 int wrote_u16 = php_stream_write_unicode(stream, Z_USTRVAL_P(data), Z_USTRLEN_P(data));
     741                 : 
     742             319 :                                 numchars = ustrlen;
     743             319 :                                 if (wrote_u16 < 0) {
     744               0 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write %d characters to %s", ustrlen, filename);
     745               0 :                                         numchars = -1;
     746             319 :                                 } else if (wrote_u16 != Z_USTRLEN_P(data)) {
     747               0 :                                         int written_numchars = u_countChar32(Z_USTRVAL_P(data), wrote_u16);
     748                 : 
     749               0 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %d of %d characters written, possibly out of free disk space", written_numchars, ustrlen);
     750               0 :                                         numchars = -1;
     751                 :                                 }
     752                 :                         }
     753            4425 :                         break;
     754                 :                 case IS_NULL:
     755                 :                 case IS_LONG:
     756                 :                 case IS_DOUBLE:
     757                 :                 case IS_BOOL:
     758                 :                 case IS_CONSTANT:
     759                 :                 case IS_STRING:
     760                 :                 default:
     761           19879 :                         if (Z_TYPE_P(data) != IS_STRING) {
     762              27 :                                 convert_to_string_ex(&data);
     763                 :                         }
     764           19879 :                         if (Z_STRLEN_P(data)) {
     765           19870 :                                 numchars = php_stream_write(stream, Z_STRVAL_P(data), Z_STRLEN_P(data));
     766           19870 :                                 if (numchars != Z_STRLEN_P(data)) {
     767               0 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %d of %d bytes written, possibly out of free disk space", numchars, Z_STRLEN_P(data));
     768               0 :                                         numchars = -1;
     769                 :                                 }
     770                 :                         }
     771                 :                         break;
     772                 :         }
     773           24313 :         php_stream_close(stream);
     774                 : 
     775           24313 :         if (numchars < 0) {
     776               3 :                 RETURN_FALSE;
     777                 :         }
     778                 : 
     779           24310 :         RETURN_LONG(numchars);
     780                 : }
     781                 : /* }}} */
     782                 : 
     783                 : #define PHP_FILE_BUF_SIZE       80
     784                 : 
     785                 : /* {{{ proto array file(string filename [, int flags[, resource context]]) U
     786                 :    Read entire file into an array */
     787                 : PHP_FUNCTION(file)
     788             242 : {
     789                 :         zval **ppfilename;
     790                 :         char *filename;
     791                 :         int filename_len;
     792             242 :         char *target_buf=NULL;
     793             242 :         register int i = 0;
     794                 :         int target_len;
     795             242 :         long flags = 0;
     796                 :         zend_bool use_include_path;
     797                 :         zend_bool include_new_line;
     798                 :         zend_bool skip_blank_lines;
     799                 :         zend_bool text_mode;
     800                 :         php_stream *stream;
     801             242 :         zval *zcontext = NULL;
     802             242 :         php_stream_context *context = NULL;
     803                 : 
     804                 :         /* Parse arguments */
     805             242 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|lr!", &ppfilename, &flags, &zcontext) == FAILURE) {
     806              40 :                 return;
     807                 :         }
     808             202 :         if (flags < 0 || flags > (PHP_FILE_USE_INCLUDE_PATH | PHP_FILE_IGNORE_NEW_LINES | PHP_FILE_SKIP_EMPTY_LINES | PHP_FILE_NO_DEFAULT_CONTEXT | PHP_FILE_TEXT | PHP_FILE_BINARY)) {
     809               3 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%ld' flag is not supported", flags);
     810               3 :                 RETURN_FALSE;
     811                 :         }
     812                 : 
     813             199 :         use_include_path = flags & PHP_FILE_USE_INCLUDE_PATH;
     814             199 :         include_new_line = !(flags & PHP_FILE_IGNORE_NEW_LINES);
     815             199 :         skip_blank_lines = flags & PHP_FILE_SKIP_EMPTY_LINES;
     816             199 :         text_mode = !(flags & PHP_FILE_BINARY);
     817                 : 
     818             199 :         context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
     819             199 :         if (php_stream_path_param_encode(ppfilename, &filename, &filename_len, REPORT_ERRORS, context) == FAILURE) {
     820               0 :                 RETURN_FALSE;
     821                 :         }
     822                 : 
     823             199 :         stream = php_stream_open_wrapper_ex(filename, text_mode ? "rt" : "rb", (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
     824             199 :         if (!stream) {
     825              91 :                 RETURN_FALSE;
     826                 :         }
     827                 : 
     828                 :         /* Initialize return array */
     829             108 :         array_init(return_value);
     830                 : 
     831             108 :         target_len = php_stream_copy_to_mem_ex(stream, stream->readbuf_type, (void**)&target_buf, PHP_STREAM_COPY_ALL, -1, 0);
     832                 : 
     833             108 :         if (!target_len) {
     834                 :                 /* Empty file, do nothing and return an empty array */
     835             105 :         } else if (stream->readbuf_type == IS_UNICODE) {
     836             102 :                 UChar *s = (UChar*)target_buf, *p;
     837             102 :                 UChar *e = s + target_len, eol_marker = '\n';
     838                 : 
     839             102 :                 if (!(p = php_stream_locate_eol(stream, ZSTR(target_buf), target_len TSRMLS_CC))) {
     840              20 :                         p = e;
     841              20 :                         goto uparse_eol;
     842                 :                 }
     843                 : 
     844              82 :                 if (stream->flags & PHP_STREAM_FLAG_EOL_MAC) {
     845               0 :                         eol_marker = '\r';
     846                 :                 }
     847                 : 
     848                 :                 /* for performance reasons the code is quadruplicated, so that the if (include_new_line/unicode
     849                 :                  * will not need to be done for every single line in the file. */
     850              82 :                 if (include_new_line) {
     851                 :                         do {
     852             316 :                                 p++;
     853             403 : uparse_eol:
     854             403 :                                 add_index_unicodel(return_value, i++, eustrndup(s, p-s), p-s, 0);
     855             403 :                                 s = p;
     856             403 :                         } while ((p = u_memchr(p, eol_marker, (e-p))));
     857                 :                 } else {
     858                 :                         do {
     859              67 :                                 int windows_eol = 0;
     860              67 :                                 if (p != (UChar*)target_buf && eol_marker == '\n' && *(p - 1) == '\r') {
     861               6 :                                         windows_eol++;
     862                 :                                 }
     863              67 :                                 if (skip_blank_lines && !(p-s-windows_eol)) {
     864               1 :                                         s = ++p;
     865               1 :                                         continue;
     866                 :                                 }
     867              66 :                                 add_index_unicodel(return_value, i++, eustrndup(s, p-s-windows_eol), p-s-windows_eol, 0);
     868              66 :                                 s = ++p;
     869              67 :                         } while ((p = u_memchr(p, eol_marker, (e-p))));
     870                 :                 }
     871                 : 
     872                 :                 /* handle any left overs of files without new lines */
     873             169 :                 if (s != e) {
     874              67 :                         p = e;
     875              67 :                         goto uparse_eol;
     876                 :                 }
     877                 : 
     878                 :         } else { /* !IS_UNICODE */
     879               3 :                 char *s = target_buf, *p;
     880               3 :                 char *e = target_buf + target_len, eol_marker = '\n';
     881                 : 
     882               3 :                 if (!(p = php_stream_locate_eol(stream, ZSTR(target_buf), target_len TSRMLS_CC))) {
     883               0 :                         p = e;
     884               0 :                         goto parse_eol;
     885                 :                 }
     886                 : 
     887               3 :                 if (stream->flags & PHP_STREAM_FLAG_EOL_MAC) {
     888               0 :                         eol_marker = '\r';
     889                 :                 }
     890                 : 
     891               3 :                 if (include_new_line) {
     892                 :                         do {
     893               0 :                                 p++;
     894               1 : parse_eol:
     895               1 :                                 add_index_stringl(return_value, i++, estrndup(s, p-s), p-s, 0);
     896               1 :                                 s = p;
     897               1 :                         } while ((p = memchr(p, eol_marker, (e-p))));
     898                 :                 } else {
     899                 :                         do {
     900               6 :                                 int windows_eol = 0;
     901               6 :                                 if (p != target_buf && eol_marker == '\n' && *(p - 1) == '\r') {
     902               0 :                                         windows_eol++;
     903                 :                                 }
     904               6 :                                 if (skip_blank_lines && !(p-s-windows_eol)) {
     905               0 :                                         s = ++p;
     906               0 :                                         continue;
     907                 :                                 }
     908               6 :                                 add_index_stringl(return_value, i++, estrndup(s, p-s-windows_eol), p-s-windows_eol, 0);
     909               6 :                                 s = ++p;
     910               6 :                         } while ((p = memchr(p, eol_marker, (e-p))));
     911                 :                 }
     912                 : 
     913                 :                 /* handle any left overs of files without new lines */
     914               4 :                 if (s != e) {
     915               1 :                         p = e;
     916               1 :                         goto parse_eol;
     917                 :                 }
     918                 :         }
     919                 : 
     920             108 :         if (target_buf) {
     921             105 :                 efree(target_buf);
     922                 :         }
     923             108 :         php_stream_close(stream);
     924                 : }
     925                 : /* }}} */
     926                 : 
     927                 : /* {{{ proto string tempnam(string dir, string prefix) U
     928                 :    Create a unique filename in a directory */
     929                 : PHP_FUNCTION(tempnam)
     930             700 : {
     931                 :         zval **ppdir, **ppprefix;
     932                 :         char *dir, *prefix;
     933                 :         int dir_len, tmp_prefix_len;
     934                 :         char *opened_path;
     935                 :         char *p;
     936                 :         int fd;
     937                 :         size_t p_len, prefix_len;
     938                 : 
     939             700 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &ppdir, &ppprefix) == FAILURE) {
     940               7 :                 return;
     941                 :         }
     942                 : 
     943             693 :         if (php_stream_path_param_encode(ppdir, &dir, &dir_len, REPORT_ERRORS, FG(default_context)) == FAILURE ||
     944                 :                 php_stream_path_param_encode(ppprefix, &prefix, &tmp_prefix_len, REPORT_ERRORS, FG(default_context)) == FAILURE) {
     945               0 :                 RETURN_FALSE;
     946                 :         }
     947                 : 
     948             693 :         if (php_check_open_basedir(dir TSRMLS_CC)) {
     949               7 :                 RETURN_FALSE;
     950                 :         }
     951                 : 
     952             686 :         prefix_len = tmp_prefix_len;
     953             686 :         php_basename(prefix, prefix_len, NULL, 0, &p, &p_len TSRMLS_CC);
     954             686 :         if (p_len > 64) {
     955               0 :                 p[63] = '\0';
     956                 :         }
     957                 :         
     958             686 :         RETVAL_FALSE;
     959                 : 
     960             686 :         if ((fd = php_open_temporary_fd(dir, p, &opened_path TSRMLS_CC)) >= 0) {
     961                 :                 UChar *utmpnam;
     962                 :                 int utmpnam_len;
     963                 : 
     964             686 :                 close(fd);
     965                 : 
     966             686 :                 if (SUCCESS == php_stream_path_decode(NULL, &utmpnam, &utmpnam_len, opened_path, strlen(opened_path), REPORT_ERRORS, FG(default_context))) {
     967             686 :                         RETVAL_UNICODEL(utmpnam, utmpnam_len, 0);
     968                 :                 }
     969             686 :                 efree(opened_path);
     970                 :         }
     971             686 :         efree(p);
     972                 : }
     973                 : /* }}} */
     974                 : 
     975                 : /* {{{ proto resource tmpfile(void) U
     976                 :    Create a temporary file that will be deleted automatically after use */
     977                 : PHP_NAMED_FUNCTION(php_if_tmpfile)
     978              68 : {
     979                 :         php_stream *stream;
     980                 : 
     981              68 :         if (zend_parse_parameters_none() == FAILURE) {
     982               0 :                 return;
     983                 :         }
     984                 : 
     985              68 :         stream = php_stream_fopen_tmpfile();
     986                 : 
     987              68 :         if (stream) {
     988              68 :                 php_stream_to_zval(stream, return_value);
     989                 :         } else {
     990               0 :                 RETURN_FALSE;
     991                 :         }
     992                 : }
     993                 : /* }}} */
     994                 : 
     995                 : /* {{{ proto resource fopen(string filename, string mode [, bool use_include_path [, resource context]]) U
     996                 :    Open a file or a URL and return a file pointer */
     997                 : PHP_NAMED_FUNCTION(php_if_fopen)
     998           21885 : {
     999                 :         zval **ppfilename;
    1000                 :         char *filename, *mode;
    1001                 :         int filename_len, mode_len;
    1002           21885 :         zend_bool use_include_path = 0;
    1003           21885 :         zval *zcontext = NULL;
    1004                 :         php_stream *stream;
    1005           21885 :         php_stream_context *context = NULL;
    1006                 : 
    1007           21885 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs|br", &ppfilename, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) {
    1008              40 :                 RETURN_FALSE;
    1009                 :         }
    1010                 : 
    1011           21845 :         context = php_stream_context_from_zval(zcontext, 0);
    1012                 : 
    1013           21845 :         if (FAILURE == php_stream_path_param_encode(ppfilename, &filename, &filename_len, REPORT_ERRORS, context)) {
    1014               1 :                 RETURN_FALSE;
    1015                 :         }
    1016                 : 
    1017           21844 :         stream = php_stream_open_wrapper_ex(filename, mode, (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
    1018           21843 :         if (stream == NULL) {
    1019              87 :                 RETURN_FALSE;
    1020                 :         }
    1021                 : 
    1022           21756 :         php_stream_to_zval(stream, return_value);
    1023                 : }
    1024                 : /* }}} */
    1025                 : 
    1026                 : /* {{{ proto bool fclose(resource fp) U
    1027                 :    Close an open file pointer */
    1028                 : PHPAPI PHP_FUNCTION(fclose)
    1029           38503 : {
    1030                 :         zval *arg1;
    1031                 :         php_stream *stream;
    1032                 : 
    1033           38503 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
    1034              36 :                 return;
    1035                 :         }
    1036                 : 
    1037           38467 :         PHP_STREAM_TO_ZVAL(stream, &arg1);
    1038                 : 
    1039           38466 :         if ((stream->flags & PHP_STREAM_FLAG_NO_FCLOSE) != 0) {
    1040               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%d is not a valid stream resource", stream->rsrc_id);
    1041               0 :                 RETURN_FALSE;
    1042                 :         }
    1043                 : 
    1044           38466 :         if (!stream->is_persistent) {
    1045           38466 :                 zend_list_delete(stream->rsrc_id);
    1046                 :         } else {
    1047               0 :                 php_stream_pclose(stream);
    1048                 :         }
    1049                 : 
    1050           38465 :         RETURN_TRUE;
    1051                 : }
    1052                 : /* }}} */
    1053                 : 
    1054                 : /* {{{ proto resource popen(string command, string mode) U
    1055                 :    Execute a command and open either a read or a write pipe to it */
    1056                 : PHP_FUNCTION(popen)
    1057               8 : {
    1058                 :         zval **ppcommand;
    1059                 :         char *command, *mode;
    1060                 :         int command_len, mode_len;
    1061                 :         FILE *fp;
    1062                 :         char *posix_mode;
    1063                 : 
    1064               8 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs", &ppcommand, &mode, &mode_len) == FAILURE) {
    1065               2 :                 return;
    1066                 :         }
    1067                 : 
    1068               6 :         if (php_stream_path_param_encode(ppcommand, &command, &command_len, REPORT_ERRORS, FG(default_context)) == FAILURE) {
    1069               0 :                 RETURN_FALSE;
    1070                 :         }
    1071                 : 
    1072               6 :         posix_mode = estrndup(mode, mode_len);
    1073                 : #ifndef PHP_WIN32
    1074                 :         {
    1075               6 :                 char *z = memchr(posix_mode, 'b', mode_len);
    1076               6 :                 if (z) {
    1077               1 :                         memmove(z, z + 1, mode_len - (z - posix_mode));
    1078                 :                 }
    1079                 :         }
    1080                 : #endif
    1081               6 :         fp = VCWD_POPEN(command, posix_mode);
    1082               6 :         if (!fp) {
    1083               1 :                 php_error_docref2(NULL TSRMLS_CC, command, mode, E_WARNING, "%s", strerror(errno));
    1084               1 :                 RETVAL_FALSE;
    1085                 :         } else {
    1086               5 :                 php_stream *stream = php_stream_fopen_from_pipe(fp, mode);
    1087                 : 
    1088               5 :                 if (stream == NULL)     {
    1089               0 :                         php_error_docref2(NULL TSRMLS_CC, command, mode, E_WARNING, "%s", strerror(errno));
    1090               0 :                         RETVAL_FALSE;
    1091                 :                 } else {
    1092               5 :                         php_stream_to_zval(stream, return_value);
    1093                 :                 }
    1094                 :         }
    1095                 : 
    1096               6 :         efree(posix_mode);
    1097                 : }
    1098                 : /* }}} */
    1099                 : 
    1100                 : /* {{{ proto int pclose(resource fp) U
    1101                 :    Close a file pointer opened by popen() */
    1102                 : PHP_FUNCTION(pclose)
    1103              37 : {
    1104                 :         zval *arg1;
    1105                 :         php_stream *stream;
    1106                 : 
    1107              37 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
    1108              32 :                 return;
    1109                 :         }
    1110                 : 
    1111               5 :         PHP_STREAM_TO_ZVAL(stream, &arg1);
    1112                 : 
    1113               5 :         zend_list_delete(stream->rsrc_id);
    1114               5 :         RETURN_LONG(FG(pclose_ret));
    1115                 : }
    1116                 : /* }}} */
    1117                 : 
    1118                 : /* {{{ proto bool feof(resource fp) U
    1119                 :    Test for end-of-file on a file pointer */
    1120                 : PHPAPI PHP_FUNCTION(feof)
    1121         1034630 : {
    1122                 :         zval *arg1;
    1123                 :         php_stream *stream;
    1124                 : 
    1125         1034630 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
    1126              12 :                 return;
    1127                 :         }
    1128                 : 
    1129         1034618 :         PHP_STREAM_TO_ZVAL(stream, &arg1);
    1130                 : 
    1131         1034591 :         if (php_stream_eof(stream)) {
    1132           12609 :                 RETURN_TRUE;
    1133                 :         } else {
    1134         1021982 :                 RETURN_FALSE;
    1135                 :         }
    1136                 : }
    1137                 : /* }}} */
    1138                 : 
    1139                 : /* {{{ proto string fgets(resource fp[, int lengthish]) U
    1140                 :    Get a line from file pointer */
    1141                 : PHPAPI PHP_FUNCTION(fgets)
    1142         1008747 : {
    1143                 :         php_stream *stream;
    1144                 :         zval *zstream;
    1145         1008747 :         int argc = ZEND_NUM_ARGS();
    1146         1008747 :         long length = -1;
    1147                 :         long len;
    1148                 :         zstr buf, line;
    1149         1008747 :         size_t retlen = 0;
    1150                 : 
    1151         1008747 :         if (zend_parse_parameters(argc TSRMLS_CC, "r|l", &zstream, &length) == FAILURE) {
    1152              13 :                 return;
    1153                 :         }
    1154                 : 
    1155         1008734 :         php_stream_from_zval(stream, &zstream);
    1156                 : 
    1157         1008731 :         if (argc == 2 && length <= 0) {
    1158               2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
    1159               2 :                 RETURN_FALSE;
    1160                 :         }
    1161                 : 
    1162         1008729 :         if (length == 1) {
    1163                 :                 /* For BC reasons, fgets() should only return length-1 bytes. */
    1164               1 :                 RETURN_FALSE;
    1165         1008728 :         } else if (length > 1) {
    1166            4455 :                 len = length;
    1167            4455 :                 buf.v = ecalloc(len, (stream->readbuf_type == IS_UNICODE) ? sizeof(UChar) : sizeof(char));
    1168            4455 :                 length--;
    1169                 :         } else {
    1170         1004273 :                 buf.v = NULL;
    1171         1004273 :                 len = -1;
    1172                 :         }
    1173                 : 
    1174         1008728 :         line.v = php_stream_get_line_ex(stream, stream->readbuf_type, buf, len, length, &retlen);
    1175         1008728 :         if (!line.v) {
    1176             175 :                 if (buf.v) {
    1177               1 :                         efree(buf.v);
    1178                 :                 }
    1179             175 :                 RETURN_FALSE;
    1180                 :         }
    1181                 : 
    1182         1008553 :         if (stream->readbuf_type == IS_UNICODE) {
    1183         1004038 :                 RETURN_UNICODEL(line.u, retlen, 0);
    1184                 :         } else { /* IS_STRING */
    1185            4515 :                 RETURN_STRINGL(line.s, retlen, 0);
    1186                 :         }
    1187                 : }
    1188                 : /* }}} */
    1189                 : 
    1190                 : /* {{{ proto string fgetc(resource fp) U
    1191                 :    Get a character from file pointer */
    1192                 : PHPAPI PHP_FUNCTION(fgetc)
    1193             377 : {
    1194                 :         zval *arg1;
    1195                 :         php_stream *stream;
    1196                 : 
    1197             377 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
    1198              11 :                 return;
    1199                 :         }
    1200                 : 
    1201             366 :         PHP_STREAM_TO_ZVAL(stream, &arg1);
    1202                 : 
    1203             365 :         if (stream->readbuf_type == IS_UNICODE) {
    1204              59 :                 int buflen = 1;
    1205              59 :                 UChar *buf = php_stream_read_unicode_chars(stream, &buflen);
    1206                 : 
    1207              59 :                 if (!buf || !buflen) {
    1208               2 :                         if (buf) {
    1209               2 :                                 efree(buf);
    1210                 :                         }
    1211               2 :                         RETURN_FALSE;
    1212                 :                 }
    1213              57 :                 RETURN_UNICODEL(buf, buflen, 0);
    1214                 :         } else { /* IS_STRING */
    1215                 :                 char buf[2];
    1216                 : 
    1217             306 :                 if ((buf[0] = php_stream_getc(stream)) == EOF) {
    1218              13 :                         RETURN_FALSE;
    1219                 :                 }
    1220             293 :                 buf[1] = 0;
    1221             293 :                 RETURN_STRINGL(buf, 1, 1);
    1222                 :         }
    1223                 : }
    1224                 : /* }}} */
    1225                 : 
    1226                 : /* {{{ proto string fgetss(resource fp [, int lengthish [, string allowable_tags]]) U
    1227                 :    Get a line from file pointer and strip HTML tags */
    1228                 : PHPAPI PHP_FUNCTION(fgetss)
    1229             299 : {
    1230                 :         zval *zstream;
    1231                 :         php_stream *stream;
    1232             299 :         long length = 0;
    1233                 :         long len;
    1234             299 :         zval **allow = NULL;
    1235             299 :         size_t retlen = 0;
    1236                 :         zstr buf;
    1237                 : 
    1238             299 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lZ", &zstream, &length, &allow) == FAILURE) {
    1239               9 :                 return;
    1240                 :         }
    1241                 : 
    1242             290 :         php_stream_from_zval(stream, &zstream);
    1243                 : 
    1244             288 :         if (ZEND_NUM_ARGS() >= 2 && length <= 0) {
    1245               4 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
    1246               4 :                 RETURN_FALSE;
    1247                 :         }
    1248                 : 
    1249             284 :         if (length == 1) {
    1250                 :                 /* For BC reasons, fgetss() should only return length-1 bytes. */
    1251               1 :                 RETURN_FALSE;
    1252             283 :         } else if (length > 1) {
    1253             222 :                 len = length;
    1254             222 :                 buf.v = ecalloc(len, (stream->readbuf_type == IS_UNICODE) ? sizeof(UChar) : sizeof(char));
    1255             222 :                 length--;
    1256                 :         } else {
    1257              61 :                 buf.v = NULL;
    1258              61 :                 len = -1;
    1259                 :         }
    1260                 : 
    1261             283 :         if (stream->readbuf_type == IS_UNICODE) {
    1262                 :                 UChar *line;
    1263              72 :                 UChar *allowed = NULL;
    1264              72 :                 int allowed_len = 0;
    1265                 : 
    1266              72 :                 line = php_stream_get_line_ex(stream, IS_UNICODE, buf, len, length, &retlen);
    1267              72 :                 if (!line) {
    1268              10 :                         if (buf.v) {
    1269               5 :                                 efree(buf.v);
    1270                 :                         }
    1271              10 :                         RETURN_FALSE;
    1272                 :                 }
    1273                 : 
    1274              62 :                 if (allow) {
    1275              52 :                         convert_to_unicode_ex(allow);
    1276              52 :                         allowed = Z_USTRVAL_PP(allow);
    1277              52 :                         allowed_len = Z_USTRLEN_PP(allow);
    1278                 :                 }
    1279              62 :                 retlen = php_u_strip_tags(line, retlen, &stream->fgetss_state, allowed, allowed_len TSRMLS_CC);
    1280                 : 
    1281              62 :                 RETURN_UNICODEL(line, retlen, 0);
    1282                 :         } else { /* IS_STRING */
    1283                 :                 char *line;
    1284             211 :                 char *allowed = NULL;
    1285             211 :                 int allowed_len = 0;
    1286                 : 
    1287             211 :                 line = php_stream_get_line_ex(stream, IS_STRING, buf, len, length, &retlen);
    1288             211 :                 if (!line) {
    1289              41 :                         if (buf.v) {
    1290              15 :                                 efree(buf.v);
    1291                 :                         }
    1292              41 :                         RETURN_FALSE;
    1293                 :                 }
    1294                 : 
    1295             170 :                 if (allow) {
    1296             116 :                         convert_to_string_ex(allow);
    1297             116 :                         allowed = Z_STRVAL_PP(allow);
    1298             116 :                         allowed_len = Z_STRLEN_PP(allow);
    1299                 :                 }
    1300             170 :                 retlen = php_strip_tags(line, retlen, &stream->fgetss_state, allowed, allowed_len);
    1301                 : 
    1302             170 :                 RETURN_STRINGL(line, retlen, 0);
    1303                 :         }
    1304                 : }
    1305                 : /* }}} */
    1306                 : 
    1307                 : /* {{{ proto mixed fscanf(resource stream, string format [, string ...]) U
    1308                 :    Implements a mostly ANSI compatible fscanf() */
    1309                 : PHP_FUNCTION(fscanf)
    1310            8715 : {
    1311            8715 :         int type, result, argc = 0;
    1312            8715 :         zval ***args = NULL;
    1313                 :         zval **format;
    1314                 :         zval *file_handle;
    1315                 :         char *buf;
    1316                 :         UChar *u_buf;
    1317                 :         void *what;
    1318                 : 
    1319            8715 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ*", &file_handle, &format, &args, &argc) == FAILURE) {
    1320               5 :                 return;
    1321                 :         }
    1322                 : 
    1323            8710 :         what = zend_fetch_resource(&file_handle TSRMLS_CC, -1, "File-Handle", &type, 2, php_file_le_stream(), php_file_le_pstream());
    1324                 : 
    1325                 :         /* we can't do a ZEND_VERIFY_RESOURCE(what), otherwise we end up
    1326                 :          * with a leak if we have an invalid filehandle. This needs changing
    1327                 :          * if the code behind ZEND_VERIFY_RESOURCE changed. - cc */
    1328            8710 :         if (!what) {
    1329               1 :                 if (args) {
    1330               0 :                         efree(args);
    1331                 :                 }
    1332               1 :                 RETURN_FALSE;
    1333                 :         }
    1334                 : 
    1335            8709 :         if (((php_stream *)what)->readbuf_type == IS_UNICODE) {
    1336             159 :                 u_buf = php_stream_u_get_line((php_stream *) what, NULL_ZSTR, 0, 0, NULL);
    1337             159 :                 if (u_buf == NULL) {
    1338              57 :                         if (args) {
    1339               1 :                                 efree(args);
    1340                 :                         }
    1341              57 :                         RETURN_FALSE;
    1342                 :                 }
    1343                 : 
    1344             102 :                 convert_to_unicode_ex(format);
    1345             102 :                 result = php_u_sscanf_internal(u_buf, Z_USTRVAL_PP(format), argc, args, 0, &return_value TSRMLS_CC);
    1346             102 :                 efree(u_buf);
    1347                 :         } else {
    1348            8550 :                 buf = php_stream_get_line((php_stream *) what, NULL_ZSTR, 0, NULL);
    1349            8550 :                 if (buf == NULL) {
    1350             828 :                         if (args) {
    1351               0 :                                 efree(args);
    1352                 :                         }
    1353             828 :                         RETURN_FALSE;
    1354                 :                 }
    1355                 : 
    1356            7722 :                 convert_to_string_ex(format);
    1357            7722 :                 result = php_sscanf_internal(buf, Z_STRVAL_PP(format), argc, args, 0, &return_value TSRMLS_CC);
    1358            7722 :                 efree(buf);
    1359                 :         }
    1360                 : 
    1361            7824 :         if (args) {
    1362               7 :                 efree(args);
    1363                 :         }
    1364                 : 
    1365            7824 :         if (SCAN_ERROR_WRONG_PARAM_COUNT == result) {
    1366               0 :                 WRONG_PARAM_COUNT;
    1367                 :         }
    1368                 : }
    1369                 : /* }}} */
    1370                 : 
    1371                 : /* {{{ proto int fwrite(resource fp, string str [, int length]) U
    1372                 :    Binary-safe file write */
    1373                 : PHPAPI PHP_FUNCTION(fwrite)
    1374           73083 : {
    1375           73083 :         int ret, argc = ZEND_NUM_ARGS();
    1376           73083 :         long write_len = -1;
    1377                 :         php_stream *stream;
    1378                 :         zval *zstream, *zstring;
    1379                 : 
    1380           73083 :         if (zend_parse_parameters(argc TSRMLS_CC, "rz/|l", &zstream, &zstring, &write_len) == FAILURE) {
    1381              29 :                 RETURN_NULL();
    1382                 :         }
    1383                 : 
    1384           73054 :         php_stream_from_zval(stream, &zstream);
    1385                 : 
    1386           73052 :         if (argc > 2 && write_len <= 0) {
    1387               5 :                 RETURN_LONG(0);
    1388                 :         }
    1389                 : 
    1390           73047 :         if (Z_TYPE_P(zstring) == IS_UNICODE) {
    1391            9186 :                 int32_t write_uchars = 0;
    1392                 : 
    1393            9186 :                 if (write_len < 0 || write_len > Z_USTRLEN_P(zstring)) {
    1394            9183 :                         write_len = Z_USTRLEN_P(zstring);
    1395                 :                 }
    1396                 :                 /* Convert code units to data points */
    1397                 : 
    1398            9186 :                 U16_FWD_N(Z_USTRVAL_P(zstring), write_uchars, Z_USTRLEN_P(zstring), write_len);
    1399            9186 :                 write_len = write_uchars;
    1400                 : 
    1401            9186 :                 ret = php_stream_write_unicode(stream, Z_USTRVAL_P(zstring), write_len);
    1402                 : 
    1403                 :                 /* Convert data points back to code units */
    1404            9186 :                 if (ret > 0) {
    1405            9173 :                         ret = u_countChar32(Z_USTRVAL_P(zstring), ret);
    1406                 :                 }
    1407                 :         } else {
    1408           63861 :                 convert_to_string(zstring);
    1409           63861 :                 if (write_len < 0 || write_len > Z_STRLEN_P(zstring)) {
    1410            7416 :                         write_len = Z_STRLEN_P(zstring);
    1411                 :                 }
    1412                 : 
    1413           63861 :                 ret = php_stream_write(stream, Z_STRVAL_P(zstring), write_len);
    1414                 :         }
    1415                 : 
    1416           73047 :         RETURN_LONG(ret);
    1417                 : }
    1418                 : /* }}} */
    1419                 : 
    1420                 : /* {{{ proto bool fflush(resource fp) U
    1421                 :    Flushes output */
    1422                 : PHPAPI PHP_FUNCTION(fflush)
    1423             229 : {
    1424                 :         zval *arg1;
    1425                 :         int ret;
    1426                 :         php_stream *stream;
    1427                 : 
    1428             229 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
    1429               8 :                 return;
    1430                 :         }
    1431                 : 
    1432             221 :         PHP_STREAM_TO_ZVAL(stream, &arg1);
    1433                 : 
    1434             221 :         ret = php_stream_flush(stream);
    1435             221 :         if (ret) {
    1436               0 :                 RETURN_FALSE;
    1437                 :         }
    1438             221 :         RETURN_TRUE;
    1439                 : }
    1440                 : /* }}} */
    1441                 : 
    1442                 : /* {{{ proto bool rewind(resource fp) U
    1443                 :    Rewind the position of a file pointer */
    1444                 : PHPAPI PHP_FUNCTION(rewind)
    1445            3391 : {
    1446                 :         zval *arg1;
    1447                 :         php_stream *stream;
    1448                 : 
    1449            3391 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
    1450              13 :                 return;
    1451                 :         }
    1452                 : 
    1453            3378 :         PHP_STREAM_TO_ZVAL(stream, &arg1);
    1454                 : 
    1455            3377 :         if (-1 == php_stream_rewind(stream)) {
    1456               2 :                 RETURN_FALSE;
    1457                 :         }
    1458            3375 :         RETURN_TRUE;
    1459                 : }
    1460                 : /* }}} */
    1461                 : 
    1462                 : /* {{{ proto int ftell(resource fp) U
    1463                 :    Get file pointer's read/write position */
    1464                 : PHPAPI PHP_FUNCTION(ftell)
    1465           15031 : {
    1466                 :         zval *arg1;
    1467                 :         long ret;
    1468                 :         php_stream *stream;
    1469                 : 
    1470           15031 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
    1471              11 :                 return;
    1472                 :         }
    1473                 : 
    1474           15020 :         PHP_STREAM_TO_ZVAL(stream, &arg1);
    1475                 : 
    1476           14995 :         ret = php_stream_tell(stream);
    1477           14995 :         if (ret == -1)  {
    1478              10 :                 RETURN_FALSE;
    1479                 :         }
    1480           14985 :         RETURN_LONG(ret);
    1481                 : }
    1482                 : /* }}} */
    1483                 : 
    1484                 : /* {{{ proto int fseek(resource fp, int offset [, int whence]) U
    1485                 :    Seek on a file pointer */
    1486                 : PHPAPI PHP_FUNCTION(fseek)
    1487            7666 : {
    1488                 :         zval *arg1;
    1489                 :         long arg2, arg3;
    1490            7666 :         int whence = SEEK_SET, argcount = ZEND_NUM_ARGS();
    1491                 :         php_stream *stream;
    1492                 : 
    1493            7666 :         if (zend_parse_parameters(argcount TSRMLS_CC, "rl|l", &arg1, &arg2, &arg3) == FAILURE) {
    1494              27 :                 return;
    1495                 :         }
    1496                 : 
    1497            7639 :         PHP_STREAM_TO_ZVAL(stream, &arg1);
    1498                 : 
    1499            7638 :         if (argcount > 2) {
    1500            7412 :                 whence = arg3;
    1501                 :         }
    1502                 : 
    1503            7638 :         RETURN_LONG(php_stream_seek(stream, arg2, whence));
    1504                 : }
    1505                 : /* }}} */
    1506                 : 
    1507                 : /* {{{ php_mkdir
    1508                 : */
    1509                 : 
    1510                 : /* DEPRECATED APIs: Use php_stream_mkdir() instead */
    1511                 : PHPAPI int php_mkdir_ex(char *dir, long mode, int options TSRMLS_DC)
    1512            1656 : {
    1513                 :         int ret;
    1514                 : 
    1515            1656 :         if (php_check_open_basedir(dir TSRMLS_CC)) {
    1516               0 :                 return -1;
    1517                 :         }
    1518                 : 
    1519            1656 :         if ((ret = VCWD_MKDIR(dir, (mode_t)mode)) < 0 && (options & REPORT_ERRORS)) {
    1520              49 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
    1521                 :         }
    1522                 : 
    1523            1656 :         return ret;
    1524                 : }
    1525                 : 
    1526                 : PHPAPI int php_mkdir(char *dir, long mode TSRMLS_DC)
    1527            1656 : {
    1528            1656 :         return php_mkdir_ex(dir, mode, REPORT_ERRORS TSRMLS_CC);
    1529                 : }
    1530                 : /* }}} */
    1531                 : 
    1532                 : /* {{{ proto bool mkdir(string pathname [, int mode [, bool recursive [, resource context]]]) U
    1533                 :    Create a directory */
    1534                 : PHP_FUNCTION(mkdir)
    1535            1708 : {
    1536                 :         zval **ppdir;
    1537                 :         char *dir;
    1538                 :         int dir_len;
    1539            1708 :         zval *zcontext = NULL;
    1540            1708 :         long mode = 0777;
    1541            1708 :         zend_bool recursive = 0;
    1542                 :         php_stream_context *context;
    1543                 : 
    1544            1708 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|lbr", &ppdir, &mode, &recursive, &zcontext) == FAILURE) {
    1545              50 :                 RETURN_FALSE;
    1546                 :         }
    1547                 : 
    1548            1658 :         context = php_stream_context_from_zval(zcontext, 0);
    1549            1658 :         if (php_stream_path_param_encode(ppdir, &dir, &dir_len, REPORT_ERRORS, context) == FAILURE) {
    1550               0 :                 RETURN_FALSE;
    1551                 :         }
    1552                 : 
    1553            1658 :         RETVAL_BOOL(php_stream_mkdir(dir, mode, (recursive ? PHP_STREAM_MKDIR_RECURSIVE : 0) | REPORT_ERRORS, context));
    1554                 : }
    1555                 : /* }}} */
    1556                 : 
    1557                 : /* {{{ proto bool rmdir(string dirname[, resource context]) U
    1558                 :    Remove a directory */
    1559                 : PHP_FUNCTION(rmdir)
    1560            1735 : {
    1561                 :         zval **ppdir;
    1562                 :         char *dir;
    1563                 :         int dir_len;
    1564            1735 :         zval *zcontext = NULL;
    1565                 :         php_stream_context *context;
    1566                 : 
    1567            1735 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|r", &ppdir, &zcontext) == FAILURE) {
    1568              32 :                 RETURN_FALSE;
    1569                 :         }
    1570                 : 
    1571            1703 :         context = php_stream_context_from_zval(zcontext, 0);
    1572            1703 :         if (php_stream_path_param_encode(ppdir, &dir, &dir_len, REPORT_ERRORS, context) == FAILURE) {
    1573               0 :                 RETURN_FALSE;
    1574                 :         }
    1575                 : 
    1576            1703 :         RETVAL_BOOL(php_stream_rmdir(dir, REPORT_ERRORS, context));
    1577                 : }
    1578                 : /* }}} */
    1579                 : 
    1580                 : /* {{{ proto int readfile(string filename [, int flags[, resource context]]) U
    1581                 :    Output a file or a URL */
    1582                 : PHP_FUNCTION(readfile)
    1583             459 : {
    1584                 :         zval **ppfilename;
    1585                 :         char *filename;
    1586                 :         int filename_len;
    1587             459 :         int size = 0;
    1588             459 :         long flags = 0;
    1589             459 :         zval *zcontext = NULL;
    1590                 :         php_stream *stream;
    1591             459 :         php_stream_context *context = NULL;
    1592             459 :         char *mode = "rb";
    1593                 : 
    1594             459 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|lr!", &ppfilename, &flags, &zcontext) == FAILURE) {
    1595              41 :                 RETURN_FALSE;
    1596                 :         }
    1597                 : 
    1598             418 :         context = php_stream_context_from_zval(zcontext, 0);
    1599             418 :         if (php_stream_path_param_encode(ppfilename, &filename, &filename_len, REPORT_ERRORS, context) == FAILURE) {
    1600               0 :                 RETURN_FALSE;
    1601                 :         }
    1602                 : 
    1603             418 :         if (flags & PHP_FILE_TEXT) {
    1604               3 :                 mode = "rt";
    1605                 :         }
    1606                 : 
    1607             418 :         stream = php_stream_open_wrapper_ex(filename, mode, ((flags & PHP_FILE_USE_INCLUDE_PATH) ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
    1608             418 :         if (stream) {
    1609             400 :                 size = php_stream_passthru(stream);
    1610             400 :                 php_stream_close(stream);
    1611             400 :                 RETURN_LONG(size);
    1612                 :         }
    1613                 : 
    1614              18 :         RETURN_FALSE;
    1615                 : }
    1616                 : /* }}} */
    1617                 : 
    1618                 : /* {{{ proto int umask([int mask]) U
    1619                 :    Return or change the umask */
    1620                 : PHP_FUNCTION(umask)
    1621            2128 : {
    1622            2128 :         long arg1 = 0;
    1623                 :         int oldumask;
    1624            2128 :         int arg_count = ZEND_NUM_ARGS();
    1625                 : 
    1626            2128 :         oldumask = umask(077);
    1627                 : 
    1628            2128 :         if (BG(umask) == -1) {
    1629               6 :                 BG(umask) = oldumask;
    1630                 :         }
    1631                 : 
    1632            2128 :         if (zend_parse_parameters(arg_count TSRMLS_CC, "|l", &arg1) == FAILURE) {
    1633              13 :                 return;
    1634                 :         }
    1635                 : 
    1636            2115 :         if (arg_count == 0) {
    1637            1050 :                 umask(oldumask);
    1638                 :         } else {
    1639            1065 :                 umask(arg1);
    1640                 :         }
    1641                 : 
    1642            2115 :         RETURN_LONG(oldumask);
    1643                 : }
    1644                 : /* }}} */
    1645                 : 
    1646                 : /* {{{ proto int fpassthru(resource fp) U
    1647                 :    Output all remaining data from a file pointer */
    1648                 : PHPAPI PHP_FUNCTION(fpassthru)
    1649             139 : {
    1650                 :         zval *arg1;
    1651                 :         int size;
    1652                 :         php_stream *stream;
    1653                 : 
    1654             139 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
    1655              42 :                 return;
    1656                 :         }
    1657                 : 
    1658              97 :         PHP_STREAM_TO_ZVAL(stream, &arg1);
    1659                 : 
    1660              97 :         size = php_stream_passthru(stream);
    1661              97 :         RETURN_LONG(size);
    1662                 : }
    1663                 : /* }}} */
    1664                 : 
    1665                 : /* {{{ proto bool rename(string old_name, string new_name[, resource context]) U
    1666                 :    Rename a file */
    1667                 : PHP_FUNCTION(rename)
    1668             133 : {
    1669                 :         zval **ppold, **ppnew;
    1670                 :         char *old_name, *new_name;
    1671                 :         int old_name_len, new_name_len;
    1672             133 :         zval *zcontext = NULL;
    1673                 :         php_stream_wrapper *wrapper;
    1674                 :         php_stream_context *context;
    1675                 : 
    1676             133 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|r", &ppold, &ppnew, &zcontext) == FAILURE) {
    1677              32 :                 RETURN_FALSE;
    1678                 :         }
    1679                 : 
    1680             101 :         context = php_stream_context_from_zval(zcontext, 0);
    1681             101 :         if (php_stream_path_param_encode(ppold, &old_name, &old_name_len, REPORT_ERRORS, context) == FAILURE ||
    1682                 :                 php_stream_path_param_encode(ppnew, &new_name, &new_name_len, REPORT_ERRORS, context) == FAILURE) {
    1683               0 :                 RETURN_FALSE;
    1684                 :         }
    1685                 : 
    1686             101 :         wrapper = php_stream_locate_url_wrapper(old_name, NULL, 0 TSRMLS_CC);
    1687                 : 
    1688             101 :         if (!wrapper || !wrapper->wops) {
    1689               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to locate stream wrapper");
    1690               0 :                 RETURN_FALSE;
    1691                 :         }
    1692                 : 
    1693             101 :         if (!wrapper->wops->rename) {
    1694               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s wrapper does not support renaming", wrapper->wops->label ? wrapper->wops->label : "Source");
    1695               1 :                 RETURN_FALSE;
    1696                 :         }
    1697                 : 
    1698             100 :         if (wrapper != php_stream_locate_url_wrapper(new_name, NULL, 0 TSRMLS_CC)) {
    1699               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot rename a file across wrapper types");
    1700               1 :                 RETURN_FALSE;
    1701                 :         }
    1702                 : 
    1703              99 :         RETVAL_BOOL(wrapper->wops->rename(wrapper, old_name, new_name, 0, context TSRMLS_CC));
    1704                 : }
    1705                 : /* }}} */
    1706                 : 
    1707                 : /* {{{ proto bool unlink(string filename[, context context]) U
    1708                 :    Delete a file */
    1709                 : PHP_FUNCTION(unlink)
    1710          164477 : {
    1711                 :         zval **ppfilename;
    1712                 :         char *filename;
    1713                 :         int filename_len;
    1714                 :         php_stream_wrapper *wrapper;
    1715          164477 :         zval *zcontext = NULL;
    1716          164477 :         php_stream_context *context = NULL;
    1717                 : 
    1718          164477 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|r", &ppfilename, &zcontext) == FAILURE) {
    1719              34 :                 RETURN_FALSE;
    1720                 :         }
    1721                 : 
    1722          164443 :         context = php_stream_context_from_zval(zcontext, 0);
    1723          164443 :         if (php_stream_path_param_encode(ppfilename, &filename, &filename_len, REPORT_ERRORS, context) == FAILURE) {
    1724               0 :                 RETURN_FALSE;
    1725                 :         }
    1726                 : 
    1727          164443 :         wrapper = php_stream_locate_url_wrapper(filename, NULL, 0 TSRMLS_CC);
    1728                 : 
    1729          164443 :         if (!wrapper || !wrapper->wops) {
    1730               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to locate stream wrapper");
    1731               0 :                 RETURN_FALSE;
    1732                 :         }
    1733                 : 
    1734          164443 :         if (!wrapper->wops->unlink) {
    1735               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s does not allow unlinking", wrapper->wops->label ? wrapper->wops->label : "Wrapper");
    1736               1 :                 RETURN_FALSE;
    1737                 :         }
    1738                 : 
    1739          164442 :         RETVAL_BOOL(wrapper->wops->unlink(wrapper, filename, REPORT_ERRORS, context TSRMLS_CC));
    1740                 : }
    1741                 : /* }}} */
    1742                 : 
    1743                 : /* {{{ proto bool ftruncate(resource fp, int size) U
    1744                 :    Truncate file to 'size' length */
    1745                 : PHP_NAMED_FUNCTION(php_if_ftruncate)
    1746             388 : {
    1747                 :         zval *fp;
    1748                 :         long size;
    1749                 :         php_stream *stream;
    1750                 : 
    1751             388 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &fp, &size) == FAILURE) {
    1752              12 :                 return;
    1753                 :         }
    1754                 : 
    1755             376 :         PHP_STREAM_TO_ZVAL(stream, &fp);
    1756                 : 
    1757             375 :         if (!php_stream_truncate_supported(stream)) {
    1758               2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't truncate this stream!");
    1759               2 :                 RETURN_FALSE;
    1760                 :         }
    1761                 : 
    1762             373 :         RETURN_BOOL(0 == php_stream_truncate_set_size(stream, size));
    1763                 : }
    1764                 : /* }}} */
    1765                 : 
    1766                 : /* {{{ proto array fstat(resource fp) U
    1767                 :    Stat() on a filehandle */
    1768                 : PHP_NAMED_FUNCTION(php_if_fstat)
    1769              41 : {
    1770                 :         zval *fp;
    1771                 :         zval *stat_dev, *stat_ino, *stat_mode, *stat_nlink, *stat_uid, *stat_gid, *stat_rdev,
    1772                 :                  *stat_size, *stat_atime, *stat_mtime, *stat_ctime, *stat_blksize, *stat_blocks;
    1773                 :         php_stream *stream;
    1774                 :         php_stream_statbuf stat_ssb;
    1775                 :         char *stat_sb_names[13] = {
    1776                 :                 "dev", "ino", "mode", "nlink", "uid", "gid", "rdev",
    1777                 :                 "size", "atime", "mtime", "ctime", "blksize", "blocks"
    1778              41 :         };
    1779                 : 
    1780              41 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &fp) == FAILURE) {
    1781              31 :                 return;
    1782                 :         }
    1783                 : 
    1784              10 :         PHP_STREAM_TO_ZVAL(stream, &fp);
    1785                 : 
    1786               9 :         if (php_stream_stat(stream, &stat_ssb)) {
    1787               3 :                 RETURN_FALSE;
    1788                 :         }
    1789                 : 
    1790               6 :         array_init(return_value);
    1791                 : 
    1792               6 :         MAKE_LONG_ZVAL_INCREF(stat_dev, stat_ssb.sb.st_dev);
    1793               6 :         MAKE_LONG_ZVAL_INCREF(stat_ino, stat_ssb.sb.st_ino);
    1794               6 :         MAKE_LONG_ZVAL_INCREF(stat_mode, stat_ssb.sb.st_mode);
    1795               6 :         MAKE_LONG_ZVAL_INCREF(stat_nlink, stat_ssb.sb.st_nlink);
    1796               6 :         MAKE_LONG_ZVAL_INCREF(stat_uid, stat_ssb.sb.st_uid);
    1797               6 :         MAKE_LONG_ZVAL_INCREF(stat_gid, stat_ssb.sb.st_gid);
    1798                 : #ifdef HAVE_ST_RDEV
    1799               6 :         MAKE_LONG_ZVAL_INCREF(stat_rdev, stat_ssb.sb.st_rdev);
    1800                 : #else
    1801                 :         MAKE_LONG_ZVAL_INCREF(stat_rdev, -1);
    1802                 : #endif
    1803               6 :         MAKE_LONG_ZVAL_INCREF(stat_size, stat_ssb.sb.st_size);
    1804               6 :         MAKE_LONG_ZVAL_INCREF(stat_atime, stat_ssb.sb.st_atime);
    1805               6 :         MAKE_LONG_ZVAL_INCREF(stat_mtime, stat_ssb.sb.st_mtime);
    1806               6 :         MAKE_LONG_ZVAL_INCREF(stat_ctime, stat_ssb.sb.st_ctime);
    1807                 : #ifdef HAVE_ST_BLKSIZE
    1808               6 :         MAKE_LONG_ZVAL_INCREF(stat_blksize, stat_ssb.sb.st_blksize);
    1809                 : #else
    1810                 :         MAKE_LONG_ZVAL_INCREF(stat_blksize,-1);
    1811                 : #endif
    1812                 : #ifdef HAVE_ST_BLOCKS
    1813               6 :         MAKE_LONG_ZVAL_INCREF(stat_blocks, stat_ssb.sb.st_blocks);
    1814                 : #else
    1815                 :         MAKE_LONG_ZVAL_INCREF(stat_blocks,-1);
    1816                 : #endif
    1817                 :         /* Store numeric indexes in propper order */
    1818               6 :         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_dev, sizeof(zval *), NULL);
    1819               6 :         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ino, sizeof(zval *), NULL);
    1820               6 :         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mode, sizeof(zval *), NULL);
    1821               6 :         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_nlink, sizeof(zval *), NULL);
    1822               6 :         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_uid, sizeof(zval *), NULL);
    1823               6 :         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_gid, sizeof(zval *), NULL);
    1824               6 :         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_rdev, sizeof(zval *), NULL);
    1825               6 :         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_size, sizeof(zval *), NULL);
    1826               6 :         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_atime, sizeof(zval *), NULL);
    1827               6 :         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mtime, sizeof(zval *), NULL);
    1828               6 :         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ctime, sizeof(zval *), NULL);
    1829               6 :         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blksize, sizeof(zval *), NULL);
    1830               6 :         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blocks, sizeof(zval *), NULL);
    1831                 : 
    1832                 :         /* Store string indexes referencing the same zval*/
    1833               6 :         zend_ascii_hash_update(HASH_OF(return_value), stat_sb_names[0], strlen(stat_sb_names[0])+1, (void *)&stat_dev, sizeof(zval *), NULL);
    1834               6 :         zend_ascii_hash_update(HASH_OF(return_value), stat_sb_names[1], strlen(stat_sb_names[1])+1, (void *)&stat_ino, sizeof(zval *), NULL);
    1835               6 :         zend_ascii_hash_update(HASH_OF(return_value), stat_sb_names[2], strlen(stat_sb_names[2])+1, (void *)&stat_mode, sizeof(zval *), NULL);
    1836               6 :         zend_ascii_hash_update(HASH_OF(return_value), stat_sb_names[3], strlen(stat_sb_names[3])+1, (void *)&stat_nlink, sizeof(zval *), NULL);
    1837               6 :         zend_ascii_hash_update(HASH_OF(return_value), stat_sb_names[4], strlen(stat_sb_names[4])+1, (void *)&stat_uid, sizeof(zval *), NULL);
    1838               6 :         zend_ascii_hash_update(HASH_OF(return_value), stat_sb_names[5], strlen(stat_sb_names[5])+1, (void *)&stat_gid, sizeof(zval *), NULL);
    1839               6 :         zend_ascii_hash_update(HASH_OF(return_value), stat_sb_names[6], strlen(stat_sb_names[6])+1, (void *)&stat_rdev, sizeof(zval *), NULL);
    1840               6 :         zend_ascii_hash_update(HASH_OF(return_value), stat_sb_names[7], strlen(stat_sb_names[7])+1, (void *)&stat_size, sizeof(zval *), NULL);
    1841               6 :         zend_ascii_hash_update(HASH_OF(return_value), stat_sb_names[8], strlen(stat_sb_names[8])+1, (void *)&stat_atime, sizeof(zval *), NULL);
    1842               6 :         zend_ascii_hash_update(HASH_OF(return_value), stat_sb_names[9], strlen(stat_sb_names[9])+1, (void *)&stat_mtime, sizeof(zval *), NULL);
    1843               6 :         zend_ascii_hash_update(HASH_OF(return_value), stat_sb_names[10], strlen(stat_sb_names[10])+1, (void *)&stat_ctime, sizeof(zval *), NULL);
    1844               6 :         zend_ascii_hash_update(HASH_OF(return_value), stat_sb_names[11], strlen(stat_sb_names[11])+1, (void *)&stat_blksize, sizeof(zval *), NULL);
    1845               6 :         zend_ascii_hash_update(HASH_OF(return_value), stat_sb_names[12], strlen(stat_sb_names[12])+1, (void *)&stat_blocks, sizeof(zval *), NULL);
    1846                 : }
    1847                 : /* }}} */
    1848                 : 
    1849                 : /* {{{ proto bool copy(string source_file, string destination_file[, resource context]) U
    1850                 :    Copy a file */
    1851                 : PHP_FUNCTION(copy)
    1852             182 : {
    1853             182 :         zval **source, **target, *zcontext = NULL;
    1854                 :         php_stream_context *context;
    1855                 : 
    1856             182 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|r", &source, &target, &zcontext) == FAILURE) {
    1857               3 :                 return;
    1858                 :         }
    1859                 : 
    1860             179 :         context = php_stream_context_from_zval(zcontext, 0);
    1861             179 :         if (FAILURE == php_stream_path_param_encode(source, NULL, NULL, REPORT_ERRORS, context) ||
    1862                 :                 FAILURE == php_stream_path_param_encode(target, NULL, NULL, REPORT_ERRORS, context) ||
    1863                 :                 0 != php_check_open_basedir(Z_STRVAL_PP(source) TSRMLS_CC)) {
    1864               1 :                 RETURN_FALSE;
    1865                 :         }
    1866                 : 
    1867             178 :         if (php_copy_file(Z_STRVAL_PP(source), Z_STRVAL_PP(target) TSRMLS_CC) == SUCCESS) {
    1868             149 :                 RETURN_TRUE;
    1869                 :         } else {
    1870              29 :                 RETURN_FALSE;
    1871                 :         }
    1872                 : }
    1873                 : /* }}} */
    1874                 : 
    1875                 : PHPAPI int php_copy_file(char *src, char *dest TSRMLS_DC) /* {{{ */
    1876             178 : {
    1877             178 :         return php_copy_file_ex(src, dest, 0 TSRMLS_CC);
    1878                 : }
    1879                 : /* }}} */
    1880                 : 
    1881                 : /* {{{ php_copy_file
    1882                 :  */
    1883                 : PHPAPI int php_copy_file_ex(char *src, char *dest, int src_chk TSRMLS_DC)
    1884             178 : {
    1885             178 :         php_stream *srcstream = NULL, *deststream = NULL;
    1886             178 :         int ret = FAILURE;
    1887                 :         php_stream_statbuf src_s, dest_s;
    1888                 : 
    1889             178 :         switch (php_stream_stat_path_ex(src, 0, &src_s, NULL)) {
    1890                 :                 case -1:
    1891                 :                         /* non-statable stream */
    1892               8 :                         goto safe_to_copy;
    1893                 :                         break;
    1894                 :                 case 0:
    1895                 :                         break;
    1896                 :                 default: /* failed to stat file, does not exist? */
    1897               0 :                         return ret;
    1898                 :         }
    1899             170 :         if (S_ISDIR(src_s.sb.st_mode)) {
    1900               2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument to copy() function cannot be a directory");
    1901               2 :                 return FAILURE;
    1902                 :         }
    1903                 : 
    1904             168 :         switch (php_stream_stat_path_ex(dest, PHP_STREAM_URL_STAT_QUIET, &dest_s, NULL)) {
    1905                 :                 case -1:
    1906                 :                         /* non-statable stream */
    1907             157 :                         goto safe_to_copy;
    1908                 :                         break;
    1909                 :                 case 0:
    1910                 :                         break;
    1911                 :                 default: /* failed to stat file, does not exist? */
    1912               0 :                         return ret;
    1913                 :         }
    1914              11 :         if (S_ISDIR(dest_s.sb.st_mode)) {
    1915               6 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "The second argument to copy() function cannot be a directory");
    1916               6 :                 return FAILURE;
    1917                 :         }
    1918               5 :         if (!src_s.sb.st_ino || !dest_s.sb.st_ino) {
    1919                 :                 goto no_stat;
    1920                 :         }
    1921               5 :         if (src_s.sb.st_ino == dest_s.sb.st_ino && src_s.sb.st_dev == dest_s.sb.st_dev) {
    1922               4 :                 return ret;
    1923                 :         } else {
    1924                 :                 goto safe_to_copy;
    1925                 :         }
    1926               0 : no_stat:
    1927                 :         {
    1928                 :                 char *sp, *dp;
    1929                 :                 int res;
    1930                 : 
    1931               0 :                 if ((sp = expand_filepath(src, NULL TSRMLS_CC)) == NULL) {
    1932               0 :                         return ret;
    1933                 :                 }
    1934               0 :                 if ((dp = expand_filepath(dest, NULL TSRMLS_CC)) == NULL) {
    1935               0 :                         efree(sp);
    1936               0 :                         goto safe_to_copy;
    1937                 :                 }
    1938                 : 
    1939               0 :                 res =
    1940                 : #ifndef PHP_WIN32
    1941                 :                         !strcmp(sp, dp);
    1942                 : #else
    1943                 :                         !strcasecmp(sp, dp);
    1944                 : #endif
    1945                 : 
    1946               0 :                 efree(sp);
    1947               0 :                 efree(dp);
    1948               0 :                 if (res) {
    1949               0 :                         return ret;
    1950                 :                 }
    1951                 :         }
    1952             166 : safe_to_copy:
    1953                 : 
    1954             166 :         srcstream = php_stream_open_wrapper(src, "rb", src_chk | REPORT_ERRORS, NULL);
    1955                 : 
    1956             166 :         if (!srcstream) {
    1957               6 :                 return ret;
    1958                 :         }
    1959                 : 
    1960             160 :         deststream = php_stream_open_wrapper(dest, "wb", REPORT_ERRORS, NULL);
    1961                 : 
    1962             160 :         if (srcstream && deststream) {
    1963             149 :                 ret = php_stream_copy_to_stream_ex(srcstream, deststream, PHP_STREAM_COPY_ALL, NULL);
    1964                 :         }
    1965             160 :         if (srcstream) {
    1966             160 :                 php_stream_close(srcstream);
    1967                 :         }
    1968             160 :         if (deststream) {
    1969             149 :                 php_stream_close(deststream);
    1970                 :         }
    1971             160 :         return ret;
    1972                 : }
    1973                 : /* }}} */
    1974                 : 
    1975                 : /* {{{ proto string fread(resource fp, int length) U
    1976                 :    Binary-safe file read */
    1977                 : PHPAPI PHP_FUNCTION(fread)
    1978          817924 : {
    1979                 :         zval *zstream;
    1980                 :         long len;
    1981                 :         php_stream *stream;
    1982                 : 
    1983          817924 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zstream, &len) == FAILURE) {
    1984              15 :                 RETURN_NULL();
    1985                 :         }
    1986                 : 
    1987          817909 :         php_stream_from_zval(stream, &zstream);
    1988                 : 
    1989          817906 :         if (len <= 0) {
    1990               4 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
    1991               4 :                 RETURN_FALSE;
    1992                 :         }
    1993                 : 
    1994          817902 :         if (stream->readbuf_type == IS_UNICODE) {
    1995              72 :                 int buflen = len;
    1996              72 :                 UChar *buf = php_stream_read_unicode_chars(stream, &buflen);
    1997                 : 
    1998              72 :                 RETURN_UNICODEL(buf, buflen, 0);
    1999                 :         } else { /* IS_STRING */
    2000          817830 :                 char *buf = emalloc(len + 1);
    2001          817830 :                 int buflen = php_stream_read(stream, buf, len);
    2002                 : 
    2003          817830 :                 buf[buflen] = 0;
    2004          817830 :                 RETURN_STRINGL(buf, buflen, 0);
    2005                 :         }
    2006                 : }
    2007                 : /* }}} */
    2008                 : 
    2009                 : #define FPUTCSV_FLD_CHK(c) memchr(Z_STRVAL(field), c, Z_STRLEN(field))
    2010                 : 
    2011                 : /* {{{ proto int fputcsv(resource fp, array fields [, string delimiter [, string enclosure]])
    2012                 :    Format line as CSV and write to file pointer */
    2013                 : /* UTODO: Output unicode contents */
    2014                 : PHP_FUNCTION(fputcsv)
    2015            1394 : {
    2016            1394 :         char delimiter = ',';   /* allow this to be set as parameter */
    2017            1394 :         char enclosure = '"';      /* allow this to be set as parameter */
    2018            1394 :         const char escape_char = '\\';
    2019                 :         php_stream *stream;
    2020                 :         int ret;
    2021            1394 :         zval *fp = NULL, *fields = NULL, **field_tmp = NULL, field;
    2022            1394 :         char *delimiter_str = NULL, *enclosure_str = NULL;
    2023            1394 :         int delimiter_str_len = 0, enclosure_str_len = 0;
    2024                 :         HashPosition pos;
    2025            1394 :         int count, i = 0;
    2026            1394 :         smart_str csvline = {0};
    2027                 : 
    2028            1394 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ra|ss",
    2029                 :                         &fp, &fields, &delimiter_str, &delimiter_str_len,
    2030                 :                         &enclosure_str, &enclosure_str_len) == FAILURE) {
    2031              14 :                 return;
    2032                 :         }
    2033                 : 
    2034            1380 :         if (delimiter_str != NULL) {
    2035                 :                 /* Make sure that there is at least one character in string */
    2036            1215 :                 if (delimiter_str_len < 1) {
    2037             216 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "delimiter must be a character");
    2038             216 :                         RETURN_FALSE;
    2039             999 :                 } else if (delimiter_str_len > 1) {
    2040             243 :                         php_error_docref(NULL TSRMLS_CC, E_NOTICE, "delimiter must be a single character");
    2041                 :                 }
    2042                 : 
    2043                 :                 /* use first character from string */
    2044             999 :                 delimiter = *delimiter_str;
    2045                 :         }
    2046                 : 
    2047            1164 :         if (enclosure_str != NULL) {
    2048             675 :                 if (enclosure_str_len < 1) {
    2049             108 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character");
    2050             108 :                         RETURN_FALSE;
    2051             567 :                 } else if (enclosure_str_len > 1) {
    2052             135 :                         php_error_docref(NULL TSRMLS_CC, E_NOTICE, "enclosure must be a single character");
    2053                 :                 }
    2054                 :                 /* use first character from string */
    2055             567 :                 enclosure = *enclosure_str;
    2056                 :         }
    2057                 : 
    2058            1056 :         PHP_STREAM_TO_ZVAL(stream, &fp);
    2059                 : 
    2060            1056 :         count = zend_hash_num_elements(Z_ARRVAL_P(fields));
    2061            1056 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(fields), &pos);
    2062            3231 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(fields), (void **) &field_tmp, &pos) == SUCCESS) {
    2063            1119 :                 field = **field_tmp;
    2064                 : 
    2065            1119 :                 if (Z_TYPE_PP(field_tmp) != IS_STRING) {
    2066            1119 :                         zval_copy_ctor(&field);
    2067            1119 :                         convert_to_string(&field);
    2068                 :                 }
    2069                 : 
    2070                 :                 /* enclose a field that contains a delimiter, an enclosure character, or a newline */
    2071            1744 :                 if (FPUTCSV_FLD_CHK(delimiter) ||
    2072                 :                         FPUTCSV_FLD_CHK(enclosure) ||
    2073                 :                         FPUTCSV_FLD_CHK(escape_char) ||
    2074                 :                         FPUTCSV_FLD_CHK('\n') ||
    2075                 :                         FPUTCSV_FLD_CHK('\r') ||
    2076                 :                         FPUTCSV_FLD_CHK('\t') ||
    2077                 :                         FPUTCSV_FLD_CHK(' ')
    2078                 :                 ) {
    2079             625 :                         char *ch = Z_STRVAL(field);
    2080             625 :                         char *end = ch + Z_STRLEN(field);
    2081             625 :                         int escaped = 0;
    2082                 : 
    2083             625 :                         smart_str_appendc(&csvline, enclosure);
    2084           11237 :                         while (ch < end) {
    2085            9987 :                                 if (*ch == escape_char) {
    2086              16 :                                         escaped = 1;
    2087           11558 :                                 } else if (!escaped && *ch == enclosure) {
    2088            1587 :                                         smart_str_appendc(&csvline, enclosure);
    2089                 :                                 } else {
    2090            8384 :                                         escaped = 0;
    2091                 :                                 }
    2092            9987 :                                 smart_str_appendc(&csvline, *ch);
    2093            9987 :                                 ch++;
    2094                 :                         }
    2095             625 :                         smart_str_appendc(&csvline, enclosure);
    2096                 :                 } else {
    2097             494 :                         smart_str_appendl(&csvline, Z_STRVAL(field), Z_STRLEN(field));
    2098                 :                 }
    2099                 : 
    2100            1119 :                 if (++i != count) {
    2101              63 :                         smart_str_appendl(&csvline, &delimiter, 1);
    2102                 :                 }
    2103            1119 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(fields), &pos);
    2104                 : 
    2105            1119 :                 if (Z_TYPE_PP(field_tmp) != IS_STRING) {
    2106            1119 :                         zval_dtor(&field);
    2107                 :                 }
    2108                 :         }
    2109                 : 
    2110            1056 :         smart_str_appendc(&csvline, '\n');
    2111            1056 :         smart_str_0(&csvline);
    2112                 : 
    2113            1056 :         ret = php_stream_write(stream, csvline.c, csvline.len);
    2114            1056 :         smart_str_free(&csvline);
    2115                 : 
    2116            1056 :         RETURN_LONG(ret);
    2117                 : }
    2118                 : /* }}} */
    2119                 : 
    2120                 : /* {{{ proto array fgetcsv(resource fp [,int length [, string delimiter [, string enclosure[, string escape]]]]) U
    2121                 :    Get line from file pointer and parse for CSV fields */
    2122                 : #define PHP_FGETCSV_TRUNCATE(field) \
    2123                 : if (argc > 4) { \
    2124                 :         /* Caller knows about new semantics since they're using new param, allow multichar */ \
    2125                 : } else if (field##_type == IS_STRING && field##_len > 1) { \
    2126                 :         php_error_docref(NULL TSRMLS_CC, E_NOTICE, #field " must be a single character"); \
    2127                 :         delimiter_len = 1; \
    2128                 : } else if (field##_type == IS_UNICODE && u_countChar32((UChar*)field, field##_len) > 1) { \
    2129                 :         int __tmp = 0; \
    2130                 :         php_error_docref(NULL TSRMLS_CC, E_NOTICE, #field " must be a single character"); \
    2131                 :         U16_FWD_1(((UChar*)field), __tmp, field##_len); \
    2132                 :         field##_len = __tmp; \
    2133                 : }
    2134                 : 
    2135                 : PHP_FUNCTION(fgetcsv)
    2136            3012 : {
    2137            3012 :         zend_uchar delimiter_type = IS_STRING, enclosure_type = IS_STRING, escape_type = IS_STRING;
    2138            3012 :         char *delimiter = ",", *enclosure = "\"", *escape = "\\";
    2139            3012 :         int delimiter_len = 1, enclosure_len = 1, escape_len = 1;
    2140            3012 :         long len = -1;
    2141                 :         zstr buf;
    2142                 :         size_t buf_len;
    2143            3012 :         int argc = ZEND_NUM_ARGS();
    2144                 :         php_stream *stream;
    2145                 :         zval *zstream;
    2146            3012 :         zend_uchar delimiter_free = 0, enclosure_free = 0, escape_free = 0;
    2147                 : 
    2148            3012 :         if (zend_parse_parameters(argc TSRMLS_CC, "r|lttt", &zstream, &len,
    2149                 :                                                 &delimiter, &delimiter_len, &delimiter_type,
    2150                 :                                                 &enclosure, &enclosure_len, &enclosure_type,
    2151                 :                                                 &escape,    &escape_len,    &escape_type) == FAILURE) {
    2152              14 :                 return;
    2153                 :         }
    2154                 : 
    2155            2998 :         PHP_STREAM_TO_ZVAL(stream, &zstream);
    2156                 : 
    2157                 :         /* Make sure that there is at least one character in string,
    2158                 :          * For userspace BC purposes we generally limit delimiters and enclosures to 1 character,
    2159                 :          * though the code now supports multiple characters
    2160                 :          *
    2161                 :          * If this function is called with all five parameters however,
    2162                 :          * then multiple characters are allowed for all subarguments */
    2163            2998 :         if (delimiter_len < 1) {
    2164             240 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "delimiter must be a character");
    2165             240 :                 RETURN_FALSE;
    2166            2758 :         } else PHP_FGETCSV_TRUNCATE(delimiter);
    2167                 : 
    2168            2758 :         if (enclosure_len < 1) {
    2169             120 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character");
    2170             120 :                 RETURN_FALSE;
    2171            2638 :         } else PHP_FGETCSV_TRUNCATE(enclosure);
    2172                 : 
    2173            2638 :         if (escape_len < 1) {
    2174               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "escape must be a character");
    2175               0 :                 RETURN_FALSE;
    2176                 :         }
    2177                 : 
    2178            2638 :         if (len < -1) {
    2179             360 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter may not be negative");
    2180             360 :                 RETURN_FALSE;
    2181            2278 :         } else if (len == 0) {
    2182             196 :                 len = -1;
    2183                 :         }
    2184                 : 
    2185            2278 :         if (stream->readbuf_type == IS_STRING) {
    2186                 :                 /* Binary mode stream needs binary delimiter/enclosure */
    2187            1562 :                 if (delimiter_type == IS_UNICODE) {
    2188            1210 :                         if (FAILURE == zend_unicode_to_string(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &delimiter, &delimiter_len, (UChar*)delimiter, delimiter_len TSRMLS_CC)) {
    2189               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed converting delimiter from unicode");
    2190               0 :                                 RETVAL_FALSE;
    2191               0 :                                 goto cleanup;
    2192                 :                         }
    2193            1210 :                         delimiter_free = 1;
    2194                 :                 }
    2195            1562 :                 if (enclosure_type == IS_UNICODE) {
    2196             844 :                         if (FAILURE == zend_unicode_to_string(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &enclosure, &enclosure_len, (UChar*)enclosure, enclosure_len TSRMLS_CC)) {
    2197               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed converting enclosure from unicode");
    2198               0 :                                 RETVAL_FALSE;
    2199               0 :                                 goto cleanup;
    2200                 :                         }
    2201             844 :                         enclosure_free = 1;
    2202                 :                 }
    2203            1562 :                 if (escape_type == IS_UNICODE) {
    2204               1 :                         if (FAILURE == zend_unicode_to_string(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &escape, &escape_len, (UChar*)escape, escape_len TSRMLS_CC)) {
    2205               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed converting escape from unicode");
    2206               0 :                                 RETVAL_FALSE;
    2207               0 :                                 goto cleanup;
    2208                 :                         }
    2209               1 :                         escape_free = 1;
    2210                 :                 }
    2211                 :         } else {
    2212                 :                 /* Unicode mode stream needs unicode delimiter/enclosure */
    2213             716 :                 if (delimiter_type == IS_STRING) {
    2214             151 :                         if (FAILURE == zend_string_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), (UChar**)&delimiter, &delimiter_len, delimiter, delimiter_len TSRMLS_CC)) {
    2215               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed converting delimiter to unicode");
    2216               0 :                                 RETVAL_FALSE;
    2217               0 :                                 goto cleanup;
    2218                 :                         }
    2219             151 :                         delimiter_free = 1;
    2220                 :                 }
    2221             716 :                 if (enclosure_type == IS_STRING) {
    2222             331 :                         if (FAILURE == zend_string_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), (UChar**)&enclosure, &enclosure_len, enclosure, enclosure_len TSRMLS_CC)) {
    2223               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed converting enclosure to unicode");
    2224               0 :                                 RETVAL_FALSE;
    2225               0 :                                 goto cleanup;
    2226                 :                         }
    2227             331 :                         enclosure_free = 1;
    2228                 :                 }
    2229             716 :                 if (escape_type == IS_STRING) {
    2230             716 :                         if (FAILURE == zend_string_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), (UChar**)&escape, &escape_len, escape, escape_len TSRMLS_CC)) {
    2231               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed converting escape to unicode");
    2232               0 :                                 RETVAL_FALSE;
    2233               0 :                                 goto cleanup;
    2234                 :                         }
    2235             716 :                         escape_free = 1;
    2236                 :                 }
    2237                 :         }
    2238                 : 
    2239            2278 :         if (len < 0) {
    2240             534 :                 buf.v = php_stream_get_line_ex(stream, stream->readbuf_type, NULL_ZSTR, 0, 0, &buf_len);
    2241                 :         } else {
    2242            1744 :                 buf.v = stream->readbuf_type == IS_UNICODE ? eumalloc(len + 1) : emalloc(len + 1);
    2243            1744 :                 if (php_stream_get_line_ex(stream, stream->readbuf_type, buf, len + 1, len + 1, &buf_len) == NULL) {
    2244             438 :                         efree(buf.v);
    2245             438 :                         RETVAL_FALSE;
    2246             438 :                         goto cleanup;
    2247                 :                 }
    2248                 :         }
    2249                 : 
    2250            1840 :         if (!buf.v) {
    2251                 :                 /* No data */
    2252             197 :                 RETVAL_FALSE;
    2253             197 :                 goto cleanup;
    2254                 :         }
    2255                 : 
    2256            1643 :         if (stream->readbuf_type == IS_UNICODE) {
    2257                 :                 /* Unicode mode */
    2258             531 :                 php_u_fgetcsv(stream, (UChar*)delimiter, delimiter_len, (UChar*)enclosure, enclosure_len, (UChar*)escape, escape_len, buf.u, buf_len, return_value TSRMLS_CC);
    2259                 :         } else {
    2260                 :                 /* Binary mode */
    2261            1112 :                 php_fgetcsv_ex(stream, delimiter, delimiter_len, enclosure, enclosure_len, escape, escape_len, buf.s, buf_len, return_value TSRMLS_CC);
    2262                 :         }
    2263                 : 
    2264            2278 : cleanup:
    2265            2278 :         if (delimiter_free) {
    2266            1361 :                 efree(delimiter);
    2267                 :         }
    2268            2278 :         if (enclosure_free) {
    2269            1175 :                 efree(enclosure);
    2270                 :         }
    2271            2278 :         if (escape_free) {
    2272             717 :                 efree(escape);
    2273                 :         }
    2274                 : }
    2275                 : /* }}} */
    2276                 : 
    2277                 : PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, char escape, size_t buf_len, char *buf, zval *return_value TSRMLS_DC) /* {{{ */
    2278              18 : {
    2279              18 :         char *delim = &delimiter, *enc = &enclosure, *buffer = buf, *esc = &escape;
    2280              18 :         int delim_len = 1, enc_len = 1, esc_len = 1, buffer_len = buf_len;
    2281              18 :         zend_uchar type = IS_STRING;
    2282                 : 
    2283              18 :         if (stream) {
    2284              18 :                 type = stream->readbuf_type;
    2285                 :         }
    2286                 : 
    2287              18 :         if (type == IS_UNICODE) {
    2288                 : 
    2289                 :                 /* Unicode stream, but binary delimiter/enclosures/prefetch, promote to unicode */
    2290               0 :                 if (FAILURE == zend_string_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), (UChar**)&delim, &delim_len, &delimiter, 1 TSRMLS_CC)) {
    2291               0 :                         INIT_PZVAL(return_value);
    2292               0 :                         return;
    2293                 :                 }
    2294               0 :                 if (FAILURE == zend_string_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), (UChar**)&enc, &enc_len, &enclosure, 1 TSRMLS_CC)) {
    2295               0 :                         efree(delim);
    2296               0 :                         INIT_PZVAL(return_value);
    2297               0 :                         return;
    2298                 :                 }
    2299               0 :                 if (FAILURE == zend_string_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), (UChar**)&esc, &esc_len, &escape, 1 TSRMLS_CC)) {
    2300               0 :                         efree(delim);
    2301               0 :                         efree(enc);
    2302               0 :                         INIT_PZVAL(return_value);
    2303               0 :                         return;
    2304                 :                 }
    2305               0 :                 if (FAILURE == zend_string_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), (UChar**)&buffer, &buffer_len, buf, buf_len TSRMLS_CC)) {
    2306               0 :                         efree(delim);
    2307               0 :                         efree(enc);
    2308               0 :                         efree(esc);
    2309               0 :                         INIT_PZVAL(return_value);
    2310               0 :                         return;
    2311                 :                 }
    2312                 : 
    2313               0 :                 php_u_fgetcsv(stream, (UChar*)delim, delim_len, (UChar*)enc, enc_len, (UChar*)esc, esc_len,
    2314                 :                                 (UChar*)buffer, buffer_len, return_value TSRMLS_CC);
    2315                 : 
    2316                 :                 /* Types converted, free storage */
    2317               0 :                 efree(delim);
    2318               0 :                 efree(enc);
    2319               0 :                 efree(esc);
    2320                 :         } else {
    2321                 :                 /* Binary stream with binary delimiter/enclosures/prefetch */
    2322              18 :                 php_fgetcsv_ex(stream, delim, delim_len, enc, enc_len, esc, esc_len, buffer, buffer_len, return_value TSRMLS_CC);
    2323                 :         }
    2324                 : }
    2325                 : 
    2326                 : typedef enum _php_fgetcsv_state {
    2327                 :         PHP_FGETCSV_READY,
    2328                 :         PHP_FGETCSV_FIELD_NO_ENC,
    2329                 :         PHP_FGETCSV_FIELD_WITH_ENC,
    2330                 :         PHP_FGETCSV_POST_ENC,
    2331                 : } php_fgetcsv_state;
    2332                 : 
    2333                 : #define PHP_FGETCSV_BIN_CHECK(p, e, m, mlen) ((p) < (e) && (((mlen) == 1 && *(p) == *(m)) || ((mlen) > 1 && (((e) - (p)) >= (mlen)) && memcmp((p), (m), (mlen)) == 0)))
    2334                 : 
    2335                 : /* Binary mode fgetcsv */
    2336                 : PHPAPI void php_fgetcsv_ex(php_stream *stream,
    2337                 :                 char *delimiter, int delimiter_len,
    2338                 :                 char *enclosure, int enclosure_len,
    2339                 :                 char *escape, int escape_len,
    2340                 :                 char *buffer, int buffer_len,
    2341                 :                 zval *return_value TSRMLS_DC)
    2342            1131 : {
    2343            1131 :         php_fgetcsv_state state = PHP_FGETCSV_READY;
    2344            1131 :         char *p = buffer, *e = buffer + buffer_len, *field_start = NULL, *field_end = NULL;
    2345                 : 
    2346            1131 :         array_init(return_value);
    2347                 : 
    2348            2262 :         while (*p == ' ' || *p == '\t') {
    2349               0 :                 p++;
    2350                 :         }
    2351                 : 
    2352            1131 :         if (*p == '\r' || *p == '\n') {
    2353              20 :                 add_next_index_null(return_value);
    2354              20 :                 goto end;
    2355                 :         }
    2356                 : 
    2357           21397 :         while(p < e) {
    2358           19175 :                 switch (state) {
    2359                 :                         case PHP_FGETCSV_READY:
    2360            2168 : ready_state:
    2361                 :                                 /* Ready to start a new field */
    2362                 : 
    2363                 :                                 /* Is there nothing left to scan? */
    2364            2168 :                                 if (*p == '\r' || *p == '\n') {
    2365                 :                                         /* Terminal delimiter, treat as empty field */
    2366              96 :                                         p++;
    2367              96 :                                         add_next_index_stringl(return_value, "", 0, 1);
    2368              96 :                                         break;
    2369                 :                                 }
    2370                 : 
    2371                 :                                 /* Is it enclosed? */
    2372            2072 :                                 if (PHP_FGETCSV_BIN_CHECK(p, e, enclosure, enclosure_len)) {
    2373                 :                                         /* Enclosure encountered, switch state */
    2374             847 :                                         state = PHP_FGETCSV_FIELD_WITH_ENC;
    2375             847 :                                         p += enclosure_len;
    2376             847 :                                         field_start = p;
    2377             847 :                                         break;
    2378                 :                                 }
    2379                 : 
    2380                 :                                 /* Is it an immediate delimiter? */
    2381            1225 :                                 if (PHP_FGETCSV_BIN_CHECK(p, e, delimiter, delimiter_len)) {
    2382                 :                                         /* Immediate delimiter, treate as empty field */
    2383             135 :                                         p += delimiter_len;
    2384             135 :                                         add_next_index_stringl(return_value, "", 0, 1);
    2385             135 :                                         break;
    2386                 :                                 }
    2387                 : 
    2388                 :                                 /* Whitespace? */
    2389            1090 :                                 if (*p == ' ' || *p == '\t') {
    2390               9 :                                         p++;
    2391               9 :                                         if (p >= e) break;
    2392               9 :                                         goto ready_state;
    2393                 :                                 }
    2394                 : 
    2395                 :                                 /* Otherwise, starting a new field without enclosures */
    2396            1081 :                                 state = PHP_FGETCSV_FIELD_NO_ENC;
    2397            1081 :                                 field_start = p++;
    2398            1081 :                                 field_end = NULL;
    2399                 : 
    2400                 :                                 /* Is it an escape character? */
    2401            1081 :                                 if ((PHP_FGETCSV_BIN_CHECK(p, e, escape, escape_len) && escape != enclosure) ||
    2402                 :                                         (PHP_FGETCSV_BIN_CHECK(p, e, escape, escape_len) &&
    2403                 :                                         PHP_FGETCSV_BIN_CHECK(p+1, e, escape, escape_len) && escape == enclosure)
    2404                 :                                 ) {
    2405                 :                                         /* Skip escape sequence and let next char be treated as literal
    2406                 :                                          * If enclosure is the same character as esacpe, it is considered as esacped
    2407                 :                                          * if it appears twice */
    2408               0 :                                         p += escape_len - 1;
    2409                 :                                         /* FALL THROUGH */
    2410                 :                                 }
    2411            1081 :                                 break;
    2412                 : 
    2413                 :                         case PHP_FGETCSV_FIELD_WITH_ENC:
    2414            6263 : with_enc:
    2415                 :                                 /* Check for ending enclosure */
    2416            6263 :                                 if (PHP_FGETCSV_BIN_CHECK(p, e, enclosure, enclosure_len)) {
    2417                 :                                         /* Enclosure encountered, is it paired? */
    2418             999 :                                         if (PHP_FGETCSV_BIN_CHECK(p + enclosure_len, e, enclosure, enclosure_len)) {
    2419                 :                                                 /* Double enclosure gets translated to single enclosure */
    2420             206 :                                                 memmove(p, p + enclosure_len, (e - p) - enclosure_len);
    2421             206 :                                                 e -= enclosure_len;
    2422             206 :                                                 p += enclosure_len;
    2423             206 :                                                 goto with_enc;
    2424                 :                                         } else {
    2425                 :                                                 /* Genuine end enclosure, switch state */
    2426             793 :                                                 field_end = p;
    2427             793 :                                                 p += enclosure_len;
    2428             793 :                                                 state = PHP_FGETCSV_POST_ENC;
    2429             793 :                                                 goto post_enc;
    2430                 :                                         }
    2431                 :                                 }
    2432                 : 
    2433                 :                                 /* Check for field escapes */
    2434            5264 :                                 if (PHP_FGETCSV_BIN_CHECK(p, e, escape, escape_len)) {
    2435              25 :                                         p += escape_len + 1;
    2436                 : 
    2437                 :                                         /* Reprocess for ending enclosures */
    2438              25 :                                         goto with_enc;
    2439                 :                                 }
    2440                 : 
    2441                 :                                 /* Simple character */
    2442            5239 :                                 if (e - p) {
    2443            5239 :                                         p++;
    2444                 :                                 }
    2445                 : 
    2446                 :                                 /* Hungry? */
    2447            5239 :                                 if (((e - p) < enclosure_len) && stream) {
    2448                 :                                         /* Feed me! */
    2449                 :                                         size_t new_len;
    2450              86 :                                         char *new_buf = php_stream_get_line(stream, NULL_ZSTR, 0, &new_len);
    2451                 : 
    2452              86 :                                         if (new_buf) {
    2453              82 :                                                 int tmp_len = new_len + e - field_start;
    2454              82 :                                                 char *tmp = emalloc(tmp_len);
    2455                 : 
    2456                 :                                                 /* Realign scan buffer */
    2457              82 :                                                 memcpy(tmp, field_start, e - field_start);
    2458              82 :                                                 memcpy(tmp + (e - field_start), new_buf, new_len);
    2459              82 :                                                 field_start = tmp;
    2460              82 :                                                 if (field_end) {
    2461               0 :                                                         field_end = tmp + (field_end - field_start);
    2462                 :                                                 }
    2463              82 :                                                 efree(buffer);
    2464              82 :                                                 efree(new_buf);
    2465              82 :                                                 buffer = tmp;
    2466              82 :                                                 buffer_len = tmp_len;
    2467              82 :                                                 p = buffer;
    2468              82 :                                                 e = buffer + buffer_len;
    2469                 :                                         }
    2470                 :                                 }
    2471                 : 
    2472            5239 :                                 if ((e - p) == 0) {
    2473                 :                                         /* Nothing left to consume the buffer, use it */
    2474               4 :                                         add_next_index_stringl(return_value, field_start, p - field_start, 1);
    2475                 : 
    2476                 :                                         /* Loop is dying anyway, but be pedantic */
    2477               4 :                                         state = PHP_FGETCSV_READY;
    2478               4 :                                         field_start = field_end = NULL;
    2479               4 :                                         break;
    2480                 :                                 }
    2481            5235 :                                 break;
    2482                 : 
    2483                 :                         case PHP_FGETCSV_POST_ENC:
    2484            2276 : post_enc:
    2485                 :                                 /* Check for delimiters or EOL */
    2486            2276 :                                 if (p >= e || *p == '\r' || *p == '\n' || PHP_FGETCSV_BIN_CHECK(p, e, delimiter, delimiter_len)) {
    2487             793 :                                         int field_len = field_end - field_start;
    2488                 :                                         char *field;
    2489                 : 
    2490             793 :                                         if ((p - enclosure_len) > field_end) {
    2491                 :                                                 /* There's cruft, append it to the proper field */
    2492             221 :                                                 int cruft_len = p - (field_end + enclosure_len);
    2493                 : 
    2494             221 :                                                 field = emalloc(field_len + cruft_len + 1);
    2495             221 :                                                 memcpy(field, field_start, field_len);
    2496             221 :                                                 memcpy(field + field_len, field_end + enclosure_len, cruft_len);
    2497                 : 
    2498             221 :                                                 field_len += cruft_len;
    2499             221 :                                                 field[field_len] = 0;
    2500                 :                                         } else {
    2501             572 :                                                 field = estrndup(field_start, field_end - field_start);
    2502                 :                                         }
    2503             793 :                                         add_next_index_stringl(return_value, field, field_len, 0);
    2504                 : 
    2505                 :                                         /* Reset scanner */
    2506             793 :                                         state = PHP_FGETCSV_READY;
    2507             793 :                                         field_start = field_end = NULL;
    2508             793 :                                         p += delimiter_len;
    2509             793 :                                         if (p >= e) break;
    2510             485 :                                         goto ready_state;
    2511                 :                                 }
    2512                 : 
    2513                 :                                 /* Queue anything else as cruft */
    2514            1483 :                                 p++;
    2515            1483 :                                 break;
    2516                 : 
    2517                 :                         case PHP_FGETCSV_FIELD_NO_ENC:
    2518                 :                                 /* Check for escapes */
    2519           10414 :                                 if (!PHP_FGETCSV_BIN_CHECK(p, e, delimiter, delimiter_len) && PHP_FGETCSV_BIN_CHECK(p, e, escape, escape_len)) {
    2520              41 :                                         p += escape_len + 1;
    2521                 :                                 }
    2522                 : 
    2523                 :                                 /* Check for delimiter */
    2524           10414 :                                 if (p >= e || *p == '\r' || *p == '\n' || PHP_FGETCSV_BIN_CHECK(p, e, delimiter, delimiter_len)) {
    2525            1044 :                                         add_next_index_stringl(return_value, field_start, p - field_start, 1);
    2526                 : 
    2527                 :                                         /* Reset scanner */
    2528            1044 :                                         state = PHP_FGETCSV_READY;
    2529            1044 :                                         field_start = field_end = NULL;
    2530            1044 :                                         p += delimiter_len;
    2531            1044 :                                         if (p >= e) break;
    2532             428 :                                         goto ready_state;
    2533                 :                                 }
    2534                 : 
    2535                 :                                 /* Simple character */
    2536            9370 :                                 p++;
    2537                 : 
    2538            9370 :                                 if (p == e) {
    2539              23 :                                         add_next_index_stringl(return_value, field_start, p - field_start, 1);
    2540                 :                                         /* Reset scanner even though we're dying */
    2541              23 :                                         state = PHP_FGETCSV_READY;
    2542              23 :                                         field_start = field_end = NULL;
    2543              23 :                                         p += delimiter_len;
    2544                 :                                 }
    2545                 :                                 break;
    2546                 :                 }
    2547                 :         }
    2548            1131 : end:
    2549            1131 :         if (stream) {
    2550            1130 :                 efree(buffer);
    2551                 :         }
    2552            1131 : }
    2553                 : /* }}} */
    2554                 : 
    2555                 : #define PHP_FGETCSV_UNI_CHECK(p, e, m, mlen) ((p) < (e) && (((mlen) == 1 && *(p) == *(m)) || ((mlen) > 1 && (((e) - (p)) >= (mlen)) && memcmp((p), (m), UBYTES(mlen)) == 0)))
    2556                 : 
    2557                 : /* Unicode mode fgetcsv */
    2558                 : PHPAPI void php_u_fgetcsv(php_stream *stream, UChar *delimiter, int delimiter_len, UChar *enclosure, int enclosure_len, UChar *escape, int escape_len, UChar *buffer, int buffer_len, zval *return_value TSRMLS_DC) /* {{{ */
    2559             542 : {
    2560             542 :         php_fgetcsv_state state = PHP_FGETCSV_READY;
    2561             542 :         UChar *p = buffer, *e = buffer + buffer_len, *field_start = NULL, *field_end = NULL;
    2562                 : 
    2563             542 :         array_init(return_value);
    2564                 : 
    2565            1084 :         while (*p == ' ' || *p == '\t') {
    2566               0 :                 p++;
    2567                 :         }
    2568                 : 
    2569             542 :         if (*p == '\r' || *p == '\n') {
    2570              10 :                 add_next_index_null(return_value);
    2571              10 :                 goto end;
    2572                 :         }
    2573                 : 
    2574            9545 :         while(p < e) {
    2575            8481 :                 switch (state) {
    2576                 :                         case PHP_FGETCSV_READY:
    2577            1457 : ready_state:
    2578                 :                                 /* Ready to start a new field */
    2579                 : 
    2580                 :                                 /* Is there nothing left to scan? */
    2581            1457 :                                 if (*p == '\r' || *p == '\n') {
    2582                 :                                         /* Terminal delimiter, treat as empty field */
    2583              70 :                                         p++;
    2584              70 :                                         add_next_index_unicodel(return_value, (UChar*)"", 0, 1);
    2585              70 :                                         break;
    2586                 :                                 }
    2587                 : 
    2588                 :                                 /* Is it enclosed? */
    2589            1387 :                                 if (PHP_FGETCSV_UNI_CHECK(p, e, enclosure, enclosure_len)) {
    2590                 :                                         /* Enclosure encountered, switch state */
    2591             403 :                                         state = PHP_FGETCSV_FIELD_WITH_ENC;
    2592             403 :                                         p += enclosure_len;
    2593             403 :                                         field_start = p;
    2594             403 :                                         break;
    2595                 :                                 }
    2596                 : 
    2597                 :                                 /* Is it an immediate delimiter? */
    2598             984 :                                 if (PHP_FGETCSV_UNI_CHECK(p, e, delimiter, delimiter_len)) {
    2599                 :                                         /* Immediate delimiter, treate as empty field */
    2600              66 :                                         p += delimiter_len;
    2601              66 :                                         add_next_index_unicodel(return_value, (UChar*)"", 0, 1);
    2602              66 :                                         break;
    2603                 :                                 }
    2604                 : 
    2605                 :                                 /* Whitespace? */
    2606             918 :                                 if (*p == ' ' || *p == '\t') {
    2607               2 :                                         p++;
    2608               2 :                                         if (p >= e) break;
    2609               2 :                                         goto ready_state;
    2610                 :                                 }
    2611                 : 
    2612                 :                                 /* Otherwise, starting a new field without enclosures */
    2613             916 :                                 state = PHP_FGETCSV_FIELD_NO_ENC;
    2614             916 :                                 field_start = p++;
    2615             916 :                                 field_end = NULL;
    2616                 : 
    2617                 :                                 /* Is it an escape character? */
    2618             916 :                                 if ((PHP_FGETCSV_UNI_CHECK(p, e, escape, escape_len) && escape != enclosure) ||
    2619                 :                                         (PHP_FGETCSV_UNI_CHECK(p, e, escape, escape_len) &&
    2620                 :                                         PHP_FGETCSV_UNI_CHECK(p+1, e, escape, escape_len) && escape == enclosure)
    2621                 :                                 ) {
    2622                 :                                         /* Skip escape sequence and let next char be treated as literal
    2623                 :                                          * If enclosure is the same character as escape, it is considered as escaped
    2624                 :                                          * if it appears twice */
    2625               0 :                                         p += escape_len - 1;
    2626                 :                                         /* FALL THROUGH */
    2627                 :                                 }
    2628             916 :                                 break;
    2629                 : 
    2630                 :                         case PHP_FGETCSV_FIELD_WITH_ENC:
    2631            2133 : with_enc:
    2632                 :                                 /* Check for ending enclosure */
    2633            2133 :                                 if (PHP_FGETCSV_UNI_CHECK(p, e, enclosure, enclosure_len)) {
    2634                 :                                         /* Enclosure encountered, is it paired? */
    2635             455 :                                         if (PHP_FGETCSV_UNI_CHECK(p + enclosure_len, e, enclosure, enclosure_len)) {
    2636                 :                                                 /* Double enclosure gets translated to single enclosure */
    2637              77 :                                                 memmove(p, p + enclosure_len, UBYTES((e - p) - enclosure_len));
    2638              77 :                                                 e -= enclosure_len;
    2639              77 :                                                 p += enclosure_len;
    2640              77 :                                                 if (p >= e) break;
    2641              77 :                                                 goto with_enc;
    2642                 :                                         } else {
    2643                 :                                                 /* Genuine end enclosure, switch state */
    2644             378 :                                                 field_end = p;
    2645             378 :                                                 p += enclosure_len;
    2646             378 :                                                 state = PHP_FGETCSV_POST_ENC;
    2647             378 :                                                 goto post_enc;
    2648                 :                                         }
    2649                 :                                 }
    2650                 : 
    2651                 :                                 /* Check for field escapes */
    2652            1678 :                                 if (PHP_FGETCSV_UNI_CHECK(p, e, escape, escape_len)) {
    2653               2 :                                         p += escape_len + 1;
    2654                 : 
    2655                 :                                         /* Reprocess for ending enclosures */
    2656               2 :                                         if (p >= e) break;
    2657               2 :                                         goto with_enc;
    2658                 :                                 }
    2659                 : 
    2660                 :                                 /* Simple character */
    2661            1676 :                                 if (e - p) {
    2662            1676 :                                         p++;
    2663                 :                                 }
    2664                 : 
    2665                 :                                 /* Hungry? */
    2666            1676 :                                 if (((e - p) < enclosure_len) && stream) {
    2667                 :                                         /* Feed me! */
    2668                 :                                         size_t new_len;
    2669              30 :                                         UChar *new_buf = (UChar*)php_stream_get_line_ex(stream, IS_UNICODE, NULL_ZSTR, 0, 0, &new_len);
    2670                 : 
    2671              30 :                                         if (new_buf) {
    2672              30 :                                                 int tmp_len = new_len + e - field_start;
    2673              30 :                                                 UChar *tmp = eumalloc(tmp_len);
    2674                 : 
    2675                 :                                                 /* Realign scan buffer, ick -- expensive */
    2676              30 :                                                 memcpy(tmp, field_start, UBYTES(e - field_start));
    2677              30 :                                                 memcpy(tmp + (e - field_start), new_buf, UBYTES(new_len));
    2678              30 :                                                 field_start = tmp;
    2679              30 :                                                 if (field_end) {
    2680               0 :                                                         field_end = tmp + (field_end - field_start);
    2681                 :                                                 }
    2682              30 :                                                 efree(buffer);
    2683              30 :                                                 efree(new_buf);
    2684              30 :                                                 buffer = tmp;
    2685              30 :                                                 buffer_len = tmp_len;
    2686              30 :                                                 p = buffer;
    2687              30 :                                                 e = buffer + buffer_len;
    2688                 :                                         }
    2689                 :                                 }
    2690                 : 
    2691            1676 :                                 if ((e - p) == 0) {
    2692                 :                                         /* Nothing left to consume the buffer */
    2693               0 :                                         add_next_index_unicodel(return_value, field_start, p - field_start, 1);
    2694                 : 
    2695                 :                                         /* Loop is dying, but cleanup anyway */
    2696               0 :                                         state = PHP_FGETCSV_READY;
    2697               0 :                                         field_start = field_end = NULL;
    2698               0 :                                         break;
    2699                 :                                 }
    2700            1676 :                                 break;
    2701                 : 
    2702                 :                         case PHP_FGETCSV_POST_ENC:
    2703            1123 : post_enc:
    2704                 :                                 /* Check for delimiters or EOL */
    2705            1123 :                                 if (p >= e || *p == '\r' || *p == '\n' || PHP_FGETCSV_UNI_CHECK(p, e, delimiter, delimiter_len)) {
    2706             377 :                                         int field_len = field_end - field_start;
    2707                 :                                         UChar *field;
    2708                 : 
    2709             377 :                                         if ((p - enclosure_len) > field_end) {
    2710                 :                                                 /* There's cruft, append it to the regular field */
    2711             110 :                                                 int cruft_len = p - (field_end + enclosure_len);
    2712                 : 
    2713             110 :                                                 field = eumalloc(field_len + cruft_len + 1);
    2714             110 :                                                 memcpy(field, field_start, UBYTES(field_len));
    2715             110 :                                                 memcpy(field + field_len, field_end + enclosure_len, UBYTES(cruft_len));
    2716             110 :                                                 field_len += cruft_len;
    2717             110 :                                                 field[field_len] = 0;
    2718                 :                                         } else {
    2719             267 :                                                 field = eustrndup(field_start, field_len);
    2720                 :                                         }
    2721             377 :                                         add_next_index_unicodel(return_value, field, field_len, 0);
    2722                 : 
    2723                 :                                         /* Reset scanner state */
    2724             377 :                                         state = PHP_FGETCSV_READY;
    2725             377 :                                         field_start = field_end = NULL;
    2726             377 :                                         p += delimiter_len;
    2727             377 :                                         goto ready_state;
    2728                 :                                 }
    2729                 : 
    2730                 :                                 /* Queue anything else as cruft */
    2731             746 :                                 p++;
    2732             746 :                                 break;
    2733                 : 
    2734                 :                         case PHP_FGETCSV_FIELD_NO_ENC:
    2735                 :                                 /* Check for escapes */
    2736            5086 :                                 if (!PHP_FGETCSV_UNI_CHECK(p, e, delimiter, delimiter_len) && PHP_FGETCSV_UNI_CHECK(p, e, escape, escape_len)) {
    2737              20 :                                         p += escape_len + 1;
    2738                 :                                 }
    2739                 : 
    2740                 :                                 /* Check for delimiter */
    2741            5086 :                                 if (p >= e || *p == '\r' || *p == '\n' || PHP_FGETCSV_UNI_CHECK(p, e, delimiter, delimiter_len)) {
    2742             482 :                                         add_next_index_unicodel(return_value, field_start, p - field_start, 1);
    2743             482 :                                         state = PHP_FGETCSV_READY;
    2744             482 :                                         field_start = field_end = NULL;
    2745             482 :                                         p += delimiter_len;
    2746             482 :                                         goto ready_state;
    2747                 :                                 }
    2748                 : 
    2749                 :                                 /* Simple character */
    2750            4604 :                                 p++;
    2751                 : 
    2752            4604 :                                 if (p == e) {
    2753              13 :                                         add_next_index_unicodel(return_value, field_start, p - field_start, 1);
    2754                 :                                         /* Reset scanner even though we're dying */
    2755              13 :                                         state = PHP_FGETCSV_READY;
    2756              13 :                                         field_start = field_end = NULL;
    2757              13 :                                         p += delimiter_len;
    2758                 :                                 }
    2759                 :                                 break;
    2760                 :                 }
    2761                 :         }
    2762             542 : end:
    2763             542 :         if (stream) {
    2764             531 :                 efree(buffer);
    2765                 :         }
    2766             542 : }
    2767                 : /* }}} */
    2768                 : 
    2769                 : #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
    2770                 : /* {{{ proto string realpath(string path) U
    2771                 :    Return the resolved path */
    2772                 : PHP_FUNCTION(realpath)
    2773           23016 : {
    2774                 :         zval **ppfilename;
    2775                 :         char *filename;
    2776                 :         int filename_len;
    2777                 :         char resolved_path_buff[MAXPATHLEN];
    2778                 : 
    2779           23016 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &ppfilename) == FAILURE ||
    2780                 :                 php_stream_path_param_encode(ppfilename, &filename, &filename_len, REPORT_ERRORS, FG(default_context)) == FAILURE) {
    2781               2 :                 return;
    2782                 :         }
    2783                 : 
    2784           23014 :         if (VCWD_REALPATH(filename, resolved_path_buff)) {
    2785                 : #ifdef ZTS
    2786                 :                 if (VCWD_ACCESS(resolved_path_buff, F_OK)) {
    2787                 :                         RETVAL_FALSE;
    2788                 :                 } else
    2789                 : #endif
    2790                 :                 {
    2791                 :                         UChar *path;
    2792                 :                         int path_len;
    2793                 : 
    2794           22989 :                         if (php_stream_path_decode(&php_plain_files_wrapper, &path, &path_len, resolved_path_buff, strlen(resolved_path_buff), REPORT_ERRORS, FG(default_context)) == SUCCESS) {
    2795           22989 :                                 RETVAL_UNICODEL(path, path_len, 0);
    2796                 :                         } else {
    2797                 :                                 /* Fallback */
    2798               0 :                                 RETVAL_STRING(resolved_path_buff, 1);
    2799                 :                         }
    2800                 :                 }
    2801                 :         } else {
    2802              25 :                 RETVAL_FALSE;
    2803                 :         }
    2804                 : }
    2805                 : /* }}} */
    2806                 : #endif
    2807                 : 
    2808                 : /* See http://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2.2 */
    2809                 : #define PHP_META_HTML401_CHARS "-_.:"
    2810                 : 
    2811                 : /* {{{ php_next_meta_token
    2812                 :    Tokenizes an HTML file for get_meta_tags */
    2813                 : php_meta_tags_token php_next_meta_token(php_meta_tags_data *md TSRMLS_DC)
    2814             210 : {
    2815             210 :         int ch = 0, compliment;
    2816                 :         char buff[META_DEF_BUFSIZE + 1];
    2817                 : 
    2818             210 :         memset((void *)buff, 0, META_DEF_BUFSIZE + 1);
    2819                 : 
    2820             210 :         while (md->ulc || (!php_stream_eof(md->stream) && (ch = php_stream_getc(md->stream)))) {
    2821             222 :                 if (php_stream_eof(md->stream)) {
    2822               6 :                         break;
    2823                 :                 }
    2824                 : 
    2825             216 :                 if (md->ulc) {
    2826              43 :                         ch = md->lc;
    2827              43 :                         md->ulc = 0;
    2828                 :                 }
    2829                 : 
    2830             216 :                 switch (ch) {
    2831                 :                         case '<':
    2832              25 :                                 return TOK_OPENTAG;
    2833                 :                                 break;
    2834                 : 
    2835                 :                         case '>':
    2836              13 :                                 return TOK_CLOSETAG;
    2837                 :                                 break;
    2838                 : 
    2839                 :                         case '=':
    2840              26 :                                 return TOK_EQUAL;
    2841                 :                                 break;
    2842                 :                         case '/':
    2843               2 :                                 return TOK_SLASH;
    2844                 :                                 break;
    2845                 : 
    2846                 :                         case '\'':
    2847                 :                         case '"':
    2848              26 :                                 compliment = ch;
    2849              26 :                                 md->token_len = 0;
    2850             311 :                                 while (!php_stream_eof(md->stream) && (ch = php_stream_getc(md->stream)) && ch != compliment && ch != '<' && ch != '>') {
    2851             259 :                                         buff[(md->token_len)++] = ch;
    2852                 : 
    2853             259 :                                         if (md->token_len == META_DEF_BUFSIZE) {
    2854               0 :                                                 break;
    2855                 :                                         }
    2856                 :                                 }
    2857                 : 
    2858              26 :                                 if (ch == '<' || ch == '>') {
    2859                 :                                         /* Was just an apostrohpe */
    2860               0 :                                         md->ulc = 1;
    2861               0 :                                         md->lc = ch;
    2862                 :                                 }
    2863                 : 
    2864                 :                                 /* We don't need to alloc unless we are in a meta tag */
    2865              26 :                                 if (md->in_meta) {
    2866              26 :                                         md->token_data = (char *) emalloc(md->token_len + 1);
    2867              26 :                                         memcpy(md->token_data, buff, md->token_len+1);
    2868                 :                                 }
    2869                 : 
    2870              26 :                                 return TOK_STRING;
    2871                 :                                 break;
    2872                 : 
    2873                 :                         case '\n':
    2874                 :                         case '\r':
    2875                 :                         case '\t':
    2876              12 :                                 break;
    2877                 : 
    2878                 :                         case ' ':
    2879              67 :                                 return TOK_SPACE;
    2880                 :                                 break;
    2881                 : 
    2882                 :                         default:
    2883              45 :                                 if (isalnum(ch)) {
    2884              45 :                                         md->token_len = 0;
    2885              45 :                                         buff[(md->token_len)++] = ch;
    2886             264 :                                         while (!php_stream_eof(md->stream) && (ch = php_stream_getc(md->stream)) && (isalnum(ch) || strchr(PHP_META_HTML401_CHARS, ch))) {
    2887             174 :                                                 buff[(md->token_len)++] = ch;
    2888                 : 
    2889             174 :                                                 if (md->token_len == META_DEF_BUFSIZE) {
    2890               0 :                                                         break;
    2891                 :                                                 }
    2892                 :                                         }
    2893                 : 
    2894                 :                                         /* This is ugly, but we have to replace ungetc */
    2895              45 :                                         if (!isalpha(ch) && ch != '-') {
    2896              45 :                                                 md->ulc = 1;
    2897              45 :                                                 md->lc = ch;
    2898                 :                                         }
    2899                 : 
    2900              45 :                                         md->token_data = (char *) emalloc(md->token_len + 1);
    2901              45 :                                         memcpy(md->token_data, buff, md->token_len+1);
    2902                 : 
    2903              45 :                                         return TOK_ID;
    2904                 :                                 } else {
    2905               0 :                                         return TOK_OTHER;
    2906                 :                                 }
    2907                 :                                 break;
    2908                 :                 }
    2909                 :         }
    2910                 : 
    2911               6 :         return TOK_EOF;
    2912                 : }
    2913                 : /* }}} */
    2914                 : 
    2915                 : #ifdef HAVE_FNMATCH
    2916                 : /* {{{ proto bool fnmatch(string pattern, string filename [, int flags]) U
    2917                 :    Match filename against pattern */
    2918                 : PHP_FUNCTION(fnmatch)
    2919             253 : {
    2920                 :         zstr pattern, filename;
    2921                 :         int pattern_len, filename_len;
    2922                 :         char *pattern_utf8, *filename_utf8;
    2923                 :         int pattern_utf8_len, filename_utf8_len;
    2924                 :         zend_uchar type;
    2925             253 :         long flags = 0;
    2926             253 :         UErrorCode status = U_ZERO_ERROR;
    2927                 : 
    2928             253 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "TT|l", &pattern, &pattern_len, &type, &filename, &filename_len, &type, &flags) == FAILURE) {
    2929               6 :                 return;
    2930                 :         }
    2931                 : 
    2932             247 :         if (type == IS_UNICODE) {
    2933             246 :                 zend_unicode_to_string_ex(UG(utf8_conv), &pattern_utf8, &pattern_utf8_len, pattern.u, pattern_len, &status);
    2934             246 :                 zend_unicode_to_string_ex(UG(utf8_conv), &filename_utf8, &filename_utf8_len, filename.u, filename_len, &status);
    2935             246 :                 pattern.s = pattern_utf8;
    2936             246 :                 filename.s = filename_utf8;
    2937             246 :                 filename_len = filename_utf8_len;
    2938                 :         }
    2939             247 :         if (filename_len >= MAXPATHLEN) {
    2940               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filename exceeds the maximum allowed length of %d characters", MAXPATHLEN);
    2941               0 :                 RETURN_FALSE;
    2942                 :         }
    2943                 : 
    2944             247 :         RETVAL_BOOL( ! fnmatch( pattern.s, filename.s, flags ));
    2945                 : 
    2946             247 :         if (type == IS_UNICODE) {
    2947             246 :                 efree(pattern_utf8);
    2948             246 :                 efree(filename_utf8);
    2949                 :         }
    2950                 : }
    2951                 : /* }}} */
    2952                 : #endif
    2953                 : 
    2954                 : /* {{{ proto string sys_get_temp_dir() U
    2955                 :    Returns directory path used for temporary files */
    2956                 : PHP_FUNCTION(sys_get_temp_dir)
    2957             585 : {
    2958                 :         UChar *utemp_dir;
    2959             585 :         char *temp_dir = (char *)php_get_temporary_directory();
    2960             585 :         int temp_dir_len = strlen(temp_dir), utemp_dir_len;
    2961                 : 
    2962                 :         /* else UG(unicode) */
    2963             585 :         if (FAILURE == php_stream_path_decode(NULL, &utemp_dir, &utemp_dir_len, temp_dir, temp_dir_len, REPORT_ERRORS, FG(default_context))) {
    2964               0 :                 RETURN_FALSE;
    2965                 :         }
    2966                 : 
    2967             585 :         RETURN_UNICODEL(utemp_dir, utemp_dir_len, 0);
    2968                 : }
    2969                 : /* }}} */
    2970                 : 
    2971                 : /*
    2972                 :  * Local variables:
    2973                 :  * tab-width: 4
    2974                 :  * c-basic-offset: 4
    2975                 :  * End:
    2976                 :  * vim600: noet sw=4 ts=4 fdm=marker
    2977                 :  * vim<600: noet sw=4 ts=4
    2978                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:43 +0000 (33 hours ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.