PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/zip - zip_stream.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 116 140 82.9 %
Date: 2022-01-18 Functions: 6 7 85.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 7                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 1997-2018 The PHP Group                                |
       6             :   +----------------------------------------------------------------------+
       7             :   | This source file is subject to version 3.01 of the PHP license,      |
       8             :   | that is bundled with this package in the file LICENSE, and is        |
       9             :   | available through the world-wide-web at the following url:           |
      10             :   | http://www.php.net/license/3_01.txt.                                 |
      11             :   | If you did not receive a copy of the PHP license and are unable to   |
      12             :   | obtain it through the world-wide-web, please send a note to          |
      13             :   | license@php.net so we can mail you a copy immediately.               |
      14             :   +----------------------------------------------------------------------+
      15             :   | Author: Piere-Alain Joye <pierre@php.net>                            |
      16             :   +----------------------------------------------------------------------+
      17             : */
      18             : 
      19             : #ifdef HAVE_CONFIG_H
      20             : #   include "config.h"
      21             : #endif
      22             : #include "php.h"
      23             : #if HAVE_ZIP
      24             : 
      25             : #include "php_streams.h"
      26             : #include "ext/standard/file.h"
      27             : #include "ext/standard/php_string.h"
      28             : #include "fopen_wrappers.h"
      29             : #include "php_zip.h"
      30             : 
      31             : #include "ext/standard/url.h"
      32             : 
      33             : /* needed for ssize_t definition */
      34             : #include <sys/types.h>
      35             : 
      36             : struct php_zip_stream_data_t {
      37             :         struct zip *za;
      38             :         struct zip_file *zf;
      39             :         size_t cursor;
      40             :         php_stream *stream;
      41             : };
      42             : 
      43             : #define STREAM_DATA_FROM_STREAM() \
      44             :         struct php_zip_stream_data_t *self = (struct php_zip_stream_data_t *) stream->abstract;
      45             : 
      46             : 
      47             : /* {{{ php_zip_ops_read */
      48         117 : static size_t php_zip_ops_read(php_stream *stream, char *buf, size_t count)
      49             : {
      50         117 :         ssize_t n = 0;
      51         117 :         STREAM_DATA_FROM_STREAM();
      52             : 
      53         117 :         if (self->za && self->zf) {
      54         117 :                 n = zip_fread(self->zf, buf, count);
      55         117 :                 if (n < 0) {
      56             : #if LIBZIP_VERSION_MAJOR < 1
      57             :                         int ze, se;
      58             :                         zip_file_error_get(self->zf, &ze, &se);
      59             :                         stream->eof = 1;
      60             :                         php_error_docref(NULL, E_WARNING, "Zip stream error: %s", zip_file_strerror(self->zf));
      61             : #else
      62             :                         zip_error_t *err;
      63           1 :                         err = zip_file_get_error(self->zf);
      64           1 :                         stream->eof = 1;
      65           1 :                         php_error_docref(NULL, E_WARNING, "Zip stream error: %s", zip_error_strerror(err));
      66           1 :                         zip_error_fini(err);
      67             : #endif
      68           1 :                         return 0;
      69             :                 }
      70             :                 /* cast count to signed value to avoid possibly negative n
      71             :                  * being cast to unsigned value */
      72         116 :                 if (n == 0 || n < (ssize_t)count) {
      73           9 :                         stream->eof = 1;
      74             :                 } else {
      75         107 :                         self->cursor += n;
      76             :                 }
      77             :         }
      78         116 :         return (n < 1 ? 0 : (size_t)n);
      79             : }
      80             : /* }}} */
      81             : 
      82             : /* {{{ php_zip_ops_write */
      83           0 : static size_t php_zip_ops_write(php_stream *stream, const char *buf, size_t count)
      84             : {
      85           0 :         if (!stream) {
      86           0 :                 return 0;
      87             :         }
      88             : 
      89           0 :         return count;
      90             : }
      91             : /* }}} */
      92             : 
      93             : /* {{{ php_zip_ops_close */
      94           9 : static int php_zip_ops_close(php_stream *stream, int close_handle)
      95             : {
      96           9 :         STREAM_DATA_FROM_STREAM();
      97           9 :         if (close_handle) {
      98           9 :                 if (self->zf) {
      99           9 :                         zip_fclose(self->zf);
     100           9 :                         self->zf = NULL;
     101             :                 }
     102             : 
     103           9 :                 if (self->za) {
     104           9 :                         zip_close(self->za);
     105           9 :                         self->za = NULL;
     106             :                 }
     107             :         }
     108           9 :         efree(self);
     109           9 :         stream->abstract = NULL;
     110           9 :         return EOF;
     111             : }
     112             : /* }}} */
     113             : 
     114             : /* {{{ php_zip_ops_flush */
     115           1 : static int php_zip_ops_flush(php_stream *stream)
     116             : {
     117           1 :         if (!stream) {
     118           0 :                 return 0;
     119             :         }
     120             : 
     121           1 :         return 0;
     122             : }
     123             : /* }}} */
     124             : 
     125           5 : static int php_zip_ops_stat(php_stream *stream, php_stream_statbuf *ssb) /* {{{ */
     126             : {
     127             :         struct zip_stat sb;
     128           5 :         const char *path = stream->orig_path;
     129           5 :         size_t path_len = strlen(stream->orig_path);
     130             :         char file_dirname[MAXPATHLEN];
     131             :         struct zip *za;
     132             :         char *fragment;
     133             :         size_t fragment_len;
     134             :         int err;
     135             :         zend_string *file_basename;
     136             : 
     137           5 :         fragment = strchr(path, '#');
     138           5 :         if (!fragment) {
     139           1 :                 return -1;
     140             :         }
     141             : 
     142             : 
     143           4 :         if (strncasecmp("zip://", path, 6) == 0) {
     144           4 :                 path += 6;
     145             :         }
     146             : 
     147           4 :         fragment_len = strlen(fragment);
     148             : 
     149           4 :         if (fragment_len < 1) {
     150           0 :                 return -1;
     151             :         }
     152           4 :         path_len = strlen(path);
     153           4 :         if (path_len >= MAXPATHLEN) {
     154           0 :                 return -1;
     155             :         }
     156             : 
     157           4 :         memcpy(file_dirname, path, path_len - fragment_len);
     158           4 :         file_dirname[path_len - fragment_len] = '\0';
     159             : 
     160           4 :         file_basename = php_basename((char *)path, path_len - fragment_len, NULL, 0);
     161           4 :         fragment++;
     162             : 
     163           4 :         if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname)) {
     164             :                 zend_string_release_ex(file_basename, 0);
     165           0 :                 return -1;
     166             :         }
     167             : 
     168           4 :         za = zip_open(file_dirname, ZIP_CREATE, &err);
     169           4 :         if (za) {
     170           4 :                 memset(ssb, 0, sizeof(php_stream_statbuf));
     171           4 :                 if (zip_stat(za, fragment, ZIP_FL_NOCASE, &sb) != 0) {
     172           0 :                         zip_close(za);
     173             :                         zend_string_release_ex(file_basename, 0);
     174           0 :                         return -1;
     175             :                 }
     176           4 :                 zip_close(za);
     177             : 
     178           4 :                 if (path[path_len-1] != '/') {
     179           3 :                         ssb->sb.st_size = sb.size;
     180           3 :                         ssb->sb.st_mode |= S_IFREG; /* regular file */
     181             :                 } else {
     182           1 :                         ssb->sb.st_size = 0;
     183           1 :                         ssb->sb.st_mode |= S_IFDIR; /* regular directory */
     184             :                 }
     185             : 
     186           4 :                 ssb->sb.st_mtime = sb.mtime;
     187           4 :                 ssb->sb.st_atime = sb.mtime;
     188           4 :                 ssb->sb.st_ctime = sb.mtime;
     189           4 :                 ssb->sb.st_nlink = 1;
     190           4 :                 ssb->sb.st_rdev = -1;
     191             : #ifndef PHP_WIN32
     192           4 :                 ssb->sb.st_blksize = -1;
     193           4 :                 ssb->sb.st_blocks = -1;
     194             : #endif
     195           4 :                 ssb->sb.st_ino = -1;
     196             :         }
     197             :         zend_string_release_ex(file_basename, 0);
     198           4 :         return 0;
     199             : }
     200             : /* }}} */
     201             : 
     202             : const php_stream_ops php_stream_zipio_ops = {
     203             :         php_zip_ops_write, php_zip_ops_read,
     204             :         php_zip_ops_close, php_zip_ops_flush,
     205             :         "zip",
     206             :         NULL, /* seek */
     207             :         NULL, /* cast */
     208             :         php_zip_ops_stat, /* stat */
     209             :         NULL  /* set_option */
     210             : };
     211             : 
     212             : /* {{{ php_stream_zip_open */
     213           4 : php_stream *php_stream_zip_open(const char *filename, const char *path, const char *mode STREAMS_DC)
     214             : {
     215           4 :         struct zip_file *zf = NULL;
     216           4 :         int err = 0;
     217             : 
     218           4 :         php_stream *stream = NULL;
     219             :         struct php_zip_stream_data_t *self;
     220             :         struct zip *stream_za;
     221             : 
     222           4 :         if (strncmp(mode,"r", strlen("r")) != 0) {
     223           0 :                 return NULL;
     224             :         }
     225             : 
     226           4 :         if (filename) {
     227           4 :                 if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
     228           0 :                         return NULL;
     229             :                 }
     230             : 
     231             :                 /* duplicate to make the stream za independent (esp. for MSHUTDOWN) */
     232           4 :                 stream_za = zip_open(filename, ZIP_CREATE, &err);
     233           4 :                 if (!stream_za) {
     234           0 :                         return NULL;
     235             :                 }
     236             : 
     237           4 :                 zf = zip_fopen(stream_za, path, 0);
     238           4 :                 if (zf) {
     239           4 :                         self = emalloc(sizeof(*self));
     240             : 
     241           4 :                         self->za = stream_za;
     242           4 :                         self->zf = zf;
     243           4 :                         self->stream = NULL;
     244           4 :                         self->cursor = 0;
     245           4 :                         stream = php_stream_alloc(&php_stream_zipio_ops, self, NULL, mode);
     246           4 :                         stream->orig_path = estrdup(path);
     247             :                 } else {
     248           0 :                         zip_close(stream_za);
     249             :                 }
     250             :         }
     251             : 
     252           4 :         if (!stream) {
     253           0 :                 return NULL;
     254             :         } else {
     255           4 :                 return stream;
     256             :         }
     257             : 
     258             : }
     259             : /* }}} */
     260             : 
     261             : /* {{{ php_stream_zip_opener */
     262           5 : php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper,
     263             :                                                                                         const char *path,
     264             :                                                                                         const char *mode,
     265             :                                                                                         int options,
     266             :                                                                                         zend_string **opened_path,
     267             :                                                                                         php_stream_context *context STREAMS_DC)
     268             : {
     269             :         size_t path_len;
     270             : 
     271             :         zend_string *file_basename;
     272             :         char file_dirname[MAXPATHLEN];
     273             : 
     274             :         struct zip *za;
     275           5 :         struct zip_file *zf = NULL;
     276             :         char *fragment;
     277             :         size_t fragment_len;
     278             :         int err;
     279             : 
     280           5 :         php_stream *stream = NULL;
     281             :         struct php_zip_stream_data_t *self;
     282             : 
     283           5 :         fragment = strchr(path, '#');
     284           5 :         if (!fragment) {
     285           0 :                 return NULL;
     286             :         }
     287             : 
     288           5 :         if (strncasecmp("zip://", path, 6) == 0) {
     289           5 :                 path += 6;
     290             :         }
     291             : 
     292           5 :         fragment_len = strlen(fragment);
     293             : 
     294           5 :         if (fragment_len < 1) {
     295           0 :                 return NULL;
     296             :         }
     297           5 :         path_len = strlen(path);
     298           5 :         if (path_len >= MAXPATHLEN || mode[0] != 'r') {
     299           0 :                 return NULL;
     300             :         }
     301             : 
     302           5 :         memcpy(file_dirname, path, path_len - fragment_len);
     303           5 :         file_dirname[path_len - fragment_len] = '\0';
     304             : 
     305           5 :         file_basename = php_basename(path, path_len - fragment_len, NULL, 0);
     306           5 :         fragment++;
     307             : 
     308           5 :         if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname)) {
     309             :                 zend_string_release_ex(file_basename, 0);
     310           0 :                 return NULL;
     311             :         }
     312             : 
     313           5 :         za = zip_open(file_dirname, ZIP_CREATE, &err);
     314           5 :         if (za) {
     315             :                 zval *tmpzval;
     316             : 
     317           5 :                 if (context && NULL != (tmpzval = php_stream_context_get_option(context, "zip", "password"))) {
     318           0 :                         if (Z_TYPE_P(tmpzval) != IS_STRING || zip_set_default_password(za, Z_STRVAL_P(tmpzval))) {
     319           0 :                                 php_error_docref(NULL, E_WARNING, "Can't set zip password");
     320             :                         }
     321             :                 }
     322             : 
     323           5 :                 zf = zip_fopen(za, fragment, 0);
     324           5 :                 if (zf) {
     325           5 :                         self = emalloc(sizeof(*self));
     326             : 
     327           5 :                         self->za = za;
     328           5 :                         self->zf = zf;
     329           5 :                         self->stream = NULL;
     330           5 :                         self->cursor = 0;
     331           5 :                         stream = php_stream_alloc(&php_stream_zipio_ops, self, NULL, mode);
     332             : 
     333           5 :                         if (opened_path) {
     334           0 :                                 *opened_path = zend_string_init(path, strlen(path), 0);
     335             :                         }
     336             :                 } else {
     337           0 :                         zip_close(za);
     338             :                 }
     339             :         }
     340             : 
     341             :         zend_string_release_ex(file_basename, 0);
     342             : 
     343           5 :         if (!stream) {
     344           0 :                 return NULL;
     345             :         } else {
     346           5 :                 return stream;
     347             :         }
     348             : }
     349             : /* }}} */
     350             : 
     351             : static const php_stream_wrapper_ops zip_stream_wops = {
     352             :         php_stream_zip_opener,
     353             :         NULL,   /* close */
     354             :         NULL,   /* fstat */
     355             :         NULL,   /* stat */
     356             :         NULL,   /* opendir */
     357             :         "zip wrapper",
     358             :         NULL,   /* unlink */
     359             :         NULL,   /* rename */
     360             :         NULL,   /* mkdir */
     361             :         NULL,   /* rmdir */
     362             :         NULL    /* metadata */
     363             : };
     364             : 
     365             : const php_stream_wrapper php_stream_zip_wrapper = {
     366             :         &zip_stream_wops,
     367             :         NULL,
     368             :         0 /* is_url */
     369             : };
     370             : #endif /* HAVE_ZIP */

Generated by: LCOV version 1.10

Generated at Wed, 19 Jan 2022 00:14:27 +0000 (3 days ago)

Copyright © 2005-2022 The PHP Group
All rights reserved.