23#define PHAR_GET_16(var) ((uint16_t)((((uint16_t)var[0]) & 0xff) | \
24 (((uint16_t)var[1]) & 0xff) << 8))
25#define PHAR_GET_32(var) ((uint32_t)((((uint32_t)var[0]) & 0xff) | \
26 (((uint32_t)var[1]) & 0xff) << 8 | \
27 (((uint32_t)var[2]) & 0xff) << 16 | \
28 (((uint32_t)var[3]) & 0xff) << 24))
29static inline void phar_write_32(
char buffer[4], uint32_t
value)
31 buffer[3] = (
unsigned char) ((
value & 0xff000000) >> 24);
32 buffer[2] = (
unsigned char) ((
value & 0xff0000) >> 16);
33 buffer[1] = (
unsigned char) ((
value & 0xff00) >> 8);
36static inline void phar_write_16(
char buffer[2], uint32_t
value)
38 buffer[1] = (
unsigned char) ((
value & 0xff00) >> 8);
41# define PHAR_SET_32(var, value) phar_write_32(var, (uint32_t) (value));
42# define PHAR_SET_16(var, value) phar_write_16(var, (uint16_t) (value));
54 if (
sizeof(h.header) !=
php_stream_read(fp, (
char *) &h.header,
sizeof(h.header))) {
58 if (h.header.tag[0] ==
'U' && h.header.tag[1] ==
'T') {
64 const size_t min_size = 5;
66 if (header_size >= min_size) {
68 if (read != min_size) {
71 if (h.time.flags & (1 << 0)) {
76 len -= header_size + 4;
79 if (header_size != read) {
87 if (h.header.tag[0] !=
'n' || h.header.tag[1] !=
'u') {
95 read =
php_stream_read(fp, (
char *) &(h.unix3.crc32),
sizeof(h.unix3) -
sizeof(h.header));
98 if (
sizeof(h.unix3) -
sizeof(h.header) != read) {
102 if (
PHAR_GET_16(h.unix3.size) >
sizeof(h.unix3) - 4) {
155static time_t phar_zip_d2u_time(
const char *cdtime,
const char *cddate)
158 struct tm *tm, tmbuf;
164 tm->tm_year = ((ddate>>9)&127) + 1980 - 1900;
165 tm->tm_mon = ((ddate>>5)&15) - 1;
166 tm->tm_mday = ddate&31;
168 tm->tm_hour = (dtime>>11)&31;
169 tm->tm_min = (dtime>>5)&63;
170 tm->tm_sec = (dtime<<1)&62;
176static void phar_zip_u2d_time(time_t
time,
char *dtime,
char *ddate)
178 uint16_t ctime, cdate;
179 struct tm *tm, tmbuf;
183 if (tm->tm_year >= 80) {
184 cdate = ((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) + tm->tm_mday;
185 ctime = ((tm->tm_hour)<<11) + ((tm->tm_min)<<5) + ((tm->tm_sec)>>1);
197static char *phar_find_eocd(
const char *
s,
size_t n)
203 uint16_t comment_len;
204 const char *eocd_start = zend_memnrstr(
s,
"PK\5\6",
sizeof(
"PK\5\6") - 1,
end);
206 if (eocd_start ==
NULL) {
213 return (
char *) eocd_start;
232 char buf[
sizeof(locator) + 65536];
238 char *metadata =
NULL;
242 if (
size >
sizeof(locator) + 65536) {
244 size =
sizeof(locator) + 65536;
248 spprintf(
error, 4096,
"phar error: unable to search for end of central directory in zip-based phar \"%s\"", fname);
259 spprintf(
error, 4096,
"phar error: unable to read in data to search for end of central directory in zip-based phar \"%s\"", fname);
265 memcpy((
void *)&locator, (
void *)
p,
sizeof(locator));
270 spprintf(
error, 4096,
"phar error: split archives spanning multiple zips cannot be processed in zip-based phar \"%s\"", fname);
277 spprintf(
error, 4096,
"phar error: corrupt zip archive, conflicting file count in end of central directory record in zip-based phar \"%s\"", fname);
289 metadata =
p +
sizeof(locator);
293 spprintf(
error, 4096,
"phar error: corrupt zip archive, zip file comment truncated in zip-based phar \"%s\"", fname);
311 spprintf(
error, 4096,
"phar error: end of central directory not found in zip-based phar \"%s\"", fname);
318 phar_unixify_path_separators(mydata->
fname, fname_len);
325 mydata->
ext = memchr(
ext,
'.', (mydata->
fname + fname_len) -
ext);
327 mydata->
ext = memchr(
ext + 1,
'.', (mydata->
fname + fname_len) -
ext - 1);
348#define PHAR_ZIP_FAIL_FREE(errmsg, save) \
349 zend_hash_destroy(&mydata->manifest); \
350 HT_INVALIDATE(&mydata->manifest); \
351 zend_hash_destroy(&mydata->mounted_dirs); \
352 HT_INVALIDATE(&mydata->mounted_dirs); \
353 zend_hash_destroy(&mydata->virtual_dirs); \
354 HT_INVALIDATE(&mydata->virtual_dirs); \
355 php_stream_close(fp); \
356 phar_metadata_tracker_free(&mydata->metadata_tracker, mydata->is_persistent); \
357 if (mydata->signature) { \
358 efree(mydata->signature); \
361 spprintf(error, 4096, "phar error: %s in zip-based phar \"%s\"", errmsg, mydata->fname); \
363 pefree(mydata->fname, mydata->is_persistent); \
364 if (mydata->alias) { \
365 pefree(mydata->alias, mydata->is_persistent); \
367 pefree(mydata, mydata->is_persistent); \
370#define PHAR_ZIP_FAIL(errmsg) \
371 zend_hash_destroy(&mydata->manifest); \
372 HT_INVALIDATE(&mydata->manifest); \
373 zend_hash_destroy(&mydata->mounted_dirs); \
374 HT_INVALIDATE(&mydata->mounted_dirs); \
375 zend_hash_destroy(&mydata->virtual_dirs); \
376 HT_INVALIDATE(&mydata->virtual_dirs); \
377 php_stream_close(fp); \
378 phar_metadata_tracker_free(&mydata->metadata_tracker, mydata->is_persistent); \
379 if (mydata->signature) { \
380 efree(mydata->signature); \
383 spprintf(error, 4096, "phar error: %s in zip-based phar \"%s\"", errmsg, mydata->fname); \
385 pefree(mydata->fname, mydata->is_persistent); \
386 if (mydata->alias) { \
387 pefree(mydata->alias, mydata->is_persistent); \
389 pefree(mydata, mydata->is_persistent); \
400 if (
sizeof(zipentry) !=
php_stream_read(fp, (
char *) &zipentry,
sizeof(zipentry))) {
401 PHAR_ZIP_FAIL(
"unable to read central directory entry, truncated");
405 if (memcmp(
"PK\1\2", zipentry.
signature, 4)) {
407 PHAR_ZIP_FAIL(
"corrupted central directory entry, no magic signature");
427 PHAR_ZIP_FAIL(
"Cannot process zips created from stdin (zero-length filename)");
435 PHAR_ZIP_FAIL(
"unable to read in filename from central directory, truncated");
460 if (
sizeof(local) !=
php_stream_read(fp, (
char *) &local,
sizeof(local))) {
462 PHAR_ZIP_FAIL(
"phar error: internal corruption (cannot read local file header)");
472 PHAR_ZIP_FAIL(
"phar error: internal corruption (local file header does not match central directory)");
486 if (entry.
filename_len ==
sizeof(
".phar/signature.bin")-1 && !
strncmp(entry.
filename,
".phar/signature.bin",
sizeof(
".phar/signature.bin")-1)) {
495 PHAR_ZIP_FAIL(
"signatures larger than 64 KiB are not supported");
527 spprintf(&save, 4096,
"signature cannot be verified: %s", *
error);
540 PHAR_ZIP_FAIL(
"entries exist after signature, invalid phar");
552 PHAR_ZIP_FAIL(
"Unable to process extra field header for file in central directory");
577 PHAR_ZIP_FAIL(
"unsupported compression method (Shrunk) used in this zip");
583 PHAR_ZIP_FAIL(
"unsupported compression method (Reduce) used in this zip");
586 PHAR_ZIP_FAIL(
"unsupported compression method (Implode) used in this zip");
589 PHAR_ZIP_FAIL(
"unsupported compression method (Tokenize) used in this zip");
592 PHAR_ZIP_FAIL(
"unsupported compression method (Deflate64) used in this zip");
595 PHAR_ZIP_FAIL(
"unsupported compression method (PKWare Implode/old IBM TERSE) used in this zip");
598 PHAR_ZIP_FAIL(
"unsupported compression method (LZMA) used in this zip");
601 PHAR_ZIP_FAIL(
"unsupported compression method (IBM TERSE) used in this zip");
604 PHAR_ZIP_FAIL(
"unsupported compression method (IBM LZ77) used in this zip");
607 PHAR_ZIP_FAIL(
"unsupported compression method (WavPack) used in this zip");
610 PHAR_ZIP_FAIL(
"unsupported compression method (PPMd) used in this zip");
613 PHAR_ZIP_FAIL(
"unsupported compression method (unknown) used in this zip");
629 if (!actual_alias && entry.
filename_len ==
sizeof(
".phar/alias.txt")-1 && !
strncmp(entry.
filename,
".phar/alias.txt",
sizeof(
".phar/alias.txt")-1)) {
638 PHAR_ZIP_FAIL(
"phar error: internal corruption of zip-based phar (local header of alias does not match central directory)");
657 PHAR_ZIP_FAIL(
"unable to decompress alias, zlib filter creation failed");
689 PHAR_ZIP_FAIL(
"unable to read in alias, bzip2 filter creation failed");
740 phar_set_inode(&entry);
744 if (zend_hash_str_exists(&(mydata->
manifest),
".phar/stub.php",
sizeof(
".phar/stub.php")-1)) {
762 if (!phar_validate_alias(actual_alias, mydata->
alias_len)) {
764 spprintf(
error, 4096,
"phar error: invalid alias \"%s\" in zip-based phar \"%s\"", actual_alias, fname);
776 spprintf(
error, 4096,
"phar error: Unable to add zip-based phar \"%s\" with implicit alias, alias is already in use", fname);
798 spprintf(
error, 4096,
"phar error: Unable to add zip-based phar \"%s\" with explicit alias, alias is already in use", fname);
854 spprintf(
error, 4096,
"phar zip error: phar \"%s\" already exists as a regular phar and must be deleted from disk prior to creating as a zip-based phar", fname);
878 int not_really_modified = 0;
880 uint16_t general_purpose_flags;
896 memset(&local, 0,
sizeof(local));
897 memset(¢ral, 0,
sizeof(central));
898 memset(&perms, 0,
sizeof(perms));
953 spprintf(
p->error, 0,
"unable to open file contents of file \"%s\" in zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
959 not_really_modified = 1;
964 spprintf(
p->error, 0,
"unable to seek to start of file \"%s\" to zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1002 spprintf(
p->error, 0,
"unable to create temporary file for file \"%s\" while creating zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1009 spprintf(
p->error, 0,
"unable to seek to start of file \"%s\" to zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1016 spprintf(
p->error, 0,
"unable to copy compressed file contents of file \"%s\" while creating new phar \"%s\"", entry->
filename, entry->
phar->
fname);
1039 spprintf(
p->error, 0,
"unable to seek to start of file \"%s\" while creating zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1057 if (
sizeof(local) !=
php_stream_write(
p->filefp, (
char *)&local,
sizeof(local))) {
1058 spprintf(
p->error, 0,
"unable to write local file header of file \"%s\" to zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1062 if (
sizeof(central) !=
php_stream_write(
p->centralfp, (
char *)¢ral,
sizeof(central))) {
1063 spprintf(
p->error, 0,
"unable to write central directory entry for file \"%s\" while creating zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1069 spprintf(
p->error, 0,
"unable to write filename to local directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1074 spprintf(
p->error, 0,
"unable to write filename to local directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1079 spprintf(
p->error, 0,
"unable to write filename to central directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1084 spprintf(
p->error, 0,
"unable to write filename to central directory entry for directory \"%s\" while creating zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1089 spprintf(
p->error, 0,
"unable to write filename to local directory entry for file \"%s\" while creating zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1094 spprintf(
p->error, 0,
"unable to write filename to central directory entry for file \"%s\" while creating zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1099 if (
sizeof(perms) !=
php_stream_write(
p->filefp, (
char *)&perms,
sizeof(perms))) {
1100 spprintf(
p->error, 0,
"unable to write local extra permissions file header of file \"%s\" to zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1104 if (
sizeof(perms) !=
php_stream_write(
p->centralfp, (
char *)&perms,
sizeof(perms))) {
1105 spprintf(
p->error, 0,
"unable to write central extra permissions file header of file \"%s\" to zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1112 spprintf(
p->error, 0,
"unable to write compressed contents of file \"%s\" in zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1126 spprintf(
p->error, 0,
"unable to write contents of file \"%s\" in zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1152 spprintf(
p->error, 0,
"unable to copy contents of file \"%s\" while creating zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1163 spprintf(
p->error, 0,
"unable to write metadata as file comment for file \"%s\" while creating zip-based phar \"%s\"", entry->
filename, entry->
phar->
fname);
1172static int phar_zip_changed_apply(
zval *
zv,
void *
arg)
1182 size_t signature_length;
1183 char *signature, sigbuf[8];
1189 if (newfile ==
NULL) {
1190 spprintf(
pass->error, 0,
"phar error: unable to create temporary file for the signature file");
1206 char *save = *(
pass->error);
1207 spprintf(
pass->error, 0,
"phar error: unable to write signature to zip-based phar: %s", save);
1215 entry.
filename =
".phar/signature.bin";
1221 spprintf(
pass->error, 0,
"phar error: unable to create temporary file for signature");
1231 spprintf(
pass->error, 0,
"phar error: unable to write signature to zip-based phar %s", phar->
fname);
1242 phar_zip_changed_apply_int(&entry, (
void *)
pass);
1245 if (
pass->error && *(
pass->error)) {
1256 static const char newstub[] =
"<?php // zip-based phar archive stub file\n__HALT_COMPILER();";
1257 static const char halt_stub[] =
"__HALT_COMPILER();";
1260 bool must_close_old_file =
false;
1262 char *temperr =
NULL;
1265 uint32_t cdir_size, cdir_offset;
1267 pass.error = &temperr;
1277 spprintf(
error, 0,
"internal error: attempt to flush cached zip-based phar \"%s\"", phar->
fname);
1290 spprintf(
error, 0,
"phar error: unable to create temporary file");
1317 if (user_stub && !is_default_stub) {
1328 const char end_sequence[] =
" ?>\r\n";
1329 size_t end_sequence_len =
strlen(end_sequence);
1333 spprintf(
error, 0,
"phar error: unable to create temporary file");
1343 spprintf(
error, 0,
"unable to create stub from string in new zip-based phar \"%s\"", phar->
fname);
1357 spprintf(
error, 0,
"phar error: unable to create temporary file");
1363 spprintf(
error, 0,
"unable to %s stub in%szip-based phar \"%s\", failed", user_stub ?
"overwrite" :
"create", user_stub ?
" " :
" new ", phar->
fname);
1372 if (!is_default_stub) {
1373 if (!zend_hash_str_exists(&phar->
manifest,
".phar/stub.php",
sizeof(
".phar/stub.php")-1)) {
1376 efree(entry.filename);
1393 must_close_old_file =
false;
1397 must_close_old_file = oldfile !=
NULL;
1406 if (must_close_old_file) {
1410 spprintf(
error, 4096,
"phar zip flush of \"%s\" failed: unable to open temporary file", phar->
fname);
1417 if (!
pass.centralfp) {
1422 memset(&eocd, 0,
sizeof(eocd));
1424 memcpy(eocd.signature,
"PK\5\6", 4);
1447 if (must_close_old_file) {
1453 if (
FAILURE == phar_zip_applysignature(phar, &
pass)) {
1469 spprintf(
error, 4096,
"phar zip flush of \"%s\" failed: unable to write central-directory", phar->
fname);
1484 spprintf(
error, 4096,
"phar zip flush of \"%s\" failed: unable to write end of central-directory", phar->
fname);
1486 goto nocentralerror;
1491 spprintf(
error, 4096,
"phar zip flush of \"%s\" failed: unable to write metadata to zip comment", phar->
fname);
1493 goto nocentralerror;
1498 spprintf(
error, 4096,
"phar zip flush of \"%s\" failed: unable to write end of central-directory", phar->
fname);
1500 goto nocentralerror;
1504 if (phar->
fp &&
pass.free_fp) {
1509 if (
pass.free_ufp) {
1524 if (must_close_old_file) {
1539 if (must_close_old_file) {
file_private const char ext[]
strrchr(string $haystack, string $needle, bool $before_needle=false)
header(string $header, bool $replace=true, int $response_code=0)
PHPAPI zend_result php_crc32_stream_bulk_update(uint32_t *crc, php_stream *fp, size_t nr)
#define php_crc32_bulk_init()
#define php_crc32_bulk_end(c)
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
#define pass(a, b, c, mul)
PHPAPI php_stream_filter * php_stream_filter_create(const char *filtername, zval *filterparams, uint8_t persistent)
PHPAPI php_stream_filter * php_stream_filter_remove(php_stream_filter *filter, int call_dtor)
bool phar_metadata_tracker_has_data(const phar_metadata_tracker *tracker, bool persistent)
#define PHAR_GET_16(buffer, var)
zend_result phar_create_or_parse_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data **pphar, char **error)
void phar_metadata_tracker_try_ensure_has_serialized_data(phar_metadata_tracker *tracker, bool persistent)
#define PHAR_GET_32(buffer, var)
void destroy_phar_manifest_entry(zval *zv)
void phar_parse_metadata_lazy(const char *buffer, phar_metadata_tracker *tracker, uint32_t zip_metadata_len, bool persistent)
void phar_add_virtual_dirs(phar_archive_data *phar, char *filename, size_t filename_len)
char * phar_compress_filter(phar_entry_info *entry, int return_unknown)
#define PHAR_ENT_COMPRESSED_GZ
int phar_seek_efp(phar_entry_info *entry, zend_off_t offset, int whence, zend_off_t position, int follow_links)
#define PHAR_ENT_PERM_MASK
#define PHAR_ENT_PERM_DEF_DIR
php_stream * phar_get_efp(phar_entry_info *entry, int follow_links)
#define PHAR_ENT_PERM_DEF_FILE
struct _phar_archive_data phar_archive_data
#define PHAR_ENT_COMPRESSION_MASK
zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error)
#define PHAR_ENT_COMPRESSED_BZ2
zend_result phar_free_alias(phar_archive_data *phar, char *alias, size_t alias_len)
zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, char *sig, size_t sig_len, char *fname, char **signature, size_t *signature_len, char **error)
struct _phar_entry_info phar_entry_info
zend_result phar_open_entry_fp(phar_entry_info *entry, char **error, int follow_links)
zend_result phar_get_archive(phar_archive_data **archive, char *fname, size_t fname_len, char *alias, size_t alias_len, char **error)
struct _phar_zip_dir_end phar_zip_dir_end
struct _phar_zip_central_dir_file phar_zip_central_dir_file
struct _phar_zip_extra_field_header phar_zip_extra_field_header
struct _phar_zip_unix3 phar_zip_unix3
#define PHAR_ZIP_COMP_DEFLATE
struct _phar_zip_file_header phar_zip_file_header
struct _phar_zip_unix_time phar_zip_unix_time
#define PHAR_ZIP_COMP_NONE
#define PHAR_ZIP_FLAG_ENCRYPTED
#define PHAR_ZIP_COMP_BZIP2
mktime(int $hour, ?int $minute=null, ?int $second=null, ?int $month=null, ?int $day=null, ?int $year=null)
unsigned const char * end
unsigned const char * pos
PHP_JSON_API size_t int options
PHPAPI struct tm * php_localtime_r(const time_t *const timep, struct tm *p_tm)
#define php_stream_filter_append(chain, filter)
#define php_stream_filter_flush(filter, finish)
#define php_stream_fopen_tmpfile()
struct _php_stream php_stream
#define php_stream_read(stream, buf, count)
struct _php_stream_filter php_stream_filter
#define php_stream_rewind(stream)
#define PHP_STREAM_COPY_ALL
#define php_stream_seek(stream, offset, whence)
#define php_stream_flush(stream)
#define php_stream_close(stream)
#define php_stream_tell(stream)
#define php_stream_is_persistent(stream)
#define php_stream_copy_to_mem(src, maxlen, persistent)
#define php_stream_open_wrapper(path, mode, options, opened)
#define php_stream_copy_to_stream_ex(src, dest, maxlen, len)
#define php_stream_write(stream, buf, count)
PHPAPI char * php_stristr(const char *s, const char *t, size_t s_len, size_t t_len)
phar_metadata_tracker metadata_tracker
uint32_t is_temporary_alias
uint32_t compressed_filesize
phar_metadata_tracker metadata_tracker
enum phar_fp_type fp_type
uint32_t uncompressed_filesize
php_stream_filter_chain writefilters
php_stream_filter_chain readfilters
#define estrndup(s, length)
#define pestrndup(s, length, persistent)
#define pefree(ptr, persistent)
#define pemalloc(size, persistent)
#define pecalloc(nmemb, size, persistent)
strncmp(string $string1, string $string2, int $length)
zend_string_release_ex(func->internal_function.function_name, 0)
ZEND_API void ZEND_FASTCALL zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument)
ZEND_API zend_result ZEND_FASTCALL zend_hash_str_del(HashTable *ht, const char *str, size_t len)
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
#define ZEND_HASH_APPLY_STOP
#define ZEND_HASH_APPLY_REMOVE
#define ZEND_HASH_APPLY_KEEP
struct _zend_string zend_string
#define PHAR_SET_32(var, value)
#define PHAR_ZIP_FAIL_FREE(errmsg, save)
int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alias, size_t alias_len, phar_archive_data **pphar, char **error)
#define PHAR_SET_16(var, value)
#define PHAR_ZIP_FAIL(errmsg)
int phar_open_or_create_zip(char *fname, size_t fname_len, char *alias, size_t alias_len, int is_data, uint32_t options, phar_archive_data **pphar, char **error)
void phar_zip_flush(phar_archive_data *phar, zend_string *user_stub, bool is_default_stub, char **error)