summaryrefslogtreecommitdiff
path: root/ext/phar/phar_internal.h
blob: 8fdfefe24fc4a413486006bbb3a715b3a49e47e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
/*
  +----------------------------------------------------------------------+
  | phar php single-file executable PHP extension                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 2006-2007 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 3.01 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.php.net/license/3_01.txt.                                 |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Authors: Gregory Beaver <cellog@php.net>                             |
  |          Marcus Boerger <helly@php.net>                              |
  +----------------------------------------------------------------------+
*/

/* $Id$ */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <time.h>
#include "php.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 "main/php_streams.h"
#include "ext/standard/info.h"
#include "ext/standard/basic_functions.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"
#if HAVE_SPL
#include "ext/spl/spl_array.h"
#include "ext/spl/spl_directory.h"
#include "ext/spl/spl_engine.h"
#include "ext/spl/spl_exceptions.h"
#include "ext/spl/spl_iterators.h"
#endif
#include "php_phar.h"
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#if HAVE_HASH_EXT
#include "ext/hash/php_hash.h"
#include "ext/hash/php_hash_sha.h"
#endif

#ifndef E_RECOVERABLE_ERROR
#define E_RECOVERABLE_ERROR E_ERROR
#endif

#define PHAR_EXT_VERSION_STR      "1.2.2"
#define PHAR_API_VERSION_STR      "1.1.0"
/* x.y.z maps to 0xyz0 */
#define PHAR_API_VERSION          0x1100
#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_SIG_MD5              0x0001
#define PHAR_SIG_SHA1             0x0002
#define PHAR_SIG_SHA256           0x0003
#define PHAR_SIG_SHA512           0x0004
#define PHAR_SIG_PGP              0x0010

/* flags byte for each file adheres to these bitmasks.
   All unused values are reserved */
#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

ZEND_BEGIN_MODULE_GLOBALS(phar)
	HashTable   phar_fname_map;
	HashTable   phar_alias_map;
	HashTable   phar_plain_map;
	char*       extract_list;
	int         readonly;
	zend_bool   readonly_orig;
	zend_bool   require_hash_orig;
	int         request_init;
	int         require_hash;
	int         request_done;
	int         request_ends;
ZEND_END_MODULE_GLOBALS(phar)

ZEND_EXTERN_MODULE_GLOBALS(phar)

#ifdef ZTS
#	include "TSRM.h"
#	define PHAR_G(v) TSRMG(phar_globals_id, zend_phar_globals *, v)
#	define PHAR_GLOBALS ((zend_phar_globals *) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(phar_globals_id)])
#else
#	define PHAR_G(v) (phar_globals.v)
#	define PHAR_GLOBALS (&phar_globals)
#endif

#ifndef php_uint16
# if SIZEOF_SHORT == 2
#  define php_uint16 unsigned short
# else
#  define php_uint16 uint16_t
# endif
#endif

#if HAVE_SPL
typedef union _phar_archive_object  phar_archive_object;
typedef union _phar_entry_object    phar_entry_object;
#endif

typedef struct _phar_archive_data phar_archive_data;
/* entry for one file in a phar file */
typedef struct _phar_entry_info {
	/* first bytes are exactly as in file */
	php_uint32               uncompressed_filesize;
	php_uint32               timestamp;
	php_uint32               compressed_filesize;
	php_uint32               crc32;
	php_uint32               flags;
	/* remainder */
	/* when changing compression, save old flags in case fp is NULL */
	php_uint32               old_flags;
	zval                     *metadata;
	php_uint32               filename_len;
	char                     *filename;
	long                     offset_within_phar;
	php_stream               *fp;
	php_stream               *cfp;
	int                      fp_refcount;
	int                      is_crc_checked:1;
	int                      is_modified:1;
	int                      is_deleted:1;
	/* used when iterating */
	int                      is_dir:1;
	phar_archive_data        *phar;
	smart_str                metadata_str;
} phar_entry_info;

/* information about a phar file (the archive itself) */
struct _phar_archive_data {
	char                     *fname;
	int                      fname_len;
	char                     *alias;
	int                      alias_len;
	char                     version[12];
	size_t                   internal_file_start;
	size_t                   halt_offset;
	HashTable                manifest;
	php_uint32               flags;
	php_uint32               min_timestamp;
	php_uint32               max_timestamp;
	php_stream               *fp;
	int                      refcount;
	php_uint32               sig_flags;
	int                      sig_len;
	char                     *signature;
	zval                     *metadata;
	int                      is_explicit_alias:1;
	int                      is_modified:1;
	int                      is_writeable:1;
	int                      is_brandnew:1;
	/* defer phar creation */
	int                      donotflush:1;
};


/* stream access data for one file entry in a phar file */
typedef struct _phar_entry_data {
	phar_archive_data        *phar;
	/* stream position proxy, allows multiple open streams referring to the same fp */
	php_stream               *fp;
	off_t                    position;
	/* for copies of the phar fp, defines where 0 is */
	off_t                    zero;
	int                      for_write:1;
	phar_entry_info          *internal_file;
} phar_entry_data;

#if HAVE_SPL
/* archive php object */
union _phar_archive_object {
	zend_object              std;
	spl_filesystem_object    spl;
	struct {
	    zend_object          std;
	    phar_archive_data    *archive;
	} arc;
};
#endif

#if HAVE_SPL
/* entry php object */
union _phar_entry_object {
	zend_object              std;
	spl_filesystem_object    spl;
	struct {
	    zend_object          std;
	    phar_entry_info      *entry;
	} ent;
};
#endif

BEGIN_EXTERN_C()

void phar_request_initialize(TSRMLS_D);

void phar_object_init(TSRMLS_D);

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

#ifdef PHAR_MAIN

static int phar_open_fp(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error TSRMLS_DC);

static php_url* phar_open_url(php_stream_wrapper *wrapper, char *filename, char *mode, int options TSRMLS_DC);

static php_stream* phar_wrapper_open_url(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
static php_stream* phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
static int phar_wrapper_rename(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC);
static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC);
static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC);

/* file/stream handlers */
static size_t phar_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC);
static size_t phar_stream_read( php_stream *stream, char *buf, size_t count TSRMLS_DC);
static int    phar_stream_close(php_stream *stream, int close_handle TSRMLS_DC);
static int    phar_stream_flush(php_stream *stream TSRMLS_DC);
static int    phar_stream_seek( php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC);
static int    phar_stream_stat( php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC);

/* directory handlers */
static size_t phar_dir_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC);
static size_t phar_dir_read( php_stream *stream, char *buf, size_t count TSRMLS_DC);
static int    phar_dir_close(php_stream *stream, int close_handle TSRMLS_DC);
static int    phar_dir_flush(php_stream *stream TSRMLS_DC);
static int    phar_dir_seek( php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC);
static int    phar_dir_stat( php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC);

#endif

int phar_archive_delref(phar_archive_data *phar TSRMLS_DC);
int phar_entry_delref(phar_entry_data *idata TSRMLS_DC);

phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len, char **error TSRMLS_DC);
phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, int path_len, char dir, char **error TSRMLS_DC);
phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC);
int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **error TSRMLS_DC);
int phar_detect_phar_fname_ext(const char *filename, int check_length, char **ext_str, int *ext_len);
int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len TSRMLS_DC);

typedef enum {
	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
} phar_path_check_result;

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

END_EXTERN_C()

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */