root/ext/standard/file.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. php_le_stream_context
  2. ZEND_RSRC_DTOR_FUNC
  3. file_globals_ctor
  4. file_globals_dtor
  5. PHP_INI_BEGIN
  6. PHP_MSHUTDOWN_FUNCTION
  7. PHP_FUNCTION
  8. PHP_FUNCTION
  9. PHP_FUNCTION
  10. PHP_FUNCTION
  11. PHP_FUNCTION
  12. PHP_FUNCTION
  13. PHP_NAMED_FUNCTION
  14. PHP_NAMED_FUNCTION
  15. PHP_FUNCTION
  16. PHP_FUNCTION
  17. PHP_FUNCTION
  18. PHP_FUNCTION
  19. PHP_FUNCTION
  20. PHP_FUNCTION
  21. PHP_FUNCTION
  22. PHP_FUNCTION
  23. PHP_FUNCTION
  24. PHP_FUNCTION
  25. PHP_FUNCTION
  26. PHP_FUNCTION
  27. PHP_FUNCTION
  28. php_mkdir_ex
  29. php_mkdir
  30. PHP_FUNCTION
  31. PHP_FUNCTION
  32. PHP_FUNCTION
  33. PHP_FUNCTION
  34. PHP_FUNCTION
  35. PHP_FUNCTION
  36. PHP_FUNCTION
  37. PHP_NAMED_FUNCTION
  38. PHP_NAMED_FUNCTION
  39. PHP_FUNCTION
  40. php_copy_file
  41. php_copy_file_ex
  42. php_copy_file_ctx
  43. PHP_FUNCTION
  44. php_fgetcsv_lookup_trailing_spaces
  45. PHP_FUNCTION
  46. php_fputcsv
  47. PHP_FUNCTION
  48. php_fgetcsv
  49. PHP_FUNCTION
  50. php_next_meta_token
  51. PHP_FUNCTION
  52. PHP_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 5                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 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$ */
  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(TSRMLS_D)
 142 {
 143         return le_stream_context;
 144 }
 145 /* }}} */
 146 
 147 /* {{{ Module-Stuff
 148 */
 149 static ZEND_RSRC_DTOR_FUNC(file_context_dtor)
 150 {
 151         php_stream_context *context = (php_stream_context*)rsrc->ptr;
 152         if (context->options) {
 153                 zval_ptr_dtor(&context->options);
 154                 context->options = NULL;
 155         }
 156         php_stream_context_free(context);
 157 }
 158 
 159 static void file_globals_ctor(php_file_globals *file_globals_p TSRMLS_DC)
 160 {
 161         FG(pclose_ret) = 0;
 162         FG(pclose_wait) = 0;
 163         FG(user_stream_current_filename) = NULL;
 164         FG(def_chunk_size) = PHP_SOCK_CHUNK_SIZE;
 165         FG(wrapper_errors) = NULL;
 166 }
 167 
 168 static void file_globals_dtor(php_file_globals *file_globals_p TSRMLS_DC)
 169 {
 170 }
 171 
 172 PHP_INI_BEGIN()
 173         STD_PHP_INI_ENTRY("user_agent", NULL, PHP_INI_ALL, OnUpdateString, user_agent, php_file_globals, file_globals)
 174         STD_PHP_INI_ENTRY("from", NULL, PHP_INI_ALL, OnUpdateString, from_address, php_file_globals, file_globals)
 175         STD_PHP_INI_ENTRY("default_socket_timeout", "60", PHP_INI_ALL, OnUpdateLong, default_socket_timeout, php_file_globals, file_globals)
 176         STD_PHP_INI_ENTRY("auto_detect_line_endings", "0", PHP_INI_ALL, OnUpdateLong, auto_detect_line_endings, php_file_globals, file_globals)
 177 PHP_INI_END()
 178 
 179 PHP_MINIT_FUNCTION(file)
 180 {
 181         le_stream_context = zend_register_list_destructors_ex(file_context_dtor, NULL, "stream-context", module_number);
 182 
 183 #ifdef ZTS
 184         ts_allocate_id(&file_globals_id, sizeof(php_file_globals), (ts_allocate_ctor) file_globals_ctor, (ts_allocate_dtor) file_globals_dtor);
 185 #else
 186         file_globals_ctor(&file_globals TSRMLS_CC);
 187 #endif
 188 
 189         REGISTER_INI_ENTRIES();
 190 
 191         REGISTER_LONG_CONSTANT("SEEK_SET", SEEK_SET, CONST_CS | CONST_PERSISTENT);
 192         REGISTER_LONG_CONSTANT("SEEK_CUR", SEEK_CUR, CONST_CS | CONST_PERSISTENT);
 193         REGISTER_LONG_CONSTANT("SEEK_END", SEEK_END, CONST_CS | CONST_PERSISTENT);
 194         REGISTER_LONG_CONSTANT("LOCK_SH", PHP_LOCK_SH, CONST_CS | CONST_PERSISTENT);
 195         REGISTER_LONG_CONSTANT("LOCK_EX", PHP_LOCK_EX, CONST_CS | CONST_PERSISTENT);
 196         REGISTER_LONG_CONSTANT("LOCK_UN", PHP_LOCK_UN, CONST_CS | CONST_PERSISTENT);
 197         REGISTER_LONG_CONSTANT("LOCK_NB", PHP_LOCK_NB, CONST_CS | CONST_PERSISTENT);
 198 
 199         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_CONNECT",                 PHP_STREAM_NOTIFY_CONNECT,                      CONST_CS | CONST_PERSISTENT);
 200         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_AUTH_REQUIRED",   PHP_STREAM_NOTIFY_AUTH_REQUIRED,        CONST_CS | CONST_PERSISTENT);
 201         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_AUTH_RESULT",             PHP_STREAM_NOTIFY_AUTH_RESULT,          CONST_CS | CONST_PERSISTENT);
 202         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_MIME_TYPE_IS",    PHP_STREAM_NOTIFY_MIME_TYPE_IS,         CONST_CS | CONST_PERSISTENT);
 203         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_FILE_SIZE_IS",    PHP_STREAM_NOTIFY_FILE_SIZE_IS,         CONST_CS | CONST_PERSISTENT);
 204         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_REDIRECTED",              PHP_STREAM_NOTIFY_REDIRECTED,           CONST_CS | CONST_PERSISTENT);
 205         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_PROGRESS",                PHP_STREAM_NOTIFY_PROGRESS,                     CONST_CS | CONST_PERSISTENT);
 206         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_FAILURE",                 PHP_STREAM_NOTIFY_FAILURE,                      CONST_CS | CONST_PERSISTENT);
 207         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_COMPLETED",               PHP_STREAM_NOTIFY_COMPLETED,            CONST_CS | CONST_PERSISTENT);
 208         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_RESOLVE",                 PHP_STREAM_NOTIFY_RESOLVE,                      CONST_CS | CONST_PERSISTENT);
 209 
 210         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_SEVERITY_INFO",   PHP_STREAM_NOTIFY_SEVERITY_INFO,        CONST_CS | CONST_PERSISTENT);
 211         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_SEVERITY_WARN",   PHP_STREAM_NOTIFY_SEVERITY_WARN,        CONST_CS | CONST_PERSISTENT);
 212         REGISTER_LONG_CONSTANT("STREAM_NOTIFY_SEVERITY_ERR",    PHP_STREAM_NOTIFY_SEVERITY_ERR,         CONST_CS | CONST_PERSISTENT);
 213 
 214         REGISTER_LONG_CONSTANT("STREAM_FILTER_READ",                    PHP_STREAM_FILTER_READ,                         CONST_CS | CONST_PERSISTENT);
 215         REGISTER_LONG_CONSTANT("STREAM_FILTER_WRITE",                   PHP_STREAM_FILTER_WRITE,                        CONST_CS | CONST_PERSISTENT);
 216         REGISTER_LONG_CONSTANT("STREAM_FILTER_ALL",                             PHP_STREAM_FILTER_ALL,                          CONST_CS | CONST_PERSISTENT);
 217 
 218         REGISTER_LONG_CONSTANT("STREAM_CLIENT_PERSISTENT",              PHP_STREAM_CLIENT_PERSISTENT,           CONST_CS | CONST_PERSISTENT);
 219         REGISTER_LONG_CONSTANT("STREAM_CLIENT_ASYNC_CONNECT",   PHP_STREAM_CLIENT_ASYNC_CONNECT,        CONST_CS | CONST_PERSISTENT);
 220         REGISTER_LONG_CONSTANT("STREAM_CLIENT_CONNECT",                 PHP_STREAM_CLIENT_CONNECT,      CONST_CS | CONST_PERSISTENT);
 221 
 222         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_ANY_CLIENT",       STREAM_CRYPTO_METHOD_ANY_CLIENT,        CONST_CS|CONST_PERSISTENT);
 223         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv2_CLIENT",     STREAM_CRYPTO_METHOD_SSLv2_CLIENT,      CONST_CS|CONST_PERSISTENT);
 224         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv3_CLIENT",     STREAM_CRYPTO_METHOD_SSLv3_CLIENT,      CONST_CS|CONST_PERSISTENT);
 225         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv23_CLIENT",    STREAM_CRYPTO_METHOD_SSLv23_CLIENT,     CONST_CS|CONST_PERSISTENT);
 226         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLS_CLIENT",       STREAM_CRYPTO_METHOD_TLS_CLIENT,        CONST_CS|CONST_PERSISTENT);
 227         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT",   STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT,    CONST_CS|CONST_PERSISTENT);
 228         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT",   STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT,    CONST_CS|CONST_PERSISTENT);
 229         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT",   STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT,    CONST_CS|CONST_PERSISTENT);
 230         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_ANY_SERVER",       STREAM_CRYPTO_METHOD_ANY_SERVER,        CONST_CS|CONST_PERSISTENT);
 231         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv2_SERVER",     STREAM_CRYPTO_METHOD_SSLv2_SERVER,      CONST_CS|CONST_PERSISTENT);
 232         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv3_SERVER",     STREAM_CRYPTO_METHOD_SSLv3_SERVER,      CONST_CS|CONST_PERSISTENT);
 233         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv23_SERVER",    STREAM_CRYPTO_METHOD_SSLv23_SERVER,     CONST_CS|CONST_PERSISTENT);
 234         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLS_SERVER",       STREAM_CRYPTO_METHOD_TLS_SERVER,        CONST_CS|CONST_PERSISTENT);
 235         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_0_SERVER",   STREAM_CRYPTO_METHOD_TLSv1_0_SERVER,    CONST_CS|CONST_PERSISTENT);
 236         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_1_SERVER",   STREAM_CRYPTO_METHOD_TLSv1_1_SERVER,    CONST_CS|CONST_PERSISTENT);
 237         REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_2_SERVER",   STREAM_CRYPTO_METHOD_TLSv1_2_SERVER,    CONST_CS|CONST_PERSISTENT);
 238 
 239         REGISTER_LONG_CONSTANT("STREAM_SHUT_RD",        STREAM_SHUT_RD,         CONST_CS|CONST_PERSISTENT);
 240         REGISTER_LONG_CONSTANT("STREAM_SHUT_WR",        STREAM_SHUT_WR,         CONST_CS|CONST_PERSISTENT);
 241         REGISTER_LONG_CONSTANT("STREAM_SHUT_RDWR",      STREAM_SHUT_RDWR,       CONST_CS|CONST_PERSISTENT);
 242 
 243 #ifdef PF_INET
 244         REGISTER_LONG_CONSTANT("STREAM_PF_INET", PF_INET, CONST_CS|CONST_PERSISTENT);
 245 #elif defined(AF_INET)
 246         REGISTER_LONG_CONSTANT("STREAM_PF_INET", AF_INET, CONST_CS|CONST_PERSISTENT);
 247 #endif
 248 
 249 #if HAVE_IPV6
 250 # ifdef PF_INET6
 251         REGISTER_LONG_CONSTANT("STREAM_PF_INET6", PF_INET6, CONST_CS|CONST_PERSISTENT);
 252 # elif defined(AF_INET6)
 253         REGISTER_LONG_CONSTANT("STREAM_PF_INET6", AF_INET6, CONST_CS|CONST_PERSISTENT);
 254 # endif
 255 #endif
 256 
 257 #ifdef PF_UNIX
 258         REGISTER_LONG_CONSTANT("STREAM_PF_UNIX", PF_UNIX, CONST_CS|CONST_PERSISTENT);
 259 #elif defined(AF_UNIX)
 260         REGISTER_LONG_CONSTANT("STREAM_PF_UNIX", AF_UNIX, CONST_CS|CONST_PERSISTENT);
 261 #endif
 262 
 263 #ifdef IPPROTO_IP
 264         /* most people will use this one when calling socket() or socketpair() */
 265         REGISTER_LONG_CONSTANT("STREAM_IPPROTO_IP", IPPROTO_IP, CONST_CS|CONST_PERSISTENT);
 266 #endif
 267 
 268 #ifdef IPPROTO_TCP
 269         REGISTER_LONG_CONSTANT("STREAM_IPPROTO_TCP", IPPROTO_TCP, CONST_CS|CONST_PERSISTENT);
 270 #endif
 271 
 272 #ifdef IPPROTO_UDP
 273         REGISTER_LONG_CONSTANT("STREAM_IPPROTO_UDP", IPPROTO_UDP, CONST_CS|CONST_PERSISTENT);
 274 #endif
 275 
 276 #ifdef IPPROTO_ICMP
 277         REGISTER_LONG_CONSTANT("STREAM_IPPROTO_ICMP", IPPROTO_ICMP, CONST_CS|CONST_PERSISTENT);
 278 #endif
 279 
 280 #ifdef IPPROTO_RAW
 281         REGISTER_LONG_CONSTANT("STREAM_IPPROTO_RAW", IPPROTO_RAW, CONST_CS|CONST_PERSISTENT);
 282 #endif
 283 
 284         REGISTER_LONG_CONSTANT("STREAM_SOCK_STREAM", SOCK_STREAM, CONST_CS|CONST_PERSISTENT);
 285         REGISTER_LONG_CONSTANT("STREAM_SOCK_DGRAM", SOCK_DGRAM, CONST_CS|CONST_PERSISTENT);
 286 
 287 #ifdef SOCK_RAW
 288         REGISTER_LONG_CONSTANT("STREAM_SOCK_RAW", SOCK_RAW, CONST_CS|CONST_PERSISTENT);
 289 #endif
 290 
 291 #ifdef SOCK_SEQPACKET
 292         REGISTER_LONG_CONSTANT("STREAM_SOCK_SEQPACKET", SOCK_SEQPACKET, CONST_CS|CONST_PERSISTENT);
 293 #endif
 294 
 295 #ifdef SOCK_RDM
 296         REGISTER_LONG_CONSTANT("STREAM_SOCK_RDM", SOCK_RDM, CONST_CS|CONST_PERSISTENT);
 297 #endif
 298 
 299         REGISTER_LONG_CONSTANT("STREAM_PEEK", STREAM_PEEK, CONST_CS | CONST_PERSISTENT);
 300         REGISTER_LONG_CONSTANT("STREAM_OOB",  STREAM_OOB, CONST_CS | CONST_PERSISTENT);
 301 
 302         REGISTER_LONG_CONSTANT("STREAM_SERVER_BIND",                    STREAM_XPORT_BIND,                                      CONST_CS | CONST_PERSISTENT);
 303         REGISTER_LONG_CONSTANT("STREAM_SERVER_LISTEN",                  STREAM_XPORT_LISTEN,                            CONST_CS | CONST_PERSISTENT);
 304 
 305         REGISTER_LONG_CONSTANT("FILE_USE_INCLUDE_PATH",                 PHP_FILE_USE_INCLUDE_PATH,                      CONST_CS | CONST_PERSISTENT);
 306         REGISTER_LONG_CONSTANT("FILE_IGNORE_NEW_LINES",                 PHP_FILE_IGNORE_NEW_LINES,                      CONST_CS | CONST_PERSISTENT);
 307         REGISTER_LONG_CONSTANT("FILE_SKIP_EMPTY_LINES",                 PHP_FILE_SKIP_EMPTY_LINES,                      CONST_CS | CONST_PERSISTENT);
 308         REGISTER_LONG_CONSTANT("FILE_APPEND",                                   PHP_FILE_APPEND,                                        CONST_CS | CONST_PERSISTENT);
 309         REGISTER_LONG_CONSTANT("FILE_NO_DEFAULT_CONTEXT",               PHP_FILE_NO_DEFAULT_CONTEXT,            CONST_CS | CONST_PERSISTENT);
 310 
 311         REGISTER_LONG_CONSTANT("FILE_TEXT",                                             0,                                                                      CONST_CS | CONST_PERSISTENT);
 312         REGISTER_LONG_CONSTANT("FILE_BINARY",                                   0,                                                                      CONST_CS | CONST_PERSISTENT);
 313 
 314 #ifdef HAVE_FNMATCH
 315         REGISTER_LONG_CONSTANT("FNM_NOESCAPE", FNM_NOESCAPE, CONST_CS | CONST_PERSISTENT);
 316         REGISTER_LONG_CONSTANT("FNM_PATHNAME", FNM_PATHNAME, CONST_CS | CONST_PERSISTENT);
 317         REGISTER_LONG_CONSTANT("FNM_PERIOD",   FNM_PERIOD,   CONST_CS | CONST_PERSISTENT);
 318 # ifdef FNM_CASEFOLD /* a GNU extension */ /* TODO emulate if not available */
 319         REGISTER_LONG_CONSTANT("FNM_CASEFOLD", FNM_CASEFOLD, CONST_CS | CONST_PERSISTENT);
 320 # endif
 321 #endif
 322 
 323         return SUCCESS;
 324 }
 325 /* }}} */
 326 
 327 PHP_MSHUTDOWN_FUNCTION(file) /* {{{ */
 328 {
 329 #ifndef ZTS
 330         file_globals_dtor(&file_globals TSRMLS_CC);
 331 #endif
 332         return SUCCESS;
 333 }
 334 /* }}} */
 335 
 336 static int flock_values[] = { LOCK_SH, LOCK_EX, LOCK_UN };
 337 
 338 /* {{{ proto bool flock(resource fp, int operation [, int &wouldblock])
 339    Portable file locking */
 340 PHP_FUNCTION(flock)
 341 {
 342         zval *res, *wouldblock = NULL;
 343         int act;
 344         php_stream *stream;
 345         long operation = 0;
 346 
 347         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|z", &res, &operation, &wouldblock) == FAILURE) {
 348                 return;
 349         }
 350 
 351         PHP_STREAM_TO_ZVAL(stream, &res);
 352 
 353         act = operation & 3;
 354         if (act < 1 || act > 3) {
 355                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal operation argument");
 356                 RETURN_FALSE;
 357         }
 358 
 359         if (wouldblock && PZVAL_IS_REF(wouldblock)) {
 360                 convert_to_long_ex(&wouldblock);
 361                 Z_LVAL_P(wouldblock) = 0;
 362         }
 363 
 364         /* flock_values contains all possible actions if (operation & 4) we won't block on the lock */
 365         act = flock_values[act - 1] | (operation & PHP_LOCK_NB ? LOCK_NB : 0);
 366         if (php_stream_lock(stream, act)) {
 367                 if (operation && errno == EWOULDBLOCK && wouldblock && PZVAL_IS_REF(wouldblock)) {
 368                         Z_LVAL_P(wouldblock) = 1;
 369                 }
 370                 RETURN_FALSE;
 371         }
 372         RETURN_TRUE;
 373 }
 374 /* }}} */
 375 
 376 #define PHP_META_UNSAFE ".\\+*?[^]$() "
 377 
 378 /* {{{ proto array get_meta_tags(string filename [, bool use_include_path])
 379    Extracts all meta tag content attributes from a file and returns an array */
 380 PHP_FUNCTION(get_meta_tags)
 381 {
 382         char *filename;
 383         int filename_len;
 384         zend_bool use_include_path = 0;
 385         int in_tag = 0, done = 0;
 386         int looking_for_val = 0, have_name = 0, have_content = 0;
 387         int saw_name = 0, saw_content = 0;
 388         char *name = NULL, *value = NULL, *temp = NULL;
 389         php_meta_tags_token tok, tok_last;
 390         php_meta_tags_data md;
 391 
 392         /* Initiailize our structure */
 393         memset(&md, 0, sizeof(md));
 394 
 395         /* Parse arguments */
 396         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|b", &filename, &filename_len, &use_include_path) == FAILURE) {
 397                 return;
 398         }
 399 
 400         md.stream = php_stream_open_wrapper(filename, "rb",
 401                         (use_include_path ? USE_PATH : 0) | REPORT_ERRORS,
 402                         NULL);
 403         if (!md.stream) {
 404                 RETURN_FALSE;
 405         }
 406 
 407         array_init(return_value);
 408 
 409         tok_last = TOK_EOF;
 410 
 411         while (!done && (tok = php_next_meta_token(&md TSRMLS_CC)) != TOK_EOF) {
 412                 if (tok == TOK_ID) {
 413                         if (tok_last == TOK_OPENTAG) {
 414                                 md.in_meta = !strcasecmp("meta", md.token_data);
 415                         } else if (tok_last == TOK_SLASH && in_tag) {
 416                                 if (strcasecmp("head", md.token_data) == 0) {
 417                                         /* We are done here! */
 418                                         done = 1;
 419                                 }
 420                         } else if (tok_last == TOK_EQUAL && looking_for_val) {
 421                                 if (saw_name) {
 422                                         STR_FREE(name);
 423                                         /* Get the NAME attr (Single word attr, non-quoted) */
 424                                         temp = name = estrndup(md.token_data, md.token_len);
 425 
 426                                         while (temp && *temp) {
 427                                                 if (strchr(PHP_META_UNSAFE, *temp)) {
 428                                                         *temp = '_';
 429                                                 }
 430                                                 temp++;
 431                                         }
 432 
 433                                         have_name = 1;
 434                                 } else if (saw_content) {
 435                                         STR_FREE(value);
 436                                         value = estrndup(md.token_data, md.token_len);
 437                                         have_content = 1;
 438                                 }
 439 
 440                                 looking_for_val = 0;
 441                         } else {
 442                                 if (md.in_meta) {
 443                                         if (strcasecmp("name", md.token_data) == 0) {
 444                                                 saw_name = 1;
 445                                                 saw_content = 0;
 446                                                 looking_for_val = 1;
 447                                         } else if (strcasecmp("content", md.token_data) == 0) {
 448                                                 saw_name = 0;
 449                                                 saw_content = 1;
 450                                                 looking_for_val = 1;
 451                                         }
 452                                 }
 453                         }
 454                 } else if (tok == TOK_STRING && tok_last == TOK_EQUAL && looking_for_val) {
 455                         if (saw_name) {
 456                                 STR_FREE(name);
 457                                 /* Get the NAME attr (Quoted single/double) */
 458                                 temp = name = estrndup(md.token_data, md.token_len);
 459 
 460                                 while (temp && *temp) {
 461                                         if (strchr(PHP_META_UNSAFE, *temp)) {
 462                                                 *temp = '_';
 463                                         }
 464                                         temp++;
 465                                 }
 466 
 467                                 have_name = 1;
 468                         } else if (saw_content) {
 469                                 STR_FREE(value);
 470                                 value = estrndup(md.token_data, md.token_len);
 471                                 have_content = 1;
 472                         }
 473 
 474                         looking_for_val = 0;
 475                 } else if (tok == TOK_OPENTAG) {
 476                         if (looking_for_val) {
 477                                 looking_for_val = 0;
 478                                 have_name = saw_name = 0;
 479                                 have_content = saw_content = 0;
 480                         }
 481                         in_tag = 1;
 482                 } else if (tok == TOK_CLOSETAG) {
 483                         if (have_name) {
 484                                 /* For BC */
 485                                 php_strtolower(name, strlen(name));
 486                                 if (have_content) {
 487                                         add_assoc_string(return_value, name, value, 1);
 488                                 } else {
 489                                         add_assoc_string(return_value, name, "", 1);
 490                                 }
 491 
 492                                 efree(name);
 493                                 STR_FREE(value);
 494                         } else if (have_content) {
 495                                 efree(value);
 496                         }
 497 
 498                         name = value = NULL;
 499 
 500                         /* Reset all of our flags */
 501                         in_tag = looking_for_val = 0;
 502                         have_name = saw_name = 0;
 503                         have_content = saw_content = 0;
 504                         md.in_meta = 0;
 505                 }
 506 
 507                 tok_last = tok;
 508 
 509                 if (md.token_data)
 510                         efree(md.token_data);
 511 
 512                 md.token_data = NULL;
 513         }
 514 
 515         STR_FREE(value);
 516         STR_FREE(name);
 517         php_stream_close(md.stream);
 518 }
 519 /* }}} */
 520 
 521 /* {{{ proto string file_get_contents(string filename [, bool use_include_path [, resource context [, long offset [, long maxlen]]]])
 522    Read the entire file into a string */
 523 PHP_FUNCTION(file_get_contents)
 524 {
 525         char *filename;
 526         int filename_len;
 527         char *contents;
 528         zend_bool use_include_path = 0;
 529         php_stream *stream;
 530         long len;
 531         long offset = -1;
 532         long maxlen = PHP_STREAM_COPY_ALL;
 533         zval *zcontext = NULL;
 534         php_stream_context *context = NULL;
 535 
 536         /* Parse arguments */
 537         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|br!ll", &filename, &filename_len, &use_include_path, &zcontext, &offset, &maxlen) == FAILURE) {
 538                 return;
 539         }
 540 
 541         if (ZEND_NUM_ARGS() == 5 && maxlen < 0) {
 542                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "length must be greater than or equal to zero");
 543                 RETURN_FALSE;
 544         }
 545 
 546         context = php_stream_context_from_zval(zcontext, 0);
 547 
 548         stream = php_stream_open_wrapper_ex(filename, "rb",
 549                                 (use_include_path ? USE_PATH : 0) | REPORT_ERRORS,
 550                                 NULL, context);
 551         if (!stream) {
 552                 RETURN_FALSE;
 553         }
 554 
 555         if (offset > 0 && php_stream_seek(stream, offset, SEEK_SET) < 0) {
 556                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to seek to position %ld in the stream", offset);
 557                 php_stream_close(stream);
 558                 RETURN_FALSE;
 559         }
 560 
 561         if ((len = php_stream_copy_to_mem(stream, &contents, maxlen, 0)) > 0) {
 562                 if (len > INT_MAX) {
 563                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "content truncated from %ld to %d bytes", len, INT_MAX);
 564                         len = INT_MAX;
 565                 }
 566                 RETVAL_STRINGL(contents, len, 0);
 567         } else if (len == 0) {
 568                 RETVAL_EMPTY_STRING();
 569         } else {
 570                 RETVAL_FALSE;
 571         }
 572 
 573         php_stream_close(stream);
 574 }
 575 /* }}} */
 576 
 577 /* {{{ proto int file_put_contents(string file, mixed data [, int flags [, resource context]])
 578    Write/Create a file with contents data and return the number of bytes written */
 579 PHP_FUNCTION(file_put_contents)
 580 {
 581         php_stream *stream;
 582         char *filename;
 583         int filename_len;
 584         zval *data;
 585         long numbytes = 0;
 586         long flags = 0;
 587         zval *zcontext = NULL;
 588         php_stream_context *context = NULL;
 589         php_stream *srcstream = NULL;
 590         char mode[3] = "wb";
 591 
 592         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pz/|lr!", &filename, &filename_len, &data, &flags, &zcontext) == FAILURE) {
 593                 return;
 594         }
 595 
 596         if (Z_TYPE_P(data) == IS_RESOURCE) {
 597                 php_stream_from_zval(srcstream, &data);
 598         }
 599 
 600         context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
 601 
 602         if (flags & PHP_FILE_APPEND) {
 603                 mode[0] = 'a';
 604         } else if (flags & LOCK_EX) {
 605                 /* check to make sure we are dealing with a regular file */
 606                 if (php_memnstr(filename, "://", sizeof("://") - 1, filename + filename_len)) {
 607                         if (strncasecmp(filename, "file://", sizeof("file://") - 1)) {
 608                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Exclusive locks may only be set for regular files");
 609                                 RETURN_FALSE;
 610                         }
 611                 }
 612                 mode[0] = 'c';
 613         }
 614         mode[2] = '\0';
 615 
 616         stream = php_stream_open_wrapper_ex(filename, mode, ((flags & PHP_FILE_USE_INCLUDE_PATH) ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
 617         if (stream == NULL) {
 618                 RETURN_FALSE;
 619         }
 620 
 621         if (flags & LOCK_EX && (!php_stream_supports_lock(stream) || php_stream_lock(stream, LOCK_EX))) {
 622                 php_stream_close(stream);
 623                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Exclusive locks are not supported for this stream");
 624                 RETURN_FALSE;
 625         }
 626 
 627         if (mode[0] == 'c') {
 628                 php_stream_truncate_set_size(stream, 0);
 629         }
 630 
 631         switch (Z_TYPE_P(data)) {
 632                 case IS_RESOURCE: {
 633                         size_t len;
 634                         if (php_stream_copy_to_stream_ex(srcstream, stream, PHP_STREAM_COPY_ALL, &len) != SUCCESS) {
 635                                 numbytes = -1;
 636                         } else {
 637                                 if (len > LONG_MAX) {
 638                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "content truncated from %lu to %ld bytes", (unsigned long) len, LONG_MAX);
 639                                         len = LONG_MAX;
 640                                 }
 641                                 numbytes = len;
 642                         }
 643                         break;
 644                 }
 645                 case IS_NULL:
 646                 case IS_LONG:
 647                 case IS_DOUBLE:
 648                 case IS_BOOL:
 649                 case IS_CONSTANT:
 650                         convert_to_string_ex(&data);
 651 
 652                 case IS_STRING:
 653                         if (Z_STRLEN_P(data)) {
 654                                 numbytes = php_stream_write(stream, Z_STRVAL_P(data), Z_STRLEN_P(data));
 655                                 if (numbytes != Z_STRLEN_P(data)) {
 656                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %ld of %d bytes written, possibly out of free disk space", numbytes, Z_STRLEN_P(data));
 657                                         numbytes = -1;
 658                                 }
 659                         }
 660                         break;
 661 
 662                 case IS_ARRAY:
 663                         if (zend_hash_num_elements(Z_ARRVAL_P(data))) {
 664                                 int bytes_written;
 665                                 zval **tmp;
 666                                 HashPosition pos;
 667 
 668                                 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(data), &pos);
 669                                 while (zend_hash_get_current_data_ex(Z_ARRVAL_P(data), (void **) &tmp, &pos) == SUCCESS) {
 670                                         if (Z_TYPE_PP(tmp) != IS_STRING) {
 671                                                 SEPARATE_ZVAL(tmp);
 672                                                 convert_to_string(*tmp);
 673                                         }
 674                                         if (Z_STRLEN_PP(tmp)) {
 675                                                 numbytes += Z_STRLEN_PP(tmp);
 676                                                 bytes_written = php_stream_write(stream, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
 677                                                 if (bytes_written < 0 || bytes_written != Z_STRLEN_PP(tmp)) {
 678                                                         if (bytes_written < 0) {
 679                                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write %d bytes to %s", Z_STRLEN_PP(tmp), filename);
 680                                                         } else {
 681                                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %d of %d bytes written, possibly out of free disk space", bytes_written, Z_STRLEN_PP(tmp));
 682                                                         }
 683                                                         numbytes = -1;
 684                                                         break;
 685                                                 }
 686                                         }
 687                                         zend_hash_move_forward_ex(Z_ARRVAL_P(data), &pos);
 688                                 }
 689                         }
 690                         break;
 691 
 692                 case IS_OBJECT:
 693                         if (Z_OBJ_HT_P(data) != NULL) {
 694                                 zval out;
 695 
 696                                 if (zend_std_cast_object_tostring(data, &out, IS_STRING TSRMLS_CC) == SUCCESS) {
 697                                         numbytes = php_stream_write(stream, Z_STRVAL(out), Z_STRLEN(out));
 698                                         if (numbytes != Z_STRLEN(out)) {
 699                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Only %ld of %d bytes written, possibly out of free disk space", numbytes, Z_STRLEN(out));
 700                                                 numbytes = -1;
 701                                         }
 702                                         zval_dtor(&out);
 703                                         break;
 704                                 }
 705                         }
 706                 default:
 707                         numbytes = -1;
 708                         break;
 709         }
 710         php_stream_close(stream);
 711 
 712         if (numbytes < 0) {
 713                 RETURN_FALSE;
 714         }
 715 
 716         RETURN_LONG(numbytes);
 717 }
 718 /* }}} */
 719 
 720 #define PHP_FILE_BUF_SIZE       80
 721 
 722 /* {{{ proto array file(string filename [, int flags[, resource context]])
 723    Read entire file into an array */
 724 PHP_FUNCTION(file)
 725 {
 726         char *filename;
 727         int filename_len;
 728         char *target_buf=NULL, *p, *s, *e;
 729         register int i = 0;
 730         int target_len;
 731         char eol_marker = '\n';
 732         long flags = 0;
 733         zend_bool use_include_path;
 734         zend_bool include_new_line;
 735         zend_bool skip_blank_lines;
 736         php_stream *stream;
 737         zval *zcontext = NULL;
 738         php_stream_context *context = NULL;
 739 
 740         /* Parse arguments */
 741         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|lr!", &filename, &filename_len, &flags, &zcontext) == FAILURE) {
 742                 return;
 743         }
 744         if (flags < 0 || flags > (PHP_FILE_USE_INCLUDE_PATH | PHP_FILE_IGNORE_NEW_LINES | PHP_FILE_SKIP_EMPTY_LINES | PHP_FILE_NO_DEFAULT_CONTEXT)) {
 745                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%ld' flag is not supported", flags);
 746                 RETURN_FALSE;
 747         }
 748 
 749         use_include_path = flags & PHP_FILE_USE_INCLUDE_PATH;
 750         include_new_line = !(flags & PHP_FILE_IGNORE_NEW_LINES);
 751         skip_blank_lines = flags & PHP_FILE_SKIP_EMPTY_LINES;
 752 
 753         context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
 754 
 755         stream = php_stream_open_wrapper_ex(filename, "rb", (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
 756         if (!stream) {
 757                 RETURN_FALSE;
 758         }
 759 
 760         /* Initialize return array */
 761         array_init(return_value);
 762 
 763         if ((target_len = php_stream_copy_to_mem(stream, &target_buf, PHP_STREAM_COPY_ALL, 0))) {
 764                 s = target_buf;
 765                 e = target_buf + target_len;
 766 
 767                 if (!(p = php_stream_locate_eol(stream, target_buf, target_len TSRMLS_CC))) {
 768                         p = e;
 769                         goto parse_eol;
 770                 }
 771 
 772                 if (stream->flags & PHP_STREAM_FLAG_EOL_MAC) {
 773                         eol_marker = '\r';
 774                 }
 775 
 776                 /* for performance reasons the code is duplicated, so that the if (include_new_line)
 777                  * will not need to be done for every single line in the file. */
 778                 if (include_new_line) {
 779                         do {
 780                                 p++;
 781 parse_eol:
 782                                 add_index_stringl(return_value, i++, estrndup(s, p-s), p-s, 0);
 783                                 s = p;
 784                         } while ((p = memchr(p, eol_marker, (e-p))));
 785                 } else {
 786                         do {
 787                                 int windows_eol = 0;
 788                                 if (p != target_buf && eol_marker == '\n' && *(p - 1) == '\r') {
 789                                         windows_eol++;
 790                                 }
 791                                 if (skip_blank_lines && !(p-s-windows_eol)) {
 792                                         s = ++p;
 793                                         continue;
 794                                 }
 795                                 add_index_stringl(return_value, i++, estrndup(s, p-s-windows_eol), p-s-windows_eol, 0);
 796                                 s = ++p;
 797                         } while ((p = memchr(p, eol_marker, (e-p))));
 798                 }
 799 
 800                 /* handle any left overs of files without new lines */
 801                 if (s != e) {
 802                         p = e;
 803                         goto parse_eol;
 804                 }
 805         }
 806 
 807         if (target_buf) {
 808                 efree(target_buf);
 809         }
 810         php_stream_close(stream);
 811 }
 812 /* }}} */
 813 
 814 /* {{{ proto string tempnam(string dir, string prefix)
 815    Create a unique filename in a directory */
 816 PHP_FUNCTION(tempnam)
 817 {
 818         char *dir, *prefix;
 819         int dir_len, prefix_len;
 820         size_t p_len;
 821         char *opened_path;
 822         char *p;
 823         int fd;
 824 
 825         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp", &dir, &dir_len, &prefix, &prefix_len) == FAILURE) {
 826                 return;
 827         }
 828 
 829         if (php_check_open_basedir(dir TSRMLS_CC)) {
 830                 RETURN_FALSE;
 831         }
 832 
 833         php_basename(prefix, prefix_len, NULL, 0, &p, &p_len TSRMLS_CC);
 834         if (p_len > 64) {
 835                 p[63] = '\0';
 836         }
 837 
 838         RETVAL_FALSE;
 839 
 840         if ((fd = php_open_temporary_fd_ex(dir, p, &opened_path, 1 TSRMLS_CC)) >= 0) {
 841                 close(fd);
 842                 RETVAL_STRING(opened_path, 0);
 843         }
 844         efree(p);
 845 }
 846 /* }}} */
 847 
 848 /* {{{ proto resource tmpfile(void)
 849    Create a temporary file that will be deleted automatically after use */
 850 PHP_NAMED_FUNCTION(php_if_tmpfile)
 851 {
 852         php_stream *stream;
 853 
 854         if (zend_parse_parameters_none() == FAILURE) {
 855                 return;
 856         }
 857 
 858         stream = php_stream_fopen_tmpfile();
 859 
 860         if (stream) {
 861                 php_stream_to_zval(stream, return_value);
 862         } else {
 863                 RETURN_FALSE;
 864         }
 865 }
 866 /* }}} */
 867 
 868 /* {{{ proto resource fopen(string filename, string mode [, bool use_include_path [, resource context]])
 869    Open a file or a URL and return a file pointer */
 870 PHP_NAMED_FUNCTION(php_if_fopen)
 871 {
 872         char *filename, *mode;
 873         int filename_len, mode_len;
 874         zend_bool use_include_path = 0;
 875         zval *zcontext = NULL;
 876         php_stream *stream;
 877         php_stream_context *context = NULL;
 878 
 879         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ps|br", &filename, &filename_len, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) {
 880                 RETURN_FALSE;
 881         }
 882 
 883         context = php_stream_context_from_zval(zcontext, 0);
 884 
 885         stream = php_stream_open_wrapper_ex(filename, mode, (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
 886 
 887         if (stream == NULL) {
 888                 RETURN_FALSE;
 889         }
 890 
 891         php_stream_to_zval(stream, return_value);
 892 }
 893 /* }}} */
 894 
 895 /* {{{ proto bool fclose(resource fp)
 896    Close an open file pointer */
 897 PHPAPI PHP_FUNCTION(fclose)
 898 {
 899         zval *res;
 900         php_stream *stream;
 901 
 902         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE) {
 903                 RETURN_FALSE;
 904         }
 905 
 906         PHP_STREAM_TO_ZVAL(stream, &res);
 907 
 908         if ((stream->flags & PHP_STREAM_FLAG_NO_FCLOSE) != 0) {
 909                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%d is not a valid stream resource", stream->rsrc_id);
 910                 RETURN_FALSE;
 911         }
 912 
 913         if (!stream->is_persistent) {
 914                 php_stream_close(stream);
 915         } else {
 916                 php_stream_pclose(stream);
 917         }
 918 
 919         RETURN_TRUE;
 920 }
 921 /* }}} */
 922 
 923 /* {{{ proto resource popen(string command, string mode)
 924    Execute a command and open either a read or a write pipe to it */
 925 PHP_FUNCTION(popen)
 926 {
 927         char *command, *mode;
 928         int command_len, mode_len;
 929         FILE *fp;
 930         php_stream *stream;
 931         char *posix_mode;
 932 
 933         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ps", &command, &command_len, &mode, &mode_len) == FAILURE) {
 934                 return;
 935         }
 936 
 937         posix_mode = estrndup(mode, mode_len);
 938 #ifndef PHP_WIN32
 939         {
 940                 char *z = memchr(posix_mode, 'b', mode_len);
 941                 if (z) {
 942                         memmove(z, z + 1, mode_len - (z - posix_mode));
 943                 }
 944         }
 945 #endif
 946 
 947         fp = VCWD_POPEN(command, posix_mode);
 948         if (!fp) {
 949                 php_error_docref2(NULL TSRMLS_CC, command, posix_mode, E_WARNING, "%s", strerror(errno));
 950                 efree(posix_mode);
 951                 RETURN_FALSE;
 952         }
 953 
 954         stream = php_stream_fopen_from_pipe(fp, mode);
 955 
 956         if (stream == NULL)     {
 957                 php_error_docref2(NULL TSRMLS_CC, command, mode, E_WARNING, "%s", strerror(errno));
 958                 RETVAL_FALSE;
 959         } else {
 960                 php_stream_to_zval(stream, return_value);
 961         }
 962 
 963         efree(posix_mode);
 964 }
 965 /* }}} */
 966 
 967 /* {{{ proto int pclose(resource fp)
 968    Close a file pointer opened by popen() */
 969 PHP_FUNCTION(pclose)
 970 {
 971         zval *res;
 972         php_stream *stream;
 973 
 974         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE) {
 975                 RETURN_FALSE;
 976         }
 977 
 978         PHP_STREAM_TO_ZVAL(stream, &res);
 979 
 980         FG(pclose_wait) = 1;
 981         zend_list_delete(stream->rsrc_id);
 982         FG(pclose_wait) = 0;
 983         RETURN_LONG(FG(pclose_ret));
 984 }
 985 /* }}} */
 986 
 987 /* {{{ proto bool feof(resource fp)
 988    Test for end-of-file on a file pointer */
 989 PHPAPI PHP_FUNCTION(feof)
 990 {
 991         zval *res;
 992         php_stream *stream;
 993 
 994         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE) {
 995                 RETURN_FALSE;
 996         }
 997 
 998         PHP_STREAM_TO_ZVAL(stream, &res);
 999 
1000         if (php_stream_eof(stream)) {
1001                 RETURN_TRUE;
1002         } else {
1003                 RETURN_FALSE;
1004         }
1005 }
1006 /* }}} */
1007 
1008 /* {{{ proto string fgets(resource fp[, int length])
1009    Get a line from file pointer */
1010 PHPAPI PHP_FUNCTION(fgets)
1011 {
1012         zval *res;
1013         long len = 1024;
1014         char *buf = NULL;
1015         int argc = ZEND_NUM_ARGS();
1016         size_t line_len = 0;
1017         php_stream *stream;
1018 
1019         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &res, &len) == FAILURE) {
1020                 RETURN_FALSE;
1021         }
1022 
1023         PHP_STREAM_TO_ZVAL(stream, &res);
1024 
1025         if (argc == 1) {
1026                 /* ask streams to give us a buffer of an appropriate size */
1027                 buf = php_stream_get_line(stream, NULL, 0, &line_len);
1028                 if (buf == NULL) {
1029                         goto exit_failed;
1030                 }
1031         } else if (argc > 1) {
1032                 if (len <= 0) {
1033                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
1034                         RETURN_FALSE;
1035                 }
1036 
1037                 buf = ecalloc(len + 1, sizeof(char));
1038                 if (php_stream_get_line(stream, buf, len, &line_len) == NULL) {
1039                         goto exit_failed;
1040                 }
1041         }
1042 
1043         ZVAL_STRINGL(return_value, buf, line_len, 0);
1044         /* resize buffer if it's much larger than the result.
1045          * Only needed if the user requested a buffer size. */
1046         if (argc > 1 && Z_STRLEN_P(return_value) < len / 2) {
1047                 Z_STRVAL_P(return_value) = erealloc(buf, line_len + 1);
1048         }
1049         return;
1050 
1051 exit_failed:
1052         RETVAL_FALSE;
1053         if (buf) {
1054                 efree(buf);
1055         }
1056 }
1057 /* }}} */
1058 
1059 /* {{{ proto string fgetc(resource fp)
1060    Get a character from file pointer */
1061 PHPAPI PHP_FUNCTION(fgetc)
1062 {
1063         zval *res;
1064         char buf[2];
1065         int result;
1066         php_stream *stream;
1067 
1068         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE) {
1069                 RETURN_FALSE;
1070         }
1071 
1072         PHP_STREAM_TO_ZVAL(stream, &res);
1073 
1074         result = php_stream_getc(stream);
1075 
1076         if (result == EOF) {
1077                 RETVAL_FALSE;
1078         } else {
1079                 buf[0] = result;
1080                 buf[1] = '\0';
1081 
1082                 RETURN_STRINGL(buf, 1, 1);
1083         }
1084 }
1085 /* }}} */
1086 
1087 /* {{{ proto string fgetss(resource fp [, int length [, string allowable_tags]])
1088    Get a line from file pointer and strip HTML tags */
1089 PHPAPI PHP_FUNCTION(fgetss)
1090 {
1091         zval *fd;
1092         long bytes = 0;
1093         size_t len = 0;
1094         size_t actual_len, retval_len;
1095         char *buf = NULL, *retval;
1096         php_stream *stream;
1097         char *allowed_tags=NULL;
1098         int allowed_tags_len=0;
1099 
1100         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|ls", &fd, &bytes, &allowed_tags, &allowed_tags_len) == FAILURE) {
1101                 RETURN_FALSE;
1102         }
1103 
1104         PHP_STREAM_TO_ZVAL(stream, &fd);
1105 
1106         if (ZEND_NUM_ARGS() >= 2) {
1107                 if (bytes <= 0) {
1108                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
1109                         RETURN_FALSE;
1110                 }
1111 
1112                 len = (size_t) bytes;
1113                 buf = safe_emalloc(sizeof(char), (len + 1), 0);
1114                 /*needed because recv doesnt set null char at end*/
1115                 memset(buf, 0, len + 1);
1116         }
1117 
1118         if ((retval = php_stream_get_line(stream, buf, len, &actual_len)) == NULL)      {
1119                 if (buf != NULL) {
1120                         efree(buf);
1121                 }
1122                 RETURN_FALSE;
1123         }
1124 
1125         retval_len = php_strip_tags(retval, actual_len, &stream->fgetss_state, allowed_tags, allowed_tags_len);
1126 
1127         RETURN_STRINGL(retval, retval_len, 0);
1128 }
1129 /* }}} */
1130 
1131 /* {{{ proto mixed fscanf(resource stream, string format [, string ...])
1132    Implements a mostly ANSI compatible fscanf() */
1133 PHP_FUNCTION(fscanf)
1134 {
1135         int result, format_len, type, argc = 0;
1136         zval ***args = NULL;
1137         zval *file_handle;
1138         char *buf, *format;
1139         size_t len;
1140         void *what;
1141 
1142         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs*", &file_handle, &format, &format_len, &args, &argc) == FAILURE) {
1143                 return;
1144         }
1145 
1146         what = zend_fetch_resource(&file_handle TSRMLS_CC, -1, "File-Handle", &type, 2, php_file_le_stream(), php_file_le_pstream());
1147 
1148         /* we can't do a ZEND_VERIFY_RESOURCE(what), otherwise we end up
1149          * with a leak if we have an invalid filehandle. This needs changing
1150          * if the code behind ZEND_VERIFY_RESOURCE changed. - cc */
1151         if (!what) {
1152                 if (args) {
1153                         efree(args);
1154                 }
1155                 RETURN_FALSE;
1156         }
1157 
1158         buf = php_stream_get_line((php_stream *) what, NULL, 0, &len);
1159         if (buf == NULL) {
1160                 if (args) {
1161                         efree(args);
1162                 }
1163                 RETURN_FALSE;
1164         }
1165 
1166         result = php_sscanf_internal(buf, format, argc, args, 0, &return_value TSRMLS_CC);
1167 
1168         if (args) {
1169                 efree(args);
1170         }
1171         efree(buf);
1172 
1173         if (SCAN_ERROR_WRONG_PARAM_COUNT == result) {
1174                 WRONG_PARAM_COUNT;
1175         }
1176 }
1177 /* }}} */
1178 
1179 /* {{{ proto int fwrite(resource fp, string str [, int length])
1180    Binary-safe file write */
1181 PHPAPI PHP_FUNCTION(fwrite)
1182 {
1183         zval *res;
1184         char *input;
1185         int inputlen;
1186         int ret;
1187         int num_bytes;
1188         long maxlen = 0;
1189         php_stream *stream;
1190 
1191         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &res, &input, &inputlen, &maxlen) == FAILURE) {
1192                 RETURN_FALSE;
1193         }
1194 
1195         if (ZEND_NUM_ARGS() == 2) {
1196                 num_bytes = inputlen;
1197         } else {
1198                 num_bytes = MAX(0, MIN((int) maxlen, inputlen));
1199         }
1200 
1201         if (!num_bytes) {
1202                 RETURN_LONG(0);
1203         }
1204 
1205         PHP_STREAM_TO_ZVAL(stream, &res);
1206 
1207         ret = php_stream_write(stream, input, num_bytes);
1208 
1209         RETURN_LONG(ret);
1210 }
1211 /* }}} */
1212 
1213 /* {{{ proto bool fflush(resource fp)
1214    Flushes output */
1215 PHPAPI PHP_FUNCTION(fflush)
1216 {
1217         zval *res;
1218         int ret;
1219         php_stream *stream;
1220 
1221         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE) {
1222                 RETURN_FALSE;
1223         }
1224 
1225         PHP_STREAM_TO_ZVAL(stream, &res);
1226 
1227         ret = php_stream_flush(stream);
1228         if (ret) {
1229                 RETURN_FALSE;
1230         }
1231         RETURN_TRUE;
1232 }
1233 /* }}} */
1234 
1235 /* {{{ proto bool rewind(resource fp)
1236    Rewind the position of a file pointer */
1237 PHPAPI PHP_FUNCTION(rewind)
1238 {
1239         zval *res;
1240         php_stream *stream;
1241 
1242         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE) {
1243                 RETURN_FALSE;
1244         }
1245 
1246         PHP_STREAM_TO_ZVAL(stream, &res);
1247 
1248         if (-1 == php_stream_rewind(stream)) {
1249                 RETURN_FALSE;
1250         }
1251         RETURN_TRUE;
1252 }
1253 /* }}} */
1254 
1255 /* {{{ proto int ftell(resource fp)
1256    Get file pointer's read/write position */
1257 PHPAPI PHP_FUNCTION(ftell)
1258 {
1259         zval *res;
1260         long ret;
1261         php_stream *stream;
1262 
1263         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE) {
1264                 RETURN_FALSE;
1265         }
1266 
1267         PHP_STREAM_TO_ZVAL(stream, &res);
1268 
1269         ret = php_stream_tell(stream);
1270         if (ret == -1)  {
1271                 RETURN_FALSE;
1272         }
1273         RETURN_LONG(ret);
1274 }
1275 /* }}} */
1276 
1277 /* {{{ proto int fseek(resource fp, int offset [, int whence])
1278    Seek on a file pointer */
1279 PHPAPI PHP_FUNCTION(fseek)
1280 {
1281         zval *res;
1282         long offset, whence = SEEK_SET;
1283         php_stream *stream;
1284 
1285         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|l", &res, &offset, &whence) == FAILURE) {
1286                 RETURN_FALSE;
1287         }
1288 
1289         PHP_STREAM_TO_ZVAL(stream, &res);
1290 
1291         RETURN_LONG(php_stream_seek(stream, offset, whence));
1292 }
1293 /* }}} */
1294 
1295 /* {{{ php_mkdir
1296 */
1297 
1298 /* DEPRECATED APIs: Use php_stream_mkdir() instead */
1299 PHPAPI int php_mkdir_ex(const char *dir, long mode, int options TSRMLS_DC)
1300 {
1301         int ret;
1302 
1303         if (php_check_open_basedir(dir TSRMLS_CC)) {
1304                 return -1;
1305         }
1306 
1307         if ((ret = VCWD_MKDIR(dir, (mode_t)mode)) < 0 && (options & REPORT_ERRORS)) {
1308                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno));
1309         }
1310 
1311         return ret;
1312 }
1313 
1314 PHPAPI int php_mkdir(const char *dir, long mode TSRMLS_DC)
1315 {
1316         return php_mkdir_ex(dir, mode, REPORT_ERRORS TSRMLS_CC);
1317 }
1318 /* }}} */
1319 
1320 /* {{{ proto bool mkdir(string pathname [, int mode [, bool recursive [, resource context]]])
1321    Create a directory */
1322 PHP_FUNCTION(mkdir)
1323 {
1324         char *dir;
1325         int dir_len;
1326         zval *zcontext = NULL;
1327         long mode = 0777;
1328         zend_bool recursive = 0;
1329         php_stream_context *context;
1330 
1331         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|lbr", &dir, &dir_len, &mode, &recursive, &zcontext) == FAILURE) {
1332                 RETURN_FALSE;
1333         }
1334 
1335         context = php_stream_context_from_zval(zcontext, 0);
1336 
1337         RETURN_BOOL(php_stream_mkdir(dir, mode, (recursive ? PHP_STREAM_MKDIR_RECURSIVE : 0) | REPORT_ERRORS, context));
1338 }
1339 /* }}} */
1340 
1341 /* {{{ proto bool rmdir(string dirname[, resource context])
1342    Remove a directory */
1343 PHP_FUNCTION(rmdir)
1344 {
1345         char *dir;
1346         int dir_len;
1347         zval *zcontext = NULL;
1348         php_stream_context *context;
1349 
1350         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|r", &dir, &dir_len, &zcontext) == FAILURE) {
1351                 RETURN_FALSE;
1352         }
1353 
1354         context = php_stream_context_from_zval(zcontext, 0);
1355 
1356         RETURN_BOOL(php_stream_rmdir(dir, REPORT_ERRORS, context));
1357 }
1358 /* }}} */
1359 
1360 /* {{{ proto int readfile(string filename [, bool use_include_path[, resource context]])
1361    Output a file or a URL */
1362 PHP_FUNCTION(readfile)
1363 {
1364         char *filename;
1365         int filename_len;
1366         int size = 0;
1367         zend_bool use_include_path = 0;
1368         zval *zcontext = NULL;
1369         php_stream *stream;
1370         php_stream_context *context = NULL;
1371 
1372         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) {
1373                 RETURN_FALSE;
1374         }
1375 
1376         context = php_stream_context_from_zval(zcontext, 0);
1377 
1378         stream = php_stream_open_wrapper_ex(filename, "rb", (use_include_path ? USE_PATH : 0) | REPORT_ERRORS, NULL, context);
1379         if (stream) {
1380                 size = php_stream_passthru(stream);
1381                 php_stream_close(stream);
1382                 RETURN_LONG(size);
1383         }
1384 
1385         RETURN_FALSE;
1386 }
1387 /* }}} */
1388 
1389 /* {{{ proto int umask([int mask])
1390    Return or change the umask */
1391 PHP_FUNCTION(umask)
1392 {
1393         long mask = 0;
1394         int oldumask;
1395 
1396         oldumask = umask(077);
1397 
1398         if (BG(umask) == -1) {
1399                 BG(umask) = oldumask;
1400         }
1401 
1402         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &mask) == FAILURE) {
1403                 RETURN_FALSE;
1404         }
1405 
1406         if (ZEND_NUM_ARGS() == 0) {
1407                 umask(oldumask);
1408         } else {
1409                 umask(mask);
1410         }
1411 
1412         RETURN_LONG(oldumask);
1413 }
1414 /* }}} */
1415 
1416 /* {{{ proto int fpassthru(resource fp)
1417    Output all remaining data from a file pointer */
1418 PHPAPI PHP_FUNCTION(fpassthru)
1419 {
1420         zval *res;
1421         int size;
1422         php_stream *stream;
1423 
1424         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE) {
1425                 RETURN_FALSE;
1426         }
1427 
1428         PHP_STREAM_TO_ZVAL(stream, &res);
1429 
1430         size = php_stream_passthru(stream);
1431         RETURN_LONG(size);
1432 }
1433 /* }}} */
1434 
1435 /* {{{ proto bool rename(string old_name, string new_name[, resource context])
1436    Rename a file */
1437 PHP_FUNCTION(rename)
1438 {
1439         char *old_name, *new_name;
1440         int old_name_len, new_name_len;
1441         zval *zcontext = NULL;
1442         php_stream_wrapper *wrapper;
1443         php_stream_context *context;
1444 
1445         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp|r", &old_name, &old_name_len, &new_name, &new_name_len, &zcontext) == FAILURE) {
1446                 RETURN_FALSE;
1447         }
1448 
1449         wrapper = php_stream_locate_url_wrapper(old_name, NULL, 0 TSRMLS_CC);
1450 
1451         if (!wrapper || !wrapper->wops) {
1452                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to locate stream wrapper");
1453                 RETURN_FALSE;
1454         }
1455 
1456         if (!wrapper->wops->rename) {
1457                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s wrapper does not support renaming", wrapper->wops->label ? wrapper->wops->label : "Source");
1458                 RETURN_FALSE;
1459         }
1460 
1461         if (wrapper != php_stream_locate_url_wrapper(new_name, NULL, 0 TSRMLS_CC)) {
1462                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot rename a file across wrapper types");
1463                 RETURN_FALSE;
1464         }
1465 
1466         context = php_stream_context_from_zval(zcontext, 0);
1467 
1468         RETURN_BOOL(wrapper->wops->rename(wrapper, old_name, new_name, 0, context TSRMLS_CC));
1469 }
1470 /* }}} */
1471 
1472 /* {{{ proto bool unlink(string filename[, context context])
1473    Delete a file */
1474 PHP_FUNCTION(unlink)
1475 {
1476         char *filename;
1477         int filename_len;
1478         php_stream_wrapper *wrapper;
1479         zval *zcontext = NULL;
1480         php_stream_context *context = NULL;
1481 
1482         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|r", &filename, &filename_len, &zcontext) == FAILURE) {
1483                 RETURN_FALSE;
1484         }
1485 
1486         context = php_stream_context_from_zval(zcontext, 0);
1487 
1488         wrapper = php_stream_locate_url_wrapper(filename, NULL, 0 TSRMLS_CC);
1489 
1490         if (!wrapper || !wrapper->wops) {
1491                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to locate stream wrapper");
1492                 RETURN_FALSE;
1493         }
1494 
1495         if (!wrapper->wops->unlink) {
1496                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s does not allow unlinking", wrapper->wops->label ? wrapper->wops->label : "Wrapper");
1497                 RETURN_FALSE;
1498         }
1499         RETURN_BOOL(wrapper->wops->unlink(wrapper, filename, REPORT_ERRORS, context TSRMLS_CC));
1500 }
1501 /* }}} */
1502 
1503 /* {{{ proto bool ftruncate(resource fp, int size)
1504    Truncate file to 'size' length */
1505 PHP_NAMED_FUNCTION(php_if_ftruncate)
1506 {
1507         zval *fp;
1508         long size;
1509         php_stream *stream;
1510 
1511         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &fp, &size) == FAILURE) {
1512                 RETURN_FALSE;
1513         }
1514 
1515         PHP_STREAM_TO_ZVAL(stream, &fp);
1516 
1517         if (!php_stream_truncate_supported(stream)) {
1518                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't truncate this stream!");
1519                 RETURN_FALSE;
1520         }
1521 
1522         RETURN_BOOL(0 == php_stream_truncate_set_size(stream, size));
1523 }
1524 /* }}} */
1525 
1526 /* {{{ proto array fstat(resource fp)
1527    Stat() on a filehandle */
1528 PHP_NAMED_FUNCTION(php_if_fstat)
1529 {
1530         zval *fp;
1531         zval *stat_dev, *stat_ino, *stat_mode, *stat_nlink, *stat_uid, *stat_gid, *stat_rdev,
1532                  *stat_size, *stat_atime, *stat_mtime, *stat_ctime, *stat_blksize, *stat_blocks;
1533         php_stream *stream;
1534         php_stream_statbuf stat_ssb;
1535         char *stat_sb_names[13] = {
1536                 "dev", "ino", "mode", "nlink", "uid", "gid", "rdev",
1537                 "size", "atime", "mtime", "ctime", "blksize", "blocks"
1538         };
1539 
1540         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &fp) == FAILURE) {
1541                 RETURN_FALSE;
1542         }
1543 
1544         PHP_STREAM_TO_ZVAL(stream, &fp);
1545 
1546         if (php_stream_stat(stream, &stat_ssb)) {
1547                 RETURN_FALSE;
1548         }
1549 
1550         array_init(return_value);
1551 
1552         MAKE_LONG_ZVAL_INCREF(stat_dev, stat_ssb.sb.st_dev);
1553         MAKE_LONG_ZVAL_INCREF(stat_ino, stat_ssb.sb.st_ino);
1554         MAKE_LONG_ZVAL_INCREF(stat_mode, stat_ssb.sb.st_mode);
1555         MAKE_LONG_ZVAL_INCREF(stat_nlink, stat_ssb.sb.st_nlink);
1556         MAKE_LONG_ZVAL_INCREF(stat_uid, stat_ssb.sb.st_uid);
1557         MAKE_LONG_ZVAL_INCREF(stat_gid, stat_ssb.sb.st_gid);
1558 #ifdef HAVE_ST_RDEV
1559         MAKE_LONG_ZVAL_INCREF(stat_rdev, stat_ssb.sb.st_rdev);
1560 #else
1561         MAKE_LONG_ZVAL_INCREF(stat_rdev, -1);
1562 #endif
1563         MAKE_LONG_ZVAL_INCREF(stat_size, stat_ssb.sb.st_size);
1564         MAKE_LONG_ZVAL_INCREF(stat_atime, stat_ssb.sb.st_atime);
1565         MAKE_LONG_ZVAL_INCREF(stat_mtime, stat_ssb.sb.st_mtime);
1566         MAKE_LONG_ZVAL_INCREF(stat_ctime, stat_ssb.sb.st_ctime);
1567 #ifdef HAVE_ST_BLKSIZE
1568         MAKE_LONG_ZVAL_INCREF(stat_blksize, stat_ssb.sb.st_blksize);
1569 #else
1570         MAKE_LONG_ZVAL_INCREF(stat_blksize,-1);
1571 #endif
1572 #ifdef HAVE_ST_BLOCKS
1573         MAKE_LONG_ZVAL_INCREF(stat_blocks, stat_ssb.sb.st_blocks);
1574 #else
1575         MAKE_LONG_ZVAL_INCREF(stat_blocks,-1);
1576 #endif
1577         /* Store numeric indexes in propper order */
1578         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_dev, sizeof(zval *), NULL);
1579         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ino, sizeof(zval *), NULL);
1580         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mode, sizeof(zval *), NULL);
1581         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_nlink, sizeof(zval *), NULL);
1582         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_uid, sizeof(zval *), NULL);
1583         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_gid, sizeof(zval *), NULL);
1584         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_rdev, sizeof(zval *), NULL);
1585         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_size, sizeof(zval *), NULL);
1586         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_atime, sizeof(zval *), NULL);
1587         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mtime, sizeof(zval *), NULL);
1588         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ctime, sizeof(zval *), NULL);
1589         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blksize, sizeof(zval *), NULL);
1590         zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blocks, sizeof(zval *), NULL);
1591 
1592         /* Store string indexes referencing the same zval*/
1593         zend_hash_update(HASH_OF(return_value), stat_sb_names[0], strlen(stat_sb_names[0])+1, (void *)&stat_dev, sizeof(zval *), NULL);
1594         zend_hash_update(HASH_OF(return_value), stat_sb_names[1], strlen(stat_sb_names[1])+1, (void *)&stat_ino, sizeof(zval *), NULL);
1595         zend_hash_update(HASH_OF(return_value), stat_sb_names[2], strlen(stat_sb_names[2])+1, (void *)&stat_mode, sizeof(zval *), NULL);
1596         zend_hash_update(HASH_OF(return_value), stat_sb_names[3], strlen(stat_sb_names[3])+1, (void *)&stat_nlink, sizeof(zval *), NULL);
1597         zend_hash_update(HASH_OF(return_value), stat_sb_names[4], strlen(stat_sb_names[4])+1, (void *)&stat_uid, sizeof(zval *), NULL);
1598         zend_hash_update(HASH_OF(return_value), stat_sb_names[5], strlen(stat_sb_names[5])+1, (void *)&stat_gid, sizeof(zval *), NULL);
1599         zend_hash_update(HASH_OF(return_value), stat_sb_names[6], strlen(stat_sb_names[6])+1, (void *)&stat_rdev, sizeof(zval *), NULL);
1600         zend_hash_update(HASH_OF(return_value), stat_sb_names[7], strlen(stat_sb_names[7])+1, (void *)&stat_size, sizeof(zval *), NULL);
1601         zend_hash_update(HASH_OF(return_value), stat_sb_names[8], strlen(stat_sb_names[8])+1, (void *)&stat_atime, sizeof(zval *), NULL);
1602         zend_hash_update(HASH_OF(return_value), stat_sb_names[9], strlen(stat_sb_names[9])+1, (void *)&stat_mtime, sizeof(zval *), NULL);
1603         zend_hash_update(HASH_OF(return_value), stat_sb_names[10], strlen(stat_sb_names[10])+1, (void *)&stat_ctime, sizeof(zval *), NULL);
1604         zend_hash_update(HASH_OF(return_value), stat_sb_names[11], strlen(stat_sb_names[11])+1, (void *)&stat_blksize, sizeof(zval *), NULL);
1605         zend_hash_update(HASH_OF(return_value), stat_sb_names[12], strlen(stat_sb_names[12])+1, (void *)&stat_blocks, sizeof(zval *), NULL);
1606 }
1607 /* }}} */
1608 
1609 /* {{{ proto bool copy(string source_file, string destination_file [, resource context])
1610    Copy a file */
1611 PHP_FUNCTION(copy)
1612 {
1613         char *source, *target;
1614         int source_len, target_len;
1615         zval *zcontext = NULL;
1616         php_stream_context *context;
1617 
1618         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp|r", &source, &source_len, &target, &target_len, &zcontext) == FAILURE) {
1619                 return;
1620         }
1621 
1622         if (php_check_open_basedir(source TSRMLS_CC)) {
1623                 RETURN_FALSE;
1624         }
1625 
1626         context = php_stream_context_from_zval(zcontext, 0);
1627 
1628         if (php_copy_file_ctx(source, target, 0, context TSRMLS_CC) == SUCCESS) {
1629                 RETURN_TRUE;
1630         } else {
1631                 RETURN_FALSE;
1632         }
1633 }
1634 /* }}} */
1635 
1636 /* {{{ php_copy_file
1637  */
1638 PHPAPI int php_copy_file(const char *src, const char *dest TSRMLS_DC)
1639 {
1640         return php_copy_file_ctx(src, dest, 0, NULL TSRMLS_CC);
1641 }
1642 /* }}} */
1643 
1644 /* {{{ php_copy_file_ex
1645  */
1646 PHPAPI int php_copy_file_ex(const char *src, const char *dest, int src_flg TSRMLS_DC)
1647 {
1648         return php_copy_file_ctx(src, dest, 0, NULL TSRMLS_CC);
1649 }
1650 /* }}} */
1651 
1652 /* {{{ php_copy_file_ctx
1653  */
1654 PHPAPI int php_copy_file_ctx(const char *src, const char *dest, int src_flg, php_stream_context *ctx TSRMLS_DC)
1655 {
1656         php_stream *srcstream = NULL, *deststream = NULL;
1657         int ret = FAILURE;
1658         php_stream_statbuf src_s, dest_s;
1659 
1660         switch (php_stream_stat_path_ex(src, 0, &src_s, ctx)) {
1661                 case -1:
1662                         /* non-statable stream */
1663                         goto safe_to_copy;
1664                         break;
1665                 case 0:
1666                         break;
1667                 default: /* failed to stat file, does not exist? */
1668                         return ret;
1669         }
1670         if (S_ISDIR(src_s.sb.st_mode)) {
1671                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "The first argument to copy() function cannot be a directory");
1672                 return FAILURE;
1673         }
1674 
1675         switch (php_stream_stat_path_ex(dest, PHP_STREAM_URL_STAT_QUIET | PHP_STREAM_URL_STAT_NOCACHE, &dest_s, ctx)) {
1676                 case -1:
1677                         /* non-statable stream */
1678                         goto safe_to_copy;
1679                         break;
1680                 case 0:
1681                         break;
1682                 default: /* failed to stat file, does not exist? */
1683                         return ret;
1684         }
1685         if (S_ISDIR(dest_s.sb.st_mode)) {
1686                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "The second argument to copy() function cannot be a directory");
1687                 return FAILURE;
1688         }
1689         if (!src_s.sb.st_ino || !dest_s.sb.st_ino) {
1690                 goto no_stat;
1691         }
1692         if (src_s.sb.st_ino == dest_s.sb.st_ino && src_s.sb.st_dev == dest_s.sb.st_dev) {
1693                 return ret;
1694         } else {
1695                 goto safe_to_copy;
1696         }
1697 no_stat:
1698         {
1699                 char *sp, *dp;
1700                 int res;
1701 
1702                 if ((sp = expand_filepath(src, NULL TSRMLS_CC)) == NULL) {
1703                         return ret;
1704                 }
1705                 if ((dp = expand_filepath(dest, NULL TSRMLS_CC)) == NULL) {
1706                         efree(sp);
1707                         goto safe_to_copy;
1708                 }
1709 
1710                 res =
1711 #ifndef PHP_WIN32
1712                         !strcmp(sp, dp);
1713 #else
1714                         !strcasecmp(sp, dp);
1715 #endif
1716 
1717                 efree(sp);
1718                 efree(dp);
1719                 if (res) {
1720                         return ret;
1721                 }
1722         }
1723 safe_to_copy:
1724 
1725         srcstream = php_stream_open_wrapper_ex(src, "rb", src_flg | REPORT_ERRORS, NULL, ctx);
1726 
1727         if (!srcstream) {
1728                 return ret;
1729         }
1730 
1731         deststream = php_stream_open_wrapper_ex(dest, "wb", REPORT_ERRORS, NULL, ctx);
1732 
1733         if (srcstream && deststream) {
1734                 ret = php_stream_copy_to_stream_ex(srcstream, deststream, PHP_STREAM_COPY_ALL, NULL);
1735         }
1736         if (srcstream) {
1737                 php_stream_close(srcstream);
1738         }
1739         if (deststream) {
1740                 php_stream_close(deststream);
1741         }
1742         return ret;
1743 }
1744 /* }}} */
1745 
1746 /* {{{ proto string fread(resource fp, int length)
1747    Binary-safe file read */
1748 PHPAPI PHP_FUNCTION(fread)
1749 {
1750         zval *res;
1751         long len;
1752         php_stream *stream;
1753 
1754         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &res, &len) == FAILURE) {
1755                 RETURN_FALSE;
1756         }
1757 
1758         PHP_STREAM_TO_ZVAL(stream, &res);
1759 
1760         if (len <= 0) {
1761                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
1762                 RETURN_FALSE;
1763         }
1764 
1765         Z_STRVAL_P(return_value) = emalloc(len + 1);
1766         Z_STRLEN_P(return_value) = php_stream_read(stream, Z_STRVAL_P(return_value), len);
1767 
1768         /* needed because recv/read/gzread doesnt put a null at the end*/
1769         Z_STRVAL_P(return_value)[Z_STRLEN_P(return_value)] = 0;
1770         Z_TYPE_P(return_value) = IS_STRING;
1771 }
1772 /* }}} */
1773 
1774 static const char *php_fgetcsv_lookup_trailing_spaces(const char *ptr, size_t len, const char delimiter TSRMLS_DC) /* {{{ */
1775 {
1776         int inc_len;
1777         unsigned char last_chars[2] = { 0, 0 };
1778 
1779         while (len > 0) {
1780                 inc_len = (*ptr == '\0' ? 1: php_mblen(ptr, len));
1781                 switch (inc_len) {
1782                         case -2:
1783                         case -1:
1784                                 inc_len = 1;
1785                                 php_ignore_value(php_mblen(NULL, 0));
1786                                 break;
1787                         case 0:
1788                                 goto quit_loop;
1789                         case 1:
1790                         default:
1791                                 last_chars[0] = last_chars[1];
1792                                 last_chars[1] = *ptr;
1793                                 break;
1794                 }
1795                 ptr += inc_len;
1796                 len -= inc_len;
1797         }
1798 quit_loop:
1799         switch (last_chars[1]) {
1800                 case '\n':
1801                         if (last_chars[0] == '\r') {
1802                                 return ptr - 2;
1803                         }
1804                         /* break is omitted intentionally */
1805                 case '\r':
1806                         return ptr - 1;
1807         }
1808         return ptr;
1809 }
1810 /* }}} */
1811 
1812 #define FPUTCSV_FLD_CHK(c) memchr(Z_STRVAL(field), c, Z_STRLEN(field))
1813 
1814 /* {{{ proto int fputcsv(resource fp, array fields [, string delimiter [, string enclosure [, string escape_char]]])
1815    Format line as CSV and write to file pointer */
1816 PHP_FUNCTION(fputcsv)
1817 {
1818         char delimiter = ',';    /* allow this to be set as parameter */
1819         char enclosure = '"';    /* allow this to be set as parameter */
1820         char escape_char = '\\'; /* allow this to be set as parameter */
1821         php_stream *stream;
1822         zval *fp = NULL, *fields = NULL;
1823         int ret;
1824         char *delimiter_str = NULL, *enclosure_str = NULL, *escape_str = NULL;
1825         int delimiter_str_len = 0, enclosure_str_len = 0, escape_str_len = 0;
1826 
1827         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ra|sss",
1828                         &fp, &fields, &delimiter_str, &delimiter_str_len,
1829                         &enclosure_str, &enclosure_str_len,
1830                         &escape_str, &escape_str_len) == FAILURE) {
1831                 return;
1832         }
1833 
1834         if (delimiter_str != NULL) {
1835                 /* Make sure that there is at least one character in string */
1836                 if (delimiter_str_len < 1) {
1837                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "delimiter must be a character");
1838                         RETURN_FALSE;
1839                 } else if (delimiter_str_len > 1) {
1840                         php_error_docref(NULL TSRMLS_CC, E_NOTICE, "delimiter must be a single character");
1841                 }
1842 
1843                 /* use first character from string */
1844                 delimiter = *delimiter_str;
1845         }
1846 
1847         if (enclosure_str != NULL) {
1848                 if (enclosure_str_len < 1) {
1849                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character");
1850                         RETURN_FALSE;
1851                 } else if (enclosure_str_len > 1) {
1852                         php_error_docref(NULL TSRMLS_CC, E_NOTICE, "enclosure must be a single character");
1853                 }
1854                 /* use first character from string */
1855                 enclosure = *enclosure_str;
1856         }
1857 
1858         if (escape_str != NULL) {
1859                 if (escape_str_len < 1) {
1860                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "escape must be a character");
1861                         RETURN_FALSE;
1862                 } else if (escape_str_len > 1) {
1863                         php_error_docref(NULL TSRMLS_CC, E_NOTICE, "escape must be a single character");
1864                 }
1865                 /* use first character from string */
1866                 escape_char = *escape_str;
1867         }
1868 
1869         PHP_STREAM_TO_ZVAL(stream, &fp);
1870 
1871         ret = php_fputcsv(stream, fields, delimiter, enclosure, escape_char TSRMLS_CC);
1872         RETURN_LONG(ret);
1873 }
1874 /* }}} */
1875 
1876 /* {{{ PHPAPI int php_fputcsv(php_stream *stream, zval *fields, char delimiter, char enclosure, char escape_char TSRMLS_DC) */
1877 PHPAPI int php_fputcsv(php_stream *stream, zval *fields, char delimiter, char enclosure, char escape_char TSRMLS_DC)
1878 {
1879         int count, i = 0, ret;
1880         zval **field_tmp = NULL, field;
1881         smart_str csvline = {0};
1882         HashPosition pos;
1883 
1884         count = zend_hash_num_elements(Z_ARRVAL_P(fields));
1885         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(fields), &pos);
1886         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(fields), (void **) &field_tmp, &pos) == SUCCESS) {
1887                 field = **field_tmp;
1888 
1889                 if (Z_TYPE_PP(field_tmp) != IS_STRING) {
1890                         zval_copy_ctor(&field);
1891                         convert_to_string(&field);
1892                 }
1893 
1894                 /* enclose a field that contains a delimiter, an enclosure character, or a newline */
1895                 if (FPUTCSV_FLD_CHK(delimiter) ||
1896                         FPUTCSV_FLD_CHK(enclosure) ||
1897                         FPUTCSV_FLD_CHK(escape_char) ||
1898                         FPUTCSV_FLD_CHK('\n') ||
1899                         FPUTCSV_FLD_CHK('\r') ||
1900                         FPUTCSV_FLD_CHK('\t') ||
1901                         FPUTCSV_FLD_CHK(' ')
1902                 ) {
1903                         char *ch = Z_STRVAL(field);
1904                         char *end = ch + Z_STRLEN(field);
1905                         int escaped = 0;
1906 
1907                         smart_str_appendc(&csvline, enclosure);
1908                         while (ch < end) {
1909                                 if (*ch == escape_char) {
1910                                         escaped = 1;
1911                                 } else if (!escaped && *ch == enclosure) {
1912                                         smart_str_appendc(&csvline, enclosure);
1913                                 } else {
1914                                         escaped = 0;
1915                                 }
1916                                 smart_str_appendc(&csvline, *ch);
1917                                 ch++;
1918                         }
1919                         smart_str_appendc(&csvline, enclosure);
1920                 } else {
1921                         smart_str_appendl(&csvline, Z_STRVAL(field), Z_STRLEN(field));
1922                 }
1923 
1924                 if (++i != count) {
1925                         smart_str_appendl(&csvline, &delimiter, 1);
1926                 }
1927                 zend_hash_move_forward_ex(Z_ARRVAL_P(fields), &pos);
1928 
1929                 if (Z_TYPE_PP(field_tmp) != IS_STRING) {
1930                         zval_dtor(&field);
1931                 }
1932         }
1933 
1934         smart_str_appendc(&csvline, '\n');
1935         smart_str_0(&csvline);
1936 
1937         ret = php_stream_write(stream, csvline.c, csvline.len);
1938 
1939         smart_str_free(&csvline);
1940 
1941         return ret;
1942 }
1943 /* }}} */
1944 
1945 /* {{{ proto array fgetcsv(resource fp [,int length [, string delimiter [, string enclosure [, string escape]]]])
1946    Get line from file pointer and parse for CSV fields */
1947 PHP_FUNCTION(fgetcsv)
1948 {
1949         char delimiter = ',';   /* allow this to be set as parameter */
1950         char enclosure = '"';   /* allow this to be set as parameter */
1951         char escape = '\\';
1952 
1953         /* first section exactly as php_fgetss */
1954 
1955         long len = 0;
1956         size_t buf_len;
1957         char *buf;
1958         php_stream *stream;
1959 
1960         {
1961                 zval *fd, **len_zv = NULL;
1962                 char *delimiter_str = NULL;
1963                 int delimiter_str_len = 0;
1964                 char *enclosure_str = NULL;
1965                 int enclosure_str_len = 0;
1966                 char *escape_str = NULL;
1967                 int escape_str_len = 0;
1968 
1969                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|Zsss",
1970                         &fd, &len_zv, &delimiter_str, &delimiter_str_len,
1971                         &enclosure_str, &enclosure_str_len,
1972                         &escape_str, &escape_str_len) == FAILURE
1973                 ) {
1974                         return;
1975                 }
1976 
1977                 if (delimiter_str != NULL) {
1978                         /* Make sure that there is at least one character in string */
1979                         if (delimiter_str_len < 1) {
1980                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "delimiter must be a character");
1981                                 RETURN_FALSE;
1982                         } else if (delimiter_str_len > 1) {
1983                                 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "delimiter must be a single character");
1984                         }
1985 
1986                         /* use first character from string */
1987                         delimiter = delimiter_str[0];
1988                 }
1989 
1990                 if (enclosure_str != NULL) {
1991                         if (enclosure_str_len < 1) {
1992                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "enclosure must be a character");
1993                                 RETURN_FALSE;
1994                         } else if (enclosure_str_len > 1) {
1995                                 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "enclosure must be a single character");
1996                         }
1997 
1998                         /* use first character from string */
1999                         enclosure = enclosure_str[0];
2000                 }
2001 
2002                 if (escape_str != NULL) {
2003                         if (escape_str_len < 1) {
2004                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "escape must be character");
2005                                 RETURN_FALSE;
2006                         } else if (escape_str_len > 1) {
2007                                 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "escape must be a single character");
2008                         }
2009 
2010                         escape = escape_str[0];
2011                 }
2012 
2013                 if (len_zv != NULL && Z_TYPE_PP(len_zv) != IS_NULL) {
2014                         convert_to_long_ex(len_zv);
2015                         len = Z_LVAL_PP(len_zv);
2016                         if (len < 0) {
2017                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter may not be negative");
2018                                 RETURN_FALSE;
2019                         } else if (len == 0) {
2020                                 len = -1;
2021                         }
2022                 } else {
2023                         len = -1;
2024                 }
2025 
2026                 PHP_STREAM_TO_ZVAL(stream, &fd);
2027         }
2028 
2029         if (len < 0) {
2030                 if ((buf = php_stream_get_line(stream, NULL, 0, &buf_len)) == NULL) {
2031                         RETURN_FALSE;
2032                 }
2033         } else {
2034                 buf = emalloc(len + 1);
2035                 if (php_stream_get_line(stream, buf, len + 1, &buf_len) == NULL) {
2036                         efree(buf);
2037                         RETURN_FALSE;
2038                 }
2039         }
2040 
2041         php_fgetcsv(stream, delimiter, enclosure, escape, buf_len, buf, return_value TSRMLS_CC);
2042 }
2043 /* }}} */
2044 
2045 PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, char escape_char, size_t buf_len, char *buf, zval *return_value TSRMLS_DC) /* {{{ */
2046 {
2047         char *temp, *tptr, *bptr, *line_end, *limit;
2048         size_t temp_len, line_end_len;
2049         int inc_len;
2050         zend_bool first_field = 1;
2051 
2052         /* initialize internal state */
2053         php_ignore_value(php_mblen(NULL, 0));
2054 
2055         /* Now into new section that parses buf for delimiter/enclosure fields */
2056 
2057         /* Strip trailing space from buf, saving end of line in case required for enclosure field */
2058 
2059         bptr = buf;
2060         tptr = (char *)php_fgetcsv_lookup_trailing_spaces(buf, buf_len, delimiter TSRMLS_CC);
2061         line_end_len = buf_len - (size_t)(tptr - buf);
2062         line_end = limit = tptr;
2063 
2064         /* reserve workspace for building each individual field */
2065         temp_len = buf_len;
2066         temp = emalloc(temp_len + line_end_len + 1);
2067 
2068         /* Initialize return array */
2069         array_init(return_value);
2070 
2071         /* Main loop to read CSV fields */
2072         /* NB this routine will return a single null entry for a blank line */
2073 
2074         do {
2075                 char *comp_end, *hunk_begin;
2076 
2077                 tptr = temp;
2078 
2079                 inc_len = (bptr < limit ? (*bptr == '\0' ? 1: php_mblen(bptr, limit - bptr)): 0);
2080                 if (inc_len == 1) {
2081                         char *tmp = bptr;
2082                         while ((*tmp != delimiter) && isspace((int)*(unsigned char *)tmp)) {
2083                                 tmp++;
2084                         }
2085                         if (*tmp == enclosure) {
2086                                 bptr = tmp;
2087                         }
2088                 }
2089 
2090                 if (first_field && bptr == line_end) {
2091                         add_next_index_null(return_value);
2092                         break;
2093                 }
2094                 first_field = 0;
2095                 /* 2. Read field, leaving bptr pointing at start of next field */
2096                 if (inc_len != 0 && *bptr == enclosure) {
2097                         int state = 0;
2098 
2099                         bptr++; /* move on to first character in field */
2100                         hunk_begin = bptr;
2101 
2102                         /* 2A. handle enclosure delimited field */
2103                         for (;;) {
2104                                 switch (inc_len) {
2105                                         case 0:
2106                                                 switch (state) {
2107                                                         case 2:
2108                                                                 memcpy(tptr, hunk_begin, bptr - hunk_begin - 1);
2109                                                                 tptr += (bptr - hunk_begin - 1);
2110                                                                 hunk_begin = bptr;
2111                                                                 goto quit_loop_2;
2112 
2113                                                         case 1:
2114                                                                 memcpy(tptr, hunk_begin, bptr - hunk_begin);
2115                                                                 tptr += (bptr - hunk_begin);
2116                                                                 hunk_begin = bptr;
2117                                                                 /* break is omitted intentionally */
2118 
2119                                                         case 0: {
2120                                                                 char *new_buf;
2121                                                                 size_t new_len;
2122                                                                 char *new_temp;
2123 
2124                                                                 if (hunk_begin != line_end) {
2125                                                                         memcpy(tptr, hunk_begin, bptr - hunk_begin);
2126                                                                         tptr += (bptr - hunk_begin);
2127                                                                         hunk_begin = bptr;
2128                                                                 }
2129 
2130                                                                 /* add the embedded line end to the field */
2131                                                                 memcpy(tptr, line_end, line_end_len);
2132                                                                 tptr += line_end_len;
2133 
2134                                                                 if (stream == NULL) {
2135                                                                         goto quit_loop_2;
2136                                                                 } else if ((new_buf = php_stream_get_line(stream, NULL, 0, &new_len)) == NULL) {
2137                                                                         /* we've got an unterminated enclosure,
2138                                                                          * assign all the data from the start of
2139                                                                          * the enclosure to end of data to the
2140                                                                          * last element */
2141                                                                         if ((size_t)temp_len > (size_t)(limit - buf)) {
2142                                                                                 goto quit_loop_2;
2143                                                                         }
2144                                                                         zval_dtor(return_value);
2145                                                                         RETVAL_FALSE;
2146                                                                         goto out;
2147                                                                 }
2148                                                                 temp_len += new_len;
2149                                                                 new_temp = erealloc(temp, temp_len);
2150                                                                 tptr = new_temp + (size_t)(tptr - temp);
2151                                                                 temp = new_temp;
2152 
2153                                                                 efree(buf);
2154                                                                 buf_len = new_len;
2155                                                                 bptr = buf = new_buf;
2156                                                                 hunk_begin = buf;
2157 
2158                                                                 line_end = limit = (char *)php_fgetcsv_lookup_trailing_spaces(buf, buf_len, delimiter TSRMLS_CC);
2159                                                                 line_end_len = buf_len - (size_t)(limit - buf);
2160 
2161                                                                 state = 0;
2162                                                         } break;
2163                                                 }
2164                                                 break;
2165 
2166                                         case -2:
2167                                         case -1:
2168                                                 php_ignore_value(php_mblen(NULL, 0));
2169                                                 /* break is omitted intentionally */
2170                                         case 1:
2171                                                 /* we need to determine if the enclosure is
2172                                                  * 'real' or is it escaped */
2173                                                 switch (state) {
2174                                                         case 1: /* escaped */
2175                                                                 bptr++;
2176                                                                 state = 0;
2177                                                                 break;
2178                                                         case 2: /* embedded enclosure ? let's check it */
2179                                                                 if (*bptr != enclosure) {
2180                                                                         /* real enclosure */
2181                                                                         memcpy(tptr, hunk_begin, bptr - hunk_begin - 1);
2182                                                                         tptr += (bptr - hunk_begin - 1);
2183                                                                         hunk_begin = bptr;
2184                                                                         goto quit_loop_2;
2185                                                                 }
2186                                                                 memcpy(tptr, hunk_begin, bptr - hunk_begin);
2187                                                                 tptr += (bptr - hunk_begin);
2188                                                                 bptr++;
2189                                                                 hunk_begin = bptr;
2190                                                                 state = 0;
2191                                                                 break;
2192                                                         default:
2193                                                                 if (*bptr == enclosure) {
2194                                                                         state = 2;
2195                                                                 } else if (*bptr == escape_char) {
2196                                                                         state = 1;
2197                                                                 }
2198                                                                 bptr++;
2199                                                                 break;
2200                                                 }
2201                                                 break;
2202 
2203                                         default:
2204                                                 switch (state) {
2205                                                         case 2:
2206                                                                 /* real enclosure */
2207                                                                 memcpy(tptr, hunk_begin, bptr - hunk_begin - 1);
2208                                                                 tptr += (bptr - hunk_begin - 1);
2209                                                                 hunk_begin = bptr;
2210                                                                 goto quit_loop_2;
2211                                                         case 1:
2212                                                                 bptr += inc_len;
2213                                                                 memcpy(tptr, hunk_begin, bptr - hunk_begin);
2214                                                                 tptr += (bptr - hunk_begin);
2215                                                                 hunk_begin = bptr;
2216                                                                 break;
2217                                                         default:
2218                                                                 bptr += inc_len;
2219                                                                 break;
2220                                                 }
2221                                                 break;
2222                                 }
2223                                 inc_len = (bptr < limit ? (*bptr == '\0' ? 1: php_mblen(bptr, limit - bptr)): 0);
2224                         }
2225 
2226                 quit_loop_2:
2227                         /* look up for a delimiter */
2228                         for (;;) {
2229                                 switch (inc_len) {
2230                                         case 0:
2231                                                 goto quit_loop_3;
2232 
2233                                         case -2:
2234                                         case -1:
2235                                                 inc_len = 1;
2236                                                 php_ignore_value(php_mblen(NULL, 0));
2237                                                 /* break is omitted intentionally */
2238                                         case 1:
2239                                                 if (*bptr == delimiter) {
2240                                                         goto quit_loop_3;
2241                                                 }
2242                                                 break;
2243                                         default:
2244                                                 break;
2245                                 }
2246                                 bptr += inc_len;
2247                                 inc_len = (bptr < limit ? (*bptr == '\0' ? 1: php_mblen(bptr, limit - bptr)): 0);
2248                         }
2249 
2250                 quit_loop_3:
2251                         memcpy(tptr, hunk_begin, bptr - hunk_begin);
2252                         tptr += (bptr - hunk_begin);
2253                         bptr += inc_len;
2254                         comp_end = tptr;
2255                 } else {
2256                         /* 2B. Handle non-enclosure field */
2257 
2258                         hunk_begin = bptr;
2259 
2260                         for (;;) {
2261                                 switch (inc_len) {
2262                                         case 0:
2263                                                 goto quit_loop_4;
2264                                         case -2:
2265                                         case -1:
2266                                                 inc_len = 1;
2267                                                 php_ignore_value(php_mblen(NULL, 0));
2268                                                 /* break is omitted intentionally */
2269                                         case 1:
2270                                                 if (*bptr == delimiter) {
2271                                                         goto quit_loop_4;
2272                                                 }
2273                                                 break;
2274                                         default:
2275                                                 break;
2276                                 }
2277                                 bptr += inc_len;
2278                                 inc_len = (bptr < limit ? (*bptr == '\0' ? 1: php_mblen(bptr, limit - bptr)): 0);
2279                         }
2280                 quit_loop_4:
2281                         memcpy(tptr, hunk_begin, bptr - hunk_begin);
2282                         tptr += (bptr - hunk_begin);
2283 
2284                         comp_end = (char *)php_fgetcsv_lookup_trailing_spaces(temp, tptr - temp, delimiter TSRMLS_CC);
2285                         if (*bptr == delimiter) {
2286                                 bptr++;
2287                         }
2288                 }
2289 
2290                 /* 3. Now pass our field back to php */
2291                 *comp_end = '\0';
2292                 add_next_index_stringl(return_value, temp, comp_end - temp, 1);
2293         } while (inc_len > 0);
2294 
2295 out:
2296         efree(temp);
2297         if (stream) {
2298                 efree(buf);
2299         }
2300 }
2301 /* }}} */
2302 
2303 #if (!defined(__BEOS__) && !defined(NETWARE) && HAVE_REALPATH) || defined(ZTS)
2304 /* {{{ proto string realpath(string path)
2305    Return the resolved path */
2306 PHP_FUNCTION(realpath)
2307 {
2308         char *filename;
2309         int filename_len;
2310         char resolved_path_buff[MAXPATHLEN];
2311 
2312         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
2313                 return;
2314         }
2315 
2316         if (VCWD_REALPATH(filename, resolved_path_buff)) {
2317                 if (php_check_open_basedir(resolved_path_buff TSRMLS_CC)) {
2318                         RETURN_FALSE;
2319                 }
2320 
2321 #ifdef ZTS
2322                 if (VCWD_ACCESS(resolved_path_buff, F_OK)) {
2323                         RETURN_FALSE;
2324                 }
2325 #endif
2326                 RETURN_STRING(resolved_path_buff, 1);
2327         } else {
2328                 RETURN_FALSE;
2329         }
2330 }
2331 /* }}} */
2332 #endif
2333 
2334 /* See http://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2.2 */
2335 #define PHP_META_HTML401_CHARS "-_.:"
2336 
2337 /* {{{ php_next_meta_token
2338    Tokenizes an HTML file for get_meta_tags */
2339 php_meta_tags_token php_next_meta_token(php_meta_tags_data *md TSRMLS_DC)
2340 {
2341         int ch = 0, compliment;
2342         char buff[META_DEF_BUFSIZE + 1];
2343 
2344         memset((void *)buff, 0, META_DEF_BUFSIZE + 1);
2345 
2346         while (md->ulc || (!php_stream_eof(md->stream) && (ch = php_stream_getc(md->stream)))) {
2347                 if (php_stream_eof(md->stream)) {
2348                         break;
2349                 }
2350 
2351                 if (md->ulc) {
2352                         ch = md->lc;
2353                         md->ulc = 0;
2354                 }
2355 
2356                 switch (ch) {
2357                         case '<':
2358                                 return TOK_OPENTAG;
2359                                 break;
2360 
2361                         case '>':
2362                                 return TOK_CLOSETAG;
2363                                 break;
2364 
2365                         case '=':
2366                                 return TOK_EQUAL;
2367                                 break;
2368                         case '/':
2369                                 return TOK_SLASH;
2370                                 break;
2371 
2372                         case '\'':
2373                         case '"':
2374                                 compliment = ch;
2375                                 md->token_len = 0;
2376                                 while (!php_stream_eof(md->stream) && (ch = php_stream_getc(md->stream)) && ch != compliment && ch != '<' && ch != '>') {
2377                                         buff[(md->token_len)++] = ch;
2378 
2379                                         if (md->token_len == META_DEF_BUFSIZE) {
2380                                                 break;
2381                                         }
2382                                 }
2383 
2384                                 if (ch == '<' || ch == '>') {
2385                                         /* Was just an apostrohpe */
2386                                         md->ulc = 1;
2387                                         md->lc = ch;
2388                                 }
2389 
2390                                 /* We don't need to alloc unless we are in a meta tag */
2391                                 if (md->in_meta) {
2392                                         md->token_data = (char *) emalloc(md->token_len + 1);
2393                                         memcpy(md->token_data, buff, md->token_len+1);
2394                                 }
2395 
2396                                 return TOK_STRING;
2397                                 break;
2398 
2399                         case '\n':
2400                         case '\r':
2401                         case '\t':
2402                                 break;
2403 
2404                         case ' ':
2405                                 return TOK_SPACE;
2406                                 break;
2407 
2408                         default:
2409                                 if (isalnum(ch)) {
2410                                         md->token_len = 0;
2411                                         buff[(md->token_len)++] = ch;
2412                                         while (!php_stream_eof(md->stream) && (ch = php_stream_getc(md->stream)) && (isalnum(ch) || strchr(PHP_META_HTML401_CHARS, ch))) {
2413                                                 buff[(md->token_len)++] = ch;
2414 
2415                                                 if (md->token_len == META_DEF_BUFSIZE) {
2416                                                         break;
2417                                                 }
2418                                         }
2419 
2420                                         /* This is ugly, but we have to replace ungetc */
2421                                         if (!isalpha(ch) && ch != '-') {
2422                                                 md->ulc = 1;
2423                                                 md->lc = ch;
2424                                         }
2425 
2426                                         md->token_data = (char *) emalloc(md->token_len + 1);
2427                                         memcpy(md->token_data, buff, md->token_len+1);
2428 
2429                                         return TOK_ID;
2430                                 } else {
2431                                         return TOK_OTHER;
2432                                 }
2433                                 break;
2434                 }
2435         }
2436 
2437         return TOK_EOF;
2438 }
2439 /* }}} */
2440 
2441 #ifdef HAVE_FNMATCH
2442 /* {{{ proto bool fnmatch(string pattern, string filename [, int flags])
2443    Match filename against pattern */
2444 PHP_FUNCTION(fnmatch)
2445 {
2446         char *pattern, *filename;
2447         int pattern_len, filename_len;
2448         long flags = 0;
2449 
2450         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pp|l", &pattern, &pattern_len, &filename, &filename_len, &flags) == FAILURE) {
2451                 return;
2452         }
2453 
2454         if (filename_len >= MAXPATHLEN) {
2455                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filename exceeds the maximum allowed length of %d characters", MAXPATHLEN);
2456                 RETURN_FALSE;
2457         }
2458         if (pattern_len >= MAXPATHLEN) {
2459                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN);
2460                 RETURN_FALSE;
2461         }
2462 
2463         RETURN_BOOL( ! fnmatch( pattern, filename, flags ));
2464 }
2465 /* }}} */
2466 #endif
2467 
2468 /* {{{ proto string sys_get_temp_dir()
2469    Returns directory path used for temporary files */
2470 PHP_FUNCTION(sys_get_temp_dir)
2471 {
2472         if (zend_parse_parameters_none() == FAILURE) {
2473                 return;
2474         }
2475         RETURN_STRING((char *)php_get_temporary_directory(TSRMLS_C), 1);
2476 }
2477 /* }}} */
2478 
2479 /*
2480  * Local variables:
2481  * tab-width: 4
2482  * c-basic-offset: 4
2483  * End:
2484  * vim600: noet sw=4 ts=4 fdm=marker
2485  * vim<600: noet sw=4 ts=4
2486  */

/* [<][>][^][v][top][bottom][index][help] */