Annotation of embedaddon/php/ext/standard/file.c, revision 1.1.1.3

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>