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