Back to index

php5  5.3.10
Classes | Defines | Typedefs | Enumerations | Functions | Variables
phar_internal.h File Reference
#include <time.h>
#include "php.h"
#include "tar.h"
#include "php_ini.h"
#include "zend_constants.h"
#include "zend_execute.h"
#include "zend_exceptions.h"
#include "zend_hash.h"
#include "zend_interfaces.h"
#include "zend_operators.h"
#include "zend_qsort.h"
#include "zend_vm.h"
#include "main/php_streams.h"
#include "main/streams/php_stream_plain_wrapper.h"
#include "main/SAPI.h"
#include "main/php_main.h"
#include "main/php_open_temporary_file.h"
#include "ext/standard/info.h"
#include "ext/standard/basic_functions.h"
#include "ext/standard/file.h"
#include "ext/standard/php_string.h"
#include "ext/standard/url.h"
#include "ext/standard/crc32.h"
#include "ext/standard/md5.h"
#include "ext/standard/sha1.h"
#include "ext/standard/php_var.h"
#include "ext/standard/php_smart_str.h"
#include "ext/standard/php_versioning.h"
#include "TSRM/tsrm_strtok_r.h"
#include "TSRM/tsrm_virtual_cwd.h"
#include "php_phar.h"
#include "pharzip.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  _phar_archive_data
struct  _phar_entry_fp_info
struct  _phar_entry_fp
struct  _phar_mime_type
struct  _phar_entry_data

Defines

#define E_RECOVERABLE_ERROR   E_ERROR
#define pestrndup(s, length, persistent)   ((persistent)?zend_strndup((s),(length)):estrndup((s),(length)))
#define ALLOC_PERMANENT_ZVAL(z)   (z) = (zval*)malloc(sizeof(zval))
#define PHP_PHAR_API_VERSION   "1.1.1"
#define PHAR_API_VERSION   0x1110
#define PHAR_API_VERSION_NODIR   0x1100
#define PHAR_API_MIN_DIR   0x1110
#define PHAR_API_MIN_READ   0x1000
#define PHAR_API_MAJORVERSION   0x1000
#define PHAR_API_MAJORVER_MASK   0xF000
#define PHAR_API_VER_MASK   0xFFF0
#define PHAR_HDR_COMPRESSION_MASK   0x0000F000
#define PHAR_HDR_COMPRESSED_NONE   0x00000000
#define PHAR_HDR_COMPRESSED_GZ   0x00001000
#define PHAR_HDR_COMPRESSED_BZ2   0x00002000
#define PHAR_HDR_SIGNATURE   0x00010000
#define PHAR_FILE_COMPRESSION_MASK   0x00F00000
#define PHAR_FILE_COMPRESSED_NONE   0x00000000
#define PHAR_FILE_COMPRESSED_GZ   0x00100000
#define PHAR_FILE_COMPRESSED_BZ2   0x00200000
#define PHAR_SIG_MD5   0x0001
#define PHAR_SIG_SHA1   0x0002
#define PHAR_SIG_SHA256   0x0003
#define PHAR_SIG_SHA512   0x0004
#define PHAR_SIG_OPENSSL   0x0010
#define PHAR_ENT_COMPRESSION_MASK   0x0000F000
#define PHAR_ENT_COMPRESSED_NONE   0x00000000
#define PHAR_ENT_COMPRESSED_GZ   0x00001000
#define PHAR_ENT_COMPRESSED_BZ2   0x00002000
#define PHAR_ENT_PERM_MASK   0x000001FF
#define PHAR_ENT_PERM_MASK_USR   0x000001C0
#define PHAR_ENT_PERM_SHIFT_USR   6
#define PHAR_ENT_PERM_MASK_GRP   0x00000038
#define PHAR_ENT_PERM_SHIFT_GRP   3
#define PHAR_ENT_PERM_MASK_OTH   0x00000007
#define PHAR_ENT_PERM_DEF_FILE   0x000001B6
#define PHAR_ENT_PERM_DEF_DIR   0x000001FF
#define PHAR_FORMAT_SAME   0
#define PHAR_FORMAT_PHAR   1
#define PHAR_FORMAT_TAR   2
#define PHAR_FORMAT_ZIP   3
#define TAR_FILE   '0'
#define TAR_LINK   '1'
#define TAR_SYMLINK   '2'
#define TAR_DIR   '5'
#define TAR_NEW   '8'
#define PHAR_MUNG_PHP_SELF   (1<<0)
#define PHAR_MUNG_REQUEST_URI   (1<<1)
#define PHAR_MUNG_SCRIPT_NAME   (1<<2)
#define PHAR_MUNG_SCRIPT_FILENAME   (1<<3)
#define PHAR_G(v)   (phar_globals.v)
#define PHAR_GLOBALS   (&phar_globals)
#define php_uint16   uint16_t
#define PHAR_MIME_PHP   '\0'
#define PHAR_MIME_PHPS   '\1'
#define PHAR_MIME_OTHER   '\2'
#define PHAR_STR(a, b)   b = a;
#define PHAR_ZSTR(a, b)   b = a;
#define PHAR_STR_FREE(a)

Typedefs

typedef struct _phar_entry_fp
typedef struct _phar_archive_data
typedef struct _phar_entry_info phar_entry_info
typedef struct _phar_entry_fp_info phar_entry_fp_info
typedef struct _phar_mime_type phar_mime_type
typedef struct _phar_entry_data phar_entry_data
typedef char * phar_zstr

Enumerations

enum  phar_fp_type { PHAR_FP, PHAR_UFP, PHAR_MOD, PHAR_TMP }
enum  phar_path_check_result {
  pcr_use_query, pcr_is_ok, pcr_err_double_slash, pcr_err_up_dir,
  pcr_err_curr_dir, pcr_err_back_slash, pcr_err_star, pcr_err_illegal_char,
  pcr_err_empty_entry
}

Functions

static php_stream * phar_get_entrypfp (phar_entry_info *entry TSRMLS_DC)
static php_stream * phar_get_entrypufp (phar_entry_info *entry TSRMLS_DC)
static void phar_set_entrypfp (phar_entry_info *entry, php_stream *fp TSRMLS_DC)
static void phar_set_entrypufp (phar_entry_info *entry, php_stream *fp TSRMLS_DC)
static php_stream * phar_get_pharfp (phar_archive_data *phar TSRMLS_DC)
static php_stream * phar_get_pharufp (phar_archive_data *phar TSRMLS_DC)
static void phar_set_pharfp (phar_archive_data *phar, php_stream *fp TSRMLS_DC)
static void phar_set_pharufp (phar_archive_data *phar, php_stream *fp TSRMLS_DC)
static void phar_set_fp_type (phar_entry_info *entry, enum phar_fp_type type, off_t offset TSRMLS_DC)
static enum phar_fp_type phar_get_fp_type (phar_entry_info *entry TSRMLS_DC)
static off_t phar_get_fp_offset (phar_entry_info *entry TSRMLS_DC)
static size_t phar_stream_copy_to_stream (php_stream *src, php_stream *dest, size_t maxlen, size_t *len STREAMS_DC TSRMLS_DC)
static int phar_validate_alias (const char *alias, int alias_len)
 validate an alias, returns 1 for success, 0 for failure
static void phar_set_inode (phar_entry_info *entry TSRMLS_DC)
void phar_request_initialize (TSRMLS_D)
void phar_object_init (TSRMLS_D)
void phar_destroy_phar_data (phar_archive_data *phar TSRMLS_DC)
 When all uses of a phar have been concluded, this frees the manifest and the phar slot.
int phar_open_entry_file (phar_archive_data *phar, phar_entry_info *entry, char **error TSRMLS_DC)
int phar_postprocess_file (phar_entry_data *idata, php_uint32 crc32, char **error, int process_zip TSRMLS_DC)
 Validate the CRC32 of a file opened from within the phar.
int phar_open_from_filename (char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data **pphar, char **error TSRMLS_DC)
 Return an already opened filename.
int phar_open_or_create_filename (char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data **pphar, char **error TSRMLS_DC)
 Create or open a phar for writing.
int phar_create_or_parse_filename (char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data **pphar, char **error TSRMLS_DC)
int phar_open_executed_filename (char *alias, int alias_len, char **error TSRMLS_DC)
 Invoked when a user calls Phar::mapPhar() from within an executing .phar to set up its manifest directly.
int phar_free_alias (phar_archive_data *phar, char *alias, int alias_len TSRMLS_DC)
int phar_get_archive (phar_archive_data **archive, char *fname, int fname_len, char *alias, int alias_len, char **error TSRMLS_DC)
 Looks up a phar archive in the filename map, connecting it to the alias (if any) or returns null.
int phar_open_parsed_phar (char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data **pphar, char **error TSRMLS_DC)
 Open an already loaded phar.
int phar_verify_signature (php_stream *fp, size_t end_of_phar, php_uint32 sig_type, char *sig, int sig_len, char *fname, char **signature, int *signature_len, char **error TSRMLS_DC)
int phar_create_signature (phar_archive_data *phar, php_stream *fp, char **signature, int *signature_length, char **error TSRMLS_DC)
char * phar_create_default_stub (const char *index_php, const char *web_index, size_t *len, char **error TSRMLS_DC)
char * phar_decompress_filter (phar_entry_info *entry, int return_unknown)
 Determine which stream decompression filter (if any) we need to read this file.
char * phar_compress_filter (phar_entry_info *entry, int return_unknown)
 Determine which stream compression filter (if any) we need to read this file.
void phar_remove_virtual_dirs (phar_archive_data *phar, char *filename, int filename_len TSRMLS_DC)
void phar_add_virtual_dirs (phar_archive_data *phar, char *filename, int filename_len TSRMLS_DC)
int phar_mount_entry (phar_archive_data *phar, char *filename, int filename_len, char *path, int path_len TSRMLS_DC)
char * phar_find_in_include_path (char *file, int file_len, phar_archive_data **pphar TSRMLS_DC)
char * phar_fix_filepath (char *path, int *new_len, int use_cwd TSRMLS_DC)
 Remove .
phar_entry_infophar_open_jit (phar_archive_data *phar, phar_entry_info *entry, char **error TSRMLS_DC)
 helper function to open an internal file's fp just-in-time
int phar_parse_metadata (char **buffer, zval **metadata, int zip_metadata_len TSRMLS_DC)
 Parse out metadata from the manifest for a single file.
void destroy_phar_manifest_entry (void *pDest)
 destructor for the manifest hash, frees each file's entry
int phar_seek_efp (phar_entry_info *entry, off_t offset, int whence, off_t position, int follow_links TSRMLS_DC)
php_stream * phar_get_efp (phar_entry_info *entry, int follow_links TSRMLS_DC)
int phar_copy_entry_fp (phar_entry_info *source, phar_entry_info *dest, char **error TSRMLS_DC)
int phar_open_entry_fp (phar_entry_info *entry, char **error, int follow_links TSRMLS_DC)
phar_entry_infophar_get_link_source (phar_entry_info *entry TSRMLS_DC)
int phar_create_writeable_entry (phar_archive_data *phar, phar_entry_info *entry, char **error TSRMLS_DC)
int phar_separate_entry_fp (phar_entry_info *entry, char **error TSRMLS_DC)
int phar_open_archive_fp (phar_archive_data *phar TSRMLS_DC)
int phar_copy_on_write (phar_archive_data **pphar TSRMLS_DC)
int phar_is_tar (char *buf, char *fname)
int phar_parse_tarfile (php_stream *fp, char *fname, int fname_len, char *alias, int alias_len, phar_archive_data **pphar, int is_data, php_uint32 compression, char **error TSRMLS_DC)
int phar_open_or_create_tar (char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data **pphar, char **error TSRMLS_DC)
int phar_tar_flush (phar_archive_data *phar, char *user_stub, long len, int defaultstub, char **error TSRMLS_DC)
int phar_parse_zipfile (php_stream *fp, char *fname, int fname_len, char *alias, int alias_len, phar_archive_data **pphar, char **error TSRMLS_DC)
 Does not check for a previously opened phar in the cache.
int phar_open_or_create_zip (char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data **pphar, char **error TSRMLS_DC)
 Create or open a zip-based phar for writing.
int phar_zip_flush (phar_archive_data *archive, char *user_stub, long len, int defaultstub, char **error TSRMLS_DC)
int phar_archive_delref (phar_archive_data *phar TSRMLS_DC)
 Delete refcount and destruct if needed.
int phar_entry_delref (phar_entry_data *idata TSRMLS_DC)
phar_entry_infophar_get_entry_info (phar_archive_data *phar, char *path, int path_len, char **error, int security TSRMLS_DC)
 retrieve information on a file contained within a phar, or null if it ain't there
phar_entry_infophar_get_entry_info_dir (phar_archive_data *phar, char *path, int path_len, char dir, char **error, int security TSRMLS_DC)
 retrieve information on a file or directory contained within a phar, or null if none found allow_dir is 0 for none, 1 for both empty directories in the phar and temp directories, and 2 for only valid pre-existing empty directory entries
phar_entry_dataphar_get_or_create_entry_data (char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error, int security TSRMLS_DC)
 Create a new dummy file slot within a writeable phar for a newly created file.
int phar_get_entry_data (phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode, char allow_dir, char **error, int security TSRMLS_DC)
 Retrieve a copy of the file information on a single file within a phar, or null.
int phar_flush (phar_archive_data *archive, char *user_stub, long len, int convert, char **error TSRMLS_DC)
 Save phar contents to disk.
int phar_detect_phar_fname_ext (const char *filename, int filename_len, const char **ext_str, int *ext_len, int executable, int for_create, int is_complete TSRMLS_DC)
int phar_split_fname (char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len, int executable, int for_create TSRMLS_DC)
 Process a phar stream name, ensuring we can handle any of:
phar_path_check_result phar_path_check (char **p, int *len, const char **error)

Variables

HashTable phar_persist_map
HashTable phar_fname_map
phar_entry_fp * cached_fp
HashTable phar_alias_map
int phar_SERVER_mung_list
int readonly
char * cache_list
int manifest_cached
int persist
int has_zlib
int has_bz2
zend_bool readonly_orig
zend_bool require_hash_orig
zend_bool intercepted
int request_init
int require_hash
int request_done
int request_ends
void(* orig_fopen )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_file_get_contents )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_is_file )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_is_link )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_is_dir )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_opendir )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_file_exists )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_fileperms )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_fileinode )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_filesize )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_fileowner )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_filegroup )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_fileatime )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_filemtime )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_filectime )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_filetype )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_is_writable )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_is_readable )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_is_executable )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_lstat )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_readfile )(INTERNAL_FUNCTION_PARAMETERS)
void(* orig_stat )(INTERNAL_FUNCTION_PARAMETERS)
char * cwd
int cwd_len
int cwd_init
char * openssl_privatekey
int openssl_privatekey_len
char * last_phar_name
int last_phar_name_len
char * last_alias
int last_alias_len
phar_archive_data * last_phar
HashTable mime_types
HashTable cached_phars
HashTable cached_alias

Class Documentation

struct _phar_entry_info

Definition at line 252 of file phar_internal.h.

Class Members
php_uint32 compressed_filesize
php_uint32 crc32
char * filename
php_uint32 filename_len
php_uint32 flags
zval * metadata
int metadata_len
php_uint32 old_flags
php_uint32 timestamp
php_uint32 uncompressed_filesize
struct _phar_archive_data

Definition at line 304 of file phar_internal.h.

Collaboration diagram for _phar_archive_data:
Class Members
char * alias
int alias_len
unsigned int donotflush:1
char * ext
int ext_len
php_uint32 flags
char * fname
int fname_len
php_stream * fp
size_t halt_offset
size_t internal_file_start
unsigned int is_brandnew:1
unsigned int is_data:1
unsigned int is_modified:1
unsigned int is_persistent:1
unsigned int is_tar:1
unsigned int is_temporary_alias:1
unsigned int is_writeable:1
unsigned int is_zip:1
HashTable manifest
php_uint32 max_timestamp
zval * metadata
int metadata_len
php_uint32 min_timestamp
HashTable mounted_dirs
uint phar_pos
int refcount
php_uint32 sig_flags
int sig_len
char * signature
php_stream * ufp
char version
HashTable virtual_dirs
struct _phar_entry_fp_info

Definition at line 350 of file phar_internal.h.

struct _phar_entry_fp

Definition at line 356 of file phar_internal.h.

Collaboration diagram for _phar_entry_fp:
Class Members
php_stream * fp
phar_entry_fp_info * manifest
php_stream * ufp
struct _phar_mime_type

Definition at line 473 of file phar_internal.h.

Class Members
int len
char * mime
char type
struct _phar_entry_data

Definition at line 481 of file phar_internal.h.

Collaboration diagram for _phar_entry_data:
Class Members
int for_write:1
php_stream * fp
phar_entry_info * internal_file
int is_tar:1
int is_zip:1
phar_archive_data * phar
off_t position
off_t zero

Define Documentation

#define ALLOC_PERMANENT_ZVAL (   z)    (z) = (zval*)malloc(sizeof(zval))

Definition at line 83 of file phar_internal.h.

Definition at line 75 of file phar_internal.h.

#define pestrndup (   s,
  length,
  persistent 
)    ((persistent)?zend_strndup((s),(length)):estrndup((s),(length)))

Definition at line 79 of file phar_internal.h.

#define PHAR_API_MAJORVER_MASK   0xF000

Definition at line 96 of file phar_internal.h.

#define PHAR_API_MAJORVERSION   0x1000

Definition at line 95 of file phar_internal.h.

#define PHAR_API_MIN_DIR   0x1110

Definition at line 93 of file phar_internal.h.

#define PHAR_API_MIN_READ   0x1000

Definition at line 94 of file phar_internal.h.

#define PHAR_API_VER_MASK   0xFFF0

Definition at line 97 of file phar_internal.h.

#define PHAR_API_VERSION   0x1110

Definition at line 90 of file phar_internal.h.

#define PHAR_API_VERSION_NODIR   0x1100

Definition at line 92 of file phar_internal.h.

#define PHAR_ENT_COMPRESSED_BZ2   0x00002000

Definition at line 122 of file phar_internal.h.

#define PHAR_ENT_COMPRESSED_GZ   0x00001000

Definition at line 121 of file phar_internal.h.

#define PHAR_ENT_COMPRESSED_NONE   0x00000000

Definition at line 120 of file phar_internal.h.

#define PHAR_ENT_COMPRESSION_MASK   0x0000F000

Definition at line 119 of file phar_internal.h.

#define PHAR_ENT_PERM_DEF_DIR   0x000001FF

Definition at line 131 of file phar_internal.h.

#define PHAR_ENT_PERM_DEF_FILE   0x000001B6

Definition at line 130 of file phar_internal.h.

#define PHAR_ENT_PERM_MASK   0x000001FF

Definition at line 124 of file phar_internal.h.

#define PHAR_ENT_PERM_MASK_GRP   0x00000038

Definition at line 127 of file phar_internal.h.

#define PHAR_ENT_PERM_MASK_OTH   0x00000007

Definition at line 129 of file phar_internal.h.

#define PHAR_ENT_PERM_MASK_USR   0x000001C0

Definition at line 125 of file phar_internal.h.

#define PHAR_ENT_PERM_SHIFT_GRP   3

Definition at line 128 of file phar_internal.h.

#define PHAR_ENT_PERM_SHIFT_USR   6

Definition at line 126 of file phar_internal.h.

#define PHAR_FILE_COMPRESSED_BZ2   0x00200000

Definition at line 109 of file phar_internal.h.

#define PHAR_FILE_COMPRESSED_GZ   0x00100000

Definition at line 108 of file phar_internal.h.

#define PHAR_FILE_COMPRESSED_NONE   0x00000000

Definition at line 107 of file phar_internal.h.

#define PHAR_FILE_COMPRESSION_MASK   0x00F00000

Definition at line 106 of file phar_internal.h.

#define PHAR_FORMAT_PHAR   1

Definition at line 134 of file phar_internal.h.

#define PHAR_FORMAT_SAME   0

Definition at line 133 of file phar_internal.h.

#define PHAR_FORMAT_TAR   2

Definition at line 135 of file phar_internal.h.

#define PHAR_FORMAT_ZIP   3

Definition at line 136 of file phar_internal.h.

#define PHAR_G (   v)    (phar_globals.v)

Definition at line 218 of file phar_internal.h.

#define PHAR_GLOBALS   (&phar_globals)

Definition at line 219 of file phar_internal.h.

#define PHAR_HDR_COMPRESSED_BZ2   0x00002000

Definition at line 102 of file phar_internal.h.

#define PHAR_HDR_COMPRESSED_GZ   0x00001000

Definition at line 101 of file phar_internal.h.

#define PHAR_HDR_COMPRESSED_NONE   0x00000000

Definition at line 100 of file phar_internal.h.

#define PHAR_HDR_COMPRESSION_MASK   0x0000F000

Definition at line 99 of file phar_internal.h.

#define PHAR_HDR_SIGNATURE   0x00010000

Definition at line 103 of file phar_internal.h.

#define PHAR_MIME_OTHER   '\2'

Definition at line 471 of file phar_internal.h.

#define PHAR_MIME_PHP   '\0'

Definition at line 469 of file phar_internal.h.

#define PHAR_MIME_PHPS   '\1'

Definition at line 470 of file phar_internal.h.

#define PHAR_MUNG_PHP_SELF   (1<<0)

Definition at line 144 of file phar_internal.h.

#define PHAR_MUNG_REQUEST_URI   (1<<1)

Definition at line 145 of file phar_internal.h.

#define PHAR_MUNG_SCRIPT_FILENAME   (1<<3)

Definition at line 147 of file phar_internal.h.

#define PHAR_MUNG_SCRIPT_NAME   (1<<2)

Definition at line 146 of file phar_internal.h.

#define PHAR_SIG_MD5   0x0001

Definition at line 111 of file phar_internal.h.

#define PHAR_SIG_OPENSSL   0x0010

Definition at line 115 of file phar_internal.h.

#define PHAR_SIG_SHA1   0x0002

Definition at line 112 of file phar_internal.h.

#define PHAR_SIG_SHA256   0x0003

Definition at line 113 of file phar_internal.h.

#define PHAR_SIG_SHA512   0x0004

Definition at line 114 of file phar_internal.h.

#define PHAR_STR (   a,
 
)    b = a;

Definition at line 583 of file phar_internal.h.

#define PHAR_STR_FREE (   a)

Definition at line 587 of file phar_internal.h.

#define PHAR_ZSTR (   a,
 
)    b = a;

Definition at line 585 of file phar_internal.h.

#define PHP_PHAR_API_VERSION   "1.1.1"

Definition at line 88 of file phar_internal.h.

#define php_uint16   uint16_t

Definition at line 226 of file phar_internal.h.

#define TAR_DIR   '5'

Definition at line 141 of file phar_internal.h.

#define TAR_FILE   '0'

Definition at line 138 of file phar_internal.h.

#define TAR_LINK   '1'

Definition at line 139 of file phar_internal.h.

#define TAR_NEW   '8'

Definition at line 142 of file phar_internal.h.

#define TAR_SYMLINK   '2'

Definition at line 140 of file phar_internal.h.


Typedef Documentation

typedef struct _phar_archive_data

Definition at line 150 of file phar_internal.h.

typedef struct _phar_entry_fp

Definition at line 149 of file phar_internal.h.

typedef char* phar_zstr

Definition at line 582 of file phar_internal.h.


Enumeration Type Documentation

Enumerator:
PHAR_FP 
PHAR_UFP 
PHAR_MOD 
PHAR_TMP 

Definition at line 239 of file phar_internal.h.

                  {
       /* regular file pointer phar_archive_data->fp */
       PHAR_FP,
       /* uncompressed file pointer phar_archive_data->uncompressed_fp */
       PHAR_UFP,
       /* modified file pointer phar_entry_info->fp */
       PHAR_MOD,
       /* temporary manifest entry (file outside of the phar mapped to a location inside the phar)
          this entry stores the stream to open in link (normally used for tars, but we steal it here) */
       PHAR_TMP
};
Enumerator:
pcr_use_query 
pcr_is_ok 
pcr_err_double_slash 
pcr_err_up_dir 
pcr_err_curr_dir 
pcr_err_back_slash 
pcr_err_star 
pcr_err_illegal_char 
pcr_err_empty_entry 

Definition at line 699 of file phar_internal.h.


Function Documentation

void destroy_phar_manifest_entry ( void *  pDest)

destructor for the manifest hash, frees each file's entry

Definition at line 382 of file phar.c.

{
       phar_entry_info *entry = (phar_entry_info *)pDest;
       TSRMLS_FETCH();

       if (entry->cfp) {
              php_stream_close(entry->cfp);
              entry->cfp = 0;
       }

       if (entry->fp) {
              php_stream_close(entry->fp);
              entry->fp = 0;
       }

       if (entry->metadata) {
              if (entry->is_persistent) {
                     if (entry->metadata_len) {
                            /* for zip comments that are strings */
                            free(entry->metadata);
                     } else {
                            zval_internal_ptr_dtor(&entry->metadata);
                     }
              } else {
                     zval_ptr_dtor(&entry->metadata);
              }
              entry->metadata_len = 0;
              entry->metadata = 0;
       }

       if (entry->metadata_str.c) {
              smart_str_free(&entry->metadata_str);
              entry->metadata_str.c = 0;
       }

       pefree(entry->filename, entry->is_persistent);

       if (entry->link) {
              pefree(entry->link, entry->is_persistent);
              entry->link = 0;
       }

       if (entry->tmp) {
              pefree(entry->tmp, entry->is_persistent);
              entry->tmp = 0;
       }
}

Here is the caller graph for this function:

void phar_add_virtual_dirs ( phar_archive_data *  phar,
char *  filename,
int filename_len  TSRMLS_DC 
)

Definition at line 2219 of file util.c.

{
       char *s;

       while ((s = zend_memrchr(filename, '/', filename_len))) {
              filename_len = s - filename;
              if (FAILURE == zend_hash_add_empty_element(&phar->virtual_dirs, filename, filename_len)) {
                     break;
              }
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_archive_delref ( phar_archive_data *phar  TSRMLS_DC)

Delete refcount and destruct if needed.

On destruct return 1 else 0.

Definition at line 273 of file phar.c.

{
       if (phar->is_persistent) {
              return 0;
       }

       if (--phar->refcount < 0) {
              if (PHAR_GLOBALS->request_done
              || zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), phar->fname, phar->fname_len) != SUCCESS) {
                     phar_destroy_phar_data(phar TSRMLS_CC);
              }
              return 1;
       } else if (!phar->refcount) {
              /* invalidate phar cache */
              PHAR_G(last_phar) = NULL;
              PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;

              if (phar->fp && !(phar->flags & PHAR_FILE_COMPRESSION_MASK)) {
                     /* close open file handle - allows removal or rename of
                     the file on windows, which has greedy locking
                     only close if the archive was not already compressed.  If it
                     was compressed, then the fp does not refer to the original file */
                     php_stream_close(phar->fp);
                     phar->fp = NULL;
              }

              if (!zend_hash_num_elements(&phar->manifest)) {
                     /* this is a new phar that has perhaps had an alias/metadata set, but has never
                     been flushed */
                     if (zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), phar->fname, phar->fname_len) != SUCCESS) {
                            phar_destroy_phar_data(phar TSRMLS_CC);
                     }
                     return 1;
              }
       }
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* phar_compress_filter ( phar_entry_info entry,
int  return_unknown 
)

Determine which stream compression filter (if any) we need to read this file.

Definition at line 1412 of file util.c.

{
       switch (entry->flags & PHAR_ENT_COMPRESSION_MASK) {
       case PHAR_ENT_COMPRESSED_GZ:
              return "zlib.deflate";
       case PHAR_ENT_COMPRESSED_BZ2:
              return "bzip2.compress";
       default:
              return return_unknown ? "unknown" : NULL;
       }
}

Here is the caller graph for this function:

int phar_copy_entry_fp ( phar_entry_info source,
phar_entry_info dest,
char **error  TSRMLS_DC 
)

Definition at line 877 of file util.c.

{
       phar_entry_info *link;

       if (FAILURE == phar_open_entry_fp(source, error, 1 TSRMLS_CC)) {
              return FAILURE;
       }

       if (dest->link) {
              efree(dest->link);
              dest->link = NULL;
              dest->tar_type = (dest->is_tar ? TAR_FILE : '\0');
       }

       dest->fp_type = PHAR_MOD;
       dest->offset = 0;
       dest->is_modified = 1;
       dest->fp = php_stream_fopen_tmpfile();
       phar_seek_efp(source, 0, SEEK_SET, 0, 1 TSRMLS_CC);
       link = phar_get_link_source(source TSRMLS_CC);

       if (!link) {
              link = source;
       }

       if (SUCCESS != phar_stream_copy_to_stream(phar_get_efp(link, 0 TSRMLS_CC), dest->fp, link->uncompressed_filesize, NULL)) {
              php_stream_close(dest->fp);
              dest->fp_type = PHAR_FP;
              if (error) {
                     spprintf(error, 4096, "phar error: unable to copy contents of file \"%s\" to \"%s\" in phar archive \"%s\"", source->filename, dest->filename, source->phar->fname);
              }
              return FAILURE;
       }

       return SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_copy_on_write ( phar_archive_data **pphar  TSRMLS_DC)

Definition at line 2343 of file util.c.

{
       phar_archive_data **newpphar, *newphar = NULL;

       if (SUCCESS != zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), (*pphar)->fname, (*pphar)->fname_len, (void *)&newphar, sizeof(phar_archive_data *), (void **)&newpphar)) {
              return FAILURE;
       }

       *newpphar = *pphar;
       phar_copy_cached_phar(newpphar TSRMLS_CC);
       /* invalidate phar cache */
       PHAR_G(last_phar) = NULL;
       PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;

       if (newpphar[0]->alias_len && FAILURE == zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), newpphar[0]->alias, newpphar[0]->alias_len, (void*)newpphar, sizeof(phar_archive_data*), NULL)) {
              zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), (*pphar)->fname, (*pphar)->fname_len);
              return FAILURE;
       }

       *pphar = *newpphar;
       return SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* phar_create_default_stub ( const char *  index_php,
const char *  web_index,
size_t len,
char **error  TSRMLS_DC 
)

Definition at line 2514 of file phar.c.

{
       char *stub = NULL;
       int index_len, web_len;
       size_t dummy;

       if (!len) {
              len = &dummy;
       }

       if (error) {
              *error = NULL;
       }

       if (!index_php) {
              index_php = "index.php";
       }

       if (!web_index) {
              web_index = "index.php";
       }

       index_len = strlen(index_php);
       web_len = strlen(web_index);

       if (index_len > 400) {
              /* ridiculous size not allowed for index.php startup filename */
              if (error) {
                     spprintf(error, 0, "Illegal filename passed in for stub creation, was %d characters long, and only 400 or less is allowed", index_len);
                     return NULL;
              }
       }

       if (web_len > 400) {
              /* ridiculous size not allowed for index.php startup filename */
              if (error) {
                     spprintf(error, 0, "Illegal web filename passed in for stub creation, was %d characters long, and only 400 or less is allowed", web_len);
                     return NULL;
              }
       }

       phar_get_stub(index_php, web_index, len, &stub, index_len+1, web_len+1 TSRMLS_CC);
       return stub;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_create_or_parse_filename ( char *  fname,
int  fname_len,
char *  alias,
int  alias_len,
int  is_data,
int  options,
phar_archive_data **  pphar,
char **error  TSRMLS_DC 
)

Definition at line 1321 of file phar.c.

{
       phar_archive_data *mydata;
       php_stream *fp;
       char *actual = NULL, *p;

       if (!pphar) {
              pphar = &mydata;
       }
#if PHP_API_VERSION < 20100412
       if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
              return FAILURE;
       }
#endif
       if (php_check_open_basedir(fname TSRMLS_CC)) {
              return FAILURE;
       }

       /* first open readonly so it won't be created if not present */
       fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|0, &actual);

       if (actual) {
              fname = actual;
              fname_len = strlen(actual);
       }

       if (fp) {
              if (phar_open_from_fp(fp, fname, fname_len, alias, alias_len, options, pphar, is_data, error TSRMLS_CC) == SUCCESS) {
                     if ((*pphar)->is_data || !PHAR_G(readonly)) {
                            (*pphar)->is_writeable = 1;
                     }
                     if (actual) {
                            efree(actual);
                     }
                     return SUCCESS;
              } else {
                     /* file exists, but is either corrupt or not a phar archive */
                     if (actual) {
                            efree(actual);
                     }
                     return FAILURE;
              }
       }

       if (actual) {
              efree(actual);
       }

       if (PHAR_G(readonly) && !is_data) {
              if (options & REPORT_ERRORS) {
                     if (error) {
                            spprintf(error, 0, "creating archive \"%s\" disabled by the php.ini setting phar.readonly", fname);
                     }
              }
              return FAILURE;
       }

       /* set up our manifest */
       mydata = ecalloc(1, sizeof(phar_archive_data));
       mydata->fname = expand_filepath(fname, NULL TSRMLS_CC);
       fname_len = strlen(mydata->fname);
#ifdef PHP_WIN32
       phar_unixify_path_separators(mydata->fname, fname_len);
#endif
       p = strrchr(mydata->fname, '/');

       if (p) {
              mydata->ext = memchr(p, '.', (mydata->fname + fname_len) - p);
              if (mydata->ext == p) {
                     mydata->ext = memchr(p + 1, '.', (mydata->fname + fname_len) - p - 1);
              }
              if (mydata->ext) {
                     mydata->ext_len = (mydata->fname + fname_len) - mydata->ext;
              }
       }

       if (pphar) {
              *pphar = mydata;
       }

       zend_hash_init(&mydata->manifest, sizeof(phar_entry_info),
              zend_get_hash_value, destroy_phar_manifest_entry, 0);
       zend_hash_init(&mydata->mounted_dirs, sizeof(char *),
              zend_get_hash_value, NULL, 0);
       zend_hash_init(&mydata->virtual_dirs, sizeof(char *),
              zend_get_hash_value, NULL, (zend_bool)mydata->is_persistent);
       mydata->fname_len = fname_len;
       snprintf(mydata->version, sizeof(mydata->version), "%s", PHP_PHAR_API_VERSION);
       mydata->is_temporary_alias = alias ? 0 : 1;
       mydata->internal_file_start = -1;
       mydata->fp = NULL;
       mydata->is_writeable = 1;
       mydata->is_brandnew = 1;
       phar_request_initialize(TSRMLS_C);
       zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*),  NULL);

       if (is_data) {
              alias = NULL;
              alias_len = 0;
              mydata->is_data = 1;
              /* assume tar format, PharData can specify other */
              mydata->is_tar = 1;
       } else {
              phar_archive_data **fd_ptr;

              if (alias && SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void **)&fd_ptr)) {
                     if (SUCCESS != phar_free_alias(*fd_ptr, alias, alias_len TSRMLS_CC)) {
                            if (error) {
                                   spprintf(error, 4096, "phar error: phar \"%s\" cannot set alias \"%s\", already in use by another phar archive", mydata->fname, alias);
                            }

                            zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len);

                            if (pphar) {
                                   *pphar = NULL;
                            }

                            return FAILURE;
                     }
              }

              mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, fname_len);
              mydata->alias_len = alias ? alias_len : fname_len;
       }

       if (alias_len && alias) {
              if (FAILURE == zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL)) {
                     if (options & REPORT_ERRORS) {
                            if (error) {
                                   spprintf(error, 0, "archive \"%s\" cannot be associated with alias \"%s\", already in use", fname, alias);
                            }
                     }

                     zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len);

                     if (pphar) {
                            *pphar = NULL;
                     }

                     return FAILURE;
              }
       }

       return SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_create_signature ( phar_archive_data *  phar,
php_stream *  fp,
char **  signature,
int signature_length,
char **error  TSRMLS_DC 
)

Definition at line 2065 of file util.c.

{
       unsigned char buf[1024];
       int sig_len;

       php_stream_rewind(fp);

       if (phar->signature) {
              efree(phar->signature);
              phar->signature = NULL;
       }

       switch(phar->sig_flags) {
#ifdef PHAR_HASH_OK
              case PHAR_SIG_SHA512: {
                     unsigned char digest[64];
                     PHP_SHA512_CTX context;

                     PHP_SHA512Init(&context);

                     while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
                            PHP_SHA512Update(&context, buf, sig_len);
                     }

                     PHP_SHA512Final(digest, &context);
                     *signature = estrndup((char *) digest, 64);
                     *signature_length = 64;
                     break;
              }
              case PHAR_SIG_SHA256: {
                     unsigned char digest[32];
                     PHP_SHA256_CTX  context;

                     PHP_SHA256Init(&context);

                     while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
                            PHP_SHA256Update(&context, buf, sig_len);
                     }

                     PHP_SHA256Final(digest, &context);
                     *signature = estrndup((char *) digest, 32);
                     *signature_length = 32;
                     break;
              }
#else
              case PHAR_SIG_SHA512:
              case PHAR_SIG_SHA256:
                     if (error) {
                            spprintf(error, 0, "unable to write to phar \"%s\" with requested hash type", phar->fname);
                     }

                     return FAILURE;
#endif
              case PHAR_SIG_OPENSSL: {
                     int siglen;
                     unsigned char *sigbuf;
#ifdef PHAR_HAVE_OPENSSL
                     BIO *in;
                     EVP_PKEY *key;
                     EVP_MD *mdtype = (EVP_MD *) EVP_sha1();
                     EVP_MD_CTX md_ctx;

                     in = BIO_new_mem_buf(PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len));

                     if (in == NULL) {
                            if (error) {
                                   spprintf(error, 0, "unable to write to phar \"%s\" with requested openssl signature", phar->fname);
                            }
                            return FAILURE;
                     }

                     key = PEM_read_bio_PrivateKey(in, NULL,NULL, "");
                     BIO_free(in);

                     if (!key) {
                            if (error) {
                                   spprintf(error, 0, "unable to process private key");
                            }
                            return FAILURE;
                     }

                     siglen = EVP_PKEY_size(key);
                     sigbuf = emalloc(siglen + 1);
                     EVP_SignInit(&md_ctx, mdtype);

                     while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
                            EVP_SignUpdate(&md_ctx, buf, sig_len);
                     }

                     if (!EVP_SignFinal (&md_ctx, sigbuf,(unsigned int *)&siglen, key)) {
                            efree(sigbuf);
                            if (error) {
                                   spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname);
                            }
                            return FAILURE;
                     }

                     sigbuf[siglen] = '\0';
                     EVP_MD_CTX_cleanup(&md_ctx);
#else
                     sigbuf = NULL;
                     siglen = 0;
                     php_stream_seek(fp, 0, SEEK_END);

                     if (FAILURE == phar_call_openssl_signverify(1, fp, php_stream_tell(fp), PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len), (char **)&sigbuf, &siglen TSRMLS_CC)) {
                            if (error) {
                                   spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname);
                            }
                            return FAILURE;
                     }
#endif
                     *signature = (char *) sigbuf;
                     *signature_length = siglen;
              }
              break;
              default:
                     phar->sig_flags = PHAR_SIG_SHA1;
              case PHAR_SIG_SHA1: {
                     unsigned char digest[20];
                     PHP_SHA1_CTX  context;

                     PHP_SHA1Init(&context);

                     while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
                            PHP_SHA1Update(&context, buf, sig_len);
                     }

                     PHP_SHA1Final(digest, &context);
                     *signature = estrndup((char *) digest, 20);
                     *signature_length = 20;
                     break;
              }
              case PHAR_SIG_MD5: {
                     unsigned char digest[16];
                     PHP_MD5_CTX   context;

                     PHP_MD5Init(&context);

                     while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
                            PHP_MD5Update(&context, buf, sig_len);
                     }

                     PHP_MD5Final(digest, &context);
                     *signature = estrndup((char *) digest, 16);
                     *signature_length = 16;
                     break;
              }
       }

       phar->sig_len = phar_hex_str((const char *)*signature, *signature_length, &phar->signature TSRMLS_CC);
       return SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_create_writeable_entry ( phar_archive_data *  phar,
phar_entry_info entry,
char **error  TSRMLS_DC 
)

Definition at line 1044 of file util.c.

{
       if (entry->fp_type == PHAR_MOD) {
              /* already newly created, truncate */
#if PHP_VERSION_ID >= 50202
              php_stream_truncate_set_size(entry->fp, 0);
#else
              if (php_stream_is(entry->fp, PHP_STREAM_IS_TEMP)) {
                     if (php_stream_is(*(php_stream**)entry->fp->abstract, PHP_STREAM_IS_MEMORY)) {
                            php_stream *inner = *(php_stream**)entry->fp->abstract;
                            php_stream_memory_data *memfp = (php_stream_memory_data*)inner->abstract;
                            memfp->fpos = 0;
                            memfp->fsize = 0;
                     } else if (php_stream_is(*(php_stream**)entry->fp->abstract, PHP_STREAM_IS_STDIO)) {
                            php_stream_truncate_set_size(*(php_stream**)entry->fp->abstract, 0);
                     } else {
                            if (error) {
                                   spprintf(error, 0, "phar error: file \"%s\" cannot be opened for writing, no truncate support", phar->fname);
                            }
                            return FAILURE;
                     }
              } else if (php_stream_is(entry->fp, PHP_STREAM_IS_STDIO)) {
                     php_stream_truncate_set_size(entry->fp, 0);
              } else {
                     if (error) {
                            spprintf(error, 0, "phar error: file \"%s\" cannot be opened for writing, no truncate support", phar->fname);
                     }
                     return FAILURE;
              }
#endif
              entry->old_flags = entry->flags;
              entry->is_modified = 1;
              phar->is_modified = 1;
              /* reset file size */
              entry->uncompressed_filesize = 0;
              entry->compressed_filesize = 0;
              entry->crc32 = 0;
              entry->flags = PHAR_ENT_PERM_DEF_FILE;
              entry->fp_type = PHAR_MOD;
              entry->offset = 0;
              return SUCCESS;
       }

       if (error) {
              *error = NULL;
       }

       /* open a new temp file for writing */
       if (entry->link) {
              efree(entry->link);
              entry->link = NULL;
              entry->tar_type = (entry->is_tar ? TAR_FILE : '\0');
       }

       entry->fp = php_stream_fopen_tmpfile();

       if (!entry->fp) {
              if (error) {
                     spprintf(error, 0, "phar error: unable to create temporary file");
              }
              return FAILURE;
       }

       entry->old_flags = entry->flags;
       entry->is_modified = 1;
       phar->is_modified = 1;
       /* reset file size */
       entry->uncompressed_filesize = 0;
       entry->compressed_filesize = 0;
       entry->crc32 = 0;
       entry->flags = PHAR_ENT_PERM_DEF_FILE;
       entry->fp_type = PHAR_MOD;
       entry->offset = 0;
       return SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* phar_decompress_filter ( phar_entry_info entry,
int  return_unknown 
)

Determine which stream decompression filter (if any) we need to read this file.

Definition at line 1428 of file util.c.

{
       php_uint32 flags;

       if (entry->is_modified) {
              flags = entry->old_flags;
       } else {
              flags = entry->flags;
       }

       switch (flags & PHAR_ENT_COMPRESSION_MASK) {
              case PHAR_ENT_COMPRESSED_GZ:
                     return "zlib.inflate";
              case PHAR_ENT_COMPRESSED_BZ2:
                     return "bzip2.decompress";
              default:
                     return return_unknown ? "unknown" : NULL;
       }
}

Here is the caller graph for this function:

void phar_destroy_phar_data ( phar_archive_data *phar  TSRMLS_DC)

When all uses of a phar have been concluded, this frees the manifest and the phar slot.

Definition at line 209 of file phar.c.

{
       if (phar->alias && phar->alias != phar->fname) {
              pefree(phar->alias, phar->is_persistent);
              phar->alias = NULL;
       }

       if (phar->fname) {
              pefree(phar->fname, phar->is_persistent);
              phar->fname = NULL;
       }

       if (phar->signature) {
              pefree(phar->signature, phar->is_persistent);
              phar->signature = NULL;
       }

       if (phar->manifest.arBuckets) {
              zend_hash_destroy(&phar->manifest);
              phar->manifest.arBuckets = NULL;
       }

       if (phar->mounted_dirs.arBuckets) {
              zend_hash_destroy(&phar->mounted_dirs);
              phar->mounted_dirs.arBuckets = NULL;
       }

       if (phar->virtual_dirs.arBuckets) {
              zend_hash_destroy(&phar->virtual_dirs);
              phar->virtual_dirs.arBuckets = NULL;
       }

       if (phar->metadata) {
              if (phar->is_persistent) {
                     if (phar->metadata_len) {
                            /* for zip comments that are strings */
                            free(phar->metadata);
                     } else {
                            zval_internal_ptr_dtor(&phar->metadata);
                     }
              } else {
                     zval_ptr_dtor(&phar->metadata);
              }
              phar->metadata_len = 0;
              phar->metadata = 0;
       }

       if (phar->fp) {
              php_stream_close(phar->fp);
              phar->fp = 0;
       }

       if (phar->ufp) {
              php_stream_close(phar->ufp);
              phar->ufp = 0;
       }

       pefree(phar, phar->is_persistent);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_detect_phar_fname_ext ( const char *  filename,
int  filename_len,
const char **  ext_str,
int ext_len,
int  executable,
int  for_create,
int is_complete  TSRMLS_DC 
)

Definition at line 1897 of file phar.c.

{
       const char *pos, *slash;

       *ext_str = NULL;
       *ext_len = 0;

       if (!filename_len || filename_len == 1) {
              return FAILURE;
       }

       phar_request_initialize(TSRMLS_C);
       /* first check for alias in first segment */
       pos = memchr(filename, '/', filename_len);

       if (pos && pos != filename) {
              /* check for url like http:// or phar:// */
              if (*(pos - 1) == ':' && (pos - filename) < filename_len - 1 && *(pos + 1) == '/') {
                     *ext_len = -2;
                     *ext_str = NULL;
                     return FAILURE;
              }
              if (zend_hash_exists(&(PHAR_GLOBALS->phar_alias_map), (char *) filename, pos - filename)) {
                     *ext_str = pos;
                     *ext_len = -1;
                     return FAILURE;
              }

              if (PHAR_G(manifest_cached) && zend_hash_exists(&cached_alias, (char *) filename, pos - filename)) {
                     *ext_str = pos;
                     *ext_len = -1;
                     return FAILURE;
              }
       }

       if (zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)) || PHAR_G(manifest_cached)) {
              phar_archive_data **pphar;

              if (is_complete) {
                     if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), (char *) filename, filename_len, (void **)&pphar)) {
                            *ext_str = filename + (filename_len - (*pphar)->ext_len);
woohoo:
                            *ext_len = (*pphar)->ext_len;

                            if (executable == 2) {
                                   return SUCCESS;
                            }

                            if (executable == 1 && !(*pphar)->is_data) {
                                   return SUCCESS;
                            }

                            if (!executable && (*pphar)->is_data) {
                                   return SUCCESS;
                            }

                            return FAILURE;
                     }

                     if (PHAR_G(manifest_cached) && SUCCESS == zend_hash_find(&cached_phars, (char *) filename, filename_len, (void **)&pphar)) {
                            *ext_str = filename + (filename_len - (*pphar)->ext_len);
                            goto woohoo;
                     }
              } else {
                     phar_zstr key;
                     char *str_key;
                     uint keylen;
                     ulong unused;

                     zend_hash_internal_pointer_reset(&(PHAR_GLOBALS->phar_fname_map));

                     while (FAILURE != zend_hash_has_more_elements(&(PHAR_GLOBALS->phar_fname_map))) {
                            if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(&(PHAR_GLOBALS->phar_fname_map), &key, &keylen, &unused, 0, NULL)) {
                                   break;
                            }

                            PHAR_STR(key, str_key);

                            if (keylen > (uint) filename_len) {
                                   zend_hash_move_forward(&(PHAR_GLOBALS->phar_fname_map));
                                   PHAR_STR_FREE(str_key);
                                   continue;
                            }

                            if (!memcmp(filename, str_key, keylen) && ((uint)filename_len == keylen
                                   || filename[keylen] == '/' || filename[keylen] == '\0')) {
                                   PHAR_STR_FREE(str_key);
                                   if (FAILURE == zend_hash_get_current_data(&(PHAR_GLOBALS->phar_fname_map), (void **) &pphar)) {
                                          break;
                                   }
                                   *ext_str = filename + (keylen - (*pphar)->ext_len);
                                   goto woohoo;
                            }

                            PHAR_STR_FREE(str_key);
                            zend_hash_move_forward(&(PHAR_GLOBALS->phar_fname_map));
                     }

                     if (PHAR_G(manifest_cached)) {
                            zend_hash_internal_pointer_reset(&cached_phars);

                            while (FAILURE != zend_hash_has_more_elements(&cached_phars)) {
                                   if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(&cached_phars, &key, &keylen, &unused, 0, NULL)) {
                                          break;
                                   }

                                   PHAR_STR(key, str_key);

                                   if (keylen > (uint) filename_len) {
                                          zend_hash_move_forward(&cached_phars);
                                          PHAR_STR_FREE(str_key);
                                          continue;
                                   }

                                   if (!memcmp(filename, str_key, keylen) && ((uint)filename_len == keylen
                                          || filename[keylen] == '/' || filename[keylen] == '\0')) {
                                          PHAR_STR_FREE(str_key);
                                          if (FAILURE == zend_hash_get_current_data(&cached_phars, (void **) &pphar)) {
                                                 break;
                                          }
                                          *ext_str = filename + (keylen - (*pphar)->ext_len);
                                          goto woohoo;
                                   }
                                   PHAR_STR_FREE(str_key);
                                   zend_hash_move_forward(&cached_phars);
                            }
                     }
              }
       }

       pos = memchr(filename + 1, '.', filename_len);
next_extension:
       if (!pos) {
              return FAILURE;
       }

       while (pos != filename && (*(pos - 1) == '/' || *(pos - 1) == '\0')) {
              pos = memchr(pos + 1, '.', filename_len - (pos - filename) + 1);
              if (!pos) {
                     return FAILURE;
              }
       }

       slash = memchr(pos, '/', filename_len - (pos - filename));

       if (!slash) {
              /* this is a url like "phar://blah.phar" with no directory */
              *ext_str = pos;
              *ext_len = strlen(pos);

              /* file extension must contain "phar" */
              switch (phar_check_str(filename, *ext_str, *ext_len, executable, for_create TSRMLS_CC)) {
                     case SUCCESS:
                            return SUCCESS;
                     case FAILURE:
                            /* we are at the end of the string, so we fail */
                            return FAILURE;
              }
       }

       /* we've found an extension that ends at a directory separator */
       *ext_str = pos;
       *ext_len = slash - pos;

       switch (phar_check_str(filename, *ext_str, *ext_len, executable, for_create TSRMLS_CC)) {
              case SUCCESS:
                     return SUCCESS;
              case FAILURE:
                     /* look for more extensions */
                     pos = strchr(pos + 1, '.');
                     if (pos) {
                            *ext_str = NULL;
                            *ext_len = 0;
                     }
                     goto next_extension;
       }

       return FAILURE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_entry_delref ( phar_entry_data *idata  TSRMLS_DC)

Definition at line 431 of file phar.c.

{
       int ret = 0;

       if (idata->internal_file && !idata->internal_file->is_persistent) {
              if (--idata->internal_file->fp_refcount < 0) {
                     idata->internal_file->fp_refcount = 0;
              }

              if (idata->fp && idata->fp != idata->phar->fp && idata->fp != idata->phar->ufp && idata->fp != idata->internal_file->fp) {
                     php_stream_close(idata->fp);
              }
              /* if phar_get_or_create_entry_data returns a sub-directory, we have to free it */
              if (idata->internal_file->is_temp_dir) {
                     destroy_phar_manifest_entry((void *)idata->internal_file);
                     efree(idata->internal_file);
              }
       }

       phar_archive_delref(idata->phar TSRMLS_CC);
       efree(idata);
       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* phar_find_in_include_path ( char *  file,
int  file_len,
phar_archive_data **pphar  TSRMLS_DC 
)

Definition at line 260 of file util.c.

{
#if PHP_VERSION_ID >= 50300
       char *path, *fname, *arch, *entry, *ret, *test;
       int arch_len, entry_len, fname_len, ret_len;
       phar_archive_data *phar;

       if (pphar) {
              *pphar = NULL;
       } else {
              pphar = &phar;
       }

       if (!zend_is_executing(TSRMLS_C) || !PHAR_G(cwd)) {
              return phar_save_resolve_path(filename, filename_len TSRMLS_CC);
       }

       fname = zend_get_executed_filename(TSRMLS_C);
       fname_len = strlen(fname);

       if (PHAR_G(last_phar) && !memcmp(fname, "phar://", 7) && fname_len - 7 >= PHAR_G(last_phar_name_len) && !memcmp(fname + 7, PHAR_G(last_phar_name), PHAR_G(last_phar_name_len))) {
              arch = estrndup(PHAR_G(last_phar_name), PHAR_G(last_phar_name_len));
              arch_len = PHAR_G(last_phar_name_len);
              phar = PHAR_G(last_phar);
              goto splitted;
       }

       if (fname_len < 7 || memcmp(fname, "phar://", 7) || SUCCESS != phar_split_fname(fname, strlen(fname), &arch, &arch_len, &entry, &entry_len, 1, 0 TSRMLS_CC)) {
              return phar_save_resolve_path(filename, filename_len TSRMLS_CC);
       }

       efree(entry);

       if (*filename == '.') {
              int try_len;

              if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
                     efree(arch);
                     return phar_save_resolve_path(filename, filename_len TSRMLS_CC);
              }
splitted:
              if (pphar) {
                     *pphar = phar;
              }

              try_len = filename_len;
              test = phar_fix_filepath(estrndup(filename, filename_len), &try_len, 1 TSRMLS_CC);

              if (*test == '/') {
                     if (zend_hash_exists(&(phar->manifest), test + 1, try_len - 1)) {
                            spprintf(&ret, 0, "phar://%s%s", arch, test);
                            efree(arch);
                            efree(test);
                            return ret;
                     }
              } else {
                     if (zend_hash_exists(&(phar->manifest), test, try_len)) {
                            spprintf(&ret, 0, "phar://%s/%s", arch, test);
                            efree(arch);
                            efree(test);
                            return ret;
                     }
              }
              efree(test);
       }

       spprintf(&path, MAXPATHLEN, "phar://%s/%s%c%s", arch, PHAR_G(cwd), DEFAULT_DIR_SEPARATOR, PG(include_path));
       efree(arch);
       ret = php_resolve_path(filename, filename_len, path TSRMLS_CC);
       efree(path);

       if (ret && strlen(ret) > 8 && !strncmp(ret, "phar://", 7)) {
              ret_len = strlen(ret);
              /* found phar:// */

              if (SUCCESS != phar_split_fname(ret, ret_len, &arch, &arch_len, &entry, &entry_len, 1, 0 TSRMLS_CC)) {
                     return ret;
              }

              zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar);

              if (!pphar && PHAR_G(manifest_cached)) {
                     zend_hash_find(&cached_phars, arch, arch_len, (void **) &pphar);
              }

              efree(arch);
              efree(entry);
       }

       return ret;
#else /* PHP 5.2 */
       char resolved_path[MAXPATHLEN];
       char trypath[MAXPATHLEN];
       char *ptr, *end, *path = PG(include_path);
       php_stream_wrapper *wrapper;
       const char *p;
       int n = 0;
       char *fname, *arch, *entry, *ret, *test;
       int arch_len, entry_len;
       phar_archive_data *phar = NULL;

       if (!filename) {
              return NULL;
       }

       if (!zend_is_executing(TSRMLS_C) || !PHAR_G(cwd)) {
              goto doit;
       }

       fname = zend_get_executed_filename(TSRMLS_C);

       if (SUCCESS != phar_split_fname(fname, strlen(fname), &arch, &arch_len, &entry, &entry_len, 1, 0 TSRMLS_CC)) {
              goto doit;
       }

       efree(entry);

       if (*filename == '.') {
              int try_len;

              if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
                     efree(arch);
                     goto doit;
              }

              try_len = filename_len;
              test = phar_fix_filepath(estrndup(filename, filename_len), &try_len, 1 TSRMLS_CC);

              if (*test == '/') {
                     if (zend_hash_exists(&(phar->manifest), test + 1, try_len - 1)) {
                            spprintf(&ret, 0, "phar://%s%s", arch, test);
                            efree(arch);
                            efree(test);
                            return ret;
                     }
              } else {
                     if (zend_hash_exists(&(phar->manifest), test, try_len)) {
                            spprintf(&ret, 0, "phar://%s/%s", arch, test);
                            efree(arch);
                            efree(test);
                            return ret;
                     }
              }

              efree(test);
       }

       efree(arch);
doit:
       if (*filename == '.' || IS_ABSOLUTE_PATH(filename, filename_len) || !path || !*path) {
              if (tsrm_realpath(filename, resolved_path TSRMLS_CC)) {
                     return estrdup(resolved_path);
              } else {
                     return NULL;
              }
       }

       /* test for stream wrappers and return */
       for (p = filename; p - filename < filename_len && (isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'); ++p, ++n);

       if (n < filename_len - 3 && (*p == ':') && (!strncmp("//", p+1, 2) || ( filename_len > 4 && !memcmp("data", filename, 4)))) {
              /* found stream wrapper, this is an absolute path until stream wrappers implement realpath */
              return estrndup(filename, filename_len);
       }

       ptr = (char *) path;
       while (ptr && *ptr) {
              int len, is_stream_wrapper = 0, maybe_stream = 1;

              end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
#ifndef PHP_WIN32
              /* search for stream wrapper */
              if (end - ptr  <= 1) {
                     maybe_stream = 0;
                     goto not_stream;
              }

              for (p = ptr, n = 0; p < end && (isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'); ++p, ++n);

              if (n == end - ptr && *p && !strncmp("//", p+1, 2)) {
                     is_stream_wrapper = 1;
                     /* seek to real end of include_path portion */
                     end = strchr(end + 1, DEFAULT_DIR_SEPARATOR);
              } else {
                     maybe_stream = 0;
              }
not_stream:
#endif
              if (end) {
                     if ((end-ptr) + 1 + filename_len + 1 >= MAXPATHLEN) {
                            ptr = end + 1;
                            continue;
                     }

                     memcpy(trypath, ptr, end-ptr);
                     len = end-ptr;
                     trypath[end-ptr] = '/';
                     memcpy(trypath+(end-ptr)+1, filename, filename_len+1);
                     ptr = end+1;
              } else {
                     len = strlen(ptr);

                     if (len + 1 + filename_len + 1 >= MAXPATHLEN) {
                            break;
                     }

                     memcpy(trypath, ptr, len);
                     trypath[len] = '/';
                     memcpy(trypath+len+1, filename, filename_len+1);
                     ptr = NULL;
              }

              if (!is_stream_wrapper && maybe_stream) {
                     /* search for stream wrapper */
                     for (p = trypath, n = 0; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; ++p, ++n);
              }

              if (is_stream_wrapper || (n < len - 3 && (*p == ':') && (n > 1) && (!strncmp("//", p+1, 2) || !memcmp("data", trypath, 4)))) {
                     char *actual;

                     wrapper = php_stream_locate_url_wrapper(trypath, &actual, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);
                     if (wrapper == &php_plain_files_wrapper) {
                            strlcpy(trypath, actual, sizeof(trypath));
                     } else if (!wrapper) {
                            /* if wrapper is NULL, there was a mal-formed include_path stream wrapper, so skip this ptr */
                            continue;
                     } else {
                            if (wrapper->wops->url_stat) {
                                   php_stream_statbuf ssb;

                                   if (SUCCESS == wrapper->wops->url_stat(wrapper, trypath, 0, &ssb, NULL TSRMLS_CC)) {
                                          if (wrapper == &php_stream_phar_wrapper) {
                                                 char *arch, *entry;
                                                 int arch_len, entry_len, ret_len;

                                                 ret_len = strlen(trypath);
                                                 /* found phar:// */

                                                 if (SUCCESS != phar_split_fname(trypath, ret_len, &arch, &arch_len, &entry, &entry_len, 1, 0 TSRMLS_CC)) {
                                                        return estrndup(trypath, ret_len);
                                                 }

                                                 zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar);

                                                 if (!pphar && PHAR_G(manifest_cached)) {
                                                        zend_hash_find(&cached_phars, arch, arch_len, (void **) &pphar);
                                                 }

                                                 efree(arch);
                                                 efree(entry);

                                                 return estrndup(trypath, ret_len);
                                          }
                                          return estrdup(trypath);
                                   }
                            }
                            continue;
                     }
              }

              if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) {
                     return estrdup(resolved_path);
              }
       } /* end provided path */

       /* check in calling scripts' current working directory as a fall back case */
       if (zend_is_executing(TSRMLS_C)) {
              char *exec_fname = zend_get_executed_filename(TSRMLS_C);
              int exec_fname_length = strlen(exec_fname);
              const char *p;
              int n = 0;

              while ((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
              if (exec_fname && exec_fname[0] != '[' && 
                     exec_fname_length > 0 && 
                     exec_fname_length + 1 + filename_len + 1 < MAXPATHLEN) {
                     memcpy(trypath, exec_fname, exec_fname_length + 1);
                     memcpy(trypath+exec_fname_length + 1, filename, filename_len+1);

                     /* search for stream wrapper */
                     for (p = trypath; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; ++p, ++n);

                     if (n < exec_fname_length - 3 && (*p == ':') && (n > 1) && (!strncmp("//", p+1, 2) || !memcmp("data", trypath, 4))) {
                            char *actual;

                            wrapper = php_stream_locate_url_wrapper(trypath, &actual, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);

                            if (wrapper == &php_plain_files_wrapper) {
                                   /* this should never technically happen, but we'll leave it here for completeness */
                                   strlcpy(trypath, actual, sizeof(trypath));
                            } else if (!wrapper) {
                                   /* if wrapper is NULL, there was a malformed include_path stream wrapper
                                      this also should be impossible */
                                   return NULL;
                            } else {
                                   return estrdup(trypath);
                            }
                     }

                     if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) {
                            return estrdup(resolved_path);
                     }
              }
       }

       return NULL;
#endif /* PHP 5.2 */
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* phar_fix_filepath ( char *  path,
int new_len,
int use_cwd  TSRMLS_DC 
)

Remove .

. and . references within a phar filename

Definition at line 2148 of file phar.c.

{
       char newpath[MAXPATHLEN];
       int newpath_len;
       char *ptr;
       char *tok;
       int ptr_length, path_length = *new_len;

       if (PHAR_G(cwd_len) && use_cwd && path_length > 2 && path[0] == '.' && path[1] == '/') {
              newpath_len = PHAR_G(cwd_len);
              memcpy(newpath, PHAR_G(cwd), newpath_len);
       } else {
              newpath[0] = '/';
              newpath_len = 1;
       }

       ptr = path;

       if (*ptr == '/') {
              ++ptr;
       }

       tok = ptr;

       do {
              ptr = memchr(ptr, '/', path_length - (ptr - path));
       } while (ptr && ptr - tok == 0 && *ptr == '/' && ++ptr && ++tok);

       if (!ptr && (path_length - (tok - path))) {
              switch (path_length - (tok - path)) {
                     case 1:
                            if (*tok == '.') {
                                   efree(path);
                                   *new_len = 1;
                                   return estrndup("/", 1);
                            }
                            break;
                     case 2:
                            if (tok[0] == '.' && tok[1] == '.') {
                                   efree(path);
                                   *new_len = 1;
                                   return estrndup("/", 1);
                            }
              }
              return path;
       }

       while (ptr) {
              ptr_length = ptr - tok;
last_time:
              if (IS_DIRECTORY_UP(tok, ptr_length)) {
#define PREVIOUS newpath[newpath_len - 1]

                     while (newpath_len > 1 && !IS_BACKSLASH(PREVIOUS)) {
                            newpath_len--;
                     }

                     if (newpath[0] != '/') {
                            newpath[newpath_len] = '\0';
                     } else if (newpath_len > 1) {
                            --newpath_len;
                     }
              } else if (!IS_DIRECTORY_CURRENT(tok, ptr_length)) {
                     if (newpath_len > 1) {
                            newpath[newpath_len++] = '/';
                            memcpy(newpath + newpath_len, tok, ptr_length+1);
                     } else {
                            memcpy(newpath + newpath_len, tok, ptr_length+1);
                     }

                     newpath_len += ptr_length;
              }

              if (ptr == path + path_length) {
                     break;
              }

              tok = ++ptr;

              do {
                     ptr = memchr(ptr, '/', path_length - (ptr - path));
              } while (ptr && ptr - tok == 0 && *ptr == '/' && ++ptr && ++tok);

              if (!ptr && (path_length - (tok - path))) {
                     ptr_length = path_length - (tok - path);
                     ptr = path + path_length;
                     goto last_time;
              }
       }

       efree(path);
       *new_len = newpath_len;
       return estrndup(newpath, newpath_len);
}

Here is the caller graph for this function:

int phar_flush ( phar_archive_data *  phar,
char *  user_stub,
long  len,
int  convert,
char **error  TSRMLS_DC 
)

Save phar contents to disk.

user_stub contains either a string, or a resource pointer, if len is a negative length. user_stub and len should be both 0 if the default or existing stub should be used

Definition at line 2566 of file phar.c.

{
       char halt_stub[] = "__HALT_COMPILER();";
       char *newstub, *tmp;
       phar_entry_info *entry, *newentry;
       int halt_offset, restore_alias_len, global_flags = 0, closeoldfile;
       char *pos, has_dirs = 0;
       char manifest[18], entry_buffer[24];
       off_t manifest_ftell;
       long offset;
       size_t wrote;
       php_uint32 manifest_len, mytime, loc, new_manifest_count;
       php_uint32 newcrc32;
       php_stream *file, *oldfile, *newfile, *stubfile;
       php_stream_filter *filter;
       php_serialize_data_t metadata_hash;
       smart_str main_metadata_str = {0};
       int free_user_stub, free_fp = 1, free_ufp = 1;

       if (phar->is_persistent) {
              if (error) {
                     spprintf(error, 0, "internal error: attempt to flush cached zip-based phar \"%s\"", phar->fname);
              }
              return EOF;
       }

       if (error) {
              *error = NULL;
       }

       if (!zend_hash_num_elements(&phar->manifest) && !user_stub) {
              return EOF;
       }

       zend_hash_clean(&phar->virtual_dirs);

       if (phar->is_zip) {
              return phar_zip_flush(phar, user_stub, len, convert, error TSRMLS_CC);
       }

       if (phar->is_tar) {
              return phar_tar_flush(phar, user_stub, len, convert, error TSRMLS_CC);
       }

       if (PHAR_G(readonly)) {
              return EOF;
       }

       if (phar->fp && !phar->is_brandnew) {
              oldfile = phar->fp;
              closeoldfile = 0;
              php_stream_rewind(oldfile);
       } else {
              oldfile = php_stream_open_wrapper(phar->fname, "rb", 0, NULL);
              closeoldfile = oldfile != NULL;
       }
       newfile = php_stream_fopen_tmpfile();
       if (!newfile) {
              if (error) {
                     spprintf(error, 0, "unable to create temporary file");
              }
              if (closeoldfile) {
                     php_stream_close(oldfile);
              }
              return EOF;
       }

       if (user_stub) {
              if (len < 0) {
                     /* resource passed in */
                     if (!(php_stream_from_zval_no_verify(stubfile, (zval **)user_stub))) {
                            if (closeoldfile) {
                                   php_stream_close(oldfile);
                            }
                            php_stream_close(newfile);
                            if (error) {
                                   spprintf(error, 0, "unable to access resource to copy stub to new phar \"%s\"", phar->fname);
                            }
                            return EOF;
                     }
                     if (len == -1) {
                            len = PHP_STREAM_COPY_ALL;
                     } else {
                            len = -len;
                     }
                     user_stub = 0;
#if PHP_MAJOR_VERSION >= 6
                     if (!(len = php_stream_copy_to_mem(stubfile, (void **) &user_stub, len, 0)) || !user_stub) {
#else
                     if (!(len = php_stream_copy_to_mem(stubfile, &user_stub, len, 0)) || !user_stub) {
#endif
                            if (closeoldfile) {
                                   php_stream_close(oldfile);
                            }
                            php_stream_close(newfile);
                            if (error) {
                                   spprintf(error, 0, "unable to read resource to copy stub to new phar \"%s\"", phar->fname);
                            }
                            return EOF;
                     }
                     free_user_stub = 1;
              } else {
                     free_user_stub = 0;
              }
              tmp = estrndup(user_stub, len);
              if ((pos = php_stristr(tmp, halt_stub, len, sizeof(halt_stub) - 1)) == NULL) {
                     efree(tmp);
                     if (closeoldfile) {
                            php_stream_close(oldfile);
                     }
                     php_stream_close(newfile);
                     if (error) {
                            spprintf(error, 0, "illegal stub for phar \"%s\"", phar->fname);
                     }
                     if (free_user_stub) {
                            efree(user_stub);
                     }
                     return EOF;
              }
              pos = user_stub + (pos - tmp);
              efree(tmp);
              len = pos - user_stub + 18;
              if ((size_t)len != php_stream_write(newfile, user_stub, len)
              ||                     5 != php_stream_write(newfile, " ?>\r\n", 5)) {
                     if (closeoldfile) {
                            php_stream_close(oldfile);
                     }
                     php_stream_close(newfile);
                     if (error) {
                            spprintf(error, 0, "unable to create stub from string in new phar \"%s\"", phar->fname);
                     }
                     if (free_user_stub) {
                            efree(user_stub);
                     }
                     return EOF;
              }
              phar->halt_offset = len + 5;
              if (free_user_stub) {
                     efree(user_stub);
              }
       } else {
              size_t written;

              if (!user_stub && phar->halt_offset && oldfile && !phar->is_brandnew) {
                     phar_stream_copy_to_stream(oldfile, newfile, phar->halt_offset, &written);
                     newstub = NULL;
              } else {
                     /* this is either a brand new phar or a default stub overwrite */
                     newstub = phar_create_default_stub(NULL, NULL, &(phar->halt_offset), NULL TSRMLS_CC);
                     written = php_stream_write(newfile, newstub, phar->halt_offset);
              }
              if (phar->halt_offset != written) {
                     if (closeoldfile) {
                            php_stream_close(oldfile);
                     }
                     php_stream_close(newfile);
                     if (error) {
                            if (newstub) {
                                   spprintf(error, 0, "unable to create stub in new phar \"%s\"", phar->fname);
                            } else {
                                   spprintf(error, 0, "unable to copy stub of old phar to new phar \"%s\"", phar->fname);
                            }
                     }
                     if (newstub) {
                            efree(newstub);
                     }
                     return EOF;
              }
              if (newstub) {
                     efree(newstub);
              }
       }
       manifest_ftell = php_stream_tell(newfile);
       halt_offset = manifest_ftell;

       /* Check whether we can get rid of some of the deleted entries which are
        * unused. However some might still be in use so even after this clean-up
        * we need to skip entries marked is_deleted. */
       zend_hash_apply(&phar->manifest, phar_flush_clean_deleted_apply TSRMLS_CC);

       /* compress as necessary, calculate crcs, serialize meta-data, manifest size, and file sizes */
       main_metadata_str.c = 0;
       if (phar->metadata) {
              PHP_VAR_SERIALIZE_INIT(metadata_hash);
              php_var_serialize(&main_metadata_str, &phar->metadata, &metadata_hash TSRMLS_CC);
              PHP_VAR_SERIALIZE_DESTROY(metadata_hash);
       } else {
              main_metadata_str.len = 0;
       }
       new_manifest_count = 0;
       offset = 0;
       for (zend_hash_internal_pointer_reset(&phar->manifest);
              zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
              zend_hash_move_forward(&phar->manifest)) {
              if (zend_hash_get_current_data(&phar->manifest, (void **)&entry) == FAILURE) {
                     continue;
              }
              if (entry->cfp) {
                     /* did we forget to get rid of cfp last time? */
                     php_stream_close(entry->cfp);
                     entry->cfp = 0;
              }
              if (entry->is_deleted || entry->is_mounted) {
                     /* remove this from the new phar */
                     continue;
              }
              if (!entry->is_modified && entry->fp_refcount) {
                     /* open file pointers refer to this fp, do not free the stream */
                     switch (entry->fp_type) {
                            case PHAR_FP:
                                   free_fp = 0;
                                   break;
                            case PHAR_UFP:
                                   free_ufp = 0;
                            default:
                                   break;
                     }
              }
              /* after excluding deleted files, calculate manifest size in bytes and number of entries */
              ++new_manifest_count;
              phar_add_virtual_dirs(phar, entry->filename, entry->filename_len TSRMLS_CC);

              if (entry->is_dir) {
                     /* we use this to calculate API version, 1.1.1 is used for phars with directories */
                     has_dirs = 1;
              }
              if (entry->metadata) {
                     if (entry->metadata_str.c) {
                            smart_str_free(&entry->metadata_str);
                     }
                     entry->metadata_str.c = 0;
                     entry->metadata_str.len = 0;
                     PHP_VAR_SERIALIZE_INIT(metadata_hash);
                     php_var_serialize(&entry->metadata_str, &entry->metadata, &metadata_hash TSRMLS_CC);
                     PHP_VAR_SERIALIZE_DESTROY(metadata_hash);
              } else {
                     if (entry->metadata_str.c) {
                            smart_str_free(&entry->metadata_str);
                     }
                     entry->metadata_str.c = 0;
                     entry->metadata_str.len = 0;
              }

              /* 32 bits for filename length, length of filename, manifest + metadata, and add 1 for trailing / if a directory */
              offset += 4 + entry->filename_len + sizeof(entry_buffer) + entry->metadata_str.len + (entry->is_dir ? 1 : 0);

              /* compress and rehash as necessary */
              if ((oldfile && !entry->is_modified) || entry->is_dir) {
                     if (entry->fp_type == PHAR_UFP) {
                            /* reset so we can copy the compressed data over */
                            entry->fp_type = PHAR_FP;
                     }
                     continue;
              }
              if (!phar_get_efp(entry, 0 TSRMLS_CC)) {
                     /* re-open internal file pointer just-in-time */
                     newentry = phar_open_jit(phar, entry, error TSRMLS_CC);
                     if (!newentry) {
                            /* major problem re-opening, so we ignore this file and the error */
                            efree(*error);
                            *error = NULL;
                            continue;
                     }
                     entry = newentry;
              }
              file = phar_get_efp(entry, 0 TSRMLS_CC);
              if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 1 TSRMLS_CC)) {
                     if (closeoldfile) {
                            php_stream_close(oldfile);
                     }
                     php_stream_close(newfile);
                     if (error) {
                            spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname);
                     }
                     return EOF;
              }
              newcrc32 = ~0;
              mytime = entry->uncompressed_filesize;
              for (loc = 0;loc < mytime; ++loc) {
                     CRC32(newcrc32, php_stream_getc(file));
              }
              entry->crc32 = ~newcrc32;
              entry->is_crc_checked = 1;
              if (!(entry->flags & PHAR_ENT_COMPRESSION_MASK)) {
                     /* not compressed */
                     entry->compressed_filesize = entry->uncompressed_filesize;
                     continue;
              }
              filter = php_stream_filter_create(phar_compress_filter(entry, 0), NULL, 0 TSRMLS_CC);
              if (!filter) {
                     if (closeoldfile) {
                            php_stream_close(oldfile);
                     }
                     php_stream_close(newfile);
                     if (entry->flags & PHAR_ENT_COMPRESSED_GZ) {
                            if (error) {
                                   spprintf(error, 0, "unable to gzip compress file \"%s\" to new phar \"%s\"", entry->filename, phar->fname);
                            }
                     } else {
                            if (error) {
                                   spprintf(error, 0, "unable to bzip2 compress file \"%s\" to new phar \"%s\"", entry->filename, phar->fname);
                            }
                     }
                     return EOF;
              }

              /* create new file that holds the compressed version */
              /* work around inability to specify freedom in write and strictness
              in read count */
              entry->cfp = php_stream_fopen_tmpfile();
              if (!entry->cfp) {
                     if (error) {
                            spprintf(error, 0, "unable to create temporary file");
                     }
                     if (closeoldfile) {
                            php_stream_close(oldfile);
                     }
                     php_stream_close(newfile);
                     return EOF;
              }
              php_stream_flush(file);
              if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0 TSRMLS_CC)) {
                     if (closeoldfile) {
                            php_stream_close(oldfile);
                     }
                     php_stream_close(newfile);
                     if (error) {
                            spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname);
                     }
                     return EOF;
              }
              php_stream_filter_append((&entry->cfp->writefilters), filter);
              if (SUCCESS != phar_stream_copy_to_stream(file, entry->cfp, entry->uncompressed_filesize, NULL)) {
                     if (closeoldfile) {
                            php_stream_close(oldfile);
                     }
                     php_stream_close(newfile);
                     if (error) {
                            spprintf(error, 0, "unable to copy compressed file contents of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname);
                     }
                     return EOF;
              }
              php_stream_filter_flush(filter, 1);
              php_stream_flush(entry->cfp);
              php_stream_filter_remove(filter, 1 TSRMLS_CC);
              php_stream_seek(entry->cfp, 0, SEEK_END);
              entry->compressed_filesize = (php_uint32) php_stream_tell(entry->cfp);
              /* generate crc on compressed file */
              php_stream_rewind(entry->cfp);
              entry->old_flags = entry->flags;
              entry->is_modified = 1;
              global_flags |= (entry->flags & PHAR_ENT_COMPRESSION_MASK);
       }
       global_flags |= PHAR_HDR_SIGNATURE;

       /* write out manifest pre-header */
       /*  4: manifest length
        *  4: manifest entry count
        *  2: phar version
        *  4: phar global flags
        *  4: alias length
        *  ?: the alias itself
        *  4: phar metadata length
        *  ?: phar metadata
        */
       restore_alias_len = phar->alias_len;
       if (phar->is_temporary_alias) {
              phar->alias_len = 0;
       }

       manifest_len = offset + phar->alias_len + sizeof(manifest) + main_metadata_str.len;
       phar_set_32(manifest, manifest_len);
       phar_set_32(manifest+4, new_manifest_count);
       if (has_dirs) {
              *(manifest + 8) = (unsigned char) (((PHAR_API_VERSION) >> 8) & 0xFF);
              *(manifest + 9) = (unsigned char) (((PHAR_API_VERSION) & 0xF0));
       } else {
              *(manifest + 8) = (unsigned char) (((PHAR_API_VERSION_NODIR) >> 8) & 0xFF);
              *(manifest + 9) = (unsigned char) (((PHAR_API_VERSION_NODIR) & 0xF0));
       }
       phar_set_32(manifest+10, global_flags);
       phar_set_32(manifest+14, phar->alias_len);

       /* write the manifest header */
       if (sizeof(manifest) != php_stream_write(newfile, manifest, sizeof(manifest))
       || (size_t)phar->alias_len != php_stream_write(newfile, phar->alias, phar->alias_len)) {

              if (closeoldfile) {
                     php_stream_close(oldfile);
              }

              php_stream_close(newfile);
              phar->alias_len = restore_alias_len;

              if (error) {
                     spprintf(error, 0, "unable to write manifest header of new phar \"%s\"", phar->fname);
              }

              return EOF;
       }

       phar->alias_len = restore_alias_len;

       phar_set_32(manifest, main_metadata_str.len);
       if (4 != php_stream_write(newfile, manifest, 4) || (main_metadata_str.len
       && main_metadata_str.len != php_stream_write(newfile, main_metadata_str.c, main_metadata_str.len))) {
              smart_str_free(&main_metadata_str);

              if (closeoldfile) {
                     php_stream_close(oldfile);
              }

              php_stream_close(newfile);
              phar->alias_len = restore_alias_len;

              if (error) {
                     spprintf(error, 0, "unable to write manifest meta-data of new phar \"%s\"", phar->fname);
              }

              return EOF;
       }
       smart_str_free(&main_metadata_str);

       /* re-calculate the manifest location to simplify later code */
       manifest_ftell = php_stream_tell(newfile);

       /* now write the manifest */
       for (zend_hash_internal_pointer_reset(&phar->manifest);
              zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
              zend_hash_move_forward(&phar->manifest)) {

              if (zend_hash_get_current_data(&phar->manifest, (void **)&entry) == FAILURE) {
                     continue;
              }

              if (entry->is_deleted || entry->is_mounted) {
                     /* remove this from the new phar if deleted, ignore if mounted */
                     continue;
              }

              if (entry->is_dir) {
                     /* add 1 for trailing slash */
                     phar_set_32(entry_buffer, entry->filename_len + 1);
              } else {
                     phar_set_32(entry_buffer, entry->filename_len);
              }

              if (4 != php_stream_write(newfile, entry_buffer, 4)
              || entry->filename_len != php_stream_write(newfile, entry->filename, entry->filename_len)
              || (entry->is_dir && 1 != php_stream_write(newfile, "/", 1))) {
                     if (closeoldfile) {
                            php_stream_close(oldfile);
                     }
                     php_stream_close(newfile);
                     if (error) {
                            if (entry->is_dir) {
                                   spprintf(error, 0, "unable to write filename of directory \"%s\" to manifest of new phar \"%s\"", entry->filename, phar->fname);
                            } else {
                                   spprintf(error, 0, "unable to write filename of file \"%s\" to manifest of new phar \"%s\"", entry->filename, phar->fname);
                            }
                     }
                     return EOF;
              }

              /* set the manifest meta-data:
                     4: uncompressed filesize
                     4: creation timestamp
                     4: compressed filesize
                     4: crc32
                     4: flags
                     4: metadata-len
                     +: metadata
              */
              mytime = time(NULL);
              phar_set_32(entry_buffer, entry->uncompressed_filesize);
              phar_set_32(entry_buffer+4, mytime);
              phar_set_32(entry_buffer+8, entry->compressed_filesize);
              phar_set_32(entry_buffer+12, entry->crc32);
              phar_set_32(entry_buffer+16, entry->flags);
              phar_set_32(entry_buffer+20, entry->metadata_str.len);

              if (sizeof(entry_buffer) != php_stream_write(newfile, entry_buffer, sizeof(entry_buffer))
              || entry->metadata_str.len != php_stream_write(newfile, entry->metadata_str.c, entry->metadata_str.len)) {
                     if (closeoldfile) {
                            php_stream_close(oldfile);
                     }

                     php_stream_close(newfile);

                     if (error) {
                            spprintf(error, 0, "unable to write temporary manifest of file \"%s\" to manifest of new phar \"%s\"", entry->filename, phar->fname);
                     }

                     return EOF;
              }
       }

       /* now copy the actual file data to the new phar */
       offset = php_stream_tell(newfile);
       for (zend_hash_internal_pointer_reset(&phar->manifest);
              zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
              zend_hash_move_forward(&phar->manifest)) {

              if (zend_hash_get_current_data(&phar->manifest, (void **)&entry) == FAILURE) {
                     continue;
              }

              if (entry->is_deleted || entry->is_dir || entry->is_mounted) {
                     continue;
              }

              if (entry->cfp) {
                     file = entry->cfp;
                     php_stream_rewind(file);
              } else {
                     file = phar_get_efp(entry, 0 TSRMLS_CC);
                     if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0 TSRMLS_CC)) {
                            if (closeoldfile) {
                                   php_stream_close(oldfile);
                            }
                            php_stream_close(newfile);
                            if (error) {
                                   spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname);
                            }
                            return EOF;
                     }
              }

              if (!file) {
                     if (closeoldfile) {
                            php_stream_close(oldfile);
                     }
                     php_stream_close(newfile);
                     if (error) {
                            spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname);
                     }
                     return EOF;
              }

              /* this will have changed for all files that have either changed compression or been modified */
              entry->offset = entry->offset_abs = offset;
              offset += entry->compressed_filesize;
              if (phar_stream_copy_to_stream(file, newfile, entry->compressed_filesize, &wrote) == FAILURE) {
                     if (closeoldfile) {
                            php_stream_close(oldfile);
                     }

                     php_stream_close(newfile);

                     if (error) {
                            spprintf(error, 0, "unable to write contents of file \"%s\" to new phar \"%s\"", entry->filename, phar->fname);
                     }

                     return EOF;
              }

              entry->is_modified = 0;

              if (entry->cfp) {
                     php_stream_close(entry->cfp);
                     entry->cfp = NULL;
              }

              if (entry->fp_type == PHAR_MOD) {
                     /* this fp is in use by a phar_entry_data returned by phar_get_entry_data, it will be closed when the phar_entry_data is phar_entry_delref'ed */
                     if (entry->fp_refcount == 0 && entry->fp != phar->fp && entry->fp != phar->ufp) {
                            php_stream_close(entry->fp);
                     }

                     entry->fp = NULL;
                     entry->fp_type = PHAR_FP;
              } else if (entry->fp_type == PHAR_UFP) {
                     entry->fp_type = PHAR_FP;
              }
       }

       /* append signature */
       if (global_flags & PHAR_HDR_SIGNATURE) {
              char sig_buf[4];

              php_stream_rewind(newfile);

              if (phar->signature) {
                     efree(phar->signature);
                     phar->signature = NULL;
              }

              switch(phar->sig_flags) {
#ifndef PHAR_HASH_OK
                     case PHAR_SIG_SHA512:
                     case PHAR_SIG_SHA256:
                            if (closeoldfile) {
                                   php_stream_close(oldfile);
                            }
                            php_stream_close(newfile);
                            if (error) {
                                   spprintf(error, 0, "unable to write contents of file \"%s\" to new phar \"%s\" with requested hash type", entry->filename, phar->fname);
                            }
                            return EOF;
#endif
                     default: {
                            char *digest = NULL;
                            int digest_len;

                            if (FAILURE == phar_create_signature(phar, newfile, &digest, &digest_len, error TSRMLS_CC)) {
                                   if (error) {
                                          char *save = *error;
                                          spprintf(error, 0, "phar error: unable to write signature: %s", save);
                                          efree(save);
                                   }
                                   if (digest) {
                                          efree(digest);
                                   }
                                   if (closeoldfile) {
                                          php_stream_close(oldfile);
                                   }
                                   php_stream_close(newfile);
                                   return EOF;
                            }

                            php_stream_write(newfile, digest, digest_len);
                            efree(digest);
                            if (phar->sig_flags == PHAR_SIG_OPENSSL) {
                                   phar_set_32(sig_buf, digest_len);
                                   php_stream_write(newfile, sig_buf, 4);
                            }
                            break;
                     }
              }
              phar_set_32(sig_buf, phar->sig_flags);
              php_stream_write(newfile, sig_buf, 4);
              php_stream_write(newfile, "GBMB", 4);
       }

       /* finally, close the temp file, rename the original phar,
          move the temp to the old phar, unlink the old phar, and reload it into memory
       */
       if (phar->fp && free_fp) {
              php_stream_close(phar->fp);
       }

       if (phar->ufp) {
              if (free_ufp) {
                     php_stream_close(phar->ufp);
              }
              phar->ufp = NULL;
       }

       if (closeoldfile) {
              php_stream_close(oldfile);
       }

       phar->internal_file_start = halt_offset + manifest_len + 4;
       phar->halt_offset = halt_offset;
       phar->is_brandnew = 0;

       php_stream_rewind(newfile);

       if (phar->donotflush) {
              /* deferred flush */
              phar->fp = newfile;
       } else {
              phar->fp = php_stream_open_wrapper(phar->fname, "w+b", IGNORE_URL|STREAM_MUST_SEEK|REPORT_ERRORS, NULL);
              if (!phar->fp) {
                     phar->fp = newfile;
                     if (error) {
                            spprintf(error, 4096, "unable to open new phar \"%s\" for writing", phar->fname);
                     }
                     return EOF;
              }

              if (phar->flags & PHAR_FILE_COMPRESSED_GZ) {
                     /* to properly compress, we have to tell zlib to add a zlib header */
                     zval filterparams;

                     array_init(&filterparams);
                     add_assoc_long(&filterparams, "window", MAX_WBITS+16);
                     filter = php_stream_filter_create("zlib.deflate", &filterparams, php_stream_is_persistent(phar->fp) TSRMLS_CC);
                     zval_dtor(&filterparams);

                     if (!filter) {
                            if (error) {
                                   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);
                            }
                            return EOF;
                     }

                     php_stream_filter_append(&phar->fp->writefilters, filter);
                     phar_stream_copy_to_stream(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL);
                     php_stream_filter_flush(filter, 1);
                     php_stream_filter_remove(filter, 1 TSRMLS_CC);
                     php_stream_close(phar->fp);
                     /* use the temp stream as our base */
                     phar->fp = newfile;
              } else if (phar->flags & PHAR_FILE_COMPRESSED_BZ2) {
                     filter = php_stream_filter_create("bzip2.compress", NULL, php_stream_is_persistent(phar->fp) TSRMLS_CC);
                     php_stream_filter_append(&phar->fp->writefilters, filter);
                     phar_stream_copy_to_stream(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL);
                     php_stream_filter_flush(filter, 1);
                     php_stream_filter_remove(filter, 1 TSRMLS_CC);
                     php_stream_close(phar->fp);
                     /* use the temp stream as our base */
                     phar->fp = newfile;
              } else {
                     phar_stream_copy_to_stream(newfile, phar->fp, PHP_STREAM_COPY_ALL, NULL);
                     /* we could also reopen the file in "rb" mode but there is no need for that */
                     php_stream_close(newfile);
              }
       }

       if (-1 == php_stream_seek(phar->fp, phar->halt_offset, SEEK_SET)) {
              if (error) {
                     spprintf(error, 0, "unable to seek to __HALT_COMPILER(); in new phar \"%s\"", phar->fname);
              }
              return EOF;
       }

       return EOF;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_free_alias ( phar_archive_data *  phar,
char *  alias,
int alias_len  TSRMLS_DC 
)

Definition at line 1183 of file util.c.

{
       if (phar->refcount || phar->is_persistent) {
              return FAILURE;
       }

       /* this archive has no open references, so emit an E_STRICT and remove it */
       if (zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), phar->fname, phar->fname_len) != SUCCESS) {
              return FAILURE;
       }

       /* invalidate phar cache */
       PHAR_G(last_phar) = NULL;
       PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;

       return SUCCESS;
}

Here is the caller graph for this function:

int phar_get_archive ( phar_archive_data **  archive,
char *  fname,
int  fname_len,
char *  alias,
int  alias_len,
char **error  TSRMLS_DC 
)

Looks up a phar archive in the filename map, connecting it to the alias (if any) or returns null.

Definition at line 1206 of file util.c.

{
       phar_archive_data *fd, **fd_ptr;
       char *my_realpath, *save;
       int save_len;
       ulong fhash, ahash = 0;

       phar_request_initialize(TSRMLS_C);

       if (error) {
              *error = NULL;
       }

       *archive = NULL;

       if (PHAR_G(last_phar) && fname_len == PHAR_G(last_phar_name_len) && !memcmp(fname, PHAR_G(last_phar_name), fname_len)) {
              *archive = PHAR_G(last_phar);
              if (alias && alias_len) {

                     if (!PHAR_G(last_phar)->is_temporary_alias && (alias_len != PHAR_G(last_phar)->alias_len || memcmp(PHAR_G(last_phar)->alias, alias, alias_len))) {
                            if (error) {
                                   spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, PHAR_G(last_phar)->fname, fname);
                            }
                            *archive = NULL;
                            return FAILURE;
                     }

                     if (PHAR_G(last_phar)->alias_len && SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), PHAR_G(last_phar)->alias, PHAR_G(last_phar)->alias_len, (void**)&fd_ptr)) {
                            zend_hash_del(&(PHAR_GLOBALS->phar_alias_map), PHAR_G(last_phar)->alias, PHAR_G(last_phar)->alias_len);
                     }

                     zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&(*archive), sizeof(phar_archive_data*), NULL);
                     PHAR_G(last_alias) = alias;
                     PHAR_G(last_alias_len) = alias_len;
              }

              return SUCCESS;
       }

       if (alias && alias_len && PHAR_G(last_phar) && alias_len == PHAR_G(last_alias_len) && !memcmp(alias, PHAR_G(last_alias), alias_len)) {
              fd = PHAR_G(last_phar);
              fd_ptr = &fd;
              goto alias_success;
       }

       if (alias && alias_len) {
              ahash = zend_inline_hash_func(alias, alias_len);
              if (SUCCESS == zend_hash_quick_find(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, ahash, (void**)&fd_ptr)) {
alias_success:
                     if (fname && (fname_len != (*fd_ptr)->fname_len || strncmp(fname, (*fd_ptr)->fname, fname_len))) {
                            if (error) {
                                   spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, (*fd_ptr)->fname, fname);
                            }
                            if (SUCCESS == phar_free_alias(*fd_ptr, alias, alias_len TSRMLS_CC)) {
                                   efree(*error);
                                   *error = NULL;
                            }
                            return FAILURE;
                     }

                     *archive = *fd_ptr;
                     fd = *fd_ptr;
                     PHAR_G(last_phar) = fd;
                     PHAR_G(last_phar_name) = fd->fname;
                     PHAR_G(last_phar_name_len) = fd->fname_len;
                     PHAR_G(last_alias) = alias;
                     PHAR_G(last_alias_len) = alias_len;

                     return SUCCESS;
              }

              if (PHAR_G(manifest_cached) && SUCCESS == zend_hash_quick_find(&cached_alias, alias, alias_len, ahash, (void **)&fd_ptr)) {
                     goto alias_success;
              }
       }

       fhash = zend_inline_hash_func(fname, fname_len);
       my_realpath = NULL;
       save = fname;
       save_len = fname_len;

       if (fname && fname_len) {
              if (SUCCESS == zend_hash_quick_find(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, fhash, (void**)&fd_ptr)) {
                     *archive = *fd_ptr;
                     fd = *fd_ptr;

                     if (alias && alias_len) {
                            if (!fd->is_temporary_alias && (alias_len != fd->alias_len || memcmp(fd->alias, alias, alias_len))) {
                                   if (error) {
                                          spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, (*fd_ptr)->fname, fname);
                                   }
                                   return FAILURE;
                            }

                            if (fd->alias_len && SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), fd->alias, fd->alias_len, (void**)&fd_ptr)) {
                                   zend_hash_del(&(PHAR_GLOBALS->phar_alias_map), fd->alias, fd->alias_len);
                            }

                            zend_hash_quick_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, ahash, (void*)&fd, sizeof(phar_archive_data*), NULL);
                     }

                     PHAR_G(last_phar) = fd;
                     PHAR_G(last_phar_name) = fd->fname;
                     PHAR_G(last_phar_name_len) = fd->fname_len;
                     PHAR_G(last_alias) = fd->alias;
                     PHAR_G(last_alias_len) = fd->alias_len;

                     return SUCCESS;
              }

              if (PHAR_G(manifest_cached) && SUCCESS == zend_hash_quick_find(&cached_phars, fname, fname_len, fhash, (void**)&fd_ptr)) {
                     *archive = *fd_ptr;
                     fd = *fd_ptr;

                     /* this could be problematic - alias should never be different from manifest alias
                        for cached phars */
                     if (!fd->is_temporary_alias && alias && alias_len) {
                            if (alias_len != fd->alias_len || memcmp(fd->alias, alias, alias_len)) {
                                   if (error) {
                                          spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, (*fd_ptr)->fname, fname);
                                   }
                                   return FAILURE;
                            }
                     }

                     PHAR_G(last_phar) = fd;
                     PHAR_G(last_phar_name) = fd->fname;
                     PHAR_G(last_phar_name_len) = fd->fname_len;
                     PHAR_G(last_alias) = fd->alias;
                     PHAR_G(last_alias_len) = fd->alias_len;

                     return SUCCESS;
              }

              if (SUCCESS == zend_hash_quick_find(&(PHAR_GLOBALS->phar_alias_map), save, save_len, fhash, (void**)&fd_ptr)) {
                     fd = *archive = *fd_ptr;

                     PHAR_G(last_phar) = fd;
                     PHAR_G(last_phar_name) = fd->fname;
                     PHAR_G(last_phar_name_len) = fd->fname_len;
                     PHAR_G(last_alias) = fd->alias;
                     PHAR_G(last_alias_len) = fd->alias_len;

                     return SUCCESS;
              }

              if (PHAR_G(manifest_cached) && SUCCESS == zend_hash_quick_find(&cached_alias, save, save_len, fhash, (void**)&fd_ptr)) {
                     fd = *archive = *fd_ptr;

                     PHAR_G(last_phar) = fd;
                     PHAR_G(last_phar_name) = fd->fname;
                     PHAR_G(last_phar_name_len) = fd->fname_len;
                     PHAR_G(last_alias) = fd->alias;
                     PHAR_G(last_alias_len) = fd->alias_len;

                     return SUCCESS;
              }

              /* not found, try converting \ to / */
              my_realpath = expand_filepath(fname, my_realpath TSRMLS_CC);

              if (my_realpath) {
                     fname_len = strlen(my_realpath);
                     fname = my_realpath;
              } else {
                     return FAILURE;
              }
#ifdef PHP_WIN32
              phar_unixify_path_separators(fname, fname_len);
#endif
              fhash = zend_inline_hash_func(fname, fname_len);

              if (SUCCESS == zend_hash_quick_find(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, fhash, (void**)&fd_ptr)) {
realpath_success:
                     *archive = *fd_ptr;
                     fd = *fd_ptr;

                     if (alias && alias_len) {
                            zend_hash_quick_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, ahash, (void*)&fd, sizeof(phar_archive_data*), NULL);
                     }

                     efree(my_realpath);

                     PHAR_G(last_phar) = fd;
                     PHAR_G(last_phar_name) = fd->fname;
                     PHAR_G(last_phar_name_len) = fd->fname_len;
                     PHAR_G(last_alias) = fd->alias;
                     PHAR_G(last_alias_len) = fd->alias_len;

                     return SUCCESS;
              }

              if (PHAR_G(manifest_cached) && SUCCESS == zend_hash_quick_find(&cached_phars, fname, fname_len, fhash, (void**)&fd_ptr)) {
                     goto realpath_success;
              }

              efree(my_realpath);
       }

       return FAILURE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

php_stream* phar_get_efp ( phar_entry_info entry,
int follow_links  TSRMLS_DC 
)

Definition at line 94 of file util.c.

{
       if (follow_links && entry->link) {
              phar_entry_info *link_entry = phar_get_link_source(entry TSRMLS_CC);

              if (link_entry && link_entry != entry) {
                     return phar_get_efp(link_entry, 1 TSRMLS_CC);
              }
       }

       if (phar_get_fp_type(entry TSRMLS_CC) == PHAR_FP) {
              if (!phar_get_entrypfp(entry TSRMLS_CC)) {
                     /* re-open just in time for cases where our refcount reached 0 on the phar archive */
                     phar_open_archive_fp(entry->phar TSRMLS_CC);
              }
              return phar_get_entrypfp(entry TSRMLS_CC);
       } else if (phar_get_fp_type(entry TSRMLS_CC) == PHAR_UFP) {
              return phar_get_entrypufp(entry TSRMLS_CC);
       } else if (entry->fp_type == PHAR_MOD) {
              return entry->fp;
       } else {
              /* temporary manifest entry */
              if (!entry->fp) {
                     entry->fp = php_stream_open_wrapper(entry->tmp, "rb", STREAM_MUST_SEEK|0, NULL);
              }
              return entry->fp;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_get_entry_data ( phar_entry_data **  ret,
char *  fname,
int  fname_len,
char *  path,
int  path_len,
char *  mode,
char  allow_dir,
char **  error,
int security  TSRMLS_DC 
)

Retrieve a copy of the file information on a single file within a phar, or null.

This also transfers the open file pointer, if any, to the entry.

If the file does not already exist, this will fail. Pre-existing files can be appended, truncated, or read. For read, if the entry is marked unmodified, it is assumed that the file pointer, if present, is opened for reading

Definition at line 578 of file util.c.

{
       phar_archive_data *phar;
       phar_entry_info *entry;
       int for_write  = mode[0] != 'r' || mode[1] == '+';
       int for_append = mode[0] == 'a';
       int for_create = mode[0] != 'r';
       int for_trunc  = mode[0] == 'w';

       if (!ret) {
              return FAILURE;
       }

       *ret = NULL;

       if (error) {
              *error = NULL;
       }

       if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error TSRMLS_CC)) {
              return FAILURE;
       }

       if (for_write && PHAR_G(readonly) && !phar->is_data) {
              if (error) {
                     spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, disabled by ini setting", path, fname);
              }
              return FAILURE;
       }

       if (!path_len) {
              if (error) {
                     spprintf(error, 4096, "phar error: file \"\" in phar \"%s\" cannot be empty", fname);
              }
              return FAILURE;
       }
really_get_entry:
       if (allow_dir) {
              if ((entry = phar_get_entry_info_dir(phar, path, path_len, allow_dir, for_create && !PHAR_G(readonly) && !phar->is_data ? NULL : error, security TSRMLS_CC)) == NULL) {
                     if (for_create && (!PHAR_G(readonly) || phar->is_data)) {
                            return SUCCESS;
                     }
                     return FAILURE;
              }
       } else {
              if ((entry = phar_get_entry_info(phar, path, path_len, for_create && !PHAR_G(readonly) && !phar->is_data ? NULL : error, security TSRMLS_CC)) == NULL) {
                     if (for_create && (!PHAR_G(readonly) || phar->is_data)) {
                            return SUCCESS;
                     }
                     return FAILURE;
              }
       }

       if (for_write && phar->is_persistent) {
              if (FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
                     if (error) {
                            spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, could not make cached phar writeable", path, fname);
                     }
                     return FAILURE;
              } else {
                     goto really_get_entry;
              }
       }

       if (entry->is_modified && !for_write) {
              if (error) {
                     spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for reading, writable file pointers are open", path, fname);
              }
              return FAILURE;
       }

       if (entry->fp_refcount && for_write) {
              if (error) {
                     spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be opened for writing, readable file pointers are open", path, fname);
              }
              return FAILURE;
       }

       if (entry->is_deleted) {
              if (!for_create) {
                     return FAILURE;
              }
              entry->is_deleted = 0;
       }

       if (entry->is_dir) {
              *ret = (phar_entry_data *) emalloc(sizeof(phar_entry_data));
              (*ret)->position = 0;
              (*ret)->fp = NULL;
              (*ret)->phar = phar;
              (*ret)->for_write = for_write;
              (*ret)->internal_file = entry;
              (*ret)->is_zip = entry->is_zip;
              (*ret)->is_tar = entry->is_tar;

              if (!phar->is_persistent) {
                     ++(entry->phar->refcount);
                     ++(entry->fp_refcount);
              }

              return SUCCESS;
       }

       if (entry->fp_type == PHAR_MOD) {
              if (for_trunc) {
                     if (FAILURE == phar_create_writeable_entry(phar, entry, error TSRMLS_CC)) {
                            return FAILURE;
                     }
              } else if (for_append) {
                     phar_seek_efp(entry, 0, SEEK_END, 0, 0 TSRMLS_CC);
              }
       } else {
              if (for_write) {
                     if (entry->link) {
                            efree(entry->link);
                            entry->link = NULL;
                            entry->tar_type = (entry->is_tar ? TAR_FILE : '\0');
                     }

                     if (for_trunc) {
                            if (FAILURE == phar_create_writeable_entry(phar, entry, error TSRMLS_CC)) {
                                   return FAILURE;
                            }
                     } else {
                            if (FAILURE == phar_separate_entry_fp(entry, error TSRMLS_CC)) {
                                   return FAILURE;
                            }
                     }
              } else {
                     if (FAILURE == phar_open_entry_fp(entry, error, 1 TSRMLS_CC)) {
                            return FAILURE;
                     }
              }
       }

       *ret = (phar_entry_data *) emalloc(sizeof(phar_entry_data));
       (*ret)->position = 0;
       (*ret)->phar = phar;
       (*ret)->for_write = for_write;
       (*ret)->internal_file = entry;
       (*ret)->is_zip = entry->is_zip;
       (*ret)->is_tar = entry->is_tar;
       (*ret)->fp = phar_get_efp(entry, 1 TSRMLS_CC);
       if (entry->link) {
              (*ret)->zero = phar_get_fp_offset(phar_get_link_source(entry TSRMLS_CC) TSRMLS_CC);
       } else {
              (*ret)->zero = phar_get_fp_offset(entry TSRMLS_CC);
       }

       if (!phar->is_persistent) {
              ++(entry->fp_refcount);
              ++(entry->phar->refcount);
       }

       return SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

phar_entry_info* phar_get_entry_info ( phar_archive_data *  phar,
char *  path,
int  path_len,
char **  error,
int security  TSRMLS_DC 
)

retrieve information on a file contained within a phar, or null if it ain't there

Definition at line 1452 of file util.c.

{
       return phar_get_entry_info_dir(phar, path, path_len, 0, error, security TSRMLS_CC);
}

Here is the call graph for this function:

Here is the caller graph for this function:

phar_entry_info* phar_get_entry_info_dir ( phar_archive_data *  phar,
char *  path,
int  path_len,
char  dir,
char **  error,
int security  TSRMLS_DC 
)

retrieve information on a file or directory contained within a phar, or null if none found allow_dir is 0 for none, 1 for both empty directories in the phar and temp directories, and 2 for only valid pre-existing empty directory entries

Definition at line 1462 of file util.c.

{
       const char *pcr_error;
       phar_entry_info *entry;
       int is_dir;

#ifdef PHP_WIN32
       phar_unixify_path_separators(path, path_len);
#endif

       is_dir = (path_len && (path[path_len - 1] == '/')) ? 1 : 0;

       if (error) {
              *error = NULL;
       }

       if (security && path_len >= sizeof(".phar")-1 && !memcmp(path, ".phar", sizeof(".phar")-1)) {
              if (error) {
                     spprintf(error, 4096, "phar error: cannot directly access magic \".phar\" directory or files within it");
              }
              return NULL;
       }

       if (!path_len && !dir) {
              if (error) {
                     spprintf(error, 4096, "phar error: invalid path \"%s\" must not be empty", path);
              }
              return NULL;
       }

       if (phar_path_check(&path, &path_len, &pcr_error) > pcr_is_ok) {
              if (error) {
                     spprintf(error, 4096, "phar error: invalid path \"%s\" contains %s", path, pcr_error);
              }
              return NULL;
       }

       if (!phar->manifest.arBuckets) {
              return NULL;
       }

       if (is_dir) {
              if (!path_len || path_len == 1) {
                     return NULL;
              }
              path_len--;
       }

       if (SUCCESS == zend_hash_find(&phar->manifest, path, path_len, (void**)&entry)) {
              if (entry->is_deleted) {
                     /* entry is deleted, but has not been flushed to disk yet */
                     return NULL;
              }
              if (entry->is_dir && !dir) {
                     if (error) {
                            spprintf(error, 4096, "phar error: path \"%s\" is a directory", path);
                     }
                     return NULL;
              }
              if (!entry->is_dir && dir == 2) {
                     /* user requested a directory, we must return one */
                     if (error) {
                            spprintf(error, 4096, "phar error: path \"%s\" exists and is a not a directory", path);
                     }
                     return NULL;
              }
              return entry;
       }

       if (dir) {
              if (zend_hash_exists(&phar->virtual_dirs, path, path_len)) {
                     /* a file or directory exists in a sub-directory of this path */
                     entry = (phar_entry_info *) ecalloc(1, sizeof(phar_entry_info));
                     /* this next line tells PharFileInfo->__destruct() to efree the filename */
                     entry->is_temp_dir = entry->is_dir = 1;
                     entry->filename = (char *) estrndup(path, path_len + 1);
                     entry->filename_len = path_len;
                     entry->phar = phar;
                     return entry;
              }
       }

       if (phar->mounted_dirs.arBuckets && zend_hash_num_elements(&phar->mounted_dirs)) {
              phar_zstr key;
              char *str_key;
              ulong unused;
              uint keylen;

              zend_hash_internal_pointer_reset(&phar->mounted_dirs);
              while (FAILURE != zend_hash_has_more_elements(&phar->mounted_dirs)) {
                     if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(&phar->mounted_dirs, &key, &keylen, &unused, 0, NULL)) {
                            break;
                     }

                     PHAR_STR(key, str_key);

                     if ((int)keylen >= path_len || strncmp(str_key, path, keylen)) {
                            PHAR_STR_FREE(str_key);
                            continue;
                     } else {
                            char *test;
                            int test_len;
                            php_stream_statbuf ssb;

                            if (SUCCESS != zend_hash_find(&phar->manifest, str_key, keylen, (void **) &entry)) {
                                   if (error) {
                                          spprintf(error, 4096, "phar internal error: mounted path \"%s\" could not be retrieved from manifest", str_key);
                                   }
                                   PHAR_STR_FREE(str_key);
                                   return NULL;
                            }

                            if (!entry->tmp || !entry->is_mounted) {
                                   if (error) {
                                          spprintf(error, 4096, "phar internal error: mounted path \"%s\" is not properly initialized as a mounted path", str_key);
                                   }
                                   PHAR_STR_FREE(str_key);
                                   return NULL;
                            }
                            PHAR_STR_FREE(str_key);

                            test_len = spprintf(&test, MAXPATHLEN, "%s%s", entry->tmp, path + keylen);

                            if (SUCCESS != php_stream_stat_path(test, &ssb)) {
                                   efree(test);
                                   return NULL;
                            }

                            if (ssb.sb.st_mode & S_IFDIR && !dir) {
                                   efree(test);
                                   if (error) {
                                          spprintf(error, 4096, "phar error: path \"%s\" is a directory", path);
                                   }
                                   return NULL;
                            }

                            if ((ssb.sb.st_mode & S_IFDIR) == 0 && dir) {
                                   efree(test);
                                   /* user requested a directory, we must return one */
                                   if (error) {
                                          spprintf(error, 4096, "phar error: path \"%s\" exists and is a not a directory", path);
                                   }
                                   return NULL;
                            }

                            /* mount the file just in time */
                            if (SUCCESS != phar_mount_entry(phar, test, test_len, path, path_len TSRMLS_CC)) {
                                   efree(test);
                                   if (error) {
                                          spprintf(error, 4096, "phar error: path \"%s\" exists as file \"%s\" and could not be mounted", path, test);
                                   }
                                   return NULL;
                            }

                            efree(test);

                            if (SUCCESS != zend_hash_find(&phar->manifest, path, path_len, (void**)&entry)) {
                                   if (error) {
                                          spprintf(error, 4096, "phar error: path \"%s\" exists as file \"%s\" and could not be retrieved after being mounted", path, test);
                                   }
                                   return NULL;
                            }
                            return entry;
                     }
              }
       }

       return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static php_stream* phar_get_entrypfp ( phar_entry_info *entry  TSRMLS_DC) [inline, static]

Definition at line 362 of file phar_internal.h.

{
       if (!entry->is_persistent) {
              return entry->phar->fp;
       }
       return PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].fp;
}

Here is the caller graph for this function:

static php_stream* phar_get_entrypufp ( phar_entry_info *entry  TSRMLS_DC) [inline, static]

Definition at line 370 of file phar_internal.h.

{
       if (!entry->is_persistent) {
              return entry->phar->ufp;
       }
       return PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].ufp;
}

Here is the caller graph for this function:

static off_t phar_get_fp_offset ( phar_entry_info *entry  TSRMLS_DC) [inline, static]

Definition at line 456 of file phar_internal.h.

{
       if (!entry->is_persistent) {
              return entry->offset;
       }
       if (PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].manifest[entry->manifest_pos].fp_type == PHAR_FP) {
              if (!PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].manifest[entry->manifest_pos].offset) {
                     PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].manifest[entry->manifest_pos].offset = entry->offset;
              }
       }
       return PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].manifest[entry->manifest_pos].offset;
}

Here is the caller graph for this function:

static enum phar_fp_type phar_get_fp_type ( phar_entry_info *entry  TSRMLS_DC) [inline, static]

Definition at line 448 of file phar_internal.h.

{
       if (!entry->is_persistent) {
              return entry->fp_type;
       }
       return PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].manifest[entry->manifest_pos].fp_type;
}

Here is the caller graph for this function:

Definition at line 68 of file util.c.

{
       phar_entry_info *link_entry;
       char *link;

       if (!entry->link) {
              return entry;
       }

       link = phar_get_link_location(entry TSRMLS_CC);
       if (SUCCESS == zend_hash_find(&(entry->phar->manifest), entry->link, strlen(entry->link), (void **)&link_entry) ||
              SUCCESS == zend_hash_find(&(entry->phar->manifest), link, strlen(link), (void **)&link_entry)) {
              if (link != entry->link) {
                     efree(link);
              }
              return phar_get_link_source(link_entry TSRMLS_CC);
       } else {
              if (link != entry->link) {
                     efree(link);
              }
              return NULL;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

phar_entry_data* phar_get_or_create_entry_data ( char *  fname,
int  fname_len,
char *  path,
int  path_len,
char *  mode,
char  allow_dir,
char **  error,
int security  TSRMLS_DC 
)

Create a new dummy file slot within a writeable phar for a newly created file.

Definition at line 739 of file util.c.

{
       phar_archive_data *phar;
       phar_entry_info *entry, etemp;
       phar_entry_data *ret;
       const char *pcr_error;
       char is_dir;

#ifdef PHP_WIN32
       phar_unixify_path_separators(path, path_len);
#endif

       is_dir = (path_len && path[path_len - 1] == '/') ? 1 : 0;

       if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error TSRMLS_CC)) {
              return NULL;
       }

       if (FAILURE == phar_get_entry_data(&ret, fname, fname_len, path, path_len, mode, allow_dir, error, security TSRMLS_CC)) {
              return NULL;
       } else if (ret) {
              return ret;
       }

       if (phar_path_check(&path, &path_len, &pcr_error) > pcr_is_ok) {
              if (error) {
                     spprintf(error, 0, "phar error: invalid path \"%s\" contains %s", path, pcr_error);
              }
              return NULL;
       }

       if (phar->is_persistent && FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
              if (error) {
                     spprintf(error, 4096, "phar error: file \"%s\" in phar \"%s\" cannot be created, could not make cached phar writeable", path, fname);
              }
              return NULL;
       }

       /* create a new phar data holder */
       ret = (phar_entry_data *) emalloc(sizeof(phar_entry_data));

       /* create an entry, this is a new file */
       memset(&etemp, 0, sizeof(phar_entry_info));
       etemp.filename_len = path_len;
       etemp.fp_type = PHAR_MOD;
       etemp.fp = php_stream_fopen_tmpfile();

       if (!etemp.fp) {
              if (error) {
                     spprintf(error, 0, "phar error: unable to create temporary file");
              }
              efree(ret);
              return NULL;
       }

       etemp.fp_refcount = 1;

       if (allow_dir == 2) {
              etemp.is_dir = 1;
              etemp.flags = etemp.old_flags = PHAR_ENT_PERM_DEF_DIR;
       } else {
              etemp.flags = etemp.old_flags = PHAR_ENT_PERM_DEF_FILE;
       }
       if (is_dir) {
              etemp.filename_len--; /* strip trailing / */
              path_len--;
       }

       phar_add_virtual_dirs(phar, path, path_len TSRMLS_CC);
       etemp.is_modified = 1;
       etemp.timestamp = time(0);
       etemp.is_crc_checked = 1;
       etemp.phar = phar;
       etemp.filename = estrndup(path, path_len);
       etemp.is_zip = phar->is_zip;

       if (phar->is_tar) {
              etemp.is_tar = phar->is_tar;
              etemp.tar_type = etemp.is_dir ? TAR_DIR : TAR_FILE;
       }

       if (FAILURE == zend_hash_add(&phar->manifest, etemp.filename, path_len, (void*)&etemp, sizeof(phar_entry_info), (void **) &entry)) {
              php_stream_close(etemp.fp);
              if (error) {
                     spprintf(error, 0, "phar error: unable to add new entry \"%s\" to phar \"%s\"", etemp.filename, phar->fname);
              }
              efree(ret);
              efree(etemp.filename);
              return NULL;
       }

       if (!entry) {
              php_stream_close(etemp.fp);
              efree(etemp.filename);
              efree(ret);
              return NULL;
       }

       ++(phar->refcount);
       ret->phar = phar;
       ret->fp = entry->fp;
       ret->position = ret->zero = 0;
       ret->for_write = 1;
       ret->is_zip = entry->is_zip;
       ret->is_tar = entry->is_tar;
       ret->internal_file = entry;

       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static php_stream* phar_get_pharfp ( phar_archive_data *phar  TSRMLS_DC) [inline, static]

Definition at line 398 of file phar_internal.h.

{
       if (!phar->is_persistent) {
              return phar->fp;
       }
       return PHAR_GLOBALS->cached_fp[phar->phar_pos].fp;
}

Here is the caller graph for this function:

static php_stream* phar_get_pharufp ( phar_archive_data *phar  TSRMLS_DC) [inline, static]

Definition at line 406 of file phar_internal.h.

{
       if (!phar->is_persistent) {
              return phar->ufp;
       }
       return PHAR_GLOBALS->cached_fp[phar->phar_pos].ufp;
}
int phar_is_tar ( char *  buf,
char *  fname 
)

Definition at line 100 of file tar.c.

{
       tar_header *header = (tar_header *) buf;
       php_uint32 checksum = phar_tar_number(header->checksum, sizeof(header->checksum));
       php_uint32 ret;
       char save[sizeof(header->checksum)];

       /* assume that the first filename in a tar won't begin with <?php */
       if (!strncmp(buf, "<?php", sizeof("<?php")-1)) {
              return 0;
       }

       memcpy(save, header->checksum, sizeof(header->checksum));
       memset(header->checksum, ' ', sizeof(header->checksum));
       ret = (checksum == phar_tar_checksum(buf, 512));
       memcpy(header->checksum, save, sizeof(header->checksum));
       if (!ret && strstr(fname, ".tar")) {
              /* probably a corrupted tar - so we will pretend it is one */
              return 1;
       }
       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_mount_entry ( phar_archive_data *  phar,
char *  filename,
int  filename_len,
char *  path,
int path_len  TSRMLS_DC 
)

Definition at line 175 of file util.c.

{
       phar_entry_info entry = {0};
       php_stream_statbuf ssb;
       int is_phar;
       const char *err;

       if (phar_path_check(&path, &path_len, &err) > pcr_is_ok) {
              return FAILURE;
       }

       if (path_len >= sizeof(".phar")-1 && !memcmp(path, ".phar", sizeof(".phar")-1)) {
              /* no creating magic phar files by mounting them */
              return FAILURE;
       }

       is_phar = (filename_len > 7 && !memcmp(filename, "phar://", 7));

       entry.phar = phar;
       entry.filename = estrndup(path, path_len);
#ifdef PHP_WIN32
       phar_unixify_path_separators(entry.filename, path_len);
#endif
       entry.filename_len = path_len;
       if (is_phar) {
              entry.tmp = estrndup(filename, filename_len);
       } else {
              entry.tmp = expand_filepath(filename, NULL TSRMLS_CC);
              if (!entry.tmp) {
                     entry.tmp = estrndup(filename, filename_len);
              }
       }
#if PHP_API_VERSION < 20100412
       if (PG(safe_mode) && !is_phar && (!php_checkuid(entry.tmp, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
              efree(entry.tmp);
              efree(entry.filename);
              return FAILURE;
       }
#endif

       filename_len = strlen(entry.tmp);
       filename = entry.tmp;

       /* only check openbasedir for files, not for phar streams */
       if (!is_phar && php_check_open_basedir(filename TSRMLS_CC)) {
              efree(entry.tmp);
              efree(entry.filename);
              return FAILURE;
       }

       entry.is_mounted = 1;
       entry.is_crc_checked = 1;
       entry.fp_type = PHAR_TMP;

       if (SUCCESS != php_stream_stat_path(filename, &ssb)) {
              efree(entry.tmp);
              efree(entry.filename);
              return FAILURE;
       }

       if (ssb.sb.st_mode & S_IFDIR) {
              entry.is_dir = 1;
              if (SUCCESS != zend_hash_add(&phar->mounted_dirs, entry.filename, path_len, (void *)&(entry.filename), sizeof(char *), NULL)) {
                     /* directory already mounted */
                     efree(entry.tmp);
                     efree(entry.filename);
                     return FAILURE;
              }
       } else {
              entry.is_dir = 0;
              entry.uncompressed_filesize = entry.compressed_filesize = ssb.sb.st_size;
       }

       entry.flags = ssb.sb.st_mode;

       if (SUCCESS == zend_hash_add(&phar->manifest, entry.filename, path_len, (void*)&entry, sizeof(phar_entry_info), NULL)) {
              return SUCCESS;
       }

       efree(entry.tmp);
       efree(entry.filename);
       return FAILURE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 5554 of file phar_object.c.

{
       zend_class_entry ce;

       INIT_CLASS_ENTRY(ce, "PharException", phar_exception_methods);
       phar_ce_PharException = zend_register_internal_class_ex(&ce, phar_exception_get_default(), NULL  TSRMLS_CC);

#if HAVE_SPL
       INIT_CLASS_ENTRY(ce, "Phar", php_archive_methods);
       phar_ce_archive = zend_register_internal_class_ex(&ce, spl_ce_RecursiveDirectoryIterator, NULL  TSRMLS_CC);

       zend_class_implements(phar_ce_archive TSRMLS_CC, 2, spl_ce_Countable, zend_ce_arrayaccess);

       INIT_CLASS_ENTRY(ce, "PharData", php_archive_methods);
       phar_ce_data = zend_register_internal_class_ex(&ce, spl_ce_RecursiveDirectoryIterator, NULL  TSRMLS_CC);

       zend_class_implements(phar_ce_data TSRMLS_CC, 2, spl_ce_Countable, zend_ce_arrayaccess);

       INIT_CLASS_ENTRY(ce, "PharFileInfo", php_entry_methods);
       phar_ce_entry = zend_register_internal_class_ex(&ce, spl_ce_SplFileInfo, NULL  TSRMLS_CC);
#else
       INIT_CLASS_ENTRY(ce, "Phar", php_archive_methods);
       phar_ce_archive = zend_register_internal_class(&ce TSRMLS_CC);
       phar_ce_archive->ce_flags |= ZEND_ACC_FINAL_CLASS;

       INIT_CLASS_ENTRY(ce, "PharData", php_archive_methods);
       phar_ce_data = zend_register_internal_class(&ce TSRMLS_CC);
       phar_ce_data->ce_flags |= ZEND_ACC_FINAL_CLASS;
#endif

       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "BZ2", PHAR_ENT_COMPRESSED_BZ2)
       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "GZ", PHAR_ENT_COMPRESSED_GZ)
       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "NONE", PHAR_ENT_COMPRESSED_NONE)
       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHAR", PHAR_FORMAT_PHAR)
       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "TAR", PHAR_FORMAT_TAR)
       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "ZIP", PHAR_FORMAT_ZIP)
       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "COMPRESSED", PHAR_ENT_COMPRESSION_MASK)
       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHP", PHAR_MIME_PHP)
       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHPS", PHAR_MIME_PHPS)
       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "MD5", PHAR_SIG_MD5)
       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "OPENSSL", PHAR_SIG_OPENSSL)
       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA1", PHAR_SIG_SHA1)
       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA256", PHAR_SIG_SHA256)
       REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA512", PHAR_SIG_SHA512)
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_open_archive_fp ( phar_archive_data *phar  TSRMLS_DC)

Definition at line 851 of file util.c.

{
       if (phar_get_pharfp(phar TSRMLS_CC)) {
              return SUCCESS;
       }
#if PHP_API_VERSION < 20100412
       if (PG(safe_mode) && (!php_checkuid(phar->fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
              return FAILURE;
       }
#endif

       if (php_check_open_basedir(phar->fname TSRMLS_CC)) {
              return FAILURE;
       }

       phar_set_pharfp(phar, php_stream_open_wrapper(phar->fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|0, NULL) TSRMLS_CC);

       if (!phar_get_pharfp(phar TSRMLS_CC)) {
              return FAILURE;
       }

       return SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_open_entry_file ( phar_archive_data *  phar,
phar_entry_info entry,
char **error  TSRMLS_DC 
)
int phar_open_entry_fp ( phar_entry_info entry,
char **  error,
int follow_links  TSRMLS_DC 
)

Definition at line 917 of file util.c.

{
       php_stream_filter *filter;
       phar_archive_data *phar = entry->phar;
       char *filtername;
       off_t loc;
       php_stream *ufp;
       phar_entry_data dummy;

       if (follow_links && entry->link) {
              phar_entry_info *link_entry = phar_get_link_source(entry TSRMLS_CC);
              if (link_entry && link_entry != entry) {
                     return phar_open_entry_fp(link_entry, error, 1 TSRMLS_CC);
              }
       }

       if (entry->is_modified) {
              return SUCCESS;
       }

       if (entry->fp_type == PHAR_TMP) {
              if (!entry->fp) {
                     entry->fp = php_stream_open_wrapper(entry->tmp, "rb", STREAM_MUST_SEEK|0, NULL);
              }
              return SUCCESS;
       }

       if (entry->fp_type != PHAR_FP) {
              /* either newly created or already modified */
              return SUCCESS;
       }

       if (!phar_get_pharfp(phar TSRMLS_CC)) {
              if (FAILURE == phar_open_archive_fp(phar TSRMLS_CC)) {
                     spprintf(error, 4096, "phar error: Cannot open phar archive \"%s\" for reading", phar->fname);
                     return FAILURE;
              }
       }

       if ((entry->old_flags && !(entry->old_flags & PHAR_ENT_COMPRESSION_MASK)) || !(entry->flags & PHAR_ENT_COMPRESSION_MASK)) {
              dummy.internal_file = entry;
              dummy.phar = phar;
              dummy.zero = entry->offset;
              dummy.fp = phar_get_pharfp(phar TSRMLS_CC);
              if (FAILURE == phar_postprocess_file(&dummy, entry->crc32, error, 1 TSRMLS_CC)) {
                     return FAILURE;
              }
              return SUCCESS;
       }

       if (!phar_get_entrypufp(entry TSRMLS_CC)) {
              phar_set_entrypufp(entry, php_stream_fopen_tmpfile() TSRMLS_CC);
              if (!phar_get_entrypufp(entry TSRMLS_CC)) {
                     spprintf(error, 4096, "phar error: Cannot open temporary file for decompressing phar archive \"%s\" file \"%s\"", phar->fname, entry->filename);
                     return FAILURE;
              }
       }

       dummy.internal_file = entry;
       dummy.phar = phar;
       dummy.zero = entry->offset;
       dummy.fp = phar_get_pharfp(phar TSRMLS_CC);
       if (FAILURE == phar_postprocess_file(&dummy, entry->crc32, error, 1 TSRMLS_CC)) {
              return FAILURE;
       }

       ufp = phar_get_entrypufp(entry TSRMLS_CC);

       if ((filtername = phar_decompress_filter(entry, 0)) != NULL) {
              filter = php_stream_filter_create(filtername, NULL, 0 TSRMLS_CC);
       } else {
              filter = NULL;
       }

       if (!filter) {
              spprintf(error, 4096, "phar error: unable to read phar \"%s\" (cannot create %s filter while decompressing file \"%s\")", phar->fname, phar_decompress_filter(entry, 1), entry->filename);
              return FAILURE;
       }

       /* now we can safely use proper decompression */
       /* save the new offset location within ufp */
       php_stream_seek(ufp, 0, SEEK_END);
       loc = php_stream_tell(ufp);
       php_stream_filter_append(&ufp->writefilters, filter);
       php_stream_seek(phar_get_entrypfp(entry TSRMLS_CC), phar_get_fp_offset(entry TSRMLS_CC), SEEK_SET);

       if (entry->uncompressed_filesize) {
              if (SUCCESS != phar_stream_copy_to_stream(phar_get_entrypfp(entry TSRMLS_CC), ufp, entry->compressed_filesize, NULL)) {
                     spprintf(error, 4096, "phar error: internal corruption of phar \"%s\" (actual filesize mismatch on file \"%s\")", phar->fname, entry->filename);
                     php_stream_filter_remove(filter, 1 TSRMLS_CC);
                     return FAILURE;
              }
       }

       php_stream_filter_flush(filter, 1);
       php_stream_flush(ufp);
       php_stream_filter_remove(filter, 1 TSRMLS_CC);

       if (php_stream_tell(ufp) - loc != (off_t) entry->uncompressed_filesize) {
              spprintf(error, 4096, "phar error: internal corruption of phar \"%s\" (actual filesize mismatch on file \"%s\")", phar->fname, entry->filename);
              return FAILURE;
       }

       entry->old_flags = entry->flags;

       /* this is now the new location of the file contents within this fp */
       phar_set_fp_type(entry, PHAR_UFP, loc TSRMLS_CC);
       dummy.zero = entry->offset;
       dummy.fp = ufp;
       if (FAILURE == phar_postprocess_file(&dummy, entry->crc32, error, 0 TSRMLS_CC)) {
              return FAILURE;
       }
       return SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_open_executed_filename ( char *  alias,
int  alias_len,
char **error  TSRMLS_DC 
)

Invoked when a user calls Phar::mapPhar() from within an executing .phar to set up its manifest directly.

Definition at line 2325 of file phar.c.

{
       char *fname;
       zval *halt_constant;
       php_stream *fp;
       int fname_len;
       char *actual = NULL;
       int ret;

       if (error) {
              *error = NULL;
       }

       fname = zend_get_executed_filename(TSRMLS_C);
       fname_len = strlen(fname);

       if (phar_open_parsed_phar(fname, fname_len, alias, alias_len, 0, REPORT_ERRORS, NULL, 0 TSRMLS_CC) == SUCCESS) {
              return SUCCESS;
       }

       if (!strcmp(fname, "[no active file]")) {
              if (error) {
                     spprintf(error, 0, "cannot initialize a phar outside of PHP execution");
              }
              return FAILURE;
       }

       MAKE_STD_ZVAL(halt_constant);

       if (0 == zend_get_constant("__COMPILER_HALT_OFFSET__", 24, halt_constant TSRMLS_CC)) {
              FREE_ZVAL(halt_constant);
              if (error) {
                     spprintf(error, 0, "__HALT_COMPILER(); must be declared in a phar");
              }
              return FAILURE;
       }

       FREE_ZVAL(halt_constant);

#if PHP_API_VERSION < 20100412
       if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
              return FAILURE;
       }
#endif

       if (php_check_open_basedir(fname TSRMLS_CC)) {
              return FAILURE;
       }

       fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK|REPORT_ERRORS, &actual);

       if (!fp) {
              if (error) {
                     spprintf(error, 0, "unable to open phar for reading \"%s\"", fname);
              }
              if (actual) {
                     efree(actual);
              }
              return FAILURE;
       }

       if (actual) {
              fname = actual;
              fname_len = strlen(actual);
       }

       ret = phar_open_from_fp(fp, fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL, 0, error TSRMLS_CC);

       if (actual) {
              efree(actual);
       }

       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_open_from_filename ( char *  fname,
int  fname_len,
char *  alias,
int  alias_len,
int  options,
phar_archive_data **  pphar,
char **error  TSRMLS_DC 
)

Return an already opened filename.

Or scan a phar file for the required __HALT_COMPILER(); ?> token and verify that the manifest is proper, then pass it to phar_parse_pharfile(). SUCCESS or FAILURE is returned and pphar is set to a pointer to the phar's manifest

Definition at line 1475 of file phar.c.

{
       php_stream *fp;
       char *actual;
       int ret, is_data = 0;

       if (error) {
              *error = NULL;
       }

       if (!strstr(fname, ".phar")) {
              is_data = 1;
       }

       if (phar_open_parsed_phar(fname, fname_len, alias, alias_len, is_data, options, pphar, error TSRMLS_CC) == SUCCESS) {
              return SUCCESS;
       } else if (error && *error) {
              return FAILURE;
       }
#if PHP_API_VERSION < 20100412
       if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
              return FAILURE;
       }
#endif
       if (php_check_open_basedir(fname TSRMLS_CC)) {
              return FAILURE;
       }

       fp = php_stream_open_wrapper(fname, "rb", IGNORE_URL|STREAM_MUST_SEEK, &actual);

       if (!fp) {
              if (options & REPORT_ERRORS) {
                     if (error) {
                            spprintf(error, 0, "unable to open phar for reading \"%s\"", fname);
                     }
              }
              if (actual) {
                     efree(actual);
              }
              return FAILURE;
       }

       if (actual) {
              fname = actual;
              fname_len = strlen(actual);
       }

       ret =  phar_open_from_fp(fp, fname, fname_len, alias, alias_len, options, pphar, is_data, error TSRMLS_CC);

       if (actual) {
              efree(actual);
       }

       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

phar_entry_info* phar_open_jit ( phar_archive_data *  phar,
phar_entry_info entry,
char **error  TSRMLS_DC 
)

helper function to open an internal file's fp just-in-time

Definition at line 1166 of file util.c.

{
       if (error) {
              *error = NULL;
       }
       /* seek to start of internal file and read it */
       if (FAILURE == phar_open_entry_fp(entry, error, 1 TSRMLS_CC)) {
              return NULL;
       }
       if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 1 TSRMLS_CC)) {
              spprintf(error, 4096, "phar error: cannot seek to start of file \"%s\" in phar \"%s\"", entry->filename, phar->fname);
              return NULL;
       }
       return entry;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_open_or_create_filename ( char *  fname,
int  fname_len,
char *  alias,
int  alias_len,
int  is_data,
int  options,
phar_archive_data **  pphar,
char **error  TSRMLS_DC 
)

Create or open a phar for writing.

Definition at line 1244 of file phar.c.

{
       const char *ext_str, *z;
       char *my_error;
       int ext_len;
       phar_archive_data **test, *unused = NULL;

       test = &unused;

       if (error) {
              *error = NULL;
       }

       /* first try to open an existing file */
       if (phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 0, 1 TSRMLS_CC) == SUCCESS) {
              goto check_file;
       }

       /* next try to create a new file */
       if (FAILURE == phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, !is_data, 1, 1 TSRMLS_CC)) {
              if (error) {
                     if (ext_len == -2) {
                            spprintf(error, 0, "Cannot create a phar archive from a URL like \"%s\". Phar objects can only be created from local files", fname);
                     } else {
                            spprintf(error, 0, "Cannot create phar '%s', file extension (or combination) not recognised or the directory does not exist", fname);
                     }
              }
              return FAILURE;
       }
check_file:
       if (phar_open_parsed_phar(fname, fname_len, alias, alias_len, is_data, options, test, &my_error TSRMLS_CC) == SUCCESS) {
              if (pphar) {
                     *pphar = *test;
              }

              if ((*test)->is_data && !(*test)->is_tar && !(*test)->is_zip) {
                     if (error) {
                            spprintf(error, 0, "Cannot open '%s' as a PharData object. Use Phar::__construct() for executable archives", fname);
                     }
                     return FAILURE;
              }

              if (PHAR_G(readonly) && !(*test)->is_data && ((*test)->is_tar || (*test)->is_zip)) {
                     phar_entry_info *stub;
                     if (FAILURE == zend_hash_find(&((*test)->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1, (void **)&stub)) {
                            spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", fname);
                            return FAILURE;
                     }
              }

              if (!PHAR_G(readonly) || (*test)->is_data) {
                     (*test)->is_writeable = 1;
              }
              return SUCCESS;
       } else if (my_error) {
              if (error) {
                     *error = my_error;
              } else {
                     efree(my_error);
              }
              return FAILURE;
       }

       if (ext_len > 3 && (z = memchr(ext_str, 'z', ext_len)) && ((ext_str + ext_len) - z >= 2) && !memcmp(z + 1, "ip", 2)) {
              /* assume zip-based phar */
              return phar_open_or_create_zip(fname, fname_len, alias, alias_len, is_data, options, pphar, error TSRMLS_CC);
       }

       if (ext_len > 3 && (z = memchr(ext_str, 't', ext_len)) && ((ext_str + ext_len) - z >= 2) && !memcmp(z + 1, "ar", 2)) {
              /* assume tar-based phar */
              return phar_open_or_create_tar(fname, fname_len, alias, alias_len, is_data, options, pphar, error TSRMLS_CC);
       }

       return phar_create_or_parse_filename(fname, fname_len, alias, alias_len, is_data, options, pphar, error TSRMLS_CC);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_open_or_create_tar ( char *  fname,
int  fname_len,
char *  alias,
int  alias_len,
int  is_data,
int  options,
phar_archive_data **  pphar,
char **error  TSRMLS_DC 
)

Definition at line 124 of file tar.c.

{
       phar_archive_data *phar;
       int ret = phar_create_or_parse_filename(fname, fname_len, alias, alias_len, is_data, options, &phar, error TSRMLS_CC);

       if (FAILURE == ret) {
              return FAILURE;
       }

       if (pphar) {
              *pphar = phar;
       }

       phar->is_data = is_data;

       if (phar->is_tar) {
              return ret;
       }

       if (phar->is_brandnew) {
              phar->is_tar = 1;
              phar->is_zip = 0;
              phar->internal_file_start = 0;
              return SUCCESS;
       }

       /* we've reached here - the phar exists and is a regular phar */
       if (error) {
              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);
       }
       return FAILURE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_open_or_create_zip ( char *  fname,
int  fname_len,
char *  alias,
int  alias_len,
int  is_data,
int  options,
phar_archive_data **  pphar,
char **error  TSRMLS_DC 
)

Create or open a zip-based phar for writing.

Definition at line 742 of file zip.c.

{
       phar_archive_data *phar;
       int ret = phar_create_or_parse_filename(fname, fname_len, alias, alias_len, is_data, options, &phar, error TSRMLS_CC);

       if (FAILURE == ret) {
              return FAILURE;
       }

       if (pphar) {
              *pphar = phar;
       }

       phar->is_data = is_data;

       if (phar->is_zip) {
              return ret;
       }

       if (phar->is_brandnew) {
              phar->internal_file_start = 0;
              phar->is_zip = 1;
              phar->is_tar = 0;
              return SUCCESS;
       }

       /* we've reached here - the phar exists and is a regular phar */
       if (error) {
              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);
       }

       return FAILURE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_open_parsed_phar ( char *  fname,
int  fname_len,
char *  alias,
int  alias_len,
int  is_data,
int  options,
phar_archive_data **  pphar,
char **error  TSRMLS_DC 
)

Open an already loaded phar.

Definition at line 531 of file phar.c.

{
       phar_archive_data *phar;
#ifdef PHP_WIN32
       char *unixfname;
#endif

       if (error) {
              *error = NULL;
       }
#ifdef PHP_WIN32
       unixfname = estrndup(fname, fname_len);
       phar_unixify_path_separators(unixfname, fname_len);

       if (SUCCESS == phar_get_archive(&phar, unixfname, fname_len, alias, alias_len, error TSRMLS_CC)
              && ((alias && fname_len == phar->fname_len
              && !strncmp(unixfname, phar->fname, fname_len)) || !alias)
       ) {
              phar_entry_info *stub;
              efree(unixfname);
#else
       if (SUCCESS == phar_get_archive(&phar, fname, fname_len, alias, alias_len, error TSRMLS_CC)
              && ((alias && fname_len == phar->fname_len
              && !strncmp(fname, phar->fname, fname_len)) || !alias)
       ) {
              phar_entry_info *stub;
#endif
              /* logic above is as follows:
                 If an explicit alias was requested, ensure the filename passed in
                 matches the phar's filename.
                 If no alias was passed in, then it can match either and be valid
               */

              if (!is_data) {
                     /* prevent any ".phar" without a stub getting through */
                     if (!phar->halt_offset && !phar->is_brandnew && (phar->is_tar || phar->is_zip)) {
                            if (PHAR_G(readonly) && FAILURE == zend_hash_find(&(phar->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1, (void **)&stub)) {
                                   if (error) {
                                          spprintf(error, 0, "'%s' is not a phar archive. Use PharData::__construct() for a standard zip or tar archive", fname);
                                   }
                                   return FAILURE;
                            }
                     }
              }

              if (pphar) {
                     *pphar = phar;
              }

              return SUCCESS;
       } else {
#ifdef PHP_WIN32
              efree(unixfname);
#endif
              if (pphar) {
                     *pphar = NULL;
              }

              if (phar && error && !(options & REPORT_ERRORS)) {
                     efree(error);
              }

              return FAILURE;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_parse_metadata ( char **  buffer,
zval **  metadata,
int zip_metadata_len  TSRMLS_DC 
)

Parse out metadata from the manifest for a single file.

Meta-data is in this format: [len32][data...]

data is the serialized zval

Definition at line 606 of file phar.c.

{
       const unsigned char *p;
       php_uint32 buf_len;
       php_unserialize_data_t var_hash;

       if (!zip_metadata_len) {
              PHAR_GET_32(*buffer, buf_len);
       } else {
              buf_len = zip_metadata_len;
       }

       if (buf_len) {
              ALLOC_ZVAL(*metadata);
              INIT_ZVAL(**metadata);
              p = (const unsigned char*) *buffer;
              PHP_VAR_UNSERIALIZE_INIT(var_hash);

              if (!php_var_unserialize(metadata, &p, p + buf_len, &var_hash TSRMLS_CC)) {
                     PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
                     zval_ptr_dtor(metadata);
                     *metadata = NULL;
                     return FAILURE;
              }

              PHP_VAR_UNSERIALIZE_DESTROY(var_hash);

              if (PHAR_G(persist)) {
                     /* lazy init metadata */
                     zval_ptr_dtor(metadata);
                     *metadata = (zval *) pemalloc(buf_len, 1);
                     memcpy(*metadata, *buffer, buf_len);
                     *buffer += buf_len;
                     return SUCCESS;
              }
       } else {
              *metadata = NULL;
       }

       if (!zip_metadata_len) {
              *buffer += buf_len;
       }

       return SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_parse_tarfile ( php_stream *  fp,
char *  fname,
int  fname_len,
char *  alias,
int  alias_len,
phar_archive_data **  pphar,
int  is_data,
php_uint32  compression,
char **error  TSRMLS_DC 
)

Definition at line 195 of file tar.c.

{
       char buf[512], *actual_alias = NULL, *p;
       phar_entry_info entry = {0};
       size_t pos = 0, read, totalsize;
       tar_header *hdr;
       php_uint32 sum1, sum2, size, old;
       phar_archive_data *myphar, **actual;
       int last_was_longlink = 0;

       if (error) {
              *error = NULL;
       }

       php_stream_seek(fp, 0, SEEK_END);
       totalsize = php_stream_tell(fp);
       php_stream_seek(fp, 0, SEEK_SET);
       read = php_stream_read(fp, buf, sizeof(buf));

       if (read != sizeof(buf)) {
              if (error) {
                     spprintf(error, 4096, "phar error: \"%s\" is not a tar file or is truncated", fname);
              }
              php_stream_close(fp);
              return FAILURE;
       }

       hdr = (tar_header*)buf;
       old = (memcmp(hdr->magic, "ustar", sizeof("ustar")-1) != 0);

       myphar = (phar_archive_data *) pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist));
       myphar->is_persistent = PHAR_G(persist);
       /* estimate number of entries, can't be certain with tar files */
       zend_hash_init(&myphar->manifest, 2 + (totalsize >> 12),
              zend_get_hash_value, destroy_phar_manifest_entry, (zend_bool)myphar->is_persistent);
       zend_hash_init(&myphar->mounted_dirs, 5,
              zend_get_hash_value, NULL, (zend_bool)myphar->is_persistent);
       zend_hash_init(&myphar->virtual_dirs, 4 + (totalsize >> 11),
              zend_get_hash_value, NULL, (zend_bool)myphar->is_persistent);
       myphar->is_tar = 1;
       /* remember whether this entire phar was compressed with gz/bzip2 */
       myphar->flags = compression;

       entry.is_tar = 1;
       entry.is_crc_checked = 1;
       entry.phar = myphar;
       pos += sizeof(buf);

       do {
              phar_entry_info *newentry;

              pos = php_stream_tell(fp);
              hdr = (tar_header*) buf;
              sum1 = phar_tar_number(hdr->checksum, sizeof(hdr->checksum));
              if (sum1 == 0 && phar_tar_checksum(buf, sizeof(buf)) == 0) {
                     break;
              }
              memset(hdr->checksum, ' ', sizeof(hdr->checksum));
              sum2 = phar_tar_checksum(buf, old?sizeof(old_tar_header):sizeof(tar_header));

              size = entry.uncompressed_filesize = entry.compressed_filesize =
                     phar_tar_number(hdr->size, sizeof(hdr->size));

              if (((!old && hdr->prefix[0] == 0) || old) && strlen(hdr->name) == sizeof(".phar/signature.bin")-1 && !strncmp(hdr->name, ".phar/signature.bin", sizeof(".phar/signature.bin")-1)) {
                     off_t curloc;

                     if (size > 511) {
                            if (error) {
                                   spprintf(error, 4096, "phar error: tar-based phar \"%s\" has signature that is larger than 511 bytes, cannot process", fname);
                            }
bail:
                            php_stream_close(fp);
                            phar_destroy_phar_data(myphar TSRMLS_CC);
                            return FAILURE;
                     }
                     curloc = php_stream_tell(fp);
                     read = php_stream_read(fp, buf, size);
                     if (read != size) {
                            if (error) {
                                   spprintf(error, 4096, "phar error: tar-based phar \"%s\" signature cannot be read", fname);
                            }
                            goto bail;
                     }
#ifdef WORDS_BIGENDIAN
# define PHAR_GET_32(buffer) \
       (((((unsigned char*)(buffer))[3]) << 24) \
              | ((((unsigned char*)(buffer))[2]) << 16) \
              | ((((unsigned char*)(buffer))[1]) <<  8) \
              | (((unsigned char*)(buffer))[0]))
#else
# define PHAR_GET_32(buffer) (php_uint32) *(buffer)
#endif
                     myphar->sig_flags = PHAR_GET_32(buf);
                     if (FAILURE == phar_verify_signature(fp, php_stream_tell(fp) - size - 512, myphar->sig_flags, buf + 8, size - 8, fname, &myphar->signature, &myphar->sig_len, error TSRMLS_CC)) {
                            if (error) {
                                   char *save = *error;
                                   spprintf(error, 4096, "phar error: tar-based phar \"%s\" signature cannot be verified: %s", fname, save);
                                   efree(save);
                            }
                            goto bail;
                     }
                     php_stream_seek(fp, curloc + 512, SEEK_SET);
                     /* signature checked out, let's ensure this is the last file in the phar */
                     if (((hdr->typeflag == '\0') || (hdr->typeflag == TAR_FILE)) && size > 0) {
                            /* this is not good enough - seek succeeds even on truncated tars */
                            php_stream_seek(fp, 512, SEEK_CUR);
                            if ((uint)php_stream_tell(fp) > totalsize) {
                                   if (error) {
                                          spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname);
                                   }
                                   php_stream_close(fp);
                                   phar_destroy_phar_data(myphar TSRMLS_CC);
                                   return FAILURE;
                            }
                     }

                     read = php_stream_read(fp, buf, sizeof(buf));

                     if (read != sizeof(buf)) {
                            if (error) {
                                   spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname);
                            }
                            php_stream_close(fp);
                            phar_destroy_phar_data(myphar TSRMLS_CC);
                            return FAILURE;
                     }

                     hdr = (tar_header*) buf;
                     sum1 = phar_tar_number(hdr->checksum, sizeof(hdr->checksum));

                     if (sum1 == 0 && phar_tar_checksum(buf, sizeof(buf)) == 0) {
                            break;
                     }

                     if (error) {
                            spprintf(error, 4096, "phar error: \"%s\" has entries after signature, invalid phar", fname);
                     }

                     goto bail;
              }

              if (!last_was_longlink && hdr->typeflag == 'L') {
                     last_was_longlink = 1;
                     /* support the ././@LongLink system for storing long filenames */
                     entry.filename_len = entry.uncompressed_filesize;
                     entry.filename = pemalloc(entry.filename_len+1, myphar->is_persistent);

                     read = php_stream_read(fp, entry.filename, entry.filename_len);
                     if (read != entry.filename_len) {
                            efree(entry.filename);
                            if (error) {
                                   spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname);
                            }
                            php_stream_close(fp);
                            phar_destroy_phar_data(myphar TSRMLS_CC);
                            return FAILURE;
                     }
                     entry.filename[entry.filename_len] = '\0';

                     /* skip blank stuff */
                     size = ((size+511)&~511) - size;

                     /* this is not good enough - seek succeeds even on truncated tars */
                     php_stream_seek(fp, size, SEEK_CUR);
                     if ((uint)php_stream_tell(fp) > totalsize) {
                            efree(entry.filename);
                            if (error) {
                                   spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname);
                            }
                            php_stream_close(fp);
                            phar_destroy_phar_data(myphar TSRMLS_CC);
                            return FAILURE;
                     }

                     read = php_stream_read(fp, buf, sizeof(buf));
       
                     if (read != sizeof(buf)) {
                            efree(entry.filename);
                            if (error) {
                                   spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname);
                            }
                            php_stream_close(fp);
                            phar_destroy_phar_data(myphar TSRMLS_CC);
                            return FAILURE;
                     }
                     continue;
              } else if (!last_was_longlink && !old && hdr->prefix[0] != 0) {
                     char name[256];
                     int i, j;

                     for (i = 0; i < 155; i++) {
                            name[i] = hdr->prefix[i];
                            if (name[i] == '\0') {
                                   break;
                            }
                     }
                     name[i++] = '/';
                     for (j = 0; j < 100; j++) {
                            name[i+j] = hdr->name[j];
                            if (name[i+j] == '\0') {
                                   break;
                            }
                     }

                     entry.filename_len = i+j;

                     if (name[entry.filename_len - 1] == '/') {
                            /* some tar programs store directories with trailing slash */
                            entry.filename_len--;
                     }
                     entry.filename = pestrndup(name, entry.filename_len, myphar->is_persistent);
              } else if (!last_was_longlink) {
                     int i;

                     /* calculate strlen, which can be no longer than 100 */
                     for (i = 0; i < 100; i++) {
                            if (hdr->name[i] == '\0') {
                                   break;
                            }
                     }
                     entry.filename_len = i;
                     entry.filename = pestrndup(hdr->name, i, myphar->is_persistent);

                     if (entry.filename[entry.filename_len - 1] == '/') {
                            /* some tar programs store directories with trailing slash */
                            entry.filename[entry.filename_len - 1] = '\0';
                            entry.filename_len--;
                     }
              }
              last_was_longlink = 0;

              phar_add_virtual_dirs(myphar, entry.filename, entry.filename_len TSRMLS_CC);

              if (sum1 != sum2) {
                     if (error) {
                            spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (checksum mismatch of file \"%s\")", fname, entry.filename);
                     }
                     pefree(entry.filename, myphar->is_persistent);
                     php_stream_close(fp);
                     phar_destroy_phar_data(myphar TSRMLS_CC);
                     return FAILURE;
              }

              entry.tar_type = ((old & (hdr->typeflag == '\0')) ? TAR_FILE : hdr->typeflag);
              entry.offset = entry.offset_abs = pos; /* header_offset unused in tar */
              entry.fp_type = PHAR_FP;
              entry.flags = phar_tar_number(hdr->mode, sizeof(hdr->mode)) & PHAR_ENT_PERM_MASK;
              entry.timestamp = phar_tar_number(hdr->mtime, sizeof(hdr->mtime));
              entry.is_persistent = myphar->is_persistent;
#ifndef S_ISDIR
#define S_ISDIR(mode)       (((mode)&S_IFMT) == S_IFDIR)
#endif
              if (old && entry.tar_type == TAR_FILE && S_ISDIR(entry.flags)) {
                     entry.tar_type = TAR_DIR;
              }

              if (entry.tar_type == TAR_DIR) {
                     entry.is_dir = 1;
              } else {
                     entry.is_dir = 0;
              }

              entry.link = NULL;

              if (entry.tar_type == TAR_LINK) {
                     if (!zend_hash_exists(&myphar->manifest, hdr->linkname, strlen(hdr->linkname))) {
                            if (error) {
                                   spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file - hard link to non-existent file \"%s\"", fname, hdr->linkname);
                            }
                            pefree(entry.filename, entry.is_persistent);
                            php_stream_close(fp);
                            phar_destroy_phar_data(myphar TSRMLS_CC);
                            return FAILURE;
                     }
                     entry.link = estrdup(hdr->linkname);
              } else if (entry.tar_type == TAR_SYMLINK) {
                     entry.link = estrdup(hdr->linkname);
              }
              phar_set_inode(&entry TSRMLS_CC);
              zend_hash_add(&myphar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info), (void **) &newentry);

              if (entry.is_persistent) {
                     ++entry.manifest_pos;
              }

              if (entry.filename_len >= sizeof(".phar/.metadata")-1 && !memcmp(entry.filename, ".phar/.metadata", sizeof(".phar/.metadata")-1)) {
                     if (FAILURE == phar_tar_process_metadata(newentry, fp TSRMLS_CC)) {
                            if (error) {
                                   spprintf(error, 4096, "phar error: tar-based phar \"%s\" has invalid metadata in magic file \"%s\"", fname, entry.filename);
                            }
                            php_stream_close(fp);
                            phar_destroy_phar_data(myphar TSRMLS_CC);
                            return FAILURE;
                     }
              }

              if (!actual_alias && entry.filename_len == sizeof(".phar/alias.txt")-1 && !strncmp(entry.filename, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
                     /* found explicit alias */
                     if (size > 511) {
                            if (error) {
                                   spprintf(error, 4096, "phar error: tar-based phar \"%s\" has alias that is larger than 511 bytes, cannot process", fname);
                            }
                            php_stream_close(fp);
                            phar_destroy_phar_data(myphar TSRMLS_CC);
                            return FAILURE;
                     }

                     read = php_stream_read(fp, buf, size);

                     if (read == size) {
                            buf[size] = '\0';
                            if (!phar_validate_alias(buf, size)) {
                                   if (size > 50) {
                                          buf[50] = '.';
                                          buf[51] = '.';
                                          buf[52] = '.';
                                          buf[53] = '\0';
                                   }

                                   if (error) {
                                          spprintf(error, 4096, "phar error: invalid alias \"%s\" in tar-based phar \"%s\"", buf, fname);
                                   }

                                   php_stream_close(fp);
                                   phar_destroy_phar_data(myphar TSRMLS_CC);
                                   return FAILURE;
                            }

                            actual_alias = pestrndup(buf, size, myphar->is_persistent);
                            myphar->alias = actual_alias;
                            myphar->alias_len = size;
                            php_stream_seek(fp, pos, SEEK_SET);
                     } else {
                            if (error) {
                                   spprintf(error, 4096, "phar error: Unable to read alias from tar-based phar \"%s\"", fname);
                            }

                            php_stream_close(fp);
                            phar_destroy_phar_data(myphar TSRMLS_CC);
                            return FAILURE;
                     }
              }

              size = (size+511)&~511;

              if (((hdr->typeflag == '\0') || (hdr->typeflag == TAR_FILE)) && size > 0) {
                     /* this is not good enough - seek succeeds even on truncated tars */
                     php_stream_seek(fp, size, SEEK_CUR);
                     if ((uint)php_stream_tell(fp) > totalsize) {
                            if (error) {
                                   spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname);
                            }
                            php_stream_close(fp);
                            phar_destroy_phar_data(myphar TSRMLS_CC);
                            return FAILURE;
                     }
              }

              read = php_stream_read(fp, buf, sizeof(buf));

              if (read != sizeof(buf)) {
                     if (error) {
                            spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname);
                     }
                     php_stream_close(fp);
                     phar_destroy_phar_data(myphar TSRMLS_CC);
                     return FAILURE;
              }
       } while (read != 0);

       if (zend_hash_exists(&(myphar->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1)) {
              myphar->is_data = 0;
       } else {
              myphar->is_data = 1;
       }

       /* ensure signature set */
       if (!myphar->is_data && PHAR_G(require_hash) && !myphar->signature) {
              php_stream_close(fp);
              phar_destroy_phar_data(myphar TSRMLS_CC);
              if (error) {
                     spprintf(error, 0, "tar-based phar \"%s\" does not have a signature", fname);
              }
              return FAILURE;
       }

       myphar->fname = pestrndup(fname, fname_len, myphar->is_persistent);
#ifdef PHP_WIN32
       phar_unixify_path_separators(myphar->fname, fname_len);
#endif
       myphar->fname_len = fname_len;
       myphar->fp = fp;
       p = strrchr(myphar->fname, '/');

       if (p) {
              myphar->ext = memchr(p, '.', (myphar->fname + fname_len) - p);
              if (myphar->ext == p) {
                     myphar->ext = memchr(p + 1, '.', (myphar->fname + fname_len) - p - 1);
              }
              if (myphar->ext) {
                     myphar->ext_len = (myphar->fname + fname_len) - myphar->ext;
              }
       }

       phar_request_initialize(TSRMLS_C);

       if (SUCCESS != zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), myphar->fname, fname_len, (void*)&myphar, sizeof(phar_archive_data*), (void **)&actual)) {
              if (error) {
                     spprintf(error, 4096, "phar error: Unable to add tar-based phar \"%s\" to phar registry", fname);
              }
              php_stream_close(fp);
              phar_destroy_phar_data(myphar TSRMLS_CC);
              return FAILURE;
       }

       myphar = *actual;

       if (actual_alias) {
              phar_archive_data **fd_ptr;

              myphar->is_temporary_alias = 0;

              if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), actual_alias, myphar->alias_len, (void **)&fd_ptr)) {
                     if (SUCCESS != phar_free_alias(*fd_ptr, actual_alias, myphar->alias_len TSRMLS_CC)) {
                            if (error) {
                                   spprintf(error, 4096, "phar error: Unable to add tar-based phar \"%s\", alias is already in use", fname);
                            }
                            zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), myphar->fname, fname_len);
                            return FAILURE;
                     }
              }

              zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, myphar->alias_len, (void*)&myphar, sizeof(phar_archive_data*), NULL);
       } else {
              phar_archive_data **fd_ptr;

              if (alias_len) {
                     if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void **)&fd_ptr)) {
                            if (SUCCESS != phar_free_alias(*fd_ptr, alias, alias_len TSRMLS_CC)) {
                                   if (error) {
                                          spprintf(error, 4096, "phar error: Unable to add tar-based phar \"%s\", alias is already in use", fname);
                                   }
                                   zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), myphar->fname, fname_len);
                                   return FAILURE;
                            }
                     }
                     zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&myphar, sizeof(phar_archive_data*), NULL);
                     myphar->alias = pestrndup(alias, alias_len, myphar->is_persistent);
                     myphar->alias_len = alias_len;
              } else {
                     myphar->alias = pestrndup(myphar->fname, fname_len, myphar->is_persistent);
                     myphar->alias_len = fname_len;
              }

              myphar->is_temporary_alias = 1;
       }

       if (pphar) {
              *pphar = myphar;
       }

       return SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_parse_zipfile ( php_stream *  fp,
char *  fname,
int  fname_len,
char *  alias,
int  alias_len,
phar_archive_data **  pphar,
char **error  TSRMLS_DC 
)

Does not check for a previously opened phar in the cache.

Parse a new one and add it to the cache, returning either SUCCESS or FAILURE, and setting pphar to the pointer to the manifest entry

This is used by phar_open_from_fp to process a zip-based phar, but can be called directly.

Definition at line 166 of file zip.c.

{
       phar_zip_dir_end locator;
       char buf[sizeof(locator) + 65536];
       long size;
       php_uint16 i;
       phar_archive_data *mydata = NULL;
       phar_entry_info entry = {0};
       char *p = buf, *ext, *actual_alias = NULL;
       char *metadata = NULL;

       size = php_stream_tell(fp);

       if (size > sizeof(locator) + 65536) {
              /* seek to max comment length + end of central directory record */
              size = sizeof(locator) + 65536;
              if (FAILURE == php_stream_seek(fp, -size, SEEK_END)) {
                     php_stream_close(fp);
                     if (error) {
                            spprintf(error, 4096, "phar error: unable to search for end of central directory in zip-based phar \"%s\"", fname);
                     }
                     return FAILURE;
              }
       } else {
              php_stream_seek(fp, 0, SEEK_SET);
       }

       if (!php_stream_read(fp, buf, size)) {
              php_stream_close(fp);
              if (error) {
                     spprintf(error, 4096, "phar error: unable to read in data to search for end of central directory in zip-based phar \"%s\"", fname);
              }
              return FAILURE;
       }

       while ((p=(char *) memchr(p + 1, 'P', (size_t) (size - (p + 1 - buf)))) != NULL) {
              if (!memcmp(p + 1, "K\5\6", 3)) {
                     memcpy((void *)&locator, (void *) p, sizeof(locator));
                     if (PHAR_GET_16(locator.centraldisk) != 0 || PHAR_GET_16(locator.disknumber) != 0) {
                            /* split archives not handled */
                            php_stream_close(fp);
                            if (error) {
                                   spprintf(error, 4096, "phar error: split archives spanning multiple zips cannot be processed in zip-based phar \"%s\"", fname);
                            }
                            return FAILURE;
                     }

                     if (PHAR_GET_16(locator.counthere) != PHAR_GET_16(locator.count)) {
                            if (error) {
                                   spprintf(error, 4096, "phar error: corrupt zip archive, conflicting file count in end of central directory record in zip-based phar \"%s\"", fname);
                            }
                            php_stream_close(fp);
                            return FAILURE;
                     }

                     mydata = pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist));
                     mydata->is_persistent = PHAR_G(persist);

                     /* read in archive comment, if any */
                     if (PHAR_GET_16(locator.comment_len)) {

                            metadata = p + sizeof(locator);

                            if (PHAR_GET_16(locator.comment_len) != size - (metadata - buf)) {
                                   if (error) {
                                          spprintf(error, 4096, "phar error: corrupt zip archive, zip file comment truncated in zip-based phar \"%s\"", fname);
                                   }
                                   php_stream_close(fp);
                                   pefree(mydata, mydata->is_persistent);
                                   return FAILURE;
                            }

                            mydata->metadata_len = PHAR_GET_16(locator.comment_len);

                            if (phar_parse_metadata(&metadata, &mydata->metadata, PHAR_GET_16(locator.comment_len) TSRMLS_CC) == FAILURE) {
                                   mydata->metadata_len = 0;
                                   /* if not valid serialized data, it is a regular string */

                                   if (entry.is_persistent) {
                                          ALLOC_PERMANENT_ZVAL(mydata->metadata);
                                   } else {
                                          ALLOC_ZVAL(mydata->metadata);
                                   }

                                   INIT_ZVAL(*mydata->metadata);
                                   metadata = pestrndup(metadata, PHAR_GET_16(locator.comment_len), mydata->is_persistent);
                                   ZVAL_STRINGL(mydata->metadata, metadata, PHAR_GET_16(locator.comment_len), 0);
                            }
                     } else {
                            mydata->metadata = NULL;
                     }

                     goto foundit;
              }
       }

       php_stream_close(fp);

       if (error) {
              spprintf(error, 4096, "phar error: end of central directory not found in zip-based phar \"%s\"", fname);
       }

       return FAILURE;
foundit:
       mydata->fname = pestrndup(fname, fname_len, mydata->is_persistent);
#ifdef PHP_WIN32
       phar_unixify_path_separators(mydata->fname, fname_len);
#endif
       mydata->is_zip = 1;
       mydata->fname_len = fname_len;
       ext = strrchr(mydata->fname, '/');

       if (ext) {
              mydata->ext = memchr(ext, '.', (mydata->fname + fname_len) - ext);
              if (mydata->ext == ext) {
                     mydata->ext = memchr(ext + 1, '.', (mydata->fname + fname_len) - ext - 1);
              }
              if (mydata->ext) {
                     mydata->ext_len = (mydata->fname + fname_len) - mydata->ext;
              }
       }

       /* clean up on big-endian systems */
       /* seek to central directory */
       php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET);
       /* read in central directory */
       zend_hash_init(&mydata->manifest, PHAR_GET_16(locator.count),
              zend_get_hash_value, destroy_phar_manifest_entry, (zend_bool)mydata->is_persistent);
       zend_hash_init(&mydata->mounted_dirs, 5,
              zend_get_hash_value, NULL, (zend_bool)mydata->is_persistent);
       zend_hash_init(&mydata->virtual_dirs, PHAR_GET_16(locator.count) * 2,
              zend_get_hash_value, NULL, (zend_bool)mydata->is_persistent);
       entry.phar = mydata;
       entry.is_zip = 1;
       entry.fp_type = PHAR_FP;
       entry.is_persistent = mydata->is_persistent;
#define PHAR_ZIP_FAIL_FREE(errmsg, save) \
                     zend_hash_destroy(&mydata->manifest); \
                     mydata->manifest.arBuckets = 0; \
                     zend_hash_destroy(&mydata->mounted_dirs); \
                     mydata->mounted_dirs.arBuckets = 0; \
                     zend_hash_destroy(&mydata->virtual_dirs); \
                     mydata->virtual_dirs.arBuckets = 0; \
                     php_stream_close(fp); \
                     if (mydata->metadata) { \
                            zval_dtor(mydata->metadata); \
                     } \
                     if (mydata->signature) { \
                            efree(mydata->signature); \
                     } \
                     if (error) { \
                            spprintf(error, 4096, "phar error: %s in zip-based phar \"%s\"", errmsg, mydata->fname); \
                     } \
                     pefree(mydata->fname, mydata->is_persistent); \
                     if (mydata->alias) { \
                            pefree(mydata->alias, mydata->is_persistent); \
                     } \
                     pefree(mydata, mydata->is_persistent); \
                     efree(save); \
                     return FAILURE;
#define PHAR_ZIP_FAIL(errmsg) \
                     zend_hash_destroy(&mydata->manifest); \
                     mydata->manifest.arBuckets = 0; \
                     zend_hash_destroy(&mydata->mounted_dirs); \
                     mydata->mounted_dirs.arBuckets = 0; \
                     zend_hash_destroy(&mydata->virtual_dirs); \
                     mydata->virtual_dirs.arBuckets = 0; \
                     php_stream_close(fp); \
                     if (mydata->metadata) { \
                            zval_dtor(mydata->metadata); \
                     } \
                     if (mydata->signature) { \
                            efree(mydata->signature); \
                     } \
                     if (error) { \
                            spprintf(error, 4096, "phar error: %s in zip-based phar \"%s\"", errmsg, mydata->fname); \
                     } \
                     pefree(mydata->fname, mydata->is_persistent); \
                     if (mydata->alias) { \
                            pefree(mydata->alias, mydata->is_persistent); \
                     } \
                     pefree(mydata, mydata->is_persistent); \
                     return FAILURE;

       /* add each central directory item to the manifest */
       for (i = 0; i < PHAR_GET_16(locator.count); ++i) {
              phar_zip_central_dir_file zipentry;
              off_t beforeus = php_stream_tell(fp);

              if (sizeof(zipentry) != php_stream_read(fp, (char *) &zipentry, sizeof(zipentry))) {
                     PHAR_ZIP_FAIL("unable to read central directory entry, truncated");
              }

              /* clean up for bigendian systems */
              if (memcmp("PK\1\2", zipentry.signature, 4)) {
                     /* corrupted entry */
                     PHAR_ZIP_FAIL("corrupted central directory entry, no magic signature");
              }

              if (entry.is_persistent) {
                     entry.manifest_pos = i;
              }

              entry.compressed_filesize = PHAR_GET_32(zipentry.compsize);
              entry.uncompressed_filesize = PHAR_GET_32(zipentry.uncompsize);
              entry.crc32 = PHAR_GET_32(zipentry.crc32);
              /* do not PHAR_GET_16 either on the next line */
              entry.timestamp = phar_zip_d2u_time(zipentry.timestamp, zipentry.datestamp);
              entry.flags = PHAR_ENT_PERM_DEF_FILE;
              entry.header_offset = PHAR_GET_32(zipentry.offset);
              entry.offset = entry.offset_abs = PHAR_GET_32(zipentry.offset) + sizeof(phar_zip_file_header) + PHAR_GET_16(zipentry.filename_len) +
                     PHAR_GET_16(zipentry.extra_len);

              if (PHAR_GET_16(zipentry.flags) & PHAR_ZIP_FLAG_ENCRYPTED) {
                     PHAR_ZIP_FAIL("Cannot process encrypted zip files");
              }

              if (!PHAR_GET_16(zipentry.filename_len)) {
                     PHAR_ZIP_FAIL("Cannot process zips created from stdin (zero-length filename)");
              }

              entry.filename_len = PHAR_GET_16(zipentry.filename_len);
              entry.filename = (char *) pemalloc(entry.filename_len + 1, entry.is_persistent);

              if (entry.filename_len != php_stream_read(fp, entry.filename, entry.filename_len)) {
                     pefree(entry.filename, entry.is_persistent);
                     PHAR_ZIP_FAIL("unable to read in filename from central directory, truncated");
              }

              entry.filename[entry.filename_len] = '\0';

              if (entry.filename[entry.filename_len - 1] == '/') {
                     entry.is_dir = 1;
                     entry.filename_len--;
                     entry.flags |= PHAR_ENT_PERM_DEF_DIR;
              } else {
                     entry.is_dir = 0;
              }

              if (entry.filename_len == sizeof(".phar/signature.bin")-1 && !strncmp(entry.filename, ".phar/signature.bin", sizeof(".phar/signature.bin")-1)) {
                     size_t read;
                     php_stream *sigfile;
                     off_t now;
                     char *sig;

                     now = php_stream_tell(fp);
                     pefree(entry.filename, entry.is_persistent);
                     sigfile = php_stream_fopen_tmpfile();
                     if (!sigfile) {
                            PHAR_ZIP_FAIL("couldn't open temporary file");
                     }

                     php_stream_seek(fp, 0, SEEK_SET);
                     /* copy file contents + local headers and zip comment, if any, to be hashed for signature */
                     phar_stream_copy_to_stream(fp, sigfile, entry.header_offset, NULL);
                     /* seek to central directory */
                     php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET);
                     /* copy central directory header */
                     phar_stream_copy_to_stream(fp, sigfile, beforeus - PHAR_GET_32(locator.cdir_offset), NULL);
                     if (metadata) {
                            php_stream_write(sigfile, metadata, PHAR_GET_16(locator.comment_len));
                     }
                     php_stream_seek(fp, sizeof(phar_zip_file_header) + entry.header_offset + entry.filename_len + PHAR_GET_16(zipentry.extra_len), SEEK_SET);
                     sig = (char *) emalloc(entry.uncompressed_filesize);
                     read = php_stream_read(fp, sig, entry.uncompressed_filesize);
                     if (read != entry.uncompressed_filesize) {
                            php_stream_close(sigfile);
                            efree(sig);
                            PHAR_ZIP_FAIL("signature cannot be read");
                     }
                     mydata->sig_flags = PHAR_GET_32(sig);
                     if (FAILURE == phar_verify_signature(sigfile, php_stream_tell(sigfile), mydata->sig_flags, sig + 8, entry.uncompressed_filesize - 8, fname, &mydata->signature, &mydata->sig_len, error TSRMLS_CC)) {
                            efree(sig);
                            if (error) {
                                   char *save;
                                   php_stream_close(sigfile);
                                   spprintf(&save, 4096, "signature cannot be verified: %s", *error);
                                   efree(*error);
                                   PHAR_ZIP_FAIL_FREE(save, save);
                            } else {
                                   php_stream_close(sigfile);
                                   PHAR_ZIP_FAIL("signature cannot be verified");
                            }
                     }
                     php_stream_close(sigfile);
                     efree(sig);
                     /* signature checked out, let's ensure this is the last file in the phar */
                     if (i != PHAR_GET_16(locator.count) - 1) {
                            PHAR_ZIP_FAIL("entries exist after signature, invalid phar");
                     }

                     continue;
              }

              phar_add_virtual_dirs(mydata, entry.filename, entry.filename_len TSRMLS_CC);

              if (PHAR_GET_16(zipentry.extra_len)) {
                     off_t loc = php_stream_tell(fp);
                     if (FAILURE == phar_zip_process_extra(fp, &entry, PHAR_GET_16(zipentry.extra_len) TSRMLS_CC)) {
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("Unable to process extra field header for file in central directory");
                     }
                     php_stream_seek(fp, loc + PHAR_GET_16(zipentry.extra_len), SEEK_SET);
              }

              switch (PHAR_GET_16(zipentry.compressed)) {
                     case PHAR_ZIP_COMP_NONE :
                            /* compression flag already set */
                            break;
                     case PHAR_ZIP_COMP_DEFLATE :
                            entry.flags |= PHAR_ENT_COMPRESSED_GZ;
                            if (!PHAR_G(has_zlib)) {
                                   pefree(entry.filename, entry.is_persistent);
                                   PHAR_ZIP_FAIL("zlib extension is required");
                            }
                            break;
                     case PHAR_ZIP_COMP_BZIP2 :
                            entry.flags |= PHAR_ENT_COMPRESSED_BZ2;
                            if (!PHAR_G(has_bz2)) {
                                   pefree(entry.filename, entry.is_persistent);
                                   PHAR_ZIP_FAIL("bzip2 extension is required");
                            }
                            break;
                     case 1 :
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("unsupported compression method (Shrunk) used in this zip");
                     case 2 :
                     case 3 :
                     case 4 :
                     case 5 :
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("unsupported compression method (Reduce) used in this zip");
                     case 6 :
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("unsupported compression method (Implode) used in this zip");
                     case 7 :
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("unsupported compression method (Tokenize) used in this zip");
                     case 9 :
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("unsupported compression method (Deflate64) used in this zip");
                     case 10 :
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("unsupported compression method (PKWare Implode/old IBM TERSE) used in this zip");
                     case 14 :
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("unsupported compression method (LZMA) used in this zip");
                     case 18 :
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("unsupported compression method (IBM TERSE) used in this zip");
                     case 19 :
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("unsupported compression method (IBM LZ77) used in this zip");
                     case 97 :
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("unsupported compression method (WavPack) used in this zip");
                     case 98 :
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("unsupported compression method (PPMd) used in this zip");
                     default :
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("unsupported compression method (unknown) used in this zip");
              }

              /* get file metadata */
              if (PHAR_GET_16(zipentry.comment_len)) {
                     if (PHAR_GET_16(zipentry.comment_len) != php_stream_read(fp, buf, PHAR_GET_16(zipentry.comment_len))) {
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("unable to read in file comment, truncated");
                     }

                     p = buf;
                     entry.metadata_len = PHAR_GET_16(zipentry.comment_len);

                     if (phar_parse_metadata(&p, &(entry.metadata), PHAR_GET_16(zipentry.comment_len) TSRMLS_CC) == FAILURE) {
                            entry.metadata_len = 0;
                            /* if not valid serialized data, it is a regular string */

                            if (entry.is_persistent) {
                                   ALLOC_PERMANENT_ZVAL(entry.metadata);
                            } else {
                                   ALLOC_ZVAL(entry.metadata);
                            }

                            INIT_ZVAL(*entry.metadata);
                            ZVAL_STRINGL(entry.metadata, pestrndup(buf, PHAR_GET_16(zipentry.comment_len), entry.is_persistent), PHAR_GET_16(zipentry.comment_len), 0);
                     }
              } else {
                     entry.metadata = NULL;
              }

              if (!actual_alias && entry.filename_len == sizeof(".phar/alias.txt")-1 && !strncmp(entry.filename, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
                     php_stream_filter *filter;
                     off_t saveloc;
                     /* verify local file header */
                     phar_zip_file_header local;

                     /* archive alias found */
                     saveloc = php_stream_tell(fp);
                     php_stream_seek(fp, PHAR_GET_32(zipentry.offset), SEEK_SET);

                     if (sizeof(local) != php_stream_read(fp, (char *) &local, sizeof(local))) {
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("phar error: internal corruption of zip-based phar (cannot read local file header for alias)");
                     }

                     /* verify local header */
                     if (entry.filename_len != PHAR_GET_16(local.filename_len) || entry.crc32 != PHAR_GET_32(local.crc32) || entry.uncompressed_filesize != PHAR_GET_32(local.uncompsize) || entry.compressed_filesize != PHAR_GET_32(local.compsize)) {
                            pefree(entry.filename, entry.is_persistent);
                            PHAR_ZIP_FAIL("phar error: internal corruption of zip-based phar (local header of alias does not match central directory)");
                     }

                     /* construct actual offset to file start - local extra_len can be different from central extra_len */
                     entry.offset = entry.offset_abs =
                            sizeof(local) + entry.header_offset + PHAR_GET_16(local.filename_len) + PHAR_GET_16(local.extra_len);
#if PHP_VERSION_ID < 50207
                     /* work around Bug #46147 */
                     fp->writepos = fp->readpos = 0;
#endif
                     php_stream_seek(fp, entry.offset, SEEK_SET);
                     /* these next lines should be for php < 5.2.6 after 5.3 filters are fixed */
                     fp->writepos = 0;
                     fp->readpos = 0;
                     php_stream_seek(fp, entry.offset, SEEK_SET);
                     fp->writepos = 0;
                     fp->readpos = 0;
                     /* the above lines should be for php < 5.2.6 after 5.3 filters are fixed */

                     mydata->alias_len = entry.uncompressed_filesize;

                     if (entry.flags & PHAR_ENT_COMPRESSED_GZ) {
                            filter = php_stream_filter_create("zlib.inflate", NULL, php_stream_is_persistent(fp) TSRMLS_CC);

                            if (!filter) {
                                   pefree(entry.filename, entry.is_persistent);
                                   PHAR_ZIP_FAIL("unable to decompress alias, zlib filter creation failed");
                            }

                            php_stream_filter_append(&fp->readfilters, filter);

#if PHP_MAJOR_VERSION >= 6
                            if (!(entry.uncompressed_filesize = php_stream_copy_to_mem(fp, (void **) &actual_alias, entry.uncompressed_filesize, 0)) || !actual_alias) {
#else
                            if (!(entry.uncompressed_filesize = php_stream_copy_to_mem(fp, &actual_alias, entry.uncompressed_filesize, 0)) || !actual_alias) {
#endif
                                   pefree(entry.filename, entry.is_persistent);
#if PHP_VERSION_ID < 50207
                                   PHAR_ZIP_FAIL("unable to read in alias, truncated (PHP 5.2.7 and newer has a potential fix for this problem)");
#endif
                                   PHAR_ZIP_FAIL("unable to read in alias, truncated");
                            }

                            php_stream_filter_flush(filter, 1);
                            php_stream_filter_remove(filter, 1 TSRMLS_CC);

                     } else if (entry.flags & PHAR_ENT_COMPRESSED_BZ2) {
                            filter = php_stream_filter_create("bzip2.decompress", NULL, php_stream_is_persistent(fp) TSRMLS_CC);

                            if (!filter) {
                                   pefree(entry.filename, entry.is_persistent);
                                   PHAR_ZIP_FAIL("unable to read in alias, bzip2 filter creation failed");
                            }

                            php_stream_filter_append(&fp->readfilters, filter);

#if PHP_MAJOR_VERSION >= 6
                            if (!(entry.uncompressed_filesize = php_stream_copy_to_mem(fp, (void **) &actual_alias, entry.uncompressed_filesize, 0)) || !actual_alias) {
#else
                            if (!(entry.uncompressed_filesize = php_stream_copy_to_mem(fp, &actual_alias, entry.uncompressed_filesize, 0)) || !actual_alias) {
#endif
                                   pefree(entry.filename, entry.is_persistent);
#if PHP_VERSION_ID < 50207
                                   PHAR_ZIP_FAIL("unable to read in alias, truncated (PHP 5.2.7 and newer has a potential fix for this problem)");
#endif
                                   PHAR_ZIP_FAIL("unable to read in alias, truncated");
                            }

                            php_stream_filter_flush(filter, 1);
                            php_stream_filter_remove(filter, 1 TSRMLS_CC);
                     } else {
#if PHP_MAJOR_VERSION >= 6
                            if (!(entry.uncompressed_filesize = php_stream_copy_to_mem(fp, (void **) &actual_alias, entry.uncompressed_filesize, 0)) || !actual_alias) {
#else
                            if (!(entry.uncompressed_filesize = php_stream_copy_to_mem(fp, &actual_alias, entry.uncompressed_filesize, 0)) || !actual_alias) {
#endif
                                   pefree(entry.filename, entry.is_persistent);
                                   PHAR_ZIP_FAIL("unable to read in alias, truncated");
                            }
                     }

                     /* return to central directory parsing */
                     php_stream_seek(fp, saveloc, SEEK_SET);
              }

              phar_set_inode(&entry TSRMLS_CC);
              zend_hash_add(&mydata->manifest, entry.filename, entry.filename_len, (void *)&entry,sizeof(phar_entry_info), NULL);
       }

       mydata->fp = fp;

       if (zend_hash_exists(&(mydata->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1)) {
              mydata->is_data = 0;
       } else {
              mydata->is_data = 1;
       }

       zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);

       if (actual_alias) {
              phar_archive_data **fd_ptr;

              if (!phar_validate_alias(actual_alias, mydata->alias_len)) {
                     if (error) {
                            spprintf(error, 4096, "phar error: invalid alias \"%s\" in zip-based phar \"%s\"", actual_alias, fname);
                     }
                     efree(actual_alias);
                     zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len);
                     return FAILURE;
              }

              mydata->is_temporary_alias = 0;

              if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), actual_alias, mydata->alias_len, (void **)&fd_ptr)) {
                     if (SUCCESS != phar_free_alias(*fd_ptr, actual_alias, mydata->alias_len TSRMLS_CC)) {
                            if (error) {
                                   spprintf(error, 4096, "phar error: Unable to add zip-based phar \"%s\" with implicit alias, alias is already in use", fname);
                            }
                            efree(actual_alias);
                            zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len);
                            return FAILURE;
                     }
              }

              mydata->alias = entry.is_persistent ? pestrndup(actual_alias, mydata->alias_len, 1) : actual_alias;

              if (entry.is_persistent) {
                     efree(actual_alias);
              }

              zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, mydata->alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
       } else {
              phar_archive_data **fd_ptr;

              if (alias_len) {
                     if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void **)&fd_ptr)) {
                            if (SUCCESS != phar_free_alias(*fd_ptr, alias, alias_len TSRMLS_CC)) {
                                   if (error) {
                                          spprintf(error, 4096, "phar error: Unable to add zip-based phar \"%s\" with explicit alias, alias is already in use", fname);
                                   }
                                   zend_hash_del(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len);
                                   return FAILURE;
                            }
                     }

                     zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, mydata->alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
                     mydata->alias = pestrndup(alias, alias_len, mydata->is_persistent);
                     mydata->alias_len = alias_len;
              } else {
                     mydata->alias = pestrndup(mydata->fname, fname_len, mydata->is_persistent);
                     mydata->alias_len = fname_len;
              }

              mydata->is_temporary_alias = 1;
       }

       if (pphar) {
              *pphar = mydata;
       }

       return SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

phar_path_check_result phar_path_check ( char **  p,
int len,
const char **  error 
)

Definition at line 25 of file phar_path_check.c.

{
       const unsigned char *p = (const unsigned char*)*s;
       const unsigned char *m;

       if (*len == 1 && *p == '.') {
              *error = "current directory reference";
              return pcr_err_curr_dir;
       } else if (*len == 2 && p[0] == '.' && p[1] == '.') {
              *error = "upper directory reference";
              return pcr_err_up_dir;
       }

#define YYCTYPE         unsigned char
#define YYCURSOR        p
#define YYLIMIT         p+*len
#define YYMARKER        m
#define YYFILL(n)

loop:

#line 47 "ext/phar/phar_path_check.c"
{
       YYCTYPE yych;

       if ((YYLIMIT - YYCURSOR) < 4) YYFILL(4);
       yych = *YYCURSOR;
       if (yych <= '.') {
              if (yych <= '\n') {
                     if (yych <= 0x00) goto yy13;
                     if (yych <= '\t') goto yy10;
                     goto yy12;
              } else {
                     if (yych <= 0x19) goto yy10;
                     if (yych == '*') goto yy6;
                     goto yy15;
              }
       } else {
              if (yych <= '?') {
                     if (yych <= '/') goto yy2;
                     if (yych <= '>') goto yy15;
                     goto yy8;
              } else {
                     if (yych == '\\') goto yy4;
                     if (yych <= 0x7F) goto yy15;
                     goto yy10;
              }
       }
yy2:
       yych = *(YYMARKER = ++YYCURSOR);
       if (yych <= '-') goto yy3;
       if (yych <= '.') goto yy16;
       if (yych <= '/') goto yy18;
yy3:
#line 93 "ext/phar/phar_path_check.re"
       {
                     goto loop;
              }
#line 84 "ext/phar/phar_path_check.c"
yy4:
       ++YYCURSOR;
#line 60 "ext/phar/phar_path_check.re"
       {
                     *error = "back-slash";
                     return pcr_err_back_slash;
              }
#line 92 "ext/phar/phar_path_check.c"
yy6:
       ++YYCURSOR;
#line 64 "ext/phar/phar_path_check.re"
       {
                     *error = "star";
                     return pcr_err_star;
              }
#line 100 "ext/phar/phar_path_check.c"
yy8:
       ++YYCURSOR;
#line 68 "ext/phar/phar_path_check.re"
       {
                     if (**s == '/') {
                            (*s)++;
                     }
                     *len = (p - (const unsigned char*)*s) -1;
                     *error = NULL;
                     return pcr_use_query;
              }
#line 112 "ext/phar/phar_path_check.c"
yy10:
       ++YYCURSOR;
yy11:
#line 76 "ext/phar/phar_path_check.re"
       {
                     *error ="illegal character";
                     return pcr_err_illegal_char;
              }
#line 121 "ext/phar/phar_path_check.c"
yy12:
       yych = *++YYCURSOR;
       goto yy11;
yy13:
       ++YYCURSOR;
#line 80 "ext/phar/phar_path_check.re"
       {
                     if (**s == '/') {
                            (*s)++;
                            (*len)--;
                     }
                     if ((p - (const unsigned char*)*s) - 1 != *len)
                     {
                            *error ="illegal character";
                            return pcr_err_illegal_char;
                     }
                     *error = NULL;
                     return pcr_is_ok;
              }
#line 141 "ext/phar/phar_path_check.c"
yy15:
       yych = *++YYCURSOR;
       goto yy3;
yy16:
       yych = *++YYCURSOR;
       if (yych <= 0x00) goto yy21;
       if (yych <= '-') goto yy17;
       if (yych <= '.') goto yy20;
       if (yych <= '/') goto yy21;
yy17:
       YYCURSOR = YYMARKER;
       goto yy3;
yy18:
       ++YYCURSOR;
#line 48 "ext/phar/phar_path_check.re"
       {
                     *error = "double slash";
                     return pcr_err_double_slash;
              }
#line 161 "ext/phar/phar_path_check.c"
yy20:
       yych = *++YYCURSOR;
       if (yych <= 0x00) goto yy23;
       if (yych == '/') goto yy23;
       goto yy17;
yy21:
       ++YYCURSOR;
#line 56 "ext/phar/phar_path_check.re"
       {
                     *error = "current directory reference";
                     return pcr_err_curr_dir;
              }
#line 174 "ext/phar/phar_path_check.c"
yy23:
       ++YYCURSOR;
#line 52 "ext/phar/phar_path_check.re"
       {
                     *error = "upper directory reference";
                     return pcr_err_up_dir;
              }
#line 182 "ext/phar/phar_path_check.c"
}
#line 96 "ext/phar/phar_path_check.re"

}

Here is the caller graph for this function:

int phar_postprocess_file ( phar_entry_data idata,
php_uint32  crc32,
char **  error,
int process_zip  TSRMLS_DC 
)

Validate the CRC32 of a file opened from within the phar.

Definition at line 2404 of file phar.c.

{
       php_uint32 crc = ~0;
       int len = idata->internal_file->uncompressed_filesize;
       php_stream *fp = idata->fp;
       phar_entry_info *entry = idata->internal_file;

       if (error) {
              *error = NULL;
       }

       if (entry->is_zip && process_zip > 0) {
              /* verify local file header */
              phar_zip_file_header local;
              phar_zip_data_desc desc;

              if (SUCCESS != phar_open_archive_fp(idata->phar TSRMLS_CC)) {
                     spprintf(error, 0, "phar error: unable to open zip-based phar archive \"%s\" to verify local file header for file \"%s\"", idata->phar->fname, entry->filename);
                     return FAILURE;
              }
              php_stream_seek(phar_get_entrypfp(idata->internal_file TSRMLS_CC), entry->header_offset, SEEK_SET);

              if (sizeof(local) != php_stream_read(phar_get_entrypfp(idata->internal_file TSRMLS_CC), (char *) &local, sizeof(local))) {

                     spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local file header for file \"%s\")", idata->phar->fname, entry->filename);
                     return FAILURE;
              }

              /* check for data descriptor */
              if (((PHAR_ZIP_16(local.flags)) & 0x8) == 0x8) {
                     php_stream_seek(phar_get_entrypfp(idata->internal_file TSRMLS_CC),
                                   entry->header_offset + sizeof(local) +
                                   PHAR_ZIP_16(local.filename_len) +
                                   PHAR_ZIP_16(local.extra_len) +
                                   entry->compressed_filesize, SEEK_SET);
                     if (sizeof(desc) != php_stream_read(phar_get_entrypfp(idata->internal_file TSRMLS_CC),
                                                     (char *) &desc, sizeof(desc))) {
                            spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local data descriptor for file \"%s\")", idata->phar->fname, entry->filename);
                            return FAILURE;
                     }
                     if (desc.signature[0] == 'P' && desc.signature[1] == 'K') {
                            memcpy(&(local.crc32), &(desc.crc32), 12);
                     } else {
                            /* old data descriptors have no signature */
                            memcpy(&(local.crc32), &desc, 12);
                     }
              }
              /* verify local header */
              if (entry->filename_len != PHAR_ZIP_16(local.filename_len) || entry->crc32 != PHAR_ZIP_32(local.crc32) || entry->uncompressed_filesize != PHAR_ZIP_32(local.uncompsize) || entry->compressed_filesize != PHAR_ZIP_32(local.compsize)) {
                     spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (local header of file \"%s\" does not match central directory)", idata->phar->fname, entry->filename);
                     return FAILURE;
              }

              /* construct actual offset to file start - local extra_len can be different from central extra_len */
              entry->offset = entry->offset_abs =
                     sizeof(local) + entry->header_offset + PHAR_ZIP_16(local.filename_len) + PHAR_ZIP_16(local.extra_len);

              if (idata->zero && idata->zero != entry->offset_abs) {
                     idata->zero = entry->offset_abs;
              }
       }

       if (process_zip == 1) {
              return SUCCESS;
       }

       php_stream_seek(fp, idata->zero, SEEK_SET);

       while (len--) {
              CRC32(crc, php_stream_getc(fp));
       }

       php_stream_seek(fp, idata->zero, SEEK_SET);

       if (~crc == crc32) {
              entry->is_crc_checked = 1;
              return SUCCESS;
       } else {
              spprintf(error, 0, "phar error: internal corruption of phar \"%s\" (crc32 mismatch on file \"%s\")", idata->phar->fname, entry->filename);
              return FAILURE;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void phar_remove_virtual_dirs ( phar_archive_data *  phar,
char *  filename,
int filename_len  TSRMLS_DC 
)

Definition at line 3582 of file phar.c.

{
       if (!PHAR_GLOBALS->request_init)
       {
              PHAR_G(last_phar) = NULL;
              PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
              PHAR_G(has_bz2) = zend_hash_exists(&module_registry, "bz2", sizeof("bz2"));
              PHAR_G(has_zlib) = zend_hash_exists(&module_registry, "zlib", sizeof("zlib"));
              PHAR_GLOBALS->request_init = 1;
              PHAR_GLOBALS->request_ends = 0;
              PHAR_GLOBALS->request_done = 0;
              zend_hash_init(&(PHAR_GLOBALS->phar_fname_map), 5, zend_get_hash_value, destroy_phar_data,  0);
              zend_hash_init(&(PHAR_GLOBALS->phar_persist_map), 5, zend_get_hash_value, NULL,  0);
              zend_hash_init(&(PHAR_GLOBALS->phar_alias_map), 5, zend_get_hash_value, NULL, 0);

              if (PHAR_G(manifest_cached)) {
                     phar_archive_data **pphar;
                     phar_entry_fp *stuff = (phar_entry_fp *) ecalloc(zend_hash_num_elements(&cached_phars), sizeof(phar_entry_fp));

                     for (zend_hash_internal_pointer_reset(&cached_phars);
                     zend_hash_get_current_data(&cached_phars, (void **)&pphar) == SUCCESS;
                     zend_hash_move_forward(&cached_phars)) {
                            stuff[pphar[0]->phar_pos].manifest = (phar_entry_fp_info *) ecalloc( zend_hash_num_elements(&(pphar[0]->manifest)), sizeof(phar_entry_fp_info));
                     }

                     PHAR_GLOBALS->cached_fp = stuff;
              }

              PHAR_GLOBALS->phar_SERVER_mung_list = 0;
              PHAR_G(cwd) = NULL;
              PHAR_G(cwd_len) = 0;
              PHAR_G(cwd_init) = 0;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_seek_efp ( phar_entry_info entry,
off_t  offset,
int  whence,
off_t  position,
int follow_links  TSRMLS_DC 
)

Definition at line 124 of file util.c.

{
       php_stream *fp = phar_get_efp(entry, follow_links TSRMLS_CC);
       off_t temp, eoffset;

       if (!fp) {
              return -1;
       }

       if (follow_links) {
              phar_entry_info *t;
              t = phar_get_link_source(entry TSRMLS_CC);
              if (t) {
                     entry = t;
              }
       }

       if (entry->is_dir) {
              return 0;
       }

       eoffset = phar_get_fp_offset(entry TSRMLS_CC);

       switch (whence) {
              case SEEK_END:
                     temp = eoffset + entry->uncompressed_filesize + offset;
                     break;
              case SEEK_CUR:
                     temp = eoffset + position + offset;
                     break;
              case SEEK_SET:
                     temp = eoffset + offset;
                     break;
              default:
                     temp = 0;
                     break;
       }

       if (temp > eoffset + (off_t) entry->uncompressed_filesize) {
              return -1;
       }

       if (temp < eoffset) {
              return -1;
       }

       return php_stream_seek(fp, temp, SEEK_SET);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int phar_separate_entry_fp ( phar_entry_info entry,
char **error  TSRMLS_DC 
)

Definition at line 1121 of file util.c.

{
       php_stream *fp;
       phar_entry_info *link;

       if (FAILURE == phar_open_entry_fp(entry, error, 1 TSRMLS_CC)) {
              return FAILURE;
       }

       if (entry->fp_type == PHAR_MOD) {
              return SUCCESS;
       }

       fp = php_stream_fopen_tmpfile();
       phar_seek_efp(entry, 0, SEEK_SET, 0, 1 TSRMLS_CC);
       link = phar_get_link_source(entry TSRMLS_CC);

       if (!link) {
              link = entry;
       }

       if (SUCCESS != phar_stream_copy_to_stream(phar_get_efp(link, 0 TSRMLS_CC), fp, link->uncompressed_filesize, NULL)) {
              if (error) {
                     spprintf(error, 4096, "phar error: cannot separate entry file \"%s\" contents in phar archive \"%s\" for write access", entry->filename, entry->phar->fname);
              }
              return FAILURE;
       }

       if (entry->link) {
              efree(entry->link);
              entry->link = NULL;
              entry->tar_type = (entry->is_tar ? TAR_FILE : '\0');
       }

       entry->offset = 0;
       entry->fp = fp;
       entry->fp_type = PHAR_MOD;
       entry->is_modified = 1;
       return SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void phar_set_entrypfp ( phar_entry_info entry,
php_stream *fp  TSRMLS_DC 
) [inline, static]

Definition at line 378 of file phar_internal.h.

{
       if (!entry->phar->is_persistent) {
              entry->phar->fp =  fp;
              return;
       }

       PHAR_GLOBALS->cached_fp[entry->phar->phar_pos].fp = fp;
}