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

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

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