Coverage Report

Created: 2026-07-25 06:39

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