Return to zip_stream.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / zip |
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 */