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