11 #include "php_streams.h"
12 #include "ext/standard/file.h"
13 #include "ext/standard/php_string.h"
14 #include "fopen_wrappers.h"
17 #include "ext/standard/url.h"
19 struct php_zip_stream_data_t
{
26 #define STREAM_DATA_FROM_STREAM() \
27 struct php_zip_stream_data_t *self = (struct php_zip_stream_data_t *) stream->abstract;
30 /* {{{ php_zip_ops_read */
31 static size_t php_zip_ops_read(php_stream
*stream
, char *buf
, size_t count TSRMLS_DC
)
34 STREAM_DATA_FROM_STREAM();
36 if (self
->za
&& self
->zf
) {
37 n
= zip_fread(self
->zf
, buf
, count
);
40 zip_file_error_get(self
->zf
, &ze
, &se
);
42 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Zip stream error: %s", zip_file_strerror(self
->zf
));
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
) {
53 return (n
< 1 ? 0 : (size_t)n
);
57 /* {{{ php_zip_ops_write */
58 static size_t php_zip_ops_write(php_stream
*stream
, const char *buf
, size_t count TSRMLS_DC
)
68 /* {{{ php_zip_ops_close */
69 static int php_zip_ops_close(php_stream
*stream
, int close_handle TSRMLS_DC
)
71 STREAM_DATA_FROM_STREAM();
84 stream
->abstract
= NULL
;
89 /* {{{ php_zip_ops_flush */
90 static int php_zip_ops_flush(php_stream
*stream TSRMLS_DC
)
100 static int php_zip_ops_stat(php_stream
*stream
, php_stream_statbuf
*ssb TSRMLS_DC
) /* {{{ */
103 const char *path
= stream
->orig_path
;
104 int path_len
= strlen(stream
->orig_path
);
106 size_t file_basename_len
;
107 char file_dirname
[MAXPATHLEN
];
113 fragment
= strchr(path
, '#');
119 if (strncasecmp("zip://", path
, 6) == 0) {
123 fragment_len
= strlen(fragment
);
125 if (fragment_len
< 1) {
128 path_len
= strlen(path
);
129 if (path_len
>= MAXPATHLEN
) {
133 memcpy(file_dirname
, path
, path_len
- fragment_len
);
134 file_dirname
[path_len
- fragment_len
] = '\0';
136 php_basename((char *)path
, path_len
- fragment_len
, NULL
, 0, &file_basename
, &file_basename_len TSRMLS_CC
);
139 if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname
)) {
140 efree(file_basename
);
144 za
= zip_open(file_dirname
, ZIP_CREATE
, &err
);
146 memset(ssb
, 0, sizeof(php_stream_statbuf
));
147 if (zip_stat(za
, fragment
, ZIP_FL_NOCASE
, &sb
) != 0) {
148 efree(file_basename
);
153 if (path
[path_len
-1] != '/') {
154 ssb
->sb
.st_size
= sb
.size
;
155 ssb
->sb
.st_mode
|= S_IFREG
; /* regular file */
158 ssb
->sb
.st_mode
|= S_IFDIR
; /* regular directory */
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;
167 ssb
->sb
.st_blksize
= -1;
168 ssb
->sb
.st_blocks
= -1;
172 efree(file_basename
);
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
,
183 php_zip_ops_stat
, /* stat */
184 NULL
/* set_option */
187 /* {{{ php_stream_zip_open */
188 php_stream
*php_stream_zip_open(char *filename
, char *path
, char *mode STREAMS_DC TSRMLS_DC
)
190 struct zip_file
*zf
= NULL
;
193 php_stream
*stream
= NULL
;
194 struct php_zip_stream_data_t
*self
;
195 struct zip
*stream_za
;
197 if (strncmp(mode
,"r", strlen("r")) != 0) {
202 if (ZIP_OPENBASEDIR_CHECKPATH(filename
)) {
206 /* duplicate to make the stream za independent (esp. for MSHUTDOWN) */
207 stream_za
= zip_open(filename
, ZIP_CREATE
, &err
);
212 zf
= zip_fopen(stream_za
, path
, 0);
214 self
= emalloc(sizeof(*self
));
216 self
->za
= stream_za
;
220 stream
= php_stream_alloc(&php_stream_zipio_ops
, self
, NULL
, mode
);
221 stream
->orig_path
= estrdup(path
);
223 zip_close(stream_za
);
236 /* {{{ php_stream_zip_opener */
237 php_stream
*php_stream_zip_opener(php_stream_wrapper
*wrapper
,
242 php_stream_context
*context STREAMS_DC TSRMLS_DC
)
247 size_t file_basename_len
;
248 char file_dirname
[MAXPATHLEN
];
251 struct zip_file
*zf
= NULL
;
256 php_stream
*stream
= NULL
;
257 struct php_zip_stream_data_t
*self
;
259 fragment
= strchr(path
, '#');
264 if (strncasecmp("zip://", path
, 6) == 0) {
268 fragment_len
= strlen(fragment
);
270 if (fragment_len
< 1) {
273 path_len
= strlen(path
);
274 if (path_len
>= MAXPATHLEN
|| mode
[0] != 'r') {
278 memcpy(file_dirname
, path
, path_len
- fragment_len
);
279 file_dirname
[path_len
- fragment_len
] = '\0';
281 php_basename(path
, path_len
- fragment_len
, NULL
, 0, &file_basename
, &file_basename_len TSRMLS_CC
);
284 if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname
)) {
285 efree(file_basename
);
289 za
= zip_open(file_dirname
, ZIP_CREATE
, &err
);
291 zf
= zip_fopen(za
, fragment
, 0);
293 self
= emalloc(sizeof(*self
));
299 stream
= php_stream_alloc(&php_stream_zipio_ops
, self
, NULL
, mode
);
302 *opened_path
= estrdup(path
);
309 efree(file_basename
);
319 static php_stream_wrapper_ops zip_stream_wops
= {
320 php_stream_zip_opener
,
332 php_stream_wrapper php_stream_zip_wrapper
= {
337 #endif /* ZEND_ENGINE_2 */
338 #endif /* HAVE_ZIP */