23static uint32_t phar_tar_number(
const char *
buf,
size_t len)
28 while (i <
len &&
buf[i] ==
' ') {
32 while (i <
len &&
buf[i] >=
'0' &&
buf[i] <=
'7') {
33 num = num * 8 + (
buf[i] -
'0');
73 *--
p = (char)(
'0' + (
val & 7));
90static uint32_t phar_tar_checksum(
char *
buf,
size_t len)
96 sum += (
unsigned char)*
buf;
106 uint32_t checksum = phar_tar_number(
header->checksum,
sizeof(
header->checksum));
108 char save[
sizeof(
header->checksum)], *bname;
111 if (!
strncmp(
buf,
"<?php",
sizeof(
"<?php")-1)) {
117 is_tar = (checksum == phar_tar_checksum(
buf, 512));
122 if (!
is_tar && (bname =
strstr(fname,
".tar")) && (bname[4] ==
'\0' || bname[4] ==
'.')) {
157 spprintf(
error, 4096,
"phar tar error: \"%s\" already exists as a regular phar and must be deleted from disk prior to creating as a tar-based phar", fname);
180 if (entry->
filename_len ==
sizeof(
".phar/.metadata.bin")-1 && !memcmp(entry->
filename,
".phar/.metadata.bin",
sizeof(
".phar/.metadata.bin")-1)) {
188 }
else if (entry->
filename_len >=
sizeof(
".phar/.metadata/") +
sizeof(
"/.metadata.bin") - 1 &&
NULL != (mentry = zend_hash_str_find_ptr(&(entry->
phar->
manifest), entry->
filename +
sizeof(
".phar/.metadata/") - 1, entry->
filename_len - (
sizeof(
"/.metadata.bin") - 1 +
sizeof(
".phar/.metadata/") - 1)))) {
207 char buf[512], *actual_alias =
NULL, *
p;
209 size_t pos = 0, read, totalsize;
211 uint32_t sum1, sum2,
size, old;
213 int last_was_longlink = 0;
225 if (read !=
sizeof(
buf)) {
227 spprintf(
error, 4096,
"phar error: \"%s\" is not a tar file or is truncated", fname);
234 old = (memcmp(hdr->
magic,
"ustar",
sizeof(
"ustar")-1) != 0);
247 myphar->
flags = compression;
259 if (sum1 == 0 && phar_tar_checksum(
buf,
sizeof(
buf)) == 0) {
265 if (old && sum2 != sum1) {
275 phar_tar_number(hdr->
size,
sizeof(hdr->
size));
283 if (((!old && hdr->
prefix[0] == 0) || old) && zend_strnlen(hdr->
name, 100) ==
sizeof(
".phar/signature.bin")-1 && !
strncmp(hdr->
name,
".phar/signature.bin",
sizeof(
".phar/signature.bin")-1)) {
289 spprintf(
error, 4096,
"phar error: tar-based phar \"%s\" has signature that is larger than 511 bytes, cannot process", fname);
298 if (read !=
size || read <= 8) {
300 spprintf(
error, 4096,
"phar error: tar-based phar \"%s\" signature cannot be read", fname);
304#ifdef WORDS_BIGENDIAN
305# define PHAR_GET_32(buffer) \
306 (((((unsigned char*)(buffer))[3]) << 24) \
307 | ((((unsigned char*)(buffer))[2]) << 16) \
308 | ((((unsigned char*)(buffer))[1]) << 8) \
309 | (((unsigned char*)(buffer))[0]))
311# define PHAR_GET_32(buffer) (uint32_t) *(buffer)
317 spprintf(
error, 4096,
"phar error: tar-based phar \"%s\" signature cannot be verified: %s", fname, save);
330 spprintf(
error, 4096,
"phar error: \"%s\" is a corrupted tar file (truncated)", fname);
340 if (read !=
sizeof(
buf)) {
342 spprintf(
error, 4096,
"phar error: \"%s\" is a corrupted tar file (truncated)", fname);
352 if (sum1 == 0 && phar_tar_checksum(
buf,
sizeof(
buf)) == 0) {
357 spprintf(
error, 4096,
"phar error: \"%s\" has entries after signature, invalid phar", fname);
363 if (!last_was_longlink && hdr->
typeflag ==
'L') {
364 last_was_longlink = 1;
371 spprintf(
error, 4096,
"phar error: \"%s\" is a corrupted tar file (invalid entry size)", fname);
383 spprintf(
error, 4096,
"phar error: \"%s\" is a corrupted tar file (truncated)", fname);
399 spprintf(
error, 4096,
"phar error: \"%s\" is a corrupted tar file (truncated)", fname);
408 if (read !=
sizeof(
buf)) {
411 spprintf(
error, 4096,
"phar error: \"%s\" is a corrupted tar file (truncated)", fname);
418 }
else if (!last_was_longlink && !old && hdr->
prefix[0] != 0) {
422 for (i = 0; i < 155; i++) {
424 if (
name[i] ==
'\0') {
429 for (
j = 0;
j < 100;
j++) {
431 if (
name[i+
j] ==
'\0') {
443 }
else if (!last_was_longlink) {
447 for (i = 0; i < 100; i++) {
448 if (hdr->
name[i] ==
'\0') {
461 last_was_longlink = 0;
467 spprintf(
error, 4096,
"phar error: \"%s\" is a corrupted tar file (checksum mismatch of file \"%s\")", fname, entry.
filename);
475 uint32_t entry_mode = phar_tar_number(hdr->
mode,
sizeof(hdr->
mode));
496 linkname_len = zend_strnlen(hdr->
linkname, 100);
498 if (!zend_hash_str_exists(&myphar->
manifest, hdr->
linkname, linkname_len)) {
500 spprintf(
error, 4096,
"phar error: \"%s\" is a corrupted tar file - hard link to non-existent file \"%.*s\"", fname, (
int)linkname_len, hdr->
linkname);
511 phar_set_inode(&entry);
516 if (entry.is_persistent) {
517 ++entry.manifest_pos;
520 if (entry.filename_len >=
sizeof(
".phar/.metadata")-1 && !memcmp(entry.filename,
".phar/.metadata",
sizeof(
".phar/.metadata")-1)) {
521 if (
FAILURE == phar_tar_process_metadata(newentry, fp)) {
523 spprintf(
error, 4096,
"phar error: tar-based phar \"%s\" has invalid metadata in magic file \"%s\"", fname, entry.filename);
531 if (!actual_alias && entry.filename_len ==
sizeof(
".phar/alias.txt")-1 && !
strncmp(entry.filename,
".phar/alias.txt",
sizeof(
".phar/alias.txt")-1)) {
535 spprintf(
error, 4096,
"phar error: tar-based phar \"%s\" has alias that is larger than 511 bytes, cannot process", fname);
546 if (!phar_validate_alias(
buf,
size)) {
555 spprintf(
error, 4096,
"phar error: invalid alias \"%s\" in tar-based phar \"%s\"",
buf, fname);
564 myphar->
alias = actual_alias;
569 spprintf(
error, 4096,
"phar error: Unable to read alias from tar-based phar \"%s\"", fname);
586 spprintf(
error, 4096,
"phar error: \"%s\" is a corrupted tar file (truncated)", fname);
601 if (read !=
sizeof(
buf)) {
603 spprintf(
error, 4096,
"phar error: \"%s\" is a corrupted tar file (truncated)", fname);
611 if (zend_hash_str_exists(&(myphar->
manifest),
".phar/stub.php",
sizeof(
".phar/stub.php")-1)) {
622 spprintf(
error, 0,
"tar-based phar \"%s\" does not have a signature", fname);
629 phar_unixify_path_separators(myphar->
fname, fname_len);
636 myphar->
ext = memchr(
p,
'.', (myphar->
fname + fname_len) -
p);
637 if (myphar->
ext ==
p) {
638 myphar->
ext = memchr(
p + 1,
'.', (myphar->
fname + fname_len) -
p - 1);
649 spprintf(
error, 4096,
"phar error: Unable to add tar-based phar \"%s\" to phar registry", fname);
666 spprintf(
error, 4096,
"phar error: Unable to add tar-based phar \"%s\", alias is already in use", fname);
681 spprintf(
error, 4096,
"phar error: Unable to add tar-based phar \"%s\", alias is already in use", fname);
714static int phar_tar_writeheaders_int(
phar_entry_info *entry,
void *argument)
741 spprintf(fp->
error, 4096,
"tar-based phar \"%s\" cannot be created, filename \"%s\" is too long for tar file format", entry->
phar->
fname, entry->
filename);
746 while (*boundary && *boundary !=
'/') {
749 if (!*boundary || ((boundary - entry->
filename) > 155)) {
751 spprintf(fp->
error, 4096,
"tar-based phar \"%s\" cannot be created, filename \"%s\" is too long for tar file format", entry->
phar->
fname, entry->
filename);
765 spprintf(fp->
error, 4096,
"tar-based phar \"%s\" cannot be created, filename \"%s\" is too large for tar file format", entry->
phar->
fname, entry->
filename);
772 spprintf(fp->
error, 4096,
"tar-based phar \"%s\" cannot be created, file modification time of file \"%s\" is too large for tar file format", entry->
phar->
fname, entry->
filename);
783 spprintf(fp->
error, 4096,
"tar-based phar \"%s\" cannot be created, link \"%s\" is too long for format", entry->
phar->
fname, entry->
link);
796 spprintf(fp->
error, 4096,
"tar-based phar \"%s\" cannot be created, checksum of file \"%s\" is too large for tar file format", entry->
phar->
fname, entry->
filename);
806 spprintf(fp->
error, 4096,
"tar-based phar \"%s\" cannot be created, header for file \"%s\" could not be written", entry->
phar->
fname, entry->
filename);
821 spprintf(fp->
error, 4096,
"tar-based phar \"%s\" cannot be created, contents of file \"%s\" could not be written, seek failed", entry->
phar->
fname, entry->
filename);
828 spprintf(fp->
error, 4096,
"tar-based phar \"%s\" cannot be created, contents of file \"%s\" could not be written", entry->
phar->
fname, entry->
filename);
867static int phar_tar_writeheaders(
zval *
zv,
void *argument)
869 return phar_tar_writeheaders_int(
Z_PTR_P(
zv), argument);
893 spprintf(
error, 0,
"phar error: unable to create temporary file");
897 spprintf(
error, 0,
"phar tar error: unable to write metadata to magic metadata file \"%s\"", entry->
filename);
906static int phar_tar_setupmetadata(
zval *
zv,
void *argument)
913 if (entry->
filename_len >=
sizeof(
".phar/.metadata") && !memcmp(entry->
filename,
".phar/.metadata",
sizeof(
".phar/.metadata")-1)) {
914 if (entry->
filename_len ==
sizeof(
".phar/.metadata.bin")-1 && !memcmp(entry->
filename,
".phar/.metadata.bin",
sizeof(
".phar/.metadata.bin")-1)) {
918 if (entry->
filename_len >=
sizeof(
".phar/.metadata/") +
sizeof(
"/.metadata.bin") - 1 && !zend_hash_str_exists(&(entry->
phar->
manifest), entry->
filename +
sizeof(
".phar/.metadata/") - 1, entry->
filename_len - (
sizeof(
"/.metadata.bin") - 1 +
sizeof(
".phar/.metadata/") - 1))) {
931 lookfor_len =
spprintf(&lookfor, 0,
".phar/.metadata/%s/.metadata.bin", entry->
filename);
939 if (
NULL != (metadata = zend_hash_str_find_ptr(&(entry->
phar->
manifest), lookfor, lookfor_len))) {
946 newentry.filename = lookfor;
947 newentry.filename_len = lookfor_len;
948 newentry.phar = entry->
phar;
954 spprintf(
error, 0,
"phar tar error: unable to add magic metadata file to manifest for file \"%s\"", entry->
filename);
964 static const char newstub[] =
"<?php // tar-based phar archive stub file\n__HALT_COMPILER();";
965 static const char halt_stub[] =
"__HALT_COMPILER();";
969 bool must_close_old_file =
false;
970 size_t signature_length;
972 char *
buf, *signature, sigbuf[8];
987 spprintf(
error, 0,
"internal error: attempt to flush cached tar-based phar \"%s\"", phar->
fname);
1003 spprintf(
error, 0,
"phar error: unable to create temporary file");
1025 if (user_stub && !is_default_stub) {
1036 const char end_sequence[] =
" ?>\r\n";
1037 size_t end_sequence_len =
strlen(end_sequence);
1041 spprintf(
error, 0,
"phar error: unable to create temporary file");
1051 spprintf(
error, 0,
"unable to create stub from string in new tar-based phar \"%s\"", phar->
fname);
1064 spprintf(
error, 0,
"phar error: unable to create temporary file");
1070 spprintf(
error, 0,
"unable to %s stub in%star-based phar \"%s\", failed", user_stub ?
"overwrite" :
"create", user_stub ?
" " :
" new ", phar->
fname);
1079 if (!is_default_stub) {
1080 if (!zend_hash_str_exists(&phar->
manifest,
".phar/stub.php",
sizeof(
".phar/stub.php")-1)) {
1083 efree(entry.filename);
1100 must_close_old_file =
false;
1104 must_close_old_file = oldfile !=
NULL;
1112 if (must_close_old_file) {
1126 if (
NULL != (mentry = zend_hash_str_find_ptr(&(phar->
manifest),
".phar/.metadata.bin",
sizeof(
".phar/.metadata.bin")-1))) {
1128 if (must_close_old_file) {
1136 newentry.
filename =
estrndup(
".phar/.metadata.bin",
sizeof(
".phar/.metadata.bin")-1);
1137 newentry.
filename_len =
sizeof(
".phar/.metadata.bin")-1;
1138 newentry.
phar = phar;
1142 if (
NULL == (mentry = zend_hash_str_add_mem(&(phar->
manifest),
".phar/.metadata.bin",
sizeof(
".phar/.metadata.bin")-1, (
void *)&newentry,
sizeof(
phar_entry_info)))) {
1143 spprintf(
error, 0,
"phar tar error: unable to add magic metadata file to manifest for phar archive \"%s\"", phar->
fname);
1144 if (must_close_old_file) {
1152 if (must_close_old_file) {
1163 if (must_close_old_file) {
1178 char *save = *
error;
1179 spprintf(
error, 0,
"phar error: unable to write signature to tar-based phar: %s", save);
1183 if (must_close_old_file) {
1191 entry.
filename =
".phar/signature.bin";
1195 spprintf(
error, 0,
"phar error: unable to create temporary file");
1198#ifdef WORDS_BIGENDIAN
1199# define PHAR_SET_32(destination, source) do { \
1200 uint32_t swapped = (((((unsigned char*)&(source))[3]) << 24) \
1201 | ((((unsigned char*)&(source))[2]) << 16) \
1202 | ((((unsigned char*)&(source))[1]) << 8) \
1203 | (((unsigned char*)&(source))[0])); \
1204 memcpy(destination, &swapped, 4); \
1207# define PHAR_SET_32(destination, source) memcpy(destination, &source, 4)
1215 spprintf(
error, 0,
"phar error: unable to write signature to tar-based phar %s", phar->
fname);
1218 if (must_close_old_file) {
1231 if (must_close_old_file) {
1245 if (must_close_old_file) {
1255 if (phar->
fp &&
pass.free_fp) {
1260 if (
pass.free_ufp) {
1292 add_assoc_long(&filterparams,
"window",
MAX_WBITS + 16);
1301 spprintf(
error, 4096,
"unable to compress all contents of phar \"%s\" using zlib, PHP versions older than 5.2.6 have a buggy zlib", phar->
fname);
strrchr(string $haystack, string $needle, bool $before_needle=false)
header(string $header, bool $replace=true, int $response_code=0)
strstr(string $haystack, string $needle, bool $before_needle=false)
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
#define pass(a, b, c, mul)
file_private int is_tar(const unsigned char *, size_t)
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)
struct _tar_header tar_header
struct _old_tar_header old_tar_header
bool phar_metadata_tracker_has_data(const phar_metadata_tracker *tracker, bool persistent)
void phar_destroy_phar_data(phar_archive_data *phar)
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_copy(phar_metadata_tracker *dest, const phar_metadata_tracker *source, bool persistent)
void phar_request_initialize(void)
void phar_metadata_tracker_try_ensure_has_serialized_data(phar_metadata_tracker *tracker, bool persistent)
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)
#define PHAR_FILE_COMPRESSED_BZ2
struct _phar_metadata_tracker phar_metadata_tracker
int phar_seek_efp(phar_entry_info *entry, zend_off_t offset, int whence, zend_off_t position, int follow_links)
#define PHAR_FILE_COMPRESSED_GZ
#define PHAR_ENT_PERM_MASK
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
zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error)
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)
#define PHP_DIR_SEPARATOR
unsigned const char * end
unsigned const char * pos
PHP_JSON_API size_t int options
#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_close(stream)
#define php_stream_tell(stream)
#define php_stream_is_persistent(stream)
#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
#define PHAR_GET_32(buffer)
#define PHAR_SET_32(destination, source)
zend_result phar_parse_tarfile(php_stream *fp, char *fname, size_t fname_len, char *alias, size_t alias_len, phar_archive_data **pphar, uint32_t compression, char **error)
void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_default_stub, char **error)
zend_result phar_open_or_create_tar(char *fname, size_t fname_len, char *alias, size_t alias_len, int is_data, uint32_t options, phar_archive_data **pphar, char **error)
bool phar_is_tar(char *buf, char *fname)
#define estrndup(s, length)
#define ecalloc(nmemb, size)
#define pestrndup(s, length, persistent)
#define pefree(ptr, persistent)
#define pemalloc(size, persistent)
#define safe_emalloc(nmemb, size, offset)
#define pecalloc(nmemb, size, persistent)
strncmp(string $string1, string $string2, int $length)
ZEND_API void ZEND_FASTCALL zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument)
ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
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
ZEND_RESULT_CODE zend_result