1
  "   l=J*e8n	1hh      42
  ,   lY>eJ}@?q1hq_I|+ ?     /*
  +----------------------------------------------------------------------+
  | phar php single-file executable PHP extension                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 2005-2016 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: 6e5cec2462a6ded53d4379ea9a69487a60d5c43c $ */

#define PHAR_MAIN 1
#include "phar_internal.h"
#include "SAPI.h"
#include "func_interceptors.h"

static void destroy_phar_data(void *pDest);

ZEND_DECLARE_MODULE_GLOBALS(phar)
char *(*phar_save_resolve_path)(const char *filename, int filename_len TSRMLS_DC);

/**
 * set's phar->is_writeable based on the current INI value
 */
static int phar_set_writeable_bit(void *pDest, void *argument TSRMLS_DC) /* {{{ */
{
	zend_bool keep = *(zend_bool *)argument;
	phar_archive_data *phar = *(phar_archive_data **)pDest;

	if (!phar->is_data) {
		phar->is_writeable = !keep;
	}

	return ZEND_HASH_APPLY_KEEP;
}
/* }}} */

/* if the original value is 0 (disabled), then allow setting/unsetting at will. Otherwise only allow 1 (enabled), and error on disabling */
ZEND_INI_MH(phar_ini_modify_handler) /* {{{ */
{
	zend_bool old, ini;

	if (entry->name_length == 14) {
		old = PHAR_G(readonly_orig);
	} else {
		old = PHAR_G(require_hash_orig);
	}

	if (new_value_length == 2 && !strcasecmp("on", new_value)) {
		ini = (zend_bool) 1;
	}
	else if (new_value_length == 3 && !strcasecmp("yes", new_value)) {
		ini = (zend_bool) 1;
	}
	else if (new_value_length == 4 && !strcasecmp("true", new_value)) {
		ini = (zend_bool) 1;
	}
	else {
		ini = (zend_bool) atoi(new_value);
	}

	/* do not allow unsetting in runtime */
	if (stage == ZEND_INI_STAGE_STARTUP) {
		if (entry->name_length == 14) {
			PHAR_G(readonly_orig) = ini;
		} else {
			PHAR_G(require_hash_orig) = ini;
		}
	} else if (old && !ini) {
		return FAILURE;
	}

	if (entry->name_length == 14) {
		PHAR_G(readonly) = ini;
		if (PHAR_GLOBALS->request_init && PHAR_GLOBALS->phar_fname_map.arBuckets) {
			zend_hash_apply_with_argument(&(PHAR_GLOBALS->phar_fname_map), phar_set_writeable_bit, (void *)&ini TSRMLS_CC);
		}
	} else {
		PHAR_G(require_hash) = ini;
	}

	return SUCCESS;
}
/* }}}*/

/* this global stores the global cached pre-parsed manifests */
HashTable cached_phars;
HashTable cached_alias;

static void phar_split_cache_list(TSRMLS_D) /* {{{ */
{
	char *tmp;
	char *key, *lasts, *end;
	char ds[2];
	phar_archive_data *phar;
	uint i = 0;

	if (!PHAR_GLOBALS->cache_list || !(PHAR_GLOBALS->cache_list[0])) {
		return;
	}

	ds[0] = DEFAULT_DIR_SEPARATOR;
	ds[1] = '\0';
	tmp = estrdup(PHAR_GLOBALS->cache_list);

	/* fake request startup */
	PHAR_GLOBALS->request_init = 1;
	if (zend_hash_init(&EG(regular_list), 0, NULL, NULL, 0) == SUCCESS) {
		EG(regular_list).nNextFreeElement=1;	/* we don't want resource id 0 */
	}

	PHAR_G(has_bz2) = zend_hash_exists(&module_registry, "bz2", sizeof("bz2"));
	PHAR_G(has_zlib) = zend_hash_exists(&module_registry, "zlib", sizeof("zlib"));
	/* these two are dummies and will be destroyed later */
	zend_hash_init(&cache