root/ext/zip/zip_stream.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. php_zip_ops_read
  2. php_zip_ops_write
  3. php_zip_ops_close
  4. php_zip_ops_flush
  5. php_zip_ops_stat
  6. php_stream_zip_open
  7. php_stream_zip_opener

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

/* [<][>][^][v][top][bottom][index][help] */