From 82e0c0bba98c716f9b36ad7aca582b7ca9c1d17e Mon Sep 17 00:00:00 2001 From: florian Date: Mon, 21 Jan 2013 15:27:42 +0000 Subject: [PATCH] [packages] php5: Remove all patched-in pecl modules, prepare for standalone pecl modules Signed-off-by: Michael Heimpold git-svn-id: svn://svn.openwrt.org/openwrt/packages@35272 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- lang/php5/Makefile | 40 +- lang/php5/patches/005-APC.patch | 22543 -------------- lang/php5/patches/010-PECL-dio.patch | 3546 --- .../011-PECL-dio-additional-baudrates.patch | 29 - lang/php5/patches/020-PECL-add-libevent.patch | 1857 -- lang/php5/patches/030-PECL-add-http.patch | 29944 ------------------- 6 files changed, 4 insertions(+), 57955 deletions(-) delete mode 100644 lang/php5/patches/005-APC.patch delete mode 100644 lang/php5/patches/010-PECL-dio.patch delete mode 100644 lang/php5/patches/011-PECL-dio-additional-baudrates.patch delete mode 100644 lang/php5/patches/020-PECL-add-libevent.patch delete mode 100644 lang/php5/patches/030-PECL-add-http.patch diff --git a/lang/php5/Makefile b/lang/php5/Makefile index 9d3170ffa..d08622361 100644 --- a/lang/php5/Makefile +++ b/lang/php5/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=php PKG_VERSION:=5.4.5 -PKG_RELEASE:=3 +PKG_RELEASE:=4 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=http://www.php.net/distributions/ @@ -19,17 +19,16 @@ PKG_FIXUP:=libtool no-autoreconf PKG_BUILD_PARALLEL:=1 PHP5_MODULES = \ - apc \ calendar ctype curl \ fileinfo \ - dio dom \ + dom \ exif \ ftp \ gettext gd gmp \ - hash http \ + hash \ iconv \ json \ - ldap libevent \ + ldap \ mbstring mcrypt mysql mysqli \ openssl \ pcntl pdo pdo-mysql pdo-pgsql pdo-sqlite pgsql \ @@ -152,12 +151,6 @@ else CONFIGURE_ARGS+= --disable-cgi endif -ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-apc),) - CONFIGURE_ARGS+= --enable-apc=shared --disable-apc-mmap --disable-apc-pthreadmutex -else - CONFIGURE_ARGS+= --disable-apc -endif - ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-calendar),) CONFIGURE_ARGS+= --enable-calendar=shared else @@ -188,12 +181,6 @@ else CONFIGURE_ARGS+= --without-gettext endif -ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-dio),) - CONFIGURE_ARGS+= --enable-dio=shared -else - CONFIGURE_ARGS+= --disable-dio -endif - ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-dom),) CONFIGURE_ARGS+= --enable-dom=shared else @@ -238,15 +225,6 @@ else CONFIGURE_ARGS+= --disable-hash endif -ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-http),) - CONFIGURE_ARGS+= \ - --enable-http=shared \ - --without-http-shared-deps \ - --with-http-curl-requests="$(STAGING_DIR)/usr" -else - CONFIGURE_ARGS+= --disable-http -endif - ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-iconv),) CONFIGURE_ARGS+= --with-iconv=shared,"$(ICONV_PREFIX)" else @@ -267,12 +245,6 @@ else CONFIGURE_ARGS+= --without-ldap endif -ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-libevent),) - CONFIGURE_ARGS+= --with-libevent=shared,"$(STAGING_DIR)/usr" -else - CONFIGURE_ARGS+= --without-libevent -endif - ifneq ($(SDK)$(CONFIG_PACKAGE_php5-mod-mbstring),) CONFIGURE_ARGS+= --enable-mbstring=shared --enable-mbregex else @@ -530,12 +502,10 @@ $(eval $(call BuildPackage,php5-cgi)) $(eval $(call BuildPackage,php5-fastcgi)) #$(eval $(call BuildModule,NAME,TITLE[,PKG DEPENDS])) -$(eval $(call BuildModule,apc,APC,+PACKAGE_php5-mod-apc:librt)) $(eval $(call BuildModule,calendar,Calendar)) $(eval $(call BuildModule,ctype,Ctype)) $(eval $(call BuildModule,curl,cURL,+PACKAGE_php5-mod-curl:libcurl)) $(eval $(call BuildModule,fileinfo,Fileinfo,+PACKAGE_php5-mod-fileinfo:libmagic)) -$(eval $(call BuildModule,dio,Direct IO)) $(eval $(call BuildModule,dom,DOM,+@PHP5_LIBXML +PACKAGE_php5-mod-dom:libxml2)) $(eval $(call BuildModule,exif,EXIF)) $(eval $(call BuildModule,ftp,FTP,+PACKAGE_php5-mod-ftp:libopenssl)) @@ -543,11 +513,9 @@ $(eval $(call BuildModule,gettext,Gettext,+PACKAGE_php5-mod-gettext:libintl-full $(eval $(call BuildModule,gd,GD graphics,+PACKAGE_php5-mod-gd:libjpeg +PACKAGE_php5-mod-gd:libpng)) $(eval $(call BuildModule,gmp,GMP,+PACKAGE_php5-mod-gmp:libgmp)) $(eval $(call BuildModule,hash,Hash)) -$(eval $(call BuildModule,http,HTTP,+PACKAGE_php5-mod-http:libcurl +PACKAGE_php5-mod-http:libevent2 +PACKAGE_php5-mod-http:librt)) $(eval $(call BuildModule,iconv,iConv,+PACKAGE_php5-mod-iconv:libiconv)) $(eval $(call BuildModule,json,JSON)) $(eval $(call BuildModule,ldap,LDAP,+PACKAGE_php5-mod-ldap:libopenldap +PACKAGE_php5-mod-ldap:libsasl2)) -$(eval $(call BuildModule,libevent,libevent,+PACKAGE_php5-mod-libevent:libevent2)) $(eval $(call BuildModule,mbstring,MBString)) $(eval $(call BuildModule,mcrypt,Mcrypt,+PACKAGE_php5-mod-mcrypt:libmcrypt +PACKAGE_php5-mod-mcrypt:libltdl)) $(eval $(call BuildModule,mysql,MySQL,+PACKAGE_php5-mod-mysql:libmysqlclient)) diff --git a/lang/php5/patches/005-APC.patch b/lang/php5/patches/005-APC.patch deleted file mode 100644 index b6c5e3b81..000000000 --- a/lang/php5/patches/005-APC.patch +++ /dev/null @@ -1,22543 +0,0 @@ -diff -Naur a/ext/apc/apc_bin.c b/ext/apc/apc_bin.c ---- a/ext/apc/apc_bin.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_bin.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,987 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Brian Shire | -+ +----------------------------------------------------------------------+ -+ -+ */ -+ -+/* $Id: apc_bin.c 324017 2012-03-08 09:46:22Z pajoye $ */ -+ -+/* Creates a binary architecture specific output to a string or file containing -+ * the current cache contents for both fies and user variables. This is accomplished -+ * via the apc_copy_* functions and "swizzling" pointer values to a position -+ * independent value, and unswizzling them on restoration. -+ */ -+ -+#include "apc_globals.h" -+#include "apc_bin.h" -+#include "apc_zend.h" -+#include "apc_php.h" -+#include "apc_sma.h" -+#include "apc_pool.h" -+#include "ext/standard/md5.h" -+#include "ext/standard/crc32.h" -+ -+extern apc_cache_t* apc_cache; -+extern apc_cache_t* apc_user_cache; -+ -+extern int _apc_store(char *strkey, int strkey_len, const zval *val, const uint ttl, const int exclusive TSRMLS_DC); /* this is hacky */ -+ -+#define APC_BINDUMP_DEBUG 0 -+ -+ -+#if APC_BINDUMP_DEBUG -+ -+#define SWIZZLE(bd, ptr) \ -+ do { \ -+ if((long)bd < (long)ptr && (ulong)ptr < ((long)bd + bd->size)) { \ -+ printf("SWIZZLE: %x ~> ", ptr); \ -+ ptr = (void*)((long)(ptr) - (long)(bd)); \ -+ printf("%x in %s on line %d", ptr, __FILE__, __LINE__); \ -+ } else if((long)ptr > bd->size) { /* not swizzled */ \ -+ apc_error("pointer to be swizzled is not within allowed memory range! (%x < %x < %x) in %s on %d" TSRMLS_CC, (long)bd, ptr, ((long)bd + bd->size), __FILE__, __LINE__); \ -+ return; \ -+ } \ -+ printf("\n"); \ -+ } while(0); -+ -+#define UNSWIZZLE(bd, ptr) \ -+ do { \ -+ printf("UNSWIZZLE: %x -> ", ptr); \ -+ ptr = (void*)((long)(ptr) + (long)(bd)); \ -+ printf("%x in %s on line %d \n", ptr, __FILE__, __LINE__); \ -+ } while(0); -+ -+#else /* !APC_BINDUMP_DEBUG */ -+ -+#define SWIZZLE(bd, ptr) \ -+ do { \ -+ if((long)bd < (long)ptr && (ulong)ptr < ((long)bd + bd->size)) { \ -+ ptr = (void*)((long)(ptr) - (long)(bd)); \ -+ } else if((ulong)ptr > bd->size) { /* not swizzled */ \ -+ apc_error("pointer to be swizzled is not within allowed memory range! (%x < %x < %x) in %s on %d" TSRMLS_CC, (long)bd, ptr, ((long)bd + bd->size), __FILE__, __LINE__); \ -+ return NULL; \ -+ } \ -+ } while(0); -+ -+#define UNSWIZZLE(bd, ptr) \ -+ do { \ -+ ptr = (void*)((long)(ptr) + (long)(bd)); \ -+ } while(0); -+ -+#endif -+ -+ -+static void *apc_bd_alloc(size_t size TSRMLS_DC); -+static void apc_bd_free(void *ptr TSRMLS_DC); -+static void *apc_bd_alloc_ex(void *ptr_new, size_t size TSRMLS_DC); -+ -+typedef void (*apc_swizzle_cb_t)(apc_bd_t *bd, zend_llist *ll, void *ptr TSRMLS_DC); -+ -+#if APC_BINDUMP_DEBUG -+#define apc_swizzle_ptr(bd, ll, ptr) _apc_swizzle_ptr(bd, ll, (void*)ptr, __FILE__, __LINE__ TSRMLS_CC) -+#else -+#define apc_swizzle_ptr(bd, ll, ptr) _apc_swizzle_ptr(bd, ll, (void*)ptr, NULL, 0 TSRMLS_CC) -+#endif -+ -+static void _apc_swizzle_ptr(apc_bd_t *bd, zend_llist *ll, void **ptr, const char* file, int line TSRMLS_DC); -+static void apc_swizzle_function(apc_bd_t *bd, zend_llist *ll, zend_function *func TSRMLS_DC); -+static void apc_swizzle_class_entry(apc_bd_t *bd, zend_llist *ll, zend_class_entry *ce TSRMLS_DC); -+static void apc_swizzle_hashtable(apc_bd_t *bd, zend_llist *ll, HashTable *ht, apc_swizzle_cb_t swizzle_cb, int is_ptr TSRMLS_DC); -+static void apc_swizzle_zval(apc_bd_t *bd, zend_llist *ll, zval *zv TSRMLS_DC); -+static void apc_swizzle_op_array(apc_bd_t *bd, zend_llist *ll, zend_op_array *op_array TSRMLS_DC); -+static void apc_swizzle_property_info(apc_bd_t *bd, zend_llist *ll, zend_property_info *pi TSRMLS_DC); -+static void apc_swizzle_function_entry(apc_bd_t *bd, zend_llist *ll, const zend_function_entry *fe TSRMLS_DC); -+static void apc_swizzle_arg_info_array(apc_bd_t *bd, zend_llist *ll, const zend_arg_info* arg_info_array, uint num_args TSRMLS_DC); -+ -+static apc_bd_t* apc_swizzle_bd(apc_bd_t* bd, zend_llist *ll TSRMLS_DC); -+static int apc_unswizzle_bd(apc_bd_t *bd, int flags TSRMLS_DC); -+ -+ -+/* {{{ apc_bd_alloc -+ * callback for copy_* functions */ -+static void *apc_bd_alloc(size_t size TSRMLS_DC) { -+ return apc_bd_alloc_ex(NULL, size TSRMLS_CC); -+} /* }}} */ -+ -+ -+/* {{{ apc_bd_free -+ * callback for copy_* functions */ -+static void apc_bd_free(void *ptr TSRMLS_DC) { -+ size_t *size; -+ if(zend_hash_index_find(&APCG(apc_bd_alloc_list), (ulong)ptr, (void**)&size) == FAILURE) { -+ apc_error("apc_bd_free could not free pointer (not found in list: %x)" TSRMLS_CC, ptr); -+ return; -+ } -+ APCG(apc_bd_alloc_ptr) = (void*)((size_t)APCG(apc_bd_alloc_ptr) - *size); -+ zend_hash_index_del(&APCG(apc_bd_alloc_list), (ulong)ptr); -+} /* }}} */ -+ -+ -+/* {{{ apc_bd_alloc_ex -+ * set ranges or allocate a block of data from an already (e)malloc'd range. -+ * if ptr_new is not NULL, it will reset the pointer to start at ptr_new, -+ * with a range of size. If ptr_new is NULL, returns the next available -+ * block of given size. -+ */ -+static void *apc_bd_alloc_ex(void *ptr_new, size_t size TSRMLS_DC) { -+ void *rval; -+ -+ rval = APCG(apc_bd_alloc_ptr); -+ if(ptr_new != NULL) { /* reset ptrs */ -+ APCG(apc_bd_alloc_ptr) = ptr_new; -+ APCG(apc_bd_alloc_ubptr) = (void*)((unsigned char *) ptr_new + size); -+ } else { /* alloc block */ -+ APCG(apc_bd_alloc_ptr) = (void*)((size_t)APCG(apc_bd_alloc_ptr) + size); -+#if APC_BINDUMP_DEBUG -+ apc_notice("apc_bd_alloc: rval: 0x%x ptr: 0x%x ubptr: 0x%x size: %d" TSRMLS_CC, rval, APCG(apc_bd_alloc_ptr), APCG(apc_bd_alloc_ubptr), size); -+#endif -+ if(APCG(apc_bd_alloc_ptr) > APCG(apc_bd_alloc_ubptr)) { -+ apc_error("Exceeded bounds check in apc_bd_alloc_ex by %d bytes." TSRMLS_CC, (unsigned char *) APCG(apc_bd_alloc_ptr) - (unsigned char *) APCG(apc_bd_alloc_ubptr)); -+ return NULL; -+ } -+ zend_hash_index_update(&APCG(apc_bd_alloc_list), (ulong)rval, &size, sizeof(size_t), NULL); -+ } -+ -+ return rval; -+} /* }}} */ -+ -+ -+/* {{{ _apc_swizzle_ptr */ -+static void _apc_swizzle_ptr(apc_bd_t *bd, zend_llist *ll, void **ptr, const char* file, int line TSRMLS_DC) { -+ if(*ptr) { -+ if((long)bd < (long)*ptr && (ulong)*ptr < ((long)bd + bd->size)) { -+ zend_llist_add_element(ll, &ptr); -+#if APC_BINDUMP_DEBUG -+ printf("[%06d] apc_swizzle_ptr: %x -> %x ", zend_llist_count(ll), ptr, *ptr); -+ printf(" in %s on line %d \n", file, line); -+#endif -+ } else if((ulong)ptr > bd->size) { -+ apc_error("pointer to be swizzled is not within allowed memory range! (%x < %x < %x) in %s on %d" TSRMLS_CC, (long)bd, *ptr, ((long)bd + bd->size), file, line); \ -+ return; -+ } -+ } -+} /* }}} */ -+ -+ -+/* {{{ apc_swizzle_op_array */ -+static void apc_swizzle_op_array(apc_bd_t *bd, zend_llist *ll, zend_op_array *op_array TSRMLS_DC) { -+ uint i; -+ -+#ifdef ZEND_ENGINE_2 -+ apc_swizzle_arg_info_array(bd, ll, op_array->arg_info, op_array->num_args TSRMLS_CC); -+ apc_swizzle_ptr(bd, ll, &op_array->arg_info); -+#else -+ if (op_array->arg_types) { -+ apc_swizzle_ptr(bd, ll, &op_array->arg_types); -+ } -+#endif -+ -+ apc_swizzle_ptr(bd, ll, &op_array->function_name); -+ apc_swizzle_ptr(bd, ll, &op_array->filename); -+ apc_swizzle_ptr(bd, ll, &op_array->refcount); -+ -+ /* swizzle op_array */ -+ for(i=0; i < op_array->last; i++) { -+#ifndef ZEND_ENGINE_2_4 -+ if(op_array->opcodes[i].result.op_type == IS_CONST) { -+ apc_swizzle_zval(bd, ll, &op_array->opcodes[i].result.u.constant TSRMLS_CC); -+ } -+ if(op_array->opcodes[i].op1.op_type == IS_CONST) { -+ apc_swizzle_zval(bd, ll, &op_array->opcodes[i].op1.u.constant TSRMLS_CC); -+ } -+ if(op_array->opcodes[i].op2.op_type == IS_CONST) { -+ apc_swizzle_zval(bd, ll, &op_array->opcodes[i].op2.u.constant TSRMLS_CC); -+ } -+#endif -+ switch (op_array->opcodes[i].opcode) { -+ case ZEND_JMP: -+#ifdef ZEND_ENGINE_2_4 -+ apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op1.jmp_addr); -+#else -+ apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op1.u.jmp_addr); -+#endif -+ case ZEND_JMPZ: -+ case ZEND_JMPNZ: -+ case ZEND_JMPZ_EX: -+ case ZEND_JMPNZ_EX: -+#ifdef ZEND_ENGINE_2_4 -+ apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op2.jmp_addr); -+#else -+ apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op2.u.jmp_addr); -+#endif -+ } -+ } -+ apc_swizzle_ptr(bd, ll, &op_array->opcodes); -+ -+ /* break-continue array ptr */ -+ if(op_array->brk_cont_array) { -+ apc_swizzle_ptr(bd, ll, &op_array->brk_cont_array); -+ } -+ -+ /* static voriables */ -+ if(op_array->static_variables) { -+ apc_swizzle_hashtable(bd, ll, op_array->static_variables, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC); -+ apc_swizzle_ptr(bd, ll, &op_array->static_variables); -+ } -+ -+#ifdef ZEND_ENGINE_2 -+ /* try-catch */ -+ if(op_array->try_catch_array) { -+ apc_swizzle_ptr(bd, ll, &op_array->try_catch_array); -+ } -+#endif -+ -+#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */ -+ /* vars */ -+ if(op_array->vars) { -+ for(i=0; (signed int) i < op_array->last_var; i++) { -+ apc_swizzle_ptr(bd, ll, &op_array->vars[i].name); -+ } -+ apc_swizzle_ptr(bd, ll, &op_array->vars); -+ } -+#endif -+ -+#ifdef ZEND_ENGINE_2 -+ /* doc comment */ -+ if(op_array->doc_comment) { -+ apc_swizzle_ptr(bd, ll, &op_array->doc_comment); -+ } -+#endif -+ -+} /* }}} */ -+ -+ -+/* {{{ apc_swizzle_function */ -+static void apc_swizzle_function(apc_bd_t *bd, zend_llist *ll, zend_function *func TSRMLS_DC) { -+ apc_swizzle_op_array(bd, ll, &func->op_array TSRMLS_CC); -+#ifdef ZEND_ENGINE_2 -+ if(func->common.scope) { -+ apc_swizzle_ptr(bd, ll, &func->common.scope); -+ } -+#endif -+} /* }}} */ -+ -+ -+/* {{{ apc_swizzle_class_entry */ -+static void apc_swizzle_class_entry(apc_bd_t *bd, zend_llist *ll, zend_class_entry *ce TSRMLS_DC) { -+ -+ uint i; -+ -+ if(ce->name) { -+ apc_swizzle_ptr(bd, ll, &ce->name); -+ } -+ -+ if (ce->type == ZEND_USER_CLASS && ZEND_CE_DOC_COMMENT(ce)) { -+ apc_swizzle_ptr(bd, ll, &ZEND_CE_DOC_COMMENT(ce)); -+ } -+ -+#ifndef ZEND_ENGINE_2 -+ apc_swizzle_ptr(bd, ll, &ce->refcount); -+#endif -+ -+ apc_swizzle_hashtable(bd, ll, &ce->function_table, (apc_swizzle_cb_t)apc_swizzle_function, 0 TSRMLS_CC); -+#ifdef ZEND_ENGINE_2_4 -+ if (ce->default_properties_table) { -+ for (i = 0; i < ce->default_properties_count; i++) { -+ if (ce->default_properties_table[i]) { -+ apc_swizzle_ptr(bd, ll, &ce->default_properties_table[i]); -+ apc_swizzle_zval(bd, ll, ce->default_properties_table[i] TSRMLS_CC); -+ } -+ } -+ } -+#else -+ apc_swizzle_hashtable(bd, ll, &ce->default_properties, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC); -+#endif -+ -+#ifdef ZEND_ENGINE_2 -+ apc_swizzle_hashtable(bd, ll, &ce->properties_info, (apc_swizzle_cb_t)apc_swizzle_property_info, 0 TSRMLS_CC); -+#endif -+ -+#ifdef ZEND_ENGINE_2_4 -+ if (ce->default_static_members_table) { -+ for (i = 0; i < ce->default_static_members_count; i++) { -+ if (ce->default_static_members_table[i]) { -+ apc_swizzle_ptr(bd, ll, &ce->default_static_members_table[i]); -+ apc_swizzle_zval(bd, ll, ce->default_static_members_table[i] TSRMLS_CC); -+ } -+ } -+ } -+ ce->static_members_table = ce->default_static_members_table; -+#else -+ apc_swizzle_hashtable(bd, ll, &ce->default_static_members, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC); -+ -+ if(ce->static_members != &ce->default_static_members) { -+ apc_swizzle_hashtable(bd, ll, ce->static_members, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC); -+ } else { -+ apc_swizzle_ptr(bd, ll, &ce->static_members); -+ } -+#endif -+ -+ apc_swizzle_hashtable(bd, ll, &ce->constants_table, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC); -+ -+ if(ce->type == ZEND_INTERNAL_CLASS && ZEND_CE_BUILTIN_FUNCTIONS(ce)) { -+ for(i=0; ZEND_CE_BUILTIN_FUNCTIONS(ce)[i].fname; i++) { -+ apc_swizzle_function_entry(bd, ll, &ZEND_CE_BUILTIN_FUNCTIONS(ce)[i] TSRMLS_CC); -+ } -+ } -+ -+ apc_swizzle_ptr(bd, ll, &ce->constructor); -+ apc_swizzle_ptr(bd, ll, &ce->destructor); -+ apc_swizzle_ptr(bd, ll, &ce->clone); -+ apc_swizzle_ptr(bd, ll, &ce->__get); -+ apc_swizzle_ptr(bd, ll, &ce->__set); -+ apc_swizzle_ptr(bd, ll, &ce->__unset); -+ apc_swizzle_ptr(bd, ll, &ce->__isset); -+ apc_swizzle_ptr(bd, ll, &ce->__call); -+ apc_swizzle_ptr(bd, ll, &ce->serialize_func); -+ apc_swizzle_ptr(bd, ll, &ce->unserialize_func); -+ -+#ifdef ZEND_ENGINE_2_2 -+ apc_swizzle_ptr(bd, ll, &ce->__tostring); -+#endif -+ -+ if (ce->type == ZEND_USER_CLASS) { -+ apc_swizzle_ptr(bd, ll, &ZEND_CE_FILENAME(ce)); -+ } -+} /* }}} */ -+ -+ -+/* {{{ apc_swizzle_property_info */ -+static void apc_swizzle_property_info(apc_bd_t *bd, zend_llist *ll, zend_property_info *pi TSRMLS_DC) { -+ apc_swizzle_ptr(bd, ll, &pi->name); -+ apc_swizzle_ptr(bd, ll, &pi->doc_comment); -+ -+#ifdef ZEND_ENGINE_2_2 -+ apc_swizzle_ptr(bd, ll, &pi->ce); -+#endif -+} /* }}} */ -+ -+ -+/* {{{ apc_swizzle_function_entry */ -+static void apc_swizzle_function_entry(apc_bd_t *bd, zend_llist *ll, const zend_function_entry *fe TSRMLS_DC) { -+ apc_swizzle_ptr(bd, ll, &fe->fname); -+ apc_swizzle_arg_info_array(bd, ll, fe->arg_info, fe->num_args TSRMLS_CC); -+ apc_swizzle_ptr(bd, ll, &fe->arg_info); -+} /* }}} */ -+ -+ -+/* {{{ apc_swizzle_arg_info_array */ -+static void apc_swizzle_arg_info_array(apc_bd_t *bd, zend_llist *ll, const zend_arg_info* arg_info_array, uint num_args TSRMLS_DC) { -+ if(arg_info_array) { -+ uint i; -+ -+ for(i=0; i < num_args; i++) { -+ apc_swizzle_ptr(bd, ll, &arg_info_array[i].name); -+ apc_swizzle_ptr(bd, ll, &arg_info_array[i].class_name); -+ } -+ } -+ -+} /* }}} */ -+ -+ -+/* {{{ apc_swizzle_hashtable */ -+static void apc_swizzle_hashtable(apc_bd_t *bd, zend_llist *ll, HashTable *ht, apc_swizzle_cb_t swizzle_cb, int is_ptr TSRMLS_DC) { -+ uint i; -+ Bucket **bp, **bp_prev; -+ -+ bp = &ht->pListHead; -+ while(*bp) { -+ bp_prev = bp; -+ bp = &(*bp)->pListNext; -+ if(is_ptr) { -+ swizzle_cb(bd, ll, *(void**)(*bp_prev)->pData TSRMLS_CC); -+ apc_swizzle_ptr(bd, ll, (*bp_prev)->pData); -+ } else { -+ swizzle_cb(bd, ll, (void**)(*bp_prev)->pData TSRMLS_CC); -+ } -+ apc_swizzle_ptr(bd, ll, &(*bp_prev)->pData); -+ if((*bp_prev)->pDataPtr) { -+ apc_swizzle_ptr(bd, ll, &(*bp_prev)->pDataPtr); -+ } -+ if((*bp_prev)->pListLast) { -+ apc_swizzle_ptr(bd, ll, &(*bp_prev)->pListLast); -+ } -+ if((*bp_prev)->pNext) { -+ apc_swizzle_ptr(bd, ll, &(*bp_prev)->pNext); -+ } -+ if((*bp_prev)->pLast) { -+ apc_swizzle_ptr(bd, ll, &(*bp_prev)->pLast); -+ } -+ apc_swizzle_ptr(bd, ll, bp_prev); -+ } -+ for(i=0; i < ht->nTableSize; i++) { -+ if(ht->arBuckets[i]) { -+ apc_swizzle_ptr(bd, ll, &ht->arBuckets[i]); -+ } -+ } -+ apc_swizzle_ptr(bd, ll, &ht->pListTail); -+ -+ apc_swizzle_ptr(bd, ll, &ht->arBuckets); -+} /* }}} */ -+ -+ -+/* {{{ apc_swizzle_zval */ -+static void apc_swizzle_zval(apc_bd_t *bd, zend_llist *ll, zval *zv TSRMLS_DC) { -+ -+ if(APCG(copied_zvals).nTableSize) { -+ if(zend_hash_index_exists(&APCG(copied_zvals), (ulong)zv)) { -+ return; -+ } -+ zend_hash_index_update(&APCG(copied_zvals), (ulong)zv, (void**)&zv, sizeof(zval*), NULL); -+ } -+ -+ switch(zv->type & IS_CONSTANT_TYPE_MASK) { -+ case IS_NULL: -+ case IS_LONG: -+ case IS_DOUBLE: -+ case IS_BOOL: -+ case IS_RESOURCE: -+ /* nothing to do */ -+ break; -+ case IS_CONSTANT: -+ case IS_STRING: -+ apc_swizzle_ptr(bd, ll, &zv->value.str.val); -+ break; -+ case IS_ARRAY: -+ case IS_CONSTANT_ARRAY: -+ apc_swizzle_hashtable(bd, ll, zv->value.ht, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC); -+ apc_swizzle_ptr(bd, ll, &zv->value.ht); -+ break; -+ case IS_OBJECT: -+ break; -+ default: -+ assert(0); /* shouldn't happen */ -+ } -+} /* }}} */ -+ -+ -+/* {{{ apc_swizzle_bd */ -+static apc_bd_t* apc_swizzle_bd(apc_bd_t* bd, zend_llist *ll TSRMLS_DC) { -+ int count, i; -+ PHP_MD5_CTX context; -+ unsigned char digest[16]; -+ register php_uint32 crc; -+ php_uint32 crcinit = 0; -+ char *crc_p; -+ void ***ptr; -+ void ***ptr_list; -+ -+ count = zend_llist_count(ll); -+ ptr_list = emalloc(count * sizeof(void**)); -+ ptr = zend_llist_get_first(ll); -+ for(i=0; i < count; i++) { -+#if APC_BINDUMP_DEBUG -+ printf("[%06d] ", i+1); -+#endif -+ SWIZZLE(bd, **ptr); /* swizzle ptr */ -+ if((long)bd < (long)*ptr && (ulong)*ptr < ((long)bd + bd->size)) { /* exclude ptrs that aren't actually included in the ptr list */ -+#if APC_BINDUMP_DEBUG -+ printf("[------] "); -+#endif -+ SWIZZLE(bd, *ptr); /* swizzle ptr list */ -+ ptr_list[i] = *ptr; -+ } -+ ptr = zend_llist_get_next(ll); -+ } -+ SWIZZLE(bd, bd->entries); -+ -+ if(count > 0) { -+ bd = erealloc(bd, bd->size + (count * sizeof(void**))); -+ bd->num_swizzled_ptrs = count; -+ bd->swizzled_ptrs = (void***)((unsigned char *)bd + bd->size -2); /* extra -1 for null termination */ -+ bd->size += count * sizeof(void**); -+ memcpy(bd->swizzled_ptrs, ptr_list, count * sizeof(void**)); -+ SWIZZLE(bd, bd->swizzled_ptrs); -+ } else { -+ bd->num_swizzled_ptrs = 0; -+ bd->swizzled_ptrs = NULL; -+ } -+ ((char*)bd)[bd->size-1] = 0; /* silence null termination for zval strings */ -+ efree(ptr_list); -+ bd->swizzled = 1; -+ -+ /* Generate MD5/CRC32 checksum */ -+ for(i=0; i<16; i++) { bd->md5[i] = 0; } -+ bd->crc=0; -+ PHP_MD5Init(&context); -+ PHP_MD5Update(&context, (const unsigned char*)bd, bd->size); -+ PHP_MD5Final(digest, &context); -+ crc = crcinit^0xFFFFFFFF; -+ crc_p = (char*)bd; -+ for(i=bd->size; i--; ++crc_p) { -+ crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*crc_p)) & 0xFF ]; -+ } -+ memcpy(bd->md5, digest, 16); -+ bd->crc = crc; -+ -+ return bd; -+} /* }}} */ -+ -+ -+/* {{{ apc_unswizzle_bd */ -+static int apc_unswizzle_bd(apc_bd_t *bd, int flags TSRMLS_DC) { -+ int i; -+ unsigned char md5_orig[16]; -+ unsigned char digest[16]; -+ PHP_MD5_CTX context; -+ register php_uint32 crc; -+ php_uint32 crcinit = 0; -+ php_uint32 crc_orig; -+ char *crc_p; -+ -+ /* Verify the md5 or crc32 before we unswizzle */ -+ memcpy(md5_orig, bd->md5, 16); -+ for(i=0; i<16; i++) { bd->md5[i] = 0; } -+ crc_orig = bd->crc; -+ bd->crc=0; -+ if(flags & APC_BIN_VERIFY_MD5) { -+ PHP_MD5Init(&context); -+ PHP_MD5Update(&context, (const unsigned char*)bd, bd->size); -+ PHP_MD5Final(digest, &context); -+ if(memcmp(md5_orig, digest, 16)) { -+ apc_error("MD5 checksum of binary dump failed." TSRMLS_CC); -+ return -1; -+ } -+ } -+ if(flags & APC_BIN_VERIFY_CRC32) { -+ crc = crcinit^0xFFFFFFFF; -+ crc_p = (char*)bd; -+ for(i=bd->size; i--; ++crc_p) { -+ crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*crc_p)) & 0xFF ]; -+ } -+ if(crc_orig != crc) { -+ apc_error("CRC32 checksum of binary dump failed." TSRMLS_CC); -+ return -1; -+ } -+ } -+ memcpy(bd->md5, md5_orig, 16); /* add back md5 checksum */ -+ bd->crc = crc_orig; -+ -+ UNSWIZZLE(bd, bd->entries); -+ UNSWIZZLE(bd, bd->swizzled_ptrs); -+ for(i=0; i < bd->num_swizzled_ptrs; i++) { -+ if(bd->swizzled_ptrs[i]) { -+ UNSWIZZLE(bd, bd->swizzled_ptrs[i]); -+ if(*bd->swizzled_ptrs[i] && (*bd->swizzled_ptrs[i] < (void*)bd)) { -+ UNSWIZZLE(bd, *bd->swizzled_ptrs[i]); -+ } -+ } -+ } -+ -+ bd->swizzled=0; -+ -+ return 0; -+} /* }}} */ -+ -+ -+/* {{{ apc_bin_checkfilter */ -+static int apc_bin_checkfilter(HashTable *filter, const char *key, uint key_len) { -+ zval **zptr; -+ -+ if(filter == NULL) { -+ return 1; -+ } -+ -+ if(zend_hash_find(filter, (char*)key, key_len, (void**)&zptr) == SUCCESS) { -+ if(Z_TYPE_PP(zptr) == IS_LONG && Z_LVAL_PP(zptr) == 0) { -+ return 0; -+ } -+ } else { -+ return 0; -+ } -+ -+ -+ return 1; -+} /* }}} */ -+ -+/* {{{ apc_bin_fixup_op_array */ -+static inline void apc_bin_fixup_op_array(zend_op_array *op_array) { -+ ulong i; -+ for (i = 0; i < op_array->last; i++) { -+ op_array->opcodes[i].handler = zend_opcode_handlers[APC_OPCODE_HANDLER_DECODE(&op_array->opcodes[i])]; -+ } -+} -+/* }}} */ -+ -+/* {{{ apc_bin_fixup_class_entry */ -+static inline void apc_bin_fixup_class_entry(zend_class_entry *ce) { -+ zend_function *fe; -+ HashPosition hpos; -+ -+ /* fixup the opcodes in each method */ -+ zend_hash_internal_pointer_reset_ex(&ce->function_table, &hpos); -+ while(zend_hash_get_current_data_ex(&ce->function_table, (void**)&fe, &hpos) == SUCCESS) { -+ apc_bin_fixup_op_array(&fe->op_array); -+ zend_hash_move_forward_ex(&ce->function_table, &hpos); -+ } -+ -+ /* fixup hashtable destructor pointers */ -+ ce->function_table.pDestructor = (dtor_func_t)zend_function_dtor; -+#ifndef ZEND_ENGINE_2_4 -+ ce->default_properties.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper; -+#endif -+ ce->properties_info.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper; -+#ifndef ZEND_ENGINE_2_4 -+ ce->default_static_members.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper; -+ if (ce->static_members) { -+ ce->static_members->pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper; -+ } -+#endif -+ ce->constants_table.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper; -+} -+/* }}} */ -+ -+/* {{{ apc_bin_dump */ -+apc_bd_t* apc_bin_dump(HashTable *files, HashTable *user_vars TSRMLS_DC) { -+ -+ int i; -+ uint fcount; -+ slot_t *sp; -+ apc_bd_entry_t *ep; -+ int count=0; -+ apc_bd_t *bd; -+ zend_llist ll; -+ zend_function *efp, *sfp; -+ long size=0; -+ apc_context_t ctxt; -+ void *pool_ptr; -+ -+ zend_llist_init(&ll, sizeof(void*), NULL, 0); -+ zend_hash_init(&APCG(apc_bd_alloc_list), 0, NULL, NULL, 0); -+ -+ /* flip the hash for faster filter checking */ -+ files = apc_flip_hash(files); -+ user_vars = apc_flip_hash(user_vars); -+ -+ /* get size and entry counts */ -+ for(i=0; i < apc_user_cache->num_slots; i++) { -+ sp = apc_user_cache->slots[i]; -+ for(; sp != NULL; sp = sp->next) { -+ if(apc_bin_checkfilter(user_vars, sp->key.data.user.identifier, sp->key.data.user.identifier_len)) { -+ size += sizeof(apc_bd_entry_t*) + sizeof(apc_bd_entry_t); -+ size += sp->value->mem_size - (sizeof(apc_cache_entry_t) - sizeof(apc_cache_entry_value_t)); -+ count++; -+ } -+ } -+ } -+ for(i=0; i < apc_cache->num_slots; i++) { -+ sp = apc_cache->slots[i]; -+ for(; sp != NULL; sp = sp->next) { -+ if(sp->key.type == APC_CACHE_KEY_FPFILE) { -+ if(apc_bin_checkfilter(files, sp->key.data.fpfile.fullpath, sp->key.data.fpfile.fullpath_len+1)) { -+ size += sizeof(apc_bd_entry_t*) + sizeof(apc_bd_entry_t); -+ size += sp->value->mem_size - (sizeof(apc_cache_entry_t) - sizeof(apc_cache_entry_value_t)); -+ count++; -+ } -+ } else { -+ /* TODO: Currently we don't support APC_CACHE_KEY_FILE type. We need to store the path and re-stat on load */ -+ apc_warning("Excluding some files from apc_bin_dump[file]. Cached files must be included using full path with apc.stat=0." TSRMLS_CC); -+ } -+ } -+ } -+ -+ size += sizeof(apc_bd_t) +1; /* +1 for null termination */ -+ bd = emalloc(size); -+ bd->size = size; -+ pool_ptr = emalloc(sizeof(apc_pool)); -+ apc_bd_alloc_ex(pool_ptr, sizeof(apc_pool) TSRMLS_CC); -+ ctxt.pool = apc_pool_create(APC_UNPOOL, apc_bd_alloc, apc_bd_free, NULL, NULL TSRMLS_CC); /* ideally the pool wouldn't be alloc'd as part of this */ -+ if (!ctxt.pool) { /* TODO need to cleanup */ -+ apc_warning("Unable to allocate memory for pool." TSRMLS_CC); -+ return NULL; -+ } -+ ctxt.copy = APC_COPY_IN_USER; /* avoid stupid ALLOC_ZVAL calls here, hack */ -+ apc_bd_alloc_ex((void*)((long)bd + sizeof(apc_bd_t)), bd->size - sizeof(apc_bd_t) -1 TSRMLS_CC); -+ bd->num_entries = count; -+ bd->entries = apc_bd_alloc_ex(NULL, sizeof(apc_bd_entry_t) * count TSRMLS_CC); -+ -+ /* User entries */ -+ zend_hash_init(&APCG(copied_zvals), 0, NULL, NULL, 0); -+ count = 0; -+ for(i=0; i < apc_user_cache->num_slots; i++) { -+ sp = apc_user_cache->slots[i]; -+ for(; sp != NULL; sp = sp->next) { -+ if(apc_bin_checkfilter(user_vars, sp->key.data.user.identifier, sp->key.data.user.identifier_len)) { -+ ep = &bd->entries[count]; -+ ep->type = sp->value->type; -+ ep->val.user.info = apc_bd_alloc(sp->value->data.user.info_len TSRMLS_CC); -+ memcpy(ep->val.user.info, sp->value->data.user.info, sp->value->data.user.info_len); -+ ep->val.user.info_len = sp->value->data.user.info_len; -+ ep->val.user.val = apc_copy_zval(NULL, sp->value->data.user.val, &ctxt TSRMLS_CC); -+ ep->val.user.ttl = sp->value->data.user.ttl; -+ -+ /* swizzle pointers */ -+ apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.user.info); -+ zend_hash_clean(&APCG(copied_zvals)); -+ apc_swizzle_zval(bd, &ll, bd->entries[count].val.user.val TSRMLS_CC); -+ apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.user.val); -+ -+ count++; -+ } -+ } -+ } -+ zend_hash_destroy(&APCG(copied_zvals)); -+ APCG(copied_zvals).nTableSize=0; -+ -+ /* File entries */ -+ for(i=0; i < apc_cache->num_slots; i++) { -+ for(sp=apc_cache->slots[i]; sp != NULL; sp = sp->next) { -+ if(sp->key.type == APC_CACHE_KEY_FPFILE) { -+ if(apc_bin_checkfilter(files, sp->key.data.fpfile.fullpath, sp->key.data.fpfile.fullpath_len+1)) { -+ ep = &bd->entries[count]; -+ ep->type = sp->key.type; -+ ep->val.file.filename = apc_bd_alloc(strlen(sp->value->data.file.filename) + 1 TSRMLS_CC); -+ strcpy(ep->val.file.filename, sp->value->data.file.filename); -+ ep->val.file.op_array = apc_copy_op_array(NULL, sp->value->data.file.op_array, &ctxt TSRMLS_CC); -+ -+ for(ep->num_functions=0; sp->value->data.file.functions[ep->num_functions].function != NULL;) { ep->num_functions++; } -+ ep->val.file.functions = apc_bd_alloc(sizeof(apc_function_t) * ep->num_functions TSRMLS_CC); -+ for(fcount=0; fcount < ep->num_functions; fcount++) { -+ memcpy(&ep->val.file.functions[fcount], &sp->value->data.file.functions[fcount], sizeof(apc_function_t)); -+ ep->val.file.functions[fcount].name = apc_xmemcpy(sp->value->data.file.functions[fcount].name, sp->value->data.file.functions[fcount].name_len+1, apc_bd_alloc TSRMLS_CC); -+ ep->val.file.functions[fcount].name_len = sp->value->data.file.functions[fcount].name_len; -+ ep->val.file.functions[fcount].function = apc_bd_alloc(sizeof(zend_function) TSRMLS_CC); -+ efp = ep->val.file.functions[fcount].function; -+ sfp = sp->value->data.file.functions[fcount].function; -+ switch(sfp->type) { -+ case ZEND_INTERNAL_FUNCTION: -+ case ZEND_OVERLOADED_FUNCTION: -+ efp->op_array = sfp->op_array; -+ break; -+ case ZEND_USER_FUNCTION: -+ case ZEND_EVAL_CODE: -+ apc_copy_op_array(&efp->op_array, &sfp->op_array, &ctxt TSRMLS_CC); -+ break; -+ default: -+ assert(0); -+ } -+#ifdef ZEND_ENGINE_2 -+ efp->common.prototype = NULL; -+ efp->common.fn_flags = sfp->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT); -+#endif -+ apc_swizzle_ptr(bd, &ll, &ep->val.file.functions[fcount].name); -+ apc_swizzle_ptr(bd, &ll, (void**)&ep->val.file.functions[fcount].function); -+ apc_swizzle_op_array(bd, &ll, &efp->op_array TSRMLS_CC); -+ } -+ -+ -+ for(ep->num_classes=0; sp->value->data.file.classes[ep->num_classes].class_entry != NULL;) { ep->num_classes++; } -+ ep->val.file.classes = apc_bd_alloc(sizeof(apc_class_t) * ep->num_classes TSRMLS_CC); -+ for(fcount=0; fcount < ep->num_classes; fcount++) { -+ ep->val.file.classes[fcount].name = apc_xmemcpy(sp->value->data.file.classes[fcount].name, sp->value->data.file.classes[fcount].name_len + 1, apc_bd_alloc TSRMLS_CC); -+ ep->val.file.classes[fcount].name_len = sp->value->data.file.classes[fcount].name_len; -+ ep->val.file.classes[fcount].class_entry = apc_copy_class_entry(NULL, sp->value->data.file.classes[fcount].class_entry, &ctxt TSRMLS_CC); -+ ep->val.file.classes[fcount].parent_name = apc_xstrdup(sp->value->data.file.classes[fcount].parent_name, apc_bd_alloc TSRMLS_CC); -+ -+ apc_swizzle_ptr(bd, &ll, &ep->val.file.classes[fcount].name); -+ apc_swizzle_ptr(bd, &ll, &ep->val.file.classes[fcount].parent_name); -+ apc_swizzle_class_entry(bd, &ll, ep->val.file.classes[fcount].class_entry TSRMLS_CC); -+ apc_swizzle_ptr(bd, &ll, &ep->val.file.classes[fcount].class_entry); -+ } -+ -+ apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.file.filename); -+ apc_swizzle_op_array(bd, &ll, bd->entries[count].val.file.op_array TSRMLS_CC); -+ apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.file.op_array); -+ apc_swizzle_ptr(bd, &ll, (void**)&ep->val.file.functions); -+ apc_swizzle_ptr(bd, &ll, (void**)&ep->val.file.classes); -+ -+ count++; -+ } else { -+ /* TODO: Currently we don't support APC_CACHE_KEY_FILE type. We need to store the path and re-stat on load */ -+ } -+ } -+ } -+ } -+ -+ /* append swizzle pointer list to bd */ -+ bd = apc_swizzle_bd(bd, &ll TSRMLS_CC); -+ zend_llist_destroy(&ll); -+ zend_hash_destroy(&APCG(apc_bd_alloc_list)); -+ -+ if(files) { -+ zend_hash_destroy(files); -+ efree(files); -+ } -+ if(user_vars) { -+ zend_hash_destroy(user_vars); -+ efree(user_vars); -+ } -+ -+ efree(pool_ptr); -+ -+ return bd; -+} /* }}} */ -+ -+ -+/* {{{ apc_bin_load */ -+int apc_bin_load(apc_bd_t *bd, int flags TSRMLS_DC) { -+ -+ apc_bd_entry_t *ep; -+ uint i, i2; -+ int ret; -+ time_t t; -+ zend_op_array *alloc_op_array = NULL; -+ apc_function_t *alloc_functions = NULL; -+ apc_class_t *alloc_classes = NULL; -+ apc_cache_entry_t *cache_entry; -+ apc_cache_key_t cache_key; -+ apc_context_t ctxt; -+ -+ if (bd->swizzled) { -+ if(apc_unswizzle_bd(bd, flags TSRMLS_CC) < 0) { -+ return -1; -+ } -+ } -+ -+ t = apc_time(); -+ -+ for(i = 0; i < bd->num_entries; i++) { -+ ctxt.pool = apc_pool_create(APC_SMALL_POOL, apc_sma_malloc, apc_sma_free, apc_sma_protect, apc_sma_unprotect TSRMLS_CC); -+ if (!ctxt.pool) { /* TODO need to cleanup previous pools */ -+ apc_warning("Unable to allocate memory for pool." TSRMLS_CC); -+ goto failure; -+ } -+ ep = &bd->entries[i]; -+ switch (ep->type) { -+ case APC_CACHE_KEY_FILE: -+ /* TODO: Currently we don't support APC_CACHE_KEY_FILE type. We need to store the path and re-stat on load (or something else perhaps?) */ -+ break; -+ case APC_CACHE_KEY_FPFILE: -+ ctxt.copy = APC_COPY_IN_OPCODE; -+ -+ HANDLE_BLOCK_INTERRUPTIONS(); -+#if NONBLOCKING_LOCK_AVAILABLE -+ if(APCG(write_lock)) { -+ if(!apc_cache_write_lock(apc_cache TSRMLS_CC)) { -+ HANDLE_UNBLOCK_INTERRUPTIONS(); -+ return -1; -+ } -+ } -+#endif -+ if(! (alloc_op_array = apc_copy_op_array(NULL, ep->val.file.op_array, &ctxt TSRMLS_CC))) { -+ goto failure; -+ } -+ apc_bin_fixup_op_array(alloc_op_array); -+ -+ if(! (alloc_functions = apc_sma_malloc(sizeof(apc_function_t) * (ep->num_functions + 1) TSRMLS_CC))) { -+ goto failure; -+ } -+ for(i2=0; i2 < ep->num_functions; i2++) { -+ if(! (alloc_functions[i2].name = apc_xmemcpy(ep->val.file.functions[i2].name, ep->val.file.functions[i2].name_len + 1, apc_sma_malloc TSRMLS_CC))) { -+ goto failure; -+ } -+ alloc_functions[i2].name_len = ep->val.file.functions[i2].name_len; -+ if(! (alloc_functions[i2].function = apc_sma_malloc(sizeof(zend_function) TSRMLS_CC))) { -+ goto failure; -+ } -+ switch(ep->val.file.functions[i2].function->type) { -+ case ZEND_INTERNAL_FUNCTION: -+ case ZEND_OVERLOADED_FUNCTION: -+ alloc_functions[i2].function->op_array = ep->val.file.functions[i2].function->op_array; -+ break; -+ case ZEND_USER_FUNCTION: -+ case ZEND_EVAL_CODE: -+ if (!apc_copy_op_array(&alloc_functions[i2].function->op_array, &ep->val.file.functions[i2].function->op_array, &ctxt TSRMLS_CC)) { -+ goto failure; -+ } -+ apc_bin_fixup_op_array(&alloc_functions[i2].function->op_array); -+ break; -+ default: -+ assert(0); -+ } -+#ifdef ZEND_ENGINE_2 -+ alloc_functions[i2].function->common.prototype=NULL; -+ alloc_functions[i2].function->common.fn_flags=ep->val.file.functions[i2].function->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT); -+#endif -+ } -+ alloc_functions[i2].name = NULL; -+ alloc_functions[i2].function = NULL; -+ -+ if(! (alloc_classes = apc_sma_malloc(sizeof(apc_class_t) * (ep->num_classes + 1) TSRMLS_CC))) { -+ goto failure; -+ } -+ for(i2=0; i2 < ep->num_classes; i2++) { -+ if(! (alloc_classes[i2].name = apc_xmemcpy(ep->val.file.classes[i2].name, ep->val.file.classes[i2].name_len+1, apc_sma_malloc TSRMLS_CC))) { -+ goto failure; -+ } -+ alloc_classes[i2].name_len = ep->val.file.classes[i2].name_len; -+ if(! (alloc_classes[i2].class_entry = apc_copy_class_entry(NULL, ep->val.file.classes[i2].class_entry, &ctxt TSRMLS_CC))) { -+ goto failure; -+ } -+ apc_bin_fixup_class_entry(alloc_classes[i2].class_entry); -+ if(! (alloc_classes[i2].parent_name = apc_xstrdup(ep->val.file.classes[i2].parent_name, apc_sma_malloc TSRMLS_CC))) { -+ if(ep->val.file.classes[i2].parent_name != NULL) { -+ goto failure; -+ } -+ } -+ } -+ alloc_classes[i2].name = NULL; -+ alloc_classes[i2].class_entry = NULL; -+ -+ if(!(cache_entry = apc_cache_make_file_entry(ep->val.file.filename, alloc_op_array, alloc_functions, alloc_classes, &ctxt TSRMLS_CC))) { -+ goto failure; -+ } -+ -+ if (!apc_cache_make_file_key(&cache_key, ep->val.file.filename, PG(include_path), t TSRMLS_CC)) { -+ goto failure; -+ } -+ -+ if ((ret = apc_cache_insert(apc_cache, cache_key, cache_entry, &ctxt, t TSRMLS_CC)) != 1) { -+ if(ret==-1) { -+ goto failure; -+ } -+ } -+ -+#if NONBLOCKING_LOCK_AVAILABLE -+ if(APCG(write_lock)) { -+ apc_cache_write_unlock(apc_cache TSRMLS_CC); -+ } -+#endif -+ HANDLE_UNBLOCK_INTERRUPTIONS(); -+ -+ break; -+ case APC_CACHE_KEY_USER: -+ ctxt.copy = APC_COPY_IN_USER; -+ _apc_store(ep->val.user.info, ep->val.user.info_len, ep->val.user.val, ep->val.user.ttl, 0 TSRMLS_CC); -+ break; -+ default: -+ break; -+ } -+ } -+ -+ return 0; -+ -+failure: -+ apc_pool_destroy(ctxt.pool TSRMLS_CC); -+ apc_warning("Unable to allocate memory for apc binary load/dump functionality." TSRMLS_CC); -+#if NONBLOCKING_LOCK_AVAILABLE -+ if(APCG(write_lock)) { -+ apc_cache_write_unlock(apc_cache TSRMLS_CC); -+ } -+#endif -+ HANDLE_UNBLOCK_INTERRUPTIONS(); -+ return -1; -+} /* }}} */ -+ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_bin.h b/ext/apc/apc_bin.h ---- a/ext/apc/apc_bin.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_bin.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,63 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Brian Shire | -+ +----------------------------------------------------------------------+ -+ -+ */ -+ -+/* $Id: apc_bin.h 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#ifndef APC_BINDUMP_H -+#define APC_BINDUMP_H -+ -+#include "apc.h" -+#include "apc_php.h" -+#include "ext/standard/basic_functions.h" -+ -+/* APC binload flags */ -+#define APC_BIN_VERIFY_MD5 1 << 0 -+#define APC_BIN_VERIFY_CRC32 1 << 1 -+ -+typedef struct _apc_bd_entry_t { -+ unsigned char type; -+ uint num_functions; -+ uint num_classes; -+ apc_cache_entry_value_t val; -+} apc_bd_entry_t; -+ -+typedef struct _apc_bd_t { -+ unsigned int size; -+ int swizzled; -+ unsigned char md5[16]; -+ php_uint32 crc; -+ unsigned int num_entries; -+ apc_bd_entry_t *entries; -+ int num_swizzled_ptrs; -+ void ***swizzled_ptrs; -+} apc_bd_t; -+ -+apc_bd_t* apc_bin_dump(HashTable *files, HashTable *user_vars TSRMLS_DC); -+int apc_bin_load(apc_bd_t *bd, int flags TSRMLS_DC); -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc.c b/ext/apc/apc.c ---- a/ext/apc/apc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,670 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | George Schlossnagle | -+ | Rasmus Lerdorf | -+ | Arun C. Murthy | -+ | Gopal Vijayaraghavan | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc.c 326710 2012-07-19 20:51:04Z rasmus $ */ -+ -+#include "apc.h" -+#include "apc_zend.h" -+#include "apc_cache.h" -+#include "apc_globals.h" -+#include "php.h" -+ -+#if HAVE_PCRE || HAVE_BUNDLED_PCRE -+/* Deal with problem present until php-5.2.2 where php_pcre.h was not installed correctly */ -+# if !HAVE_BUNDLED_PCRE && PHP_MAJOR_VERSION == 5 && (PHP_MINOR_VERSION < 2 || (PHP_MINOR_VERSION == 2 && PHP_RELEASE_VERSION < 2)) -+# include "apc_php_pcre.h" -+# else -+# include "ext/pcre/php_pcre.h" -+# endif -+# include "ext/standard/php_smart_str.h" -+#endif -+ -+#define NELEMS(a) (sizeof(a)/sizeof((a)[0])) -+ -+/* {{{ memory allocation wrappers */ -+ -+void* apc_emalloc(size_t n TSRMLS_DC) -+{ -+ void* p = malloc(n); -+ if (p == NULL) { -+ apc_error("apc_emalloc: malloc failed to allocate %u bytes:" TSRMLS_CC, n); -+ return NULL; -+ } -+ return p; -+} -+ -+void* apc_erealloc(void* p, size_t n TSRMLS_DC) -+{ -+ void *new; -+ new = realloc(p, n); -+ if (new == NULL) { -+ apc_error("apc_erealloc: realloc failed to allocate %u bytes:" TSRMLS_CC, n); -+ return NULL; -+ } -+ return new; -+} -+ -+void apc_efree(void* p TSRMLS_DC) -+{ -+ if (p == NULL) { -+ apc_error("apc_efree: attempt to free null pointer" TSRMLS_CC); -+ return; -+ } -+ free(p); -+} -+ -+char* APC_ALLOC apc_estrdup(const char* s TSRMLS_DC) -+{ -+ int len; -+ char* dup; -+ -+ if (s == NULL) { -+ return NULL; -+ } -+ len = strlen(s); -+ dup = (char*) malloc(len+1); -+ if (dup == NULL) { -+ apc_error("apc_estrdup: malloc failed to allocate %u bytes:" TSRMLS_CC, len+1); -+ return NULL; -+ } -+ memcpy(dup, s, len); -+ dup[len] = '\0'; -+ return dup; -+} -+ -+void* APC_ALLOC apc_xstrdup(const char* s, apc_malloc_t f TSRMLS_DC) -+{ -+ return s != NULL ? apc_xmemcpy(s, strlen(s)+1, f TSRMLS_CC) : NULL; -+} -+ -+void* APC_ALLOC apc_xmemcpy(const void* p, size_t n, apc_malloc_t f TSRMLS_DC) -+{ -+ void* q; -+ -+ if (p != NULL && (q = f(n TSRMLS_CC)) != NULL) { -+ memcpy(q, p, n); -+ return q; -+ } -+ return NULL; -+} -+ -+/* }}} */ -+ -+/* {{{ console display functions */ -+#ifdef ZTS -+# define APC_PRINT_FUNCTION_PARAMETER TSRMLS_C -+#else -+# define APC_PRINT_FUNCTION_PARAMETER format -+#endif -+ -+#define APC_PRINT_FUNCTION(name, verbosity) \ -+ void apc_##name(const char *format TSRMLS_DC, ...) \ -+ { \ -+ va_list args; \ -+ \ -+ va_start(args, APC_PRINT_FUNCTION_PARAMETER); \ -+ php_verror(NULL, "", verbosity, format, args TSRMLS_CC); \ -+ va_end(args); \ -+ } -+ -+APC_PRINT_FUNCTION(error, E_ERROR) -+APC_PRINT_FUNCTION(warning, E_WARNING) -+APC_PRINT_FUNCTION(notice, E_NOTICE) -+ -+#ifdef __DEBUG_APC__ -+APC_PRINT_FUNCTION(debug, E_NOTICE) -+#else -+void apc_debug(const char *format TSRMLS_DC, ...) {} -+#endif -+/* }}} */ -+ -+/* {{{ string and text manipulation */ -+ -+char* apc_append(const char* s, const char* t TSRMLS_DC) -+{ -+ int slen; -+ int tlen; -+ char* p; -+ -+ slen = strlen(s); -+ tlen = strlen(t); -+ -+ p = (char*) apc_emalloc((slen + tlen + 1) * sizeof(char) TSRMLS_CC); -+ memcpy(p, s, slen); -+ memcpy(p + slen, t, tlen + 1); -+ -+ return p; -+} -+ -+char* apc_substr(const char* s, int start, int length TSRMLS_DC) -+{ -+ char* substr; -+ int src_len = strlen(s); -+ -+ /* bring start into range */ -+ if (start < 0) { -+ start = 0; -+ } -+ else if (start >= src_len) { -+ start = src_len - 1; -+ } -+ -+ /* bring length into range */ -+ if (length < 0 || src_len - start < length) { -+ length = src_len - start; -+ } -+ -+ /* create the substring */ -+ substr = apc_xmemcpy(s + start, length + 1, apc_emalloc TSRMLS_CC); -+ substr[length] = '\0'; -+ return substr; -+} -+ -+char** apc_tokenize(const char* s, char delim TSRMLS_DC) -+{ -+ char** tokens; /* array of tokens, NULL terminated */ -+ int size; /* size of tokens array */ -+ int n; /* index of next token in tokens array */ -+ int cur; /* current position in input string */ -+ int end; /* final legal position in input string */ -+ int next; /* position of next delimiter in input */ -+ -+ if (!s) { -+ return NULL; -+ } -+ -+ size = 2; -+ n = 0; -+ cur = 0; -+ end = strlen(s) - 1; -+ -+ tokens = (char**) apc_emalloc(size * sizeof(char*) TSRMLS_CC); -+ tokens[n] = NULL; -+ -+ while (cur <= end) { -+ /* search for the next delimiter */ -+ char* p = strchr(s + cur, delim); -+ next = p ? p-s : end+1; -+ -+ /* resize token array if necessary */ -+ if (n == size-1) { -+ size *= 2; -+ tokens = (char**) apc_erealloc(tokens, size * sizeof(char*) TSRMLS_CC); -+ } -+ -+ /* save the current token */ -+ tokens[n] = apc_substr(s, cur, next-cur TSRMLS_CC); -+ -+ tokens[++n] = NULL; -+ cur = next + 1; -+ } -+ -+ return tokens; -+} -+ -+/* }}} */ -+ -+ -+/* {{{ apc_win32_restat */ -+#ifdef PHP_WIN32 -+static int apc_restat(apc_fileinfo_t *fileinfo TSRMLS_DC) -+{ -+ HANDLE hFile; -+ BY_HANDLE_FILE_INFORMATION hInfo; -+ -+ hFile = CreateFile(fileinfo->fullpath, GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS, NULL); -+ -+ if (!hFile) { -+ apc_debug("Cannot create a file HANDLE for %s\n" TSRMLS_CC, fileinfo->fullpath); -+ return -1; -+ } -+ -+ if (!GetFileInformationByHandle(hFile, &hInfo)) { -+ apc_debug("Cannot get file information from handle\n" TSRMLS_CC); -+ CloseHandle(hFile); -+ return -1; -+ } -+ -+ CloseHandle(hFile); -+ -+ fileinfo->st_buf.sb.st_dev = hInfo.dwVolumeSerialNumber; -+ fileinfo->st_buf.sb.st_ino = (((apc_ino_t)(hInfo.nFileIndexHigh) << 32) | (apc_ino_t) hInfo.nFileIndexLow); -+ -+ return 0; -+} -+#else -+static int apc_restat(apc_fileinfo_t *fileinfo TSRMLS_DC) -+{ -+ return 0; -+} -+#endif -+/* }}} */ -+ -+/* {{{ apc_search_paths */ -+/* similar to php_stream_stat_path */ -+#define APC_URL_STAT(wrapper, filename, pstatbuf) \ -+ ((wrapper)->wops->url_stat((wrapper), (filename), PHP_STREAM_URL_STAT_QUIET, (pstatbuf), NULL TSRMLS_CC)) -+ -+/* copy out to path_buf if path_for_open isn't the same as filename */ -+#define COPY_IF_CHANGED(p) \ -+ (char*) (((p) == filename) ? filename : \ -+ (strlcpy((char*)fileinfo->path_buf, (p), sizeof(fileinfo->path_buf))) \ -+ ? (fileinfo->path_buf) : NULL) -+ -+/* len checks can be skipped here because filename is NUL terminated */ -+#define IS_RELATIVE_PATH(filename, len) \ -+ ((filename) && (filename[0] == '.' && \ -+ (IS_SLASH(filename[1]) || \ -+ (filename[1] == '.' && \ -+ IS_SLASH(filename[2]))))) -+ -+/* {{{ stupid stringifcation */ -+#if DEFAULT_SLASH == '/' -+ #define DEFAULT_SLASH_STRING "/" -+#elif DEFAULT_SLASH == '\\' -+ #define DEFAULT_SLASH_STRING "\\" -+#else -+ #error "Unknown value for DEFAULT_SLASH" -+#endif -+/* }}} */ -+ -+int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo TSRMLS_DC) -+{ -+ char** paths = NULL; -+ char *exec_fname; -+ int exec_fname_length; -+ int found = 0; -+ int i; -+ php_stream_wrapper *wrapper = NULL; -+ char *path_for_open = NULL; -+ -+ assert(filename && fileinfo); -+ -+ -+ wrapper = php_stream_locate_url_wrapper(filename, &path_for_open, 0 TSRMLS_CC); -+ -+ if(!wrapper || !wrapper->wops || !wrapper->wops->url_stat) { -+ return -1; -+ } -+ -+ if(wrapper != &php_plain_files_wrapper) { -+ if(APC_URL_STAT(wrapper, path_for_open, &fileinfo->st_buf) == 0) { -+ fileinfo->fullpath = COPY_IF_CHANGED(path_for_open); -+ return apc_restat(fileinfo TSRMLS_CC); -+ } -+ return -1; /* cannot stat */ -+ } -+ -+ if (IS_ABSOLUTE_PATH(path_for_open, strlen(path_for_open)) && -+ APC_URL_STAT(wrapper, path_for_open, &fileinfo->st_buf) == 0) { -+ fileinfo->fullpath = COPY_IF_CHANGED(path_for_open); -+ return apc_restat(fileinfo TSRMLS_CC); -+ } -+ -+ if (!IS_RELATIVE_PATH(path_for_open, strlen(path_for_open))) { -+ paths = apc_tokenize(path, DEFAULT_DIR_SEPARATOR TSRMLS_CC); -+ if (!paths) -+ return -1; -+ -+ /* for each directory in paths, look for filename inside */ -+ for (i = 0; paths[i]; i++) { -+ snprintf(fileinfo->path_buf, sizeof(fileinfo->path_buf), "%s%c%s", paths[i], DEFAULT_SLASH, path_for_open); -+ if (APC_URL_STAT(wrapper, fileinfo->path_buf, &fileinfo->st_buf) == 0) { -+ fileinfo->fullpath = (char*) fileinfo->path_buf; -+ found = 1; -+ break; -+ } -+ } -+ /* in cli mode PHP explicitly checks the cwd, so we should as well */ -+ if(APCG(enable_cli) && !strcmp(sapi_module.name, "cli")) { -+ snprintf(fileinfo->path_buf, sizeof(fileinfo->path_buf), ".%c%s", DEFAULT_SLASH, path_for_open); -+ if (APC_URL_STAT(wrapper, fileinfo->path_buf, &fileinfo->st_buf) == 0) { -+ fileinfo->fullpath = (char*) fileinfo->path_buf; -+ found = 1; -+ } -+ } -+ } else { -+ /* read cwd and try to fake up fullpath */ -+ fileinfo->path_buf[0] = '\0'; -+ if(VCWD_GETCWD(fileinfo->path_buf, sizeof(fileinfo->path_buf))) { -+ strlcat(fileinfo->path_buf, DEFAULT_SLASH_STRING, sizeof(fileinfo->path_buf)); -+ strlcat(fileinfo->path_buf, path_for_open, sizeof(fileinfo->path_buf)); -+ if (APC_URL_STAT(wrapper, fileinfo->path_buf, &fileinfo->st_buf) == 0) { -+ fileinfo->fullpath = (char*) fileinfo->path_buf; -+ return apc_restat(fileinfo TSRMLS_CC); -+ } -+ } -+ } -+ -+ /* check in path of the calling scripts' current working directory */ -+ /* modified from main/streams/plain_wrapper.c */ -+ if(!found && zend_is_executing(TSRMLS_C)) { -+ exec_fname = zend_get_executed_filename(TSRMLS_C); -+ exec_fname_length = strlen(exec_fname); -+ while((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length])); -+ if((exec_fname && exec_fname[0] != '[') && exec_fname_length > 0) { -+ /* not: [no active file] or no path */ -+ memcpy(fileinfo->path_buf, exec_fname, exec_fname_length); -+ fileinfo->path_buf[exec_fname_length] = DEFAULT_SLASH; -+ strlcpy(fileinfo->path_buf +exec_fname_length +1, path_for_open,sizeof(fileinfo->path_buf)-exec_fname_length-1); -+ /* apc_warning("filename: %s, exec_fname: %s, fileinfo->path_buf: %s" TSRMLS_CC, path_for_open, exec_fname, fileinfo->path_buf); */ -+ if (APC_URL_STAT(wrapper, fileinfo->path_buf, &fileinfo->st_buf) == 0) { -+ fileinfo->fullpath = (char*) fileinfo->path_buf; -+ found = 1; -+ } -+ } -+ } -+ -+ if(paths) { -+ /* free the value returned by apc_tokenize */ -+ for (i = 0; paths[i]; i++) { -+ apc_efree(paths[i] TSRMLS_CC); -+ } -+ apc_efree(paths TSRMLS_CC); -+ } -+ -+ return found ? apc_restat(fileinfo TSRMLS_CC) : -1; -+} -+ -+/* }}} */ -+ -+/* {{{ regular expression wrapper functions */ -+ -+#if (HAVE_PCRE || HAVE_BUNDLED_PCRE) -+typedef struct { -+ pcre *preg; -+ pcre *nreg; -+} apc_regex; -+ -+#define APC_ADD_PATTERN(match, pat) do {\ -+ if(match.len > 1) {\ -+ smart_str_appendc(&match, '|');\ -+ }\ -+ smart_str_appendc(&match, '(');\ -+ while(*pat) {\ -+ if(*pat == '/') smart_str_appendc(&match, '\\');\ -+ \ -+ smart_str_appendc(&match, *(pat++));\ -+ }\ -+ smart_str_appendc(&match, ')');\ -+} while(0) -+ -+#define APC_COMPILE_PATTERN(re, match) do {\ -+ if(match.len > 2) { /* more than just "//" */\ -+ if (((re) = pcre_get_compiled_regex(match.c, NULL, NULL TSRMLS_CC)) == NULL) {\ -+ apc_warning("apc_regex_compile_array: invalid expression '%s'" TSRMLS_CC, match.c); \ -+ smart_str_free(&match);\ -+ return NULL;\ -+ }\ -+ } else { \ -+ (re) = NULL;\ -+ }\ -+} while(0) -+ -+void* apc_regex_compile_array(char* patterns[] TSRMLS_DC) -+{ -+ apc_regex* regs; -+ int npat; -+ smart_str pmatch = {0,}; -+ smart_str nmatch = {0,}; -+ char* pattern; -+ -+ if (!patterns) -+ return NULL; -+ -+ regs = (apc_regex*) apc_emalloc(sizeof(apc_regex) TSRMLS_CC); -+ -+ smart_str_appendc(&pmatch, '/'); -+ smart_str_appendc(&nmatch, '/'); -+ -+ for (npat = 0; patterns[npat] != NULL; npat++) { -+ pattern = patterns[npat]; -+ if(pattern[0] == '+') { -+ pattern += sizeof(char); -+ APC_ADD_PATTERN(pmatch, pattern); -+ } else { -+ if(pattern[0] == '-') pattern += sizeof(char); -+ APC_ADD_PATTERN(nmatch, pattern); -+ } -+ } -+ smart_str_appendc(&pmatch, '/'); -+ smart_str_appendc(&nmatch, '/'); -+ -+ smart_str_0(&nmatch); -+ smart_str_0(&pmatch); -+ -+ APC_COMPILE_PATTERN(regs->preg, pmatch); -+ APC_COMPILE_PATTERN(regs->nreg, nmatch); -+ -+ smart_str_free(&pmatch); -+ smart_str_free(&nmatch); -+ -+ return (void*) regs; -+} -+ -+void apc_regex_destroy_array(void* p TSRMLS_DC) -+{ -+ if (p != NULL) { -+ apc_regex* regs = (apc_regex*) p; -+ apc_efree(regs TSRMLS_CC); -+ } -+} -+ -+#define APC_MATCH_PATTERN(re, input, output) do {\ -+ if (re && pcre_exec(re, NULL, (input), strlen(input), 0, 0, NULL, 0) >= 0) {\ -+ return (output);\ -+ }\ -+} while(0) -+ -+ -+int apc_regex_match_array(void* p, const char* input) -+{ -+ apc_regex* regs; -+ -+ if (!p) -+ return 0; -+ -+ regs = (apc_regex*) p; -+ -+ APC_MATCH_PATTERN(regs->preg, input, APC_POSITIVE_MATCH); -+ APC_MATCH_PATTERN(regs->nreg, input, APC_NEGATIVE_MATCH); -+ -+ return 0; -+} -+#else /* no pcre */ -+void* apc_regex_compile_array(char* patterns[] TSRMLS_DC) -+{ -+ if(patterns && patterns[0] != NULL) { -+ apc_warning("pcre missing, disabling filters" TSRMLS_CC); -+ } -+ return NULL; -+} -+void apc_regex_destroy_array(void* p) -+{ -+ /* nothing */ -+} -+int apc_regex_match_array(void* p, const char* input) -+{ -+ return 0; -+} -+#endif -+/* }}} */ -+ -+/* {{{ crc32 implementation */ -+ -+/* this table was generated by crc32gen() */ -+static unsigned int crc32tab[] = { -+ /* 0 */ 0x00000000, 0x3b83984b, 0x77073096, 0x4c84a8dd, -+ /* 4 */ 0xee0e612c, 0xd58df967, 0x990951ba, 0xa28ac9f1, -+ /* 8 */ 0x076dc419, 0x3cee5c52, 0x706af48f, 0x4be96cc4, -+ /* 12 */ 0xe963a535, 0xd2e03d7e, 0x9e6495a3, 0xa5e70de8, -+ /* 16 */ 0x0edb8832, 0x35581079, 0x79dcb8a4, 0x425f20ef, -+ /* 20 */ 0xe0d5e91e, 0xdb567155, 0x97d2d988, 0xac5141c3, -+ /* 24 */ 0x09b64c2b, 0x3235d460, 0x7eb17cbd, 0x4532e4f6, -+ /* 28 */ 0xe7b82d07, 0xdc3bb54c, 0x90bf1d91, 0xab3c85da, -+ /* 32 */ 0x1db71064, 0x2634882f, 0x6ab020f2, 0x5133b8b9, -+ /* 36 */ 0xf3b97148, 0xc83ae903, 0x84be41de, 0xbf3dd995, -+ /* 40 */ 0x1adad47d, 0x21594c36, 0x6ddde4eb, 0x565e7ca0, -+ /* 44 */ 0xf4d4b551, 0xcf572d1a, 0x83d385c7, 0xb8501d8c, -+ /* 48 */ 0x136c9856, 0x28ef001d, 0x646ba8c0, 0x5fe8308b, -+ /* 52 */ 0xfd62f97a, 0xc6e16131, 0x8a65c9ec, 0xb1e651a7, -+ /* 56 */ 0x14015c4f, 0x2f82c404, 0x63066cd9, 0x5885f492, -+ /* 60 */ 0xfa0f3d63, 0xc18ca528, 0x8d080df5, 0xb68b95be, -+ /* 64 */ 0x3b6e20c8, 0x00edb883, 0x4c69105e, 0x77ea8815, -+ /* 68 */ 0xd56041e4, 0xeee3d9af, 0xa2677172, 0x99e4e939, -+ /* 72 */ 0x3c03e4d1, 0x07807c9a, 0x4b04d447, 0x70874c0c, -+ /* 76 */ 0xd20d85fd, 0xe98e1db6, 0xa50ab56b, 0x9e892d20, -+ /* 80 */ 0x35b5a8fa, 0x0e3630b1, 0x42b2986c, 0x79310027, -+ /* 84 */ 0xdbbbc9d6, 0xe038519d, 0xacbcf940, 0x973f610b, -+ /* 88 */ 0x32d86ce3, 0x095bf4a8, 0x45df5c75, 0x7e5cc43e, -+ /* 92 */ 0xdcd60dcf, 0xe7559584, 0xabd13d59, 0x9052a512, -+ /* 96 */ 0x26d930ac, 0x1d5aa8e7, 0x51de003a, 0x6a5d9871, -+ /* 100 */ 0xc8d75180, 0xf354c9cb, 0xbfd06116, 0x8453f95d, -+ /* 104 */ 0x21b4f4b5, 0x1a376cfe, 0x56b3c423, 0x6d305c68, -+ /* 108 */ 0xcfba9599, 0xf4390dd2, 0xb8bda50f, 0x833e3d44, -+ /* 112 */ 0x2802b89e, 0x138120d5, 0x5f058808, 0x64861043, -+ /* 116 */ 0xc60cd9b2, 0xfd8f41f9, 0xb10be924, 0x8a88716f, -+ /* 120 */ 0x2f6f7c87, 0x14ece4cc, 0x58684c11, 0x63ebd45a, -+ /* 124 */ 0xc1611dab, 0xfae285e0, 0xb6662d3d, 0x8de5b576, -+ /* 128 */ 0x76dc4190, 0x4d5fd9db, 0x01db7106, 0x3a58e94d, -+ /* 132 */ 0x98d220bc, 0xa351b8f7, 0xefd5102a, 0xd4568861, -+ /* 136 */ 0x71b18589, 0x4a321dc2, 0x06b6b51f, 0x3d352d54, -+ /* 140 */ 0x9fbfe4a5, 0xa43c7cee, 0xe8b8d433, 0xd33b4c78, -+ /* 144 */ 0x7807c9a2, 0x438451e9, 0x0f00f934, 0x3483617f, -+ /* 148 */ 0x9609a88e, 0xad8a30c5, 0xe10e9818, 0xda8d0053, -+ /* 152 */ 0x7f6a0dbb, 0x44e995f0, 0x086d3d2d, 0x33eea566, -+ /* 156 */ 0x91646c97, 0xaae7f4dc, 0xe6635c01, 0xdde0c44a, -+ /* 160 */ 0x6b6b51f4, 0x50e8c9bf, 0x1c6c6162, 0x27eff929, -+ /* 164 */ 0x856530d8, 0xbee6a893, 0xf262004e, 0xc9e19805, -+ /* 168 */ 0x6c0695ed, 0x57850da6, 0x1b01a57b, 0x20823d30, -+ /* 172 */ 0x8208f4c1, 0xb98b6c8a, 0xf50fc457, 0xce8c5c1c, -+ /* 176 */ 0x65b0d9c6, 0x5e33418d, 0x12b7e950, 0x2934711b, -+ /* 180 */ 0x8bbeb8ea, 0xb03d20a1, 0xfcb9887c, 0xc73a1037, -+ /* 184 */ 0x62dd1ddf, 0x595e8594, 0x15da2d49, 0x2e59b502, -+ /* 188 */ 0x8cd37cf3, 0xb750e4b8, 0xfbd44c65, 0xc057d42e, -+ /* 192 */ 0x4db26158, 0x7631f913, 0x3ab551ce, 0x0136c985, -+ /* 196 */ 0xa3bc0074, 0x983f983f, 0xd4bb30e2, 0xef38a8a9, -+ /* 200 */ 0x4adfa541, 0x715c3d0a, 0x3dd895d7, 0x065b0d9c, -+ /* 204 */ 0xa4d1c46d, 0x9f525c26, 0xd3d6f4fb, 0xe8556cb0, -+ /* 208 */ 0x4369e96a, 0x78ea7121, 0x346ed9fc, 0x0fed41b7, -+ /* 212 */ 0xad678846, 0x96e4100d, 0xda60b8d0, 0xe1e3209b, -+ /* 216 */ 0x44042d73, 0x7f87b538, 0x33031de5, 0x088085ae, -+ /* 220 */ 0xaa0a4c5f, 0x9189d414, 0xdd0d7cc9, 0xe68ee482, -+ /* 224 */ 0x5005713c, 0x6b86e977, 0x270241aa, 0x1c81d9e1, -+ /* 228 */ 0xbe0b1010, 0x8588885b, 0xc90c2086, 0xf28fb8cd, -+ /* 232 */ 0x5768b525, 0x6ceb2d6e, 0x206f85b3, 0x1bec1df8, -+ /* 236 */ 0xb966d409, 0x82e54c42, 0xce61e49f, 0xf5e27cd4, -+ /* 240 */ 0x5edef90e, 0x655d6145, 0x29d9c998, 0x125a51d3, -+ /* 244 */ 0xb0d09822, 0x8b530069, 0xc7d7a8b4, 0xfc5430ff, -+ /* 248 */ 0x59b33d17, 0x6230a55c, 0x2eb40d81, 0x153795ca, -+ /* 252 */ 0xb7bd5c3b, 0x8c3ec470, 0xc0ba6cad, 0xfb39f4e6, -+}; -+ -+unsigned int apc_crc32(const char* buf, int len) -+{ -+ int i; -+ int k; -+ unsigned int crc; -+ -+ /* preconditioning */ -+ crc = 0xFFFFFFFF; -+ -+ for (i = 0; i < len; i++) { -+ k = (crc ^ buf[i]) & 0x000000FF; -+ crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[k]; -+ } -+ -+ /* postconditioning */ -+ return ~crc; -+} -+ -+/* crc32gen: generate the nth (0..255) crc32 table value */ -+#if 0 -+static unsigned long crc32gen(int n) -+{ -+ int i; -+ unsigned long crc; -+ -+ crc = n; -+ for (i = 8; i >= 0; i--) { -+ if (crc & 1) { -+ crc = (crc >> 1) ^ 0xEDB88320; -+ } -+ else { -+ crc >>= 1; -+ } -+ } -+ return crc; -+} -+#endif -+ -+/* }}} */ -+ -+ -+/* {{{ apc_flip_hash() */ -+HashTable* apc_flip_hash(HashTable *hash) { -+ zval **entry, *data; -+ HashTable *new_hash; -+ HashPosition pos; -+ -+ if(hash == NULL) return hash; -+ -+ MAKE_STD_ZVAL(data); -+ ZVAL_LONG(data, 1); -+ -+ new_hash = emalloc(sizeof(HashTable)); -+ zend_hash_init(new_hash, hash->nTableSize, NULL, ZVAL_PTR_DTOR, 0); -+ -+ zend_hash_internal_pointer_reset_ex(hash, &pos); -+ while (zend_hash_get_current_data_ex(hash, (void **)&entry, &pos) == SUCCESS) { -+ if(Z_TYPE_PP(entry) == IS_STRING) { -+ zend_hash_update(new_hash, Z_STRVAL_PP(entry), Z_STRLEN_PP(entry) +1, &data, sizeof(data), NULL); -+ } else { -+ zend_hash_index_update(new_hash, Z_LVAL_PP(entry), &data, sizeof(data), NULL); -+ } -+ Z_ADDREF_P(data); -+ zend_hash_move_forward_ex(hash, &pos); -+ } -+ zval_ptr_dtor(&data); -+ -+ return new_hash; -+} -+/* }}} */ -+ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_cache.c b/ext/apc/apc_cache.c ---- a/ext/apc/apc_cache.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_cache.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,1383 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | Rasmus Lerdorf | -+ | Arun C. Murthy | -+ | Gopal Vijayaraghavan | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_cache.c 325482 2012-05-01 00:09:36Z rasmus $ */ -+ -+#include "apc_cache.h" -+#include "apc_zend.h" -+#include "apc_sma.h" -+#include "apc_globals.h" -+#include "SAPI.h" -+#include "TSRM.h" -+#include "ext/standard/md5.h" -+ -+/* TODO: rehash when load factor exceeds threshold */ -+ -+#define CHECK(p) { if ((p) == NULL) return NULL; } -+ -+/* {{{ key_equals */ -+#define key_equals(a, b) (a.inode==b.inode && a.device==b.device) -+/* }}} */ -+ -+static void apc_cache_expunge(apc_cache_t* cache, size_t size TSRMLS_DC); -+ -+/* {{{ hash */ -+static unsigned long hash(apc_cache_key_t key) -+{ -+ return (unsigned long)(key.data.file.device + key.data.file.inode); -+} -+/* }}} */ -+ -+/* {{{ string_nhash_8 */ -+#define string_nhash_8(s,len) (unsigned long)(zend_inline_hash_func((s), len)) -+/* }}} */ -+ -+/* {{{ murmurhash */ -+#if 0 -+static inline unsigned long murmurhash(const char *skey, size_t keylen) -+{ -+ const long m = 0x7fd652ad; -+ const long r = 16; -+ unsigned int h = 0xdeadbeef; -+ -+ while(keylen >= 4) -+ { -+ h += *(unsigned int*)skey; -+ h *= m; -+ h ^= h >> r; -+ -+ skey += 4; -+ keylen -= 4; -+ } -+ -+ switch(keylen) -+ { -+ case 3: -+ h += skey[2] << 16; -+ case 2: -+ h += skey[1] << 8; -+ case 1: -+ h += skey[0]; -+ h *= m; -+ h ^= h >> r; -+ }; -+ -+ h *= m; -+ h ^= h >> 10; -+ h *= m; -+ h ^= h >> 17; -+ -+ return h; -+} -+#endif -+/* }}} */ -+ -+ -+/* {{{ make_prime */ -+static int const primes[] = { -+ 257, /* 256 */ -+ 521, /* 512 */ -+ 1031, /* 1024 */ -+ 2053, /* 2048 */ -+ 3079, /* 3072 */ -+ 4099, /* 4096 */ -+ 5147, /* 5120 */ -+ 6151, /* 6144 */ -+ 7177, /* 7168 */ -+ 8209, /* 8192 */ -+ 9221, /* 9216 */ -+10243, /* 10240 */ -+11273, /* 11264 */ -+12289, /* 12288 */ -+13313, /* 13312 */ -+14341, /* 14336 */ -+15361, /* 15360 */ -+16411, /* 16384 */ -+17417, /* 17408 */ -+18433, /* 18432 */ -+19457, /* 19456 */ -+0 /* sentinel */ -+}; -+ -+static int make_prime(int n) -+{ -+ int *k = (int*)primes; -+ while(*k) { -+ if((*k) > n) return *k; -+ k++; -+ } -+ return *(k-1); -+} -+/* }}} */ -+ -+/* {{{ make_slot */ -+slot_t* make_slot(apc_cache_key_t *key, apc_cache_entry_t* value, slot_t* next, time_t t TSRMLS_DC) -+{ -+ slot_t* p = apc_pool_alloc(value->pool, sizeof(slot_t)); -+ -+ if (!p) return NULL; -+ -+ if(key->type == APC_CACHE_KEY_USER) { -+ char *identifier = (char*) apc_pmemcpy(key->data.user.identifier, key->data.user.identifier_len, value->pool TSRMLS_CC); -+ if (!identifier) { -+ return NULL; -+ } -+ key->data.user.identifier = identifier; -+ } else if(key->type == APC_CACHE_KEY_FPFILE) { -+ char *fullpath = (char*) apc_pstrdup(key->data.fpfile.fullpath, value->pool TSRMLS_CC); -+ if (!fullpath) { -+ return NULL; -+ } -+ key->data.fpfile.fullpath = fullpath; -+ } -+ p->key = key[0]; -+ p->value = value; -+ p->next = next; -+ p->num_hits = 0; -+ p->creation_time = t; -+ p->access_time = t; -+ p->deletion_time = 0; -+ return p; -+} -+/* }}} */ -+ -+/* {{{ free_slot */ -+static void free_slot(slot_t* slot TSRMLS_DC) -+{ -+ apc_pool_destroy(slot->value->pool TSRMLS_CC); -+} -+/* }}} */ -+ -+/* {{{ remove_slot */ -+static void remove_slot(apc_cache_t* cache, slot_t** slot TSRMLS_DC) -+{ -+ slot_t* dead = *slot; -+ *slot = (*slot)->next; -+ -+ cache->header->mem_size -= dead->value->mem_size; -+ CACHE_FAST_DEC(cache, cache->header->num_entries); -+ if (dead->value->ref_count <= 0) { -+ free_slot(dead TSRMLS_CC); -+ } -+ else { -+ dead->next = cache->header->deleted_list; -+ dead->deletion_time = time(0); -+ cache->header->deleted_list = dead; -+ } -+} -+/* }}} */ -+ -+/* {{{ process_pending_removals */ -+static void process_pending_removals(apc_cache_t* cache TSRMLS_DC) -+{ -+ slot_t** slot; -+ time_t now; -+ -+ /* This function scans the list of removed cache entries and deletes any -+ * entry whose reference count is zero (indicating that it is no longer -+ * being executed) or that has been on the pending list for more than -+ * cache->gc_ttl seconds (we issue a warning in the latter case). -+ */ -+ -+ if (!cache->header->deleted_list) -+ return; -+ -+ slot = &cache->header->deleted_list; -+ now = time(0); -+ -+ while (*slot != NULL) { -+ int gc_sec = cache->gc_ttl ? (now - (*slot)->deletion_time) : 0; -+ -+ if ((*slot)->value->ref_count <= 0 || gc_sec > cache->gc_ttl) { -+ slot_t* dead = *slot; -+ -+ if (dead->value->ref_count > 0) { -+ switch(dead->value->type) { -+ case APC_CACHE_ENTRY_FILE: -+ apc_debug("GC cache entry '%s' (dev=%d ino=%d) was on gc-list for %d seconds" TSRMLS_CC, -+ dead->value->data.file.filename, dead->key.data.file.device, dead->key.data.file.inode, gc_sec); -+ break; -+ case APC_CACHE_ENTRY_USER: -+ apc_debug("GC cache entry '%s' was on gc-list for %d seconds" TSRMLS_CC, dead->value->data.user.info, gc_sec); -+ break; -+ } -+ } -+ *slot = dead->next; -+ free_slot(dead TSRMLS_CC); -+ } -+ else { -+ slot = &(*slot)->next; -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ prevent_garbage_collection */ -+static void prevent_garbage_collection(apc_cache_entry_t* entry) -+{ -+ /* set reference counts on zend objects to an arbitrarily high value to -+ * prevent garbage collection after execution */ -+ -+ enum { BIG_VALUE = 1000 }; -+ -+ if(entry->data.file.op_array) { -+ entry->data.file.op_array->refcount[0] = BIG_VALUE; -+ } -+ if (entry->data.file.functions) { -+ int i; -+ apc_function_t* fns = entry->data.file.functions; -+ for (i=0; fns[i].function != NULL; i++) { -+ *(fns[i].function->op_array.refcount) = BIG_VALUE; -+ } -+ } -+ if (entry->data.file.classes) { -+ int i; -+ apc_class_t* classes = entry->data.file.classes; -+ for (i=0; classes[i].class_entry != NULL; i++) { -+ classes[i].class_entry->refcount = BIG_VALUE; -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ apc_cache_create */ -+apc_cache_t* apc_cache_create(int size_hint, int gc_ttl, int ttl TSRMLS_DC) -+{ -+ apc_cache_t* cache; -+ int cache_size; -+ int num_slots; -+ -+ num_slots = make_prime(size_hint > 0 ? size_hint : 2000); -+ -+ cache = (apc_cache_t*) apc_emalloc(sizeof(apc_cache_t) TSRMLS_CC); -+ cache_size = sizeof(cache_header_t) + num_slots*sizeof(slot_t*); -+ -+ cache->shmaddr = apc_sma_malloc(cache_size TSRMLS_CC); -+ if(!cache->shmaddr) { -+ apc_error("Unable to allocate shared memory for cache structures. (Perhaps your shared memory size isn't large enough?). " TSRMLS_CC); -+ return NULL; -+ } -+ memset(cache->shmaddr, 0, cache_size); -+ -+ cache->header = (cache_header_t*) cache->shmaddr; -+ cache->header->num_hits = 0; -+ cache->header->num_misses = 0; -+ cache->header->deleted_list = NULL; -+ cache->header->start_time = time(NULL); -+ cache->header->expunges = 0; -+ cache->header->busy = 0; -+ -+ cache->slots = (slot_t**) (((char*) cache->shmaddr) + sizeof(cache_header_t)); -+ cache->num_slots = num_slots; -+ cache->gc_ttl = gc_ttl; -+ cache->ttl = ttl; -+ CREATE_LOCK(cache->header->lock); -+#if NONBLOCKING_LOCK_AVAILABLE -+ CREATE_LOCK(cache->header->wrlock); -+#endif -+ memset(cache->slots, 0, sizeof(slot_t*)*num_slots); -+ cache->expunge_cb = apc_cache_expunge; -+ cache->has_lock = 0; -+ -+ return cache; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_destroy */ -+void apc_cache_destroy(apc_cache_t* cache TSRMLS_DC) -+{ -+ DESTROY_LOCK(cache->header->lock); -+#if NONBLOCKING_LOCK_AVAILABLE -+ DESTROY_LOCK(cache->header->wrlock); -+#endif -+ apc_efree(cache TSRMLS_CC); -+} -+/* }}} */ -+ -+/* {{{ apc_cache_clear */ -+void apc_cache_clear(apc_cache_t* cache TSRMLS_DC) -+{ -+ int i; -+ -+ if(!cache) return; -+ -+ CACHE_LOCK(cache); -+ cache->header->busy = 1; -+ cache->header->num_hits = 0; -+ cache->header->num_misses = 0; -+ cache->header->start_time = time(NULL); -+ cache->header->expunges = 0; -+ -+ for (i = 0; i < cache->num_slots; i++) { -+ slot_t* p = cache->slots[i]; -+ while (p) { -+ remove_slot(cache, &p TSRMLS_CC); -+ } -+ cache->slots[i] = NULL; -+ } -+ -+ memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t)); -+ -+ cache->header->busy = 0; -+ CACHE_UNLOCK(cache); -+} -+/* }}} */ -+ -+/* {{{ apc_cache_expunge */ -+static void apc_cache_expunge(apc_cache_t* cache, size_t size TSRMLS_DC) -+{ -+ int i; -+ time_t t; -+ -+ t = apc_time(); -+ -+ if(!cache) return; -+ -+ if(!cache->ttl) { -+ /* -+ * If cache->ttl is not set, we wipe out the entire cache when -+ * we run out of space. -+ */ -+ CACHE_SAFE_LOCK(cache); -+ process_pending_removals(cache TSRMLS_CC); -+ if (apc_sma_get_avail_mem() > (size_t)(APCG(shm_size)/2)) { -+ /* probably a queued up expunge, we don't need to do this */ -+ CACHE_SAFE_UNLOCK(cache); -+ return; -+ } -+ cache->header->busy = 1; -+ CACHE_FAST_INC(cache, cache->header->expunges); -+clear_all: -+ for (i = 0; i < cache->num_slots; i++) { -+ slot_t* p = cache->slots[i]; -+ while (p) { -+ remove_slot(cache, &p TSRMLS_CC); -+ } -+ cache->slots[i] = NULL; -+ } -+ memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t)); -+ cache->header->busy = 0; -+ CACHE_SAFE_UNLOCK(cache); -+ } else { -+ slot_t **p; -+ /* -+ * If the ttl for the cache is set we walk through and delete stale -+ * entries. For the user cache that is slightly confusing since -+ * we have the individual entry ttl's we can look at, but that would be -+ * too much work. So if you want the user cache expunged, set a high -+ * default apc.user_ttl and still provide a specific ttl for each entry -+ * on insert -+ */ -+ -+ CACHE_SAFE_LOCK(cache); -+ process_pending_removals(cache TSRMLS_CC); -+ if (apc_sma_get_avail_mem() > (size_t)(APCG(shm_size)/2)) { -+ /* probably a queued up expunge, we don't need to do this */ -+ CACHE_SAFE_UNLOCK(cache); -+ return; -+ } -+ cache->header->busy = 1; -+ CACHE_FAST_INC(cache, cache->header->expunges); -+ for (i = 0; i < cache->num_slots; i++) { -+ p = &cache->slots[i]; -+ while(*p) { -+ /* -+ * For the user cache we look at the individual entry ttl values -+ * and if not set fall back to the default ttl for the user cache -+ */ -+ if((*p)->value->type == APC_CACHE_ENTRY_USER) { -+ if((*p)->value->data.user.ttl) { -+ if((time_t) ((*p)->creation_time + (*p)->value->data.user.ttl) < t) { -+ remove_slot(cache, p TSRMLS_CC); -+ continue; -+ } -+ } else if(cache->ttl) { -+ if((*p)->creation_time + cache->ttl < t) { -+ remove_slot(cache, p TSRMLS_CC); -+ continue; -+ } -+ } -+ } else if((*p)->access_time < (t - cache->ttl)) { -+ remove_slot(cache, p TSRMLS_CC); -+ continue; -+ } -+ p = &(*p)->next; -+ } -+ } -+ -+ if (!apc_sma_get_avail_size(size)) { -+ /* TODO: re-do this to remove goto across locked sections */ -+ goto clear_all; -+ } -+ memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t)); -+ cache->header->busy = 0; -+ CACHE_SAFE_UNLOCK(cache); -+ } -+} -+/* }}} */ -+ -+/* {{{ apc_cache_insert */ -+static inline int _apc_cache_insert(apc_cache_t* cache, -+ apc_cache_key_t key, -+ apc_cache_entry_t* value, -+ apc_context_t* ctxt, -+ time_t t -+ TSRMLS_DC) -+{ -+ slot_t** slot; -+ -+ if (!value) { -+ return 0; -+ } -+ -+ apc_debug("Inserting [%s]\n" TSRMLS_CC, value->data.file.filename); -+ -+ process_pending_removals(cache TSRMLS_CC); -+ -+ slot = &cache->slots[key.h % cache->num_slots]; -+ -+ while(*slot) { -+ if(key.type == (*slot)->key.type) { -+ if(key.type == APC_CACHE_KEY_FILE) { -+ if(key_equals((*slot)->key.data.file, key.data.file)) { -+ /* If existing slot for the same device+inode is different, remove it and insert the new version */ -+ if (ctxt->force_update || (*slot)->key.mtime != key.mtime) { -+ remove_slot(cache, slot TSRMLS_CC); -+ break; -+ } -+ return 0; -+ } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) { -+ remove_slot(cache, slot TSRMLS_CC); -+ continue; -+ } -+ } else { /* APC_CACHE_KEY_FPFILE */ -+ if((key.h == (*slot)->key.h) && -+ !memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) { -+ /* Hrm.. it's already here, remove it and insert new one */ -+ remove_slot(cache, slot TSRMLS_CC); -+ break; -+ } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) { -+ remove_slot(cache, slot TSRMLS_CC); -+ continue; -+ } -+ } -+ } -+ slot = &(*slot)->next; -+ } -+ -+ if ((*slot = make_slot(&key, value, *slot, t TSRMLS_CC)) == NULL) { -+ return -1; -+ } -+ -+ value->mem_size = ctxt->pool->size; -+ cache->header->mem_size += ctxt->pool->size; -+ CACHE_FAST_INC(cache, cache->header->num_entries); -+ CACHE_FAST_INC(cache, cache->header->num_inserts); -+ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_insert */ -+int apc_cache_insert(apc_cache_t* cache, apc_cache_key_t key, apc_cache_entry_t* value, apc_context_t *ctxt, time_t t TSRMLS_DC) -+{ -+ int rval; -+ CACHE_LOCK(cache); -+ rval = _apc_cache_insert(cache, key, value, ctxt, t TSRMLS_CC); -+ CACHE_UNLOCK(cache); -+ return rval; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_insert */ -+int *apc_cache_insert_mult(apc_cache_t* cache, apc_cache_key_t* keys, apc_cache_entry_t** values, apc_context_t *ctxt, time_t t, int num_entries TSRMLS_DC) -+{ -+ int *rval; -+ int i; -+ -+ rval = emalloc(sizeof(int) * num_entries); -+ CACHE_LOCK(cache); -+ for (i=0; i < num_entries; i++) { -+ if (values[i]) { -+ ctxt->pool = values[i]->pool; -+ rval[i] = _apc_cache_insert(cache, keys[i], values[i], ctxt, t TSRMLS_CC); -+ } -+ } -+ CACHE_UNLOCK(cache); -+ return rval; -+} -+/* }}} */ -+ -+ -+/* {{{ apc_cache_user_insert */ -+int apc_cache_user_insert(apc_cache_t* cache, apc_cache_key_t key, apc_cache_entry_t* value, apc_context_t* ctxt, time_t t, int exclusive TSRMLS_DC) -+{ -+ slot_t** slot; -+ unsigned int keylen = key.data.user.identifier_len; -+ apc_keyid_t *lastkey = &cache->header->lastkey; -+ -+ if (!value) { -+ return 0; -+ } -+ -+ if(apc_cache_busy(cache)) { -+ /* cache cleanup in progress, do not wait */ -+ return 0; -+ } -+ -+ if(apc_cache_is_last_key(cache, &key, t TSRMLS_CC)) { -+ /* potential cache slam */ -+ return 0; -+ } -+ -+ CACHE_LOCK(cache); -+ -+ memset(lastkey, 0, sizeof(apc_keyid_t)); -+ -+ lastkey->h = key.h; -+ lastkey->keylen = keylen; -+ lastkey->mtime = t; -+#ifdef ZTS -+ lastkey->tid = tsrm_thread_id(); -+#else -+ lastkey->pid = getpid(); -+#endif -+ -+ /* we do not reset lastkey after the insert. Whether it is inserted -+ * or not, another insert in the same second is always a bad idea. -+ */ -+ -+ process_pending_removals(cache TSRMLS_CC); -+ -+ slot = &cache->slots[key.h % cache->num_slots]; -+ -+ while (*slot) { -+ if (((*slot)->key.h == key.h) && -+ (!memcmp((*slot)->key.data.user.identifier, key.data.user.identifier, keylen))) { -+ /* -+ * At this point we have found the user cache entry. If we are doing -+ * an exclusive insert (apc_add) we are going to bail right away if -+ * the user entry already exists and it has no ttl, or -+ * there is a ttl and the entry has not timed out yet. -+ */ -+ if(exclusive && ( !(*slot)->value->data.user.ttl || -+ ( (*slot)->value->data.user.ttl && (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) >= t ) -+ ) ) { -+ goto fail; -+ } -+ remove_slot(cache, slot TSRMLS_CC); -+ break; -+ } else -+ /* -+ * This is a bit nasty. The idea here is to do runtime cleanup of the linked list of -+ * slot entries so we don't always have to skip past a bunch of stale entries. We check -+ * for staleness here and get rid of them by first checking to see if the cache has a global -+ * access ttl on it and removing entries that haven't been accessed for ttl seconds and secondly -+ * we see if the entry has a hard ttl on it and remove it if it has been around longer than its ttl -+ */ -+ if((cache->ttl && (*slot)->access_time < (t - cache->ttl)) || -+ ((*slot)->value->data.user.ttl && (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t)) { -+ remove_slot(cache, slot TSRMLS_CC); -+ continue; -+ } -+ slot = &(*slot)->next; -+ } -+ -+ if ((*slot = make_slot(&key, value, *slot, t TSRMLS_CC)) == NULL) { -+ goto fail; -+ } -+ -+ value->mem_size = ctxt->pool->size; -+ cache->header->mem_size += ctxt->pool->size; -+ -+ CACHE_FAST_INC(cache, cache->header->num_entries); -+ CACHE_FAST_INC(cache, cache->header->num_inserts); -+ -+ CACHE_UNLOCK(cache); -+ -+ return 1; -+ -+fail: -+ CACHE_UNLOCK(cache); -+ -+ return 0; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_find_slot */ -+slot_t* apc_cache_find_slot(apc_cache_t* cache, apc_cache_key_t key, time_t t TSRMLS_DC) -+{ -+ slot_t** slot; -+ volatile slot_t* retval = NULL; -+ -+ CACHE_RDLOCK(cache); -+ if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots]; -+ else slot = &cache->slots[key.h % cache->num_slots]; -+ -+ while (*slot) { -+ if(key.type == (*slot)->key.type) { -+ if(key.type == APC_CACHE_KEY_FILE) { -+ if(key_equals((*slot)->key.data.file, key.data.file)) { -+ if((*slot)->key.mtime != key.mtime) { -+ #if (USE_READ_LOCKS == 0) -+ /* this is merely a memory-friendly optimization, if we do have a write-lock -+ * might as well move this to the deleted_list right-away. Otherwise an insert -+ * of the same key wil do it (or an expunge, *eventually*). -+ */ -+ remove_slot(cache, slot TSRMLS_CC); -+ #endif -+ CACHE_SAFE_INC(cache, cache->header->num_misses); -+ CACHE_RDUNLOCK(cache); -+ return NULL; -+ } -+ CACHE_SAFE_INC(cache, (*slot)->num_hits); -+ CACHE_SAFE_INC(cache, (*slot)->value->ref_count); -+ (*slot)->access_time = t; -+ prevent_garbage_collection((*slot)->value); -+ CACHE_FAST_INC(cache, cache->header->num_hits); -+ retval = *slot; -+ CACHE_RDUNLOCK(cache); -+ return (slot_t*)retval; -+ } -+ } else { /* APC_CACHE_KEY_FPFILE */ -+ if(((*slot)->key.h == key.h) && -+ !memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) { -+ /* TTL Check ? */ -+ CACHE_SAFE_INC(cache, (*slot)->num_hits); -+ CACHE_SAFE_INC(cache, (*slot)->value->ref_count); -+ (*slot)->access_time = t; -+ prevent_garbage_collection((*slot)->value); -+ CACHE_FAST_INC(cache, cache->header->num_hits); -+ retval = *slot; -+ CACHE_RDUNLOCK(cache); -+ return (slot_t*)retval; -+ } -+ } -+ } -+ slot = &(*slot)->next; -+ } -+ CACHE_FAST_INC(cache, cache->header->num_misses); -+ CACHE_RDUNLOCK(cache); -+ return NULL; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_find */ -+apc_cache_entry_t* apc_cache_find(apc_cache_t* cache, apc_cache_key_t key, time_t t TSRMLS_DC) -+{ -+ slot_t * slot = apc_cache_find_slot(cache, key, t TSRMLS_CC); -+ apc_debug("apc_cache_find [%i]\n" TSRMLS_CC, key.h); -+ return (slot) ? slot->value : NULL; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_user_find */ -+apc_cache_entry_t* apc_cache_user_find(apc_cache_t* cache, char *strkey, int keylen, time_t t TSRMLS_DC) -+{ -+ slot_t** slot; -+ volatile apc_cache_entry_t* value = NULL; -+ unsigned long h; -+ -+ if(apc_cache_busy(cache)) -+ { -+ /* cache cleanup in progress */ -+ return NULL; -+ } -+ -+ CACHE_RDLOCK(cache); -+ -+ h = string_nhash_8(strkey, keylen); -+ -+ slot = &cache->slots[h % cache->num_slots]; -+ -+ while (*slot) { -+ if ((h == (*slot)->key.h) && -+ !memcmp((*slot)->key.data.user.identifier, strkey, keylen)) { -+ /* Check to make sure this entry isn't expired by a hard TTL */ -+ if((*slot)->value->data.user.ttl && (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) { -+ #if (USE_READ_LOCKS == 0) -+ /* this is merely a memory-friendly optimization, if we do have a write-lock -+ * might as well move this to the deleted_list right-away. Otherwise an insert -+ * of the same key wil do it (or an expunge, *eventually*). -+ */ -+ remove_slot(cache, slot TSRMLS_CC); -+ #endif -+ CACHE_FAST_INC(cache, cache->header->num_misses); -+ CACHE_RDUNLOCK(cache); -+ return NULL; -+ } -+ /* Otherwise we are fine, increase counters and return the cache entry */ -+ CACHE_SAFE_INC(cache, (*slot)->num_hits); -+ CACHE_SAFE_INC(cache, (*slot)->value->ref_count); -+ (*slot)->access_time = t; -+ -+ CACHE_FAST_INC(cache, cache->header->num_hits); -+ value = (*slot)->value; -+ CACHE_RDUNLOCK(cache); -+ return (apc_cache_entry_t*)value; -+ } -+ slot = &(*slot)->next; -+ } -+ -+ CACHE_FAST_INC(cache, cache->header->num_misses); -+ CACHE_RDUNLOCK(cache); -+ return NULL; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_user_exists */ -+apc_cache_entry_t* apc_cache_user_exists(apc_cache_t* cache, char *strkey, int keylen, time_t t TSRMLS_DC) -+{ -+ slot_t** slot; -+ volatile apc_cache_entry_t* value = NULL; -+ unsigned long h; -+ -+ if(apc_cache_busy(cache)) -+ { -+ /* cache cleanup in progress */ -+ return NULL; -+ } -+ -+ CACHE_RDLOCK(cache); -+ -+ h = string_nhash_8(strkey, keylen); -+ -+ slot = &cache->slots[h % cache->num_slots]; -+ -+ while (*slot) { -+ if ((h == (*slot)->key.h) && -+ !memcmp((*slot)->key.data.user.identifier, strkey, keylen)) { -+ /* Check to make sure this entry isn't expired by a hard TTL */ -+ if((*slot)->value->data.user.ttl && (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) { -+ CACHE_UNLOCK(cache); -+ return NULL; -+ } -+ /* Return the cache entry ptr */ -+ value = (*slot)->value; -+ CACHE_RDUNLOCK(cache); -+ return (apc_cache_entry_t*)value; -+ } -+ slot = &(*slot)->next; -+ } -+ CACHE_RDUNLOCK(cache); -+ return NULL; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_user_update */ -+int _apc_cache_user_update(apc_cache_t* cache, char *strkey, int keylen, apc_cache_updater_t updater, void* data TSRMLS_DC) -+{ -+ slot_t** slot; -+ int retval; -+ unsigned long h; -+ -+ if(apc_cache_busy(cache)) -+ { -+ /* cache cleanup in progress */ -+ return 0; -+ } -+ -+ CACHE_LOCK(cache); -+ -+ h = string_nhash_8(strkey, keylen); -+ slot = &cache->slots[h % cache->num_slots]; -+ -+ while (*slot) { -+ if ((h == (*slot)->key.h) && -+ !memcmp((*slot)->key.data.user.identifier, strkey, keylen)) { -+ switch(Z_TYPE_P((*slot)->value->data.user.val) & ~IS_CONSTANT_INDEX) { -+ case IS_ARRAY: -+ case IS_CONSTANT_ARRAY: -+ case IS_OBJECT: -+ { -+ if(APCG(serializer)) { -+ retval = 0; -+ break; -+ } else { -+ /* fall through */ -+ } -+ } -+ /* fall through */ -+ default: -+ { -+ retval = updater(cache, (*slot)->value, data); -+ (*slot)->key.mtime = apc_time(); -+ } -+ break; -+ } -+ CACHE_UNLOCK(cache); -+ return retval; -+ } -+ slot = &(*slot)->next; -+ } -+ CACHE_UNLOCK(cache); -+ return 0; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_user_delete */ -+int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen TSRMLS_DC) -+{ -+ slot_t** slot; -+ unsigned long h; -+ -+ CACHE_LOCK(cache); -+ -+ h = string_nhash_8(strkey, keylen); -+ -+ slot = &cache->slots[h % cache->num_slots]; -+ -+ while (*slot) { -+ if ((h == (*slot)->key.h) && -+ !memcmp((*slot)->key.data.user.identifier, strkey, keylen)) { -+ remove_slot(cache, slot TSRMLS_CC); -+ CACHE_UNLOCK(cache); -+ return 1; -+ } -+ slot = &(*slot)->next; -+ } -+ -+ CACHE_UNLOCK(cache); -+ return 0; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_delete */ -+int apc_cache_delete(apc_cache_t* cache, char *filename, int filename_len TSRMLS_DC) -+{ -+ slot_t** slot; -+ time_t t; -+ apc_cache_key_t key; -+ -+ t = apc_time(); -+ -+ /* try to create a cache key; if we fail, give up on caching */ -+ if (!apc_cache_make_file_key(&key, filename, PG(include_path), t TSRMLS_CC)) { -+ apc_warning("Could not stat file %s, unable to delete from cache." TSRMLS_CC, filename); -+ return -1; -+ } -+ -+ CACHE_LOCK(cache); -+ -+ if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots]; -+ else slot = &cache->slots[key.h % cache->num_slots]; -+ -+ while(*slot) { -+ if(key.type == (*slot)->key.type) { -+ if(key.type == APC_CACHE_KEY_FILE) { -+ if(key_equals((*slot)->key.data.file, key.data.file)) { -+ remove_slot(cache, slot TSRMLS_CC); -+ CACHE_UNLOCK(cache); -+ return 1; -+ } -+ } else { /* APC_CACHE_KEY_FPFILE */ -+ if(((*slot)->key.h == key.h) && -+ (!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1))) { -+ remove_slot(cache, slot TSRMLS_CC); -+ CACHE_UNLOCK(cache); -+ return 1; -+ } -+ } -+ } -+ slot = &(*slot)->next; -+ } -+ -+ memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t)); -+ -+ CACHE_UNLOCK(cache); -+ return 0; -+ -+} -+/* }}} */ -+ -+/* {{{ apc_cache_release */ -+void apc_cache_release(apc_cache_t* cache, apc_cache_entry_t* entry TSRMLS_DC) -+{ -+ CACHE_SAFE_DEC(cache, entry->ref_count); -+} -+/* }}} */ -+ -+/* {{{ apc_cache_make_file_key */ -+int apc_cache_make_file_key(apc_cache_key_t* key, -+ const char* filename, -+ const char* include_path, -+ time_t t -+ TSRMLS_DC) -+{ -+ struct stat *tmp_buf=NULL; -+ struct apc_fileinfo_t *fileinfo = NULL; -+ int len; -+ -+ assert(key != NULL); -+ -+ if (!filename || !SG(request_info).path_translated) { -+ apc_debug("No filename and no path_translated - bailing\n" TSRMLS_CC); -+ goto cleanup; -+ } -+ -+ len = strlen(filename); -+ if(APCG(fpstat)==0) { -+ if(IS_ABSOLUTE_PATH(filename,len) || strstr(filename, "://")) { -+ key->data.fpfile.fullpath = filename; -+ key->data.fpfile.fullpath_len = len; -+ key->h = string_nhash_8(key->data.fpfile.fullpath, key->data.fpfile.fullpath_len); -+ key->mtime = t; -+ key->type = APC_CACHE_KEY_FPFILE; -+ goto success; -+ } else if(APCG(canonicalize)) { -+ -+ fileinfo = apc_php_malloc(sizeof(apc_fileinfo_t) TSRMLS_CC); -+ -+ if (apc_search_paths(filename, include_path, fileinfo TSRMLS_CC) != 0) { -+ apc_warning("apc failed to locate %s - bailing" TSRMLS_CC, filename); -+ goto cleanup; -+ } -+ -+ if(!VCWD_REALPATH(fileinfo->fullpath, APCG(canon_path))) { -+ apc_warning("realpath failed to canonicalize %s - bailing" TSRMLS_CC, filename); -+ goto cleanup; -+ } -+ -+ key->data.fpfile.fullpath = APCG(canon_path); -+ key->data.fpfile.fullpath_len = strlen(APCG(canon_path)); -+ key->h = string_nhash_8(key->data.fpfile.fullpath, key->data.fpfile.fullpath_len); -+ key->mtime = t; -+ key->type = APC_CACHE_KEY_FPFILE; -+ goto success; -+ } -+ /* fall through to stat mode */ -+ } -+ -+ fileinfo = apc_php_malloc(sizeof(apc_fileinfo_t) TSRMLS_CC); -+ -+ assert(fileinfo != NULL); -+ -+ if(!strcmp(SG(request_info).path_translated, filename)) { -+ tmp_buf = sapi_get_stat(TSRMLS_C); /* Apache has already done this stat() for us */ -+ } -+ -+ if(tmp_buf) { -+ fileinfo->st_buf.sb = *tmp_buf; -+ } else { -+ if (apc_search_paths(filename, include_path, fileinfo TSRMLS_CC) != 0) { -+ apc_debug("Stat failed %s - bailing (%s) (%d)\n" TSRMLS_CC, filename,SG(request_info).path_translated); -+ goto cleanup; -+ } -+ } -+ -+ if(APCG(max_file_size) < fileinfo->st_buf.sb.st_size) { -+ apc_debug("File is too big %s (%d - %ld) - bailing\n" TSRMLS_CC, filename,t,fileinfo->st_buf.sb.st_size); -+ goto cleanup; -+ } -+ -+ /* -+ * This is a bit of a hack. -+ * -+ * Here I am checking to see if the file is at least 2 seconds old. -+ * The idea is that if the file is currently being written to then its -+ * mtime is going to match or at most be 1 second off of the current -+ * request time and we want to avoid caching files that have not been -+ * completely written. Of course, people should be using atomic -+ * mechanisms to push files onto live web servers, but adding this -+ * tiny safety is easier than educating the world. This is now -+ * configurable, but the default is still 2 seconds. -+ */ -+ if(APCG(file_update_protection) && (t - fileinfo->st_buf.sb.st_mtime < APCG(file_update_protection)) && !APCG(force_file_update)) { -+ apc_debug("File is too new %s (%d - %d) - bailing\n" TSRMLS_CC,filename,t,fileinfo->st_buf.sb.st_mtime); -+ goto cleanup; -+ } -+ -+ key->data.file.device = fileinfo->st_buf.sb.st_dev; -+ key->data.file.inode = fileinfo->st_buf.sb.st_ino; -+ key->h = (unsigned long) key->data.file.device + (unsigned long) key->data.file.inode; -+ -+ /* -+ * If working with content management systems that like to munge the mtime, -+ * it might be appropriate to key off of the ctime to be immune to systems -+ * that try to backdate a template. If the mtime is set to something older -+ * than the previous mtime of a template we will obviously never see this -+ * "older" template. At some point the Smarty templating system did this. -+ * I generally disagree with using the ctime here because you lose the -+ * ability to warm up new content by saving it to a temporary file, hitting -+ * it once to cache it and then renaming it into its permanent location so -+ * set the apc.stat_ctime=true to enable this check. -+ */ -+ if(APCG(stat_ctime)) { -+ key->mtime = (fileinfo->st_buf.sb.st_ctime > fileinfo->st_buf.sb.st_mtime) ? fileinfo->st_buf.sb.st_ctime : fileinfo->st_buf.sb.st_mtime; -+ } else { -+ key->mtime = fileinfo->st_buf.sb.st_mtime; -+ } -+ key->type = APC_CACHE_KEY_FILE; -+ -+success: -+ -+ if(fileinfo != NULL) { -+ apc_php_free(fileinfo TSRMLS_CC); -+ } -+ -+ return 1; -+ -+cleanup: -+ -+ if(fileinfo != NULL) { -+ apc_php_free(fileinfo TSRMLS_CC); -+ } -+ -+ return 0; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_make_user_key */ -+int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t) -+{ -+ assert(key != NULL); -+ -+ if (!identifier) -+ return 0; -+ -+ key->data.user.identifier = identifier; -+ key->data.user.identifier_len = identifier_len; -+ key->h = string_nhash_8(key->data.user.identifier, key->data.user.identifier_len); -+ key->mtime = t; -+ key->type = APC_CACHE_KEY_USER; -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_make_file_entry */ -+apc_cache_entry_t* apc_cache_make_file_entry(const char* filename, -+ zend_op_array* op_array, -+ apc_function_t* functions, -+ apc_class_t* classes, -+ apc_context_t* ctxt -+ TSRMLS_DC) -+{ -+ apc_cache_entry_t* entry; -+ apc_pool* pool = ctxt->pool; -+ -+ entry = (apc_cache_entry_t*) apc_pool_alloc(pool, sizeof(apc_cache_entry_t)); -+ if (!entry) return NULL; -+ -+ entry->data.file.filename = apc_pstrdup(filename, pool TSRMLS_CC); -+ if(!entry->data.file.filename) { -+ apc_debug("apc_cache_make_file_entry: entry->data.file.filename is NULL - bailing\n" TSRMLS_CC); -+ return NULL; -+ } -+ apc_debug("apc_cache_make_file_entry: entry->data.file.filename is [%s]\n" TSRMLS_CC,entry->data.file.filename); -+ entry->data.file.op_array = op_array; -+ entry->data.file.functions = functions; -+ entry->data.file.classes = classes; -+ -+ entry->data.file.halt_offset = apc_file_halt_offset(filename TSRMLS_CC); -+ -+ entry->type = APC_CACHE_ENTRY_FILE; -+ entry->ref_count = 0; -+ entry->mem_size = 0; -+ entry->pool = pool; -+ return entry; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_store_zval */ -+zval* apc_cache_store_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ if (Z_TYPE_P(src) == IS_ARRAY) { -+ /* Maintain a list of zvals we've copied to properly handle recursive structures */ -+ zend_hash_init(&APCG(copied_zvals), 0, NULL, NULL, 0); -+ dst = apc_copy_zval(dst, src, ctxt TSRMLS_CC); -+ zend_hash_destroy(&APCG(copied_zvals)); -+ APCG(copied_zvals).nTableSize=0; -+ } else { -+ dst = apc_copy_zval(dst, src, ctxt TSRMLS_CC); -+ } -+ -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_fetch_zval */ -+zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ if (Z_TYPE_P(src) == IS_ARRAY) { -+ /* Maintain a list of zvals we've copied to properly handle recursive structures */ -+ zend_hash_init(&APCG(copied_zvals), 0, NULL, NULL, 0); -+ dst = apc_copy_zval(dst, src, ctxt TSRMLS_CC); -+ zend_hash_destroy(&APCG(copied_zvals)); -+ APCG(copied_zvals).nTableSize=0; -+ } else { -+ dst = apc_copy_zval(dst, src, ctxt TSRMLS_CC); -+ } -+ -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_make_user_entry */ -+apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval* val, apc_context_t* ctxt, const unsigned int ttl TSRMLS_DC) -+{ -+ apc_cache_entry_t* entry; -+ apc_pool* pool = ctxt->pool; -+ -+ entry = (apc_cache_entry_t*) apc_pool_alloc(pool, sizeof(apc_cache_entry_t)); -+ if (!entry) return NULL; -+ -+ entry->data.user.info = apc_pmemcpy(info, info_len, pool TSRMLS_CC); -+ entry->data.user.info_len = info_len; -+ if(!entry->data.user.info) { -+ return NULL; -+ } -+ entry->data.user.val = apc_cache_store_zval(NULL, val, ctxt TSRMLS_CC); -+ if(!entry->data.user.val) { -+ return NULL; -+ } -+ INIT_PZVAL(entry->data.user.val); -+ entry->data.user.ttl = ttl; -+ entry->type = APC_CACHE_ENTRY_USER; -+ entry->ref_count = 0; -+ entry->mem_size = 0; -+ entry->pool = pool; -+ return entry; -+} -+/* }}} */ -+ -+/* {{{ */ -+static zval* apc_cache_link_info(apc_cache_t *cache, slot_t* p TSRMLS_DC) -+{ -+ zval *link = NULL; -+ char md5str[33]; -+ -+ ALLOC_INIT_ZVAL(link); -+ -+ if(!link) { -+ return NULL; -+ } -+ -+ array_init(link); -+ -+ if(p->value->type == APC_CACHE_ENTRY_FILE) { -+ add_assoc_string(link, "type", "file", 1); -+ if(p->key.type == APC_CACHE_KEY_FILE) { -+ -+ #ifdef PHP_WIN32 -+ { -+ char buf[20]; -+ sprintf(buf, "%I64d", p->key.data.file.device); -+ add_assoc_string(link, "device", buf, 1); -+ -+ sprintf(buf, "%I64d", p->key.data.file.inode); -+ add_assoc_string(link, "inode", buf, 1); -+ } -+ #else -+ add_assoc_long(link, "device", p->key.data.file.device); -+ add_assoc_long(link, "inode", p->key.data.file.inode); -+ #endif -+ -+ add_assoc_string(link, "filename", p->value->data.file.filename, 1); -+ } else { /* This is a no-stat fullpath file entry */ -+ add_assoc_long(link, "device", 0); -+ add_assoc_long(link, "inode", 0); -+ add_assoc_string(link, "filename", (char*)p->key.data.fpfile.fullpath, 1); -+ } -+ if (APCG(file_md5)) { -+ make_digest(md5str, p->key.md5); -+ add_assoc_string(link, "md5", md5str, 1); -+ } -+ } else if(p->value->type == APC_CACHE_ENTRY_USER) { -+ add_assoc_stringl(link, "info", p->value->data.user.info, p->value->data.user.info_len-1, 1); -+ add_assoc_long(link, "ttl", (long)p->value->data.user.ttl); -+ add_assoc_string(link, "type", "user", 1); -+ } -+ -+ add_assoc_double(link, "num_hits", (double)p->num_hits); -+ add_assoc_long(link, "mtime", p->key.mtime); -+ add_assoc_long(link, "creation_time", p->creation_time); -+ add_assoc_long(link, "deletion_time", p->deletion_time); -+ add_assoc_long(link, "access_time", p->access_time); -+ add_assoc_long(link, "ref_count", p->value->ref_count); -+ add_assoc_long(link, "mem_size", p->value->mem_size); -+ -+ return link; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_info */ -+zval* apc_cache_info(apc_cache_t* cache, zend_bool limited TSRMLS_DC) -+{ -+ zval *info = NULL; -+ zval *list = NULL; -+ zval *deleted_list = NULL; -+ zval *slots = NULL; -+ slot_t* p; -+ int i, j; -+ -+ if(!cache) return NULL; -+ -+ CACHE_RDLOCK(cache); -+ -+ ALLOC_INIT_ZVAL(info); -+ -+ if(!info) { -+ CACHE_RDUNLOCK(cache); -+ return NULL; -+ } -+ -+ array_init(info); -+ add_assoc_long(info, "num_slots", cache->num_slots); -+ add_assoc_long(info, "ttl", cache->ttl); -+ -+ add_assoc_double(info, "num_hits", (double)cache->header->num_hits); -+ add_assoc_double(info, "num_misses", (double)cache->header->num_misses); -+ add_assoc_double(info, "num_inserts", (double)cache->header->num_inserts); -+ add_assoc_double(info, "expunges", (double)cache->header->expunges); -+ -+ add_assoc_long(info, "start_time", cache->header->start_time); -+ add_assoc_double(info, "mem_size", (double)cache->header->mem_size); -+ add_assoc_long(info, "num_entries", cache->header->num_entries); -+#ifdef MULTIPART_EVENT_FORMDATA -+ add_assoc_long(info, "file_upload_progress", 1); -+#else -+ add_assoc_long(info, "file_upload_progress", 0); -+#endif -+#if APC_MMAP -+ add_assoc_stringl(info, "memory_type", "mmap", sizeof("mmap")-1, 1); -+#else -+ add_assoc_stringl(info, "memory_type", "IPC shared", sizeof("IPC shared")-1, 1); -+#endif -+ add_assoc_stringl(info, "locking_type", APC_LOCK_TYPE, sizeof(APC_LOCK_TYPE)-1, 1); -+ -+ if(!limited) { -+ /* For each hashtable slot */ -+ ALLOC_INIT_ZVAL(list); -+ array_init(list); -+ -+ ALLOC_INIT_ZVAL(slots); -+ array_init(slots); -+ -+ for (i = 0; i < cache->num_slots; i++) { -+ p = cache->slots[i]; -+ j = 0; -+ for (; p != NULL; p = p->next) { -+ zval *link = apc_cache_link_info(cache, p TSRMLS_CC); -+ add_next_index_zval(list, link); -+ j++; -+ } -+ if(j != 0) { -+ add_index_long(slots, (ulong)i, j); -+ } -+ } -+ -+ /* For each slot pending deletion */ -+ ALLOC_INIT_ZVAL(deleted_list); -+ array_init(deleted_list); -+ -+ for (p = cache->header->deleted_list; p != NULL; p = p->next) { -+ zval *link = apc_cache_link_info(cache, p TSRMLS_CC); -+ add_next_index_zval(deleted_list, link); -+ } -+ -+ add_assoc_zval(info, "cache_list", list); -+ add_assoc_zval(info, "deleted_list", deleted_list); -+ add_assoc_zval(info, "slot_distribution", slots); -+ } -+ -+ CACHE_RDUNLOCK(cache); -+ return info; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_unlock */ -+void apc_cache_unlock(apc_cache_t* cache TSRMLS_DC) -+{ -+ CACHE_UNLOCK(cache); -+} -+/* }}} */ -+ -+/* {{{ apc_cache_busy */ -+zend_bool apc_cache_busy(apc_cache_t* cache) -+{ -+ return cache->header->busy; -+} -+/* }}} */ -+ -+/* {{{ apc_cache_is_last_key */ -+zend_bool apc_cache_is_last_key(apc_cache_t* cache, apc_cache_key_t* key, time_t t TSRMLS_DC) -+{ -+ apc_keyid_t *lastkey = &cache->header->lastkey; -+ unsigned int keylen = key->data.user.identifier_len; -+#ifdef ZTS -+ THREAD_T tid = tsrm_thread_id(); -+ #define FROM_DIFFERENT_THREAD(k) (memcmp(&((k)->tid), &tid, sizeof(THREAD_T))!=0) -+#else -+ pid_t pid = getpid(); -+ #define FROM_DIFFERENT_THREAD(k) (pid != (k)->pid) -+#endif -+ -+ -+ /* unlocked reads, but we're not shooting for 100% success with this */ -+ if(lastkey->h == key->h && keylen == lastkey->keylen) { -+ if(lastkey->mtime == t && FROM_DIFFERENT_THREAD(lastkey)) { -+ /* potential cache slam */ -+ if(APCG(slam_defense)) { -+ apc_debug("Potential cache slam averted for key '%s'" TSRMLS_CC, key->data.user.identifier); -+ return 1; -+ } -+ } -+ } -+ -+ return 0; -+} -+/* }}} */ -+ -+#if NONBLOCKING_LOCK_AVAILABLE -+/* {{{ apc_cache_write_lock */ -+zend_bool apc_cache_write_lock(apc_cache_t* cache TSRMLS_DC) -+{ -+ return apc_lck_nb_lock(cache->header->wrlock); -+} -+/* }}} */ -+ -+/* {{{ apc_cache_write_unlock */ -+void apc_cache_write_unlock(apc_cache_t* cache TSRMLS_DC) -+{ -+ apc_lck_unlock(cache->header->wrlock); -+} -+/* }}} */ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_cache.h b/ext/apc/apc_cache.h ---- a/ext/apc/apc_cache.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_cache.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,371 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | Rasmus Lerdorf | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_cache.h 324329 2012-03-18 15:29:37Z mike $ */ -+ -+#ifndef APC_CACHE_H -+#define APC_CACHE_H -+ -+/* -+ * This module defines the shared memory file cache. Basically all of the -+ * logic for storing and retrieving cache entries lives here. -+ */ -+ -+#include "apc.h" -+#include "apc_compile.h" -+#include "apc_lock.h" -+#include "apc_pool.h" -+#include "apc_main.h" -+#include "TSRM.h" -+ -+#define APC_CACHE_ENTRY_FILE 1 -+#define APC_CACHE_ENTRY_USER 2 -+ -+#define APC_CACHE_KEY_FILE 1 -+#define APC_CACHE_KEY_USER 2 -+#define APC_CACHE_KEY_FPFILE 3 -+ -+#ifdef PHP_WIN32 -+typedef unsigned __int64 apc_ino_t; -+typedef unsigned __int64 apc_dev_t; -+#else -+typedef ino_t apc_ino_t; -+typedef dev_t apc_dev_t; -+#endif -+ -+/* {{{ cache locking macros */ -+#define CACHE_LOCK(cache) { LOCK(cache->header->lock); cache->has_lock = 1; } -+#define CACHE_UNLOCK(cache) { UNLOCK(cache->header->lock); cache->has_lock = 0; } -+#define CACHE_SAFE_LOCK(cache) { if ((++cache->has_lock) == 1) LOCK(cache->header->lock); } -+#define CACHE_SAFE_UNLOCK(cache) { if ((--cache->has_lock) == 0) UNLOCK(cache->header->lock); } -+ -+#if (RDLOCK_AVAILABLE == 1) && defined(HAVE_ATOMIC_OPERATIONS) -+#define USE_READ_LOCKS 1 -+#define CACHE_RDLOCK(cache) { RDLOCK(cache->header->lock); cache->has_lock = 0; } -+#define CACHE_RDUNLOCK(cache) { RDUNLOCK(cache->header->lock); cache->has_lock = 0; } -+#define CACHE_SAFE_INC(cache, obj) { ATOMIC_INC(obj); } -+#define CACHE_SAFE_DEC(cache, obj) { ATOMIC_DEC(obj); } -+#else -+#define USE_READ_LOCKS 0 -+#define CACHE_RDLOCK(cache) { LOCK(cache->header->lock); cache->has_lock = 1; } -+#define CACHE_RDUNLOCK(cache) { UNLOCK(cache->header->lock); cache->has_lock = 0; } -+#define CACHE_SAFE_INC(cache, obj) { CACHE_SAFE_LOCK(cache); obj++; CACHE_SAFE_UNLOCK(cache);} -+#define CACHE_SAFE_DEC(cache, obj) { CACHE_SAFE_LOCK(cache); obj--; CACHE_SAFE_UNLOCK(cache);} -+#endif -+ -+#define CACHE_FAST_INC(cache, obj) { obj++; } -+#define CACHE_FAST_DEC(cache, obj) { obj--; } -+/* }}} */ -+ -+/* {{{ struct definition: apc_cache_key_t */ -+#define T apc_cache_t* -+typedef struct apc_cache_t apc_cache_t; /* opaque cache type */ -+ -+typedef union _apc_cache_key_data_t { -+ struct { -+ apc_dev_t device; /* the filesystem device */ -+ apc_ino_t inode; /* the filesystem inode */ -+ } file; -+ struct { -+ const char *identifier; -+ int identifier_len; -+ } user; -+ struct { -+ const char *fullpath; -+ int fullpath_len; -+ } fpfile; -+} apc_cache_key_data_t; -+ -+typedef struct apc_cache_key_t apc_cache_key_t; -+struct apc_cache_key_t { -+ apc_cache_key_data_t data; -+ unsigned long h; /* pre-computed hash value */ -+ time_t mtime; /* the mtime of this cached entry */ -+ unsigned char type; -+ unsigned char md5[16]; /* md5 hash of the source file */ -+}; -+ -+ -+typedef struct apc_keyid_t apc_keyid_t; -+ -+struct apc_keyid_t { -+ unsigned int h; -+ unsigned int keylen; -+ time_t mtime; -+#ifdef ZTS -+ THREAD_T tid; -+#else -+ pid_t pid; -+#endif -+}; -+/* }}} */ -+ -+/* {{{ struct definition: apc_cache_entry_t */ -+typedef union _apc_cache_entry_value_t { -+ struct { -+ char *filename; /* absolute path to source file */ -+ zend_op_array* op_array; /* op_array allocated in shared memory */ -+ apc_function_t* functions; /* array of apc_function_t's */ -+ apc_class_t* classes; /* array of apc_class_t's */ -+ long halt_offset; /* value of __COMPILER_HALT_OFFSET__ for the file */ -+ } file; -+ struct { -+ char *info; -+ int info_len; -+ zval *val; -+ unsigned int ttl; -+ } user; -+} apc_cache_entry_value_t; -+ -+typedef struct apc_cache_entry_t apc_cache_entry_t; -+struct apc_cache_entry_t { -+ apc_cache_entry_value_t data; -+ unsigned char type; -+ int ref_count; -+ size_t mem_size; -+ apc_pool *pool; -+}; -+/* }}} */ -+ -+/* -+ * apc_cache_create creates the shared memory compiler cache. This function -+ * should be called just once (ideally in the web server parent process, e.g. -+ * in apache), otherwise you will end up with multiple caches (which won't -+ * necessarily break anything). Returns a pointer to the cache object. -+ * -+ * size_hint is a "hint" at the total number of source files that will be -+ * cached. It determines the physical size of the hash table. Passing 0 for -+ * this argument will use a reasonable default value. -+ * -+ * gc_ttl is the maximum time a cache entry may speed on the garbage -+ * collection list. This is basically a work around for the inherent -+ * unreliability of our reference counting mechanism (see apc_cache_release). -+ * -+ * ttl is the maximum time a cache entry can idle in a slot in case the slot -+ * is needed. This helps in cleaning up the cache and ensuring that entries -+ * hit frequently stay cached and ones not hit very often eventually disappear. -+ */ -+extern T apc_cache_create(int size_hint, int gc_ttl, int ttl TSRMLS_DC); -+ -+/* -+ * apc_cache_destroy releases any OS resources associated with a cache object. -+ * Under apache, this function can be safely called by the child processes -+ * when they exit. -+ */ -+extern void apc_cache_destroy(T cache TSRMLS_DC); -+ -+/* -+ * apc_cache_clear empties a cache. This can safely be called at any time, -+ * even while other server processes are executing cached source files. -+ */ -+extern void apc_cache_clear(T cache TSRMLS_DC); -+ -+/* -+ * apc_cache_insert adds an entry to the cache, using a filename as a key. -+ * Internally, the filename is translated to a canonical representation, so -+ * that relative and absolute filenames will map to a single key. Returns -+ * non-zero if the file was successfully inserted, 0 otherwise. If 0 is -+ * returned, the caller must free the cache entry by calling -+ * apc_cache_free_entry (see below). -+ * -+ * key is the value created by apc_cache_make_file_key for file keys. -+ * -+ * value is a cache entry returned by apc_cache_make_entry (see below). -+ */ -+extern int apc_cache_insert(T cache, apc_cache_key_t key, -+ apc_cache_entry_t* value, apc_context_t* ctxt, time_t t TSRMLS_DC); -+ -+extern int apc_cache_user_insert(T cache, apc_cache_key_t key, -+ apc_cache_entry_t* value, apc_context_t* ctxt, time_t t, int exclusive TSRMLS_DC); -+ -+extern int *apc_cache_insert_mult(apc_cache_t* cache, apc_cache_key_t* keys, -+ apc_cache_entry_t** values, apc_context_t *ctxt, time_t t, int num_entries TSRMLS_DC); -+ -+/* -+ * apc_cache_find searches for a cache entry by filename, and returns a -+ * pointer to the entry if found, NULL otherwise. -+ * -+ * key is a value created by apc_cache_make_file_key for file keys. -+ */ -+extern apc_cache_entry_t* apc_cache_find(T cache, apc_cache_key_t key, time_t t TSRMLS_DC); -+ -+/* -+ * apc_cache_user_find searches for a cache entry by its hashed identifier, -+ * and returns a pointer to the entry if found, NULL otherwise. -+ * -+ */ -+extern apc_cache_entry_t* apc_cache_user_find(T cache, char* strkey, int keylen, time_t t TSRMLS_DC); -+ -+/* -+ * apc_cache_user_exists searches for a cache entry by its hashed identifier, -+ * and returns a pointer to the entry if found, NULL otherwise. This is a -+ * quick non-locking version of apc_cache_user_find that does not modify the -+ * shared memory segment in any way. -+ * -+ */ -+extern apc_cache_entry_t* apc_cache_user_exists(T cache, char* strkey, int keylen, time_t t TSRMLS_DC); -+ -+/* -+ * apc_cache_delete and apc_cache_user_delete finds an entry in the cache and deletes it. -+ */ -+extern int apc_cache_delete(apc_cache_t* cache, char *filename, int filename_len TSRMLS_DC); -+extern int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen TSRMLS_DC); -+ -+/* apc_cach_fetch_zval takes a zval in the cache and reconstructs a runtime -+ * zval from it. -+ * -+ */ -+zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC); -+ -+/* -+ * apc_cache_release decrements the reference count associated with a cache -+ * entry. Calling apc_cache_find automatically increments the reference count, -+ * and this function must be called post-execution to return the count to its -+ * original value. Failing to do so will prevent the entry from being -+ * garbage-collected. -+ * -+ * entry is the cache entry whose ref count you want to decrement. -+ */ -+extern void apc_cache_release(T cache, apc_cache_entry_t* entry TSRMLS_DC); -+ -+/* -+ * apc_cache_make_file_key creates a key object given a relative or absolute -+ * filename and an optional list of auxillary paths to search. include_path is -+ * searched if the filename cannot be found relative to the current working -+ * directory. -+ * -+ * key points to caller-allocated storage (must not be null). -+ * -+ * filename is the path to the source file. -+ * -+ * include_path is a colon-separated list of directories to search. -+ * -+ * and finally we pass in the current request time so we can avoid -+ * caching files with a current mtime which tends to indicate that -+ * they are still being written to. -+ */ -+extern int apc_cache_make_file_key(apc_cache_key_t* key, -+ const char* filename, -+ const char* include_path, -+ time_t t -+ TSRMLS_DC); -+ -+/* -+ * apc_cache_make_file_entry creates an apc_cache_entry_t object given a filename -+ * and the compilation results returned by the PHP compiler. -+ */ -+extern apc_cache_entry_t* apc_cache_make_file_entry(const char* filename, -+ zend_op_array* op_array, -+ apc_function_t* functions, -+ apc_class_t* classes, -+ apc_context_t* ctxt -+ TSRMLS_DC); -+ -+ -+zend_bool apc_compile_cache_entry(apc_cache_key_t *key, zend_file_handle* h, int type, time_t t, zend_op_array** op_array_pp, apc_cache_entry_t** cache_entry_pp TSRMLS_DC); -+ -+/* -+ * apc_cache_make_user_entry creates an apc_cache_entry_t object given an info string -+ * and the zval to be stored. -+ */ -+extern apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval *val, apc_context_t* ctxt, const unsigned int ttl TSRMLS_DC); -+ -+extern int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t); -+ -+/* {{{ struct definition: slot_t */ -+typedef struct slot_t slot_t; -+struct slot_t { -+ apc_cache_key_t key; /* slot key */ -+ apc_cache_entry_t* value; /* slot value */ -+ slot_t* next; /* next slot in linked list */ -+ unsigned long num_hits; /* number of hits to this bucket */ -+ time_t creation_time; /* time slot was initialized */ -+ time_t deletion_time; /* time slot was removed from cache */ -+ time_t access_time; /* time slot was last accessed */ -+}; -+/* }}} */ -+ -+/* {{{ struct definition: cache_header_t -+ Any values that must be shared among processes should go in here. */ -+typedef struct cache_header_t cache_header_t; -+struct cache_header_t { -+ apc_lck_t lock; /* read/write lock (exclusive blocking cache lock) */ -+ apc_lck_t wrlock; /* write lock (non-blocking used to prevent cache slams) */ -+ unsigned long num_hits; /* total successful hits in cache */ -+ unsigned long num_misses; /* total unsuccessful hits in cache */ -+ unsigned long num_inserts; /* total successful inserts in cache */ -+ unsigned long expunges; /* total number of expunges */ -+ slot_t* deleted_list; /* linked list of to-be-deleted slots */ -+ time_t start_time; /* time the above counters were reset */ -+ zend_bool busy; /* Flag to tell clients when we are busy cleaning the cache */ -+ int num_entries; /* Statistic on the number of entries */ -+ size_t mem_size; /* Statistic on the memory size used by this cache */ -+ apc_keyid_t lastkey; /* the key that is being inserted (user cache) */ -+}; -+/* }}} */ -+ -+typedef void (*apc_expunge_cb_t)(T cache, size_t n TSRMLS_DC); -+ -+/* {{{ struct definition: apc_cache_t */ -+struct apc_cache_t { -+ void* shmaddr; /* process (local) address of shared cache */ -+ cache_header_t* header; /* cache header (stored in SHM) */ -+ slot_t** slots; /* array of cache slots (stored in SHM) */ -+ int num_slots; /* number of slots in cache */ -+ int gc_ttl; /* maximum time on GC list for a slot */ -+ int ttl; /* if slot is needed and entry's access time is older than this ttl, remove it */ -+ apc_expunge_cb_t expunge_cb; /* cache specific expunge callback to free up sma memory */ -+ uint has_lock; /* flag for possible recursive locks within the same process */ -+}; -+/* }}} */ -+ -+extern zval* apc_cache_info(T cache, zend_bool limited TSRMLS_DC); -+extern void apc_cache_unlock(apc_cache_t* cache TSRMLS_DC); -+extern zend_bool apc_cache_busy(apc_cache_t* cache); -+extern zend_bool apc_cache_write_lock(apc_cache_t* cache TSRMLS_DC); -+extern void apc_cache_write_unlock(apc_cache_t* cache TSRMLS_DC); -+extern zend_bool apc_cache_is_last_key(apc_cache_t* cache, apc_cache_key_t* key, time_t t TSRMLS_DC); -+ -+/* used by apc_rfc1867 to update data in-place - not to be used elsewhere */ -+ -+typedef int (*apc_cache_updater_t)(apc_cache_t*, apc_cache_entry_t*, void* data); -+extern int _apc_cache_user_update(apc_cache_t* cache, char *strkey, int keylen, -+ apc_cache_updater_t updater, void* data TSRMLS_DC); -+ -+ -+#undef T -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_compile.c b/ext/apc/apc_compile.c ---- a/ext/apc/apc_compile.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_compile.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,2164 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | Rasmus Lerdorf | -+ | Arun C. Murthy | -+ | Gopal Vijayaraghavan | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_compile.c 326703 2012-07-19 17:06:12Z rasmus $ */ -+ -+#include "apc_compile.h" -+#include "apc_globals.h" -+#include "apc_zend.h" -+#include "apc_php.h" -+#include "apc_string.h" -+#include "ext/standard/php_var.h" -+#include "ext/standard/php_smart_str.h" -+ -+typedef void* (*ht_copy_fun_t)(void*, void*, apc_context_t* TSRMLS_DC); -+//typedef void (*ht_free_fun_t)(void*, apc_context_t*); -+typedef int (*ht_check_copy_fun_t)(Bucket*, va_list); -+ -+typedef void (*ht_fixup_fun_t)(Bucket*, zend_class_entry*, zend_class_entry*); -+ -+#define CHECK(p) { if ((p) == NULL) return NULL; } -+ -+/* {{{ internal function declarations */ -+ -+static zend_function* my_bitwise_copy_function(zend_function*, zend_function*, apc_context_t* TSRMLS_DC); -+ -+/* -+ * The "copy" functions perform deep-copies on a particular data structure -+ * (passed as the second argument). They also optionally allocate space for -+ * the destination data structure if the first argument is null. -+ */ -+static zval** my_copy_zval_ptr(zval**, const zval**, apc_context_t* TSRMLS_DC); -+static zval* my_copy_zval(zval*, const zval*, apc_context_t* TSRMLS_DC); -+#ifndef ZEND_ENGINE_2_4 -+static znode* my_copy_znode(znode*, znode*, apc_context_t* TSRMLS_DC); -+#endif -+static zend_op* my_copy_zend_op(zend_op*, zend_op*, apc_context_t* TSRMLS_DC); -+static zend_function* my_copy_function(zend_function*, zend_function*, apc_context_t* TSRMLS_DC); -+static zend_function_entry* my_copy_function_entry(zend_function_entry*, const zend_function_entry*, apc_context_t* TSRMLS_DC); -+static zend_class_entry* my_copy_class_entry(zend_class_entry*, zend_class_entry*, apc_context_t* TSRMLS_DC); -+static HashTable* my_copy_hashtable_ex(HashTable*, HashTable* TSRMLS_DC, ht_copy_fun_t, int, apc_context_t*, ht_check_copy_fun_t, ...); -+#define my_copy_hashtable( dst, src, copy_fn, holds_ptr, ctxt) \ -+ my_copy_hashtable_ex(dst, src TSRMLS_CC, copy_fn, holds_ptr, ctxt, NULL) -+static HashTable* my_copy_static_variables(zend_op_array* src, apc_context_t* TSRMLS_DC); -+static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_context_t* TSRMLS_DC); -+static zend_arg_info* my_copy_arg_info_array(zend_arg_info*, const zend_arg_info*, uint, apc_context_t* TSRMLS_DC); -+static zend_arg_info* my_copy_arg_info(zend_arg_info*, const zend_arg_info*, apc_context_t* TSRMLS_DC); -+ -+/* -+ * The "fixup" functions need for ZEND_ENGINE_2 -+ */ -+static void my_fixup_function( Bucket *p, zend_class_entry *src, zend_class_entry *dst ); -+static void my_fixup_hashtable( HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst ); -+/* my_fixup_function_for_execution is the same as my_fixup_function -+ * but named differently for clarity -+ */ -+#define my_fixup_function_for_execution my_fixup_function -+ -+#ifdef ZEND_ENGINE_2_2 -+static void my_fixup_property_info( Bucket *p, zend_class_entry *src, zend_class_entry *dst ); -+#define my_fixup_property_info_for_execution my_fixup_property_info -+#endif -+ -+/* -+ * These functions return "1" if the member/function is -+ * defined/overridden in the 'current' class and not inherited. -+ */ -+static int my_check_copy_function(Bucket* src, va_list args); -+static int my_check_copy_property_info(Bucket* src, va_list args); -+#ifndef ZEND_ENGINE_2_4 -+static int my_check_copy_default_property(Bucket* p, va_list args); -+static int my_check_copy_static_member(Bucket* src, va_list args); -+#endif -+static int my_check_copy_constant(Bucket* src, va_list args); -+ -+/* }}} */ -+ -+/* {{{ apc php serializers */ -+int APC_SERIALIZER_NAME(php) (APC_SERIALIZER_ARGS) -+{ -+ smart_str strbuf = {0}; -+ php_serialize_data_t var_hash; -+ PHP_VAR_SERIALIZE_INIT(var_hash); -+ php_var_serialize(&strbuf, (zval**)&value, &var_hash TSRMLS_CC); -+ PHP_VAR_SERIALIZE_DESTROY(var_hash); -+ if(strbuf.c) { -+ *buf = (unsigned char*)strbuf.c; -+ *buf_len = strbuf.len; -+ smart_str_0(&strbuf); -+ return 1; -+ } -+ return 0; -+} -+ -+int APC_UNSERIALIZER_NAME(php) (APC_UNSERIALIZER_ARGS) -+{ -+ const unsigned char *tmp = buf; -+ php_unserialize_data_t var_hash; -+ PHP_VAR_UNSERIALIZE_INIT(var_hash); -+ if(!php_var_unserialize(value, &tmp, buf + buf_len, &var_hash TSRMLS_CC)) { -+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash); -+ zval_dtor(*value); -+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %ld bytes", (long)(tmp - buf), (long)buf_len); -+ (*value)->type = IS_NULL; -+ return 0; -+ } -+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash); -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ check_op_array_integrity */ -+#if 0 -+static void check_op_array_integrity(zend_op_array* src) -+{ -+ int i, j; -+ -+ /* These sorts of checks really aren't particularly effective, but they -+ * can provide a welcome sanity check when debugging. Just don't enable -+ * for production use! */ -+ -+ assert(src->refcount != NULL); -+ assert(src->opcodes != NULL); -+ assert(src->last > 0); -+ -+ for (i = 0; i < src->last; i++) { -+ zend_op* op = &src->opcodes[i]; -+ znode* nodes[] = { &op->result, &op->op1, &op->op2 }; -+ for (j = 0; j < 3; j++) { -+ assert(nodes[j]->op_type == IS_CONST || -+ nodes[j]->op_type == IS_VAR || -+ nodes[j]->op_type == IS_TMP_VAR || -+ nodes[j]->op_type == IS_UNUSED); -+ -+ if (nodes[j]->op_type == IS_CONST) { -+ int type = nodes[j]->u.constant.type; -+ assert(type == IS_RESOURCE || -+ type == IS_BOOL || -+ type == IS_LONG || -+ type == IS_DOUBLE || -+ type == IS_NULL || -+ type == IS_CONSTANT || -+ type == IS_STRING || -+ type == FLAG_IS_BC || -+ type == IS_ARRAY || -+ type == IS_CONSTANT_ARRAY || -+ type == IS_OBJECT); -+ } -+ } -+ } -+} -+#endif -+/* }}} */ -+ -+/* {{{ my_bitwise_copy_function */ -+static zend_function* my_bitwise_copy_function(zend_function* dst, zend_function* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ apc_pool* pool = ctxt->pool; -+ -+ assert(src != NULL); -+ -+ if (!dst) { -+ CHECK(dst = (zend_function*) apc_pool_alloc(pool, sizeof(src[0]))); -+ } -+ -+ /* We only need to do a bitwise copy */ -+ memcpy(dst, src, sizeof(src[0])); -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ my_copy_zval_ptr */ -+static zval** my_copy_zval_ptr(zval** dst, const zval** src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ zval* dst_new; -+ apc_pool* pool = ctxt->pool; -+ int usegc = (ctxt->copy == APC_COPY_OUT_OPCODE) || (ctxt->copy == APC_COPY_OUT_USER); -+ -+ assert(src != NULL); -+ -+ if (!dst) { -+ CHECK(dst = (zval**) apc_pool_alloc(pool, sizeof(zval*))); -+ } -+ -+ if(usegc) { -+ ALLOC_ZVAL(dst[0]); -+ CHECK(dst[0]); -+ } else { -+ CHECK((dst[0] = (zval*) apc_pool_alloc(pool, sizeof(zval)))); -+ } -+ -+ CHECK((dst_new = my_copy_zval(*dst, *src, ctxt TSRMLS_CC))); -+ -+ if(dst_new != *dst) { -+ if(usegc) { -+ FREE_ZVAL(dst[0]); -+ } -+ *dst = dst_new; -+ } -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ my_serialize_object */ -+static zval* my_serialize_object(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ smart_str buf = {0}; -+ apc_pool* pool = ctxt->pool; -+ apc_serialize_t serialize = APC_SERIALIZER_NAME(php); -+ void *config = NULL; -+ -+ if(APCG(serializer)) { /* TODO: move to ctxt */ -+ serialize = APCG(serializer)->serialize; -+ config = APCG(serializer)->config; -+ } -+ -+ if(serialize((unsigned char**)&buf.c, &buf.len, src, config TSRMLS_CC)) { -+ dst->type = src->type & ~IS_CONSTANT_INDEX; -+ dst->value.str.len = buf.len; -+ CHECK(dst->value.str.val = apc_pmemcpy(buf.c, (buf.len + 1), pool TSRMLS_CC)); -+ } -+ -+ if(buf.c) smart_str_free(&buf); -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ my_unserialize_object */ -+static zval* my_unserialize_object(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ apc_unserialize_t unserialize = APC_UNSERIALIZER_NAME(php); -+ unsigned char *p = (unsigned char*)Z_STRVAL_P(src); -+ void *config = NULL; -+ -+ if(APCG(serializer)) { /* TODO: move to ctxt */ -+ unserialize = APCG(serializer)->unserialize; -+ config = APCG(serializer)->config; -+ } -+ -+ if(unserialize(&dst, p, Z_STRLEN_P(src), config TSRMLS_CC)) { -+ return dst; -+ } else { -+ zval_dtor(dst); -+ dst->type = IS_NULL; -+ } -+ return dst; -+} -+/* }}} */ -+ -+static char *apc_string_pmemcpy(char *str, size_t len, apc_pool* pool TSRMLS_DC) -+{ -+#ifdef ZEND_ENGINE_2_4 -+#ifndef ZTS -+ if (pool->type != APC_UNPOOL) { -+ char * ret = (char*)apc_new_interned_string((const char*)str, len TSRMLS_CC); -+ if (ret) { -+ return ret; -+ } -+ } -+#endif -+#endif -+ return apc_pmemcpy(str, len, pool TSRMLS_CC); -+} -+ -+/* {{{ my_copy_zval */ -+static APC_HOTSPOT zval* my_copy_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ zval **tmp; -+ apc_pool* pool = ctxt->pool; -+ -+ assert(dst != NULL); -+ assert(src != NULL); -+ -+ memcpy(dst, src, sizeof(src[0])); -+ -+ if(APCG(copied_zvals).nTableSize) { -+ if(zend_hash_index_find(&APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) { -+ if(Z_ISREF_P((zval*)src)) { -+ Z_SET_ISREF_PP(tmp); -+ } -+ Z_ADDREF_PP(tmp); -+ return *tmp; -+ } -+ -+ zend_hash_index_update(&APCG(copied_zvals), (ulong)src, (void**)&dst, sizeof(zval*), NULL); -+ } -+ -+ -+ if(ctxt->copy == APC_COPY_OUT_USER || ctxt->copy == APC_COPY_IN_USER) { -+ /* deep copies are refcount(1), but moved up for recursive -+ * arrays, which end up being add_ref'd during its copy. */ -+ Z_SET_REFCOUNT_P(dst, 1); -+ Z_UNSET_ISREF_P(dst); -+ } else { -+ /* code uses refcount=2 for consts */ -+ Z_SET_REFCOUNT_P(dst, Z_REFCOUNT_P((zval*)src)); -+ Z_SET_ISREF_TO_P(dst, Z_ISREF_P((zval*)src)); -+ } -+ -+ switch (src->type & IS_CONSTANT_TYPE_MASK) { -+ case IS_RESOURCE: -+ case IS_BOOL: -+ case IS_LONG: -+ case IS_DOUBLE: -+ case IS_NULL: -+ break; -+ -+ case IS_CONSTANT: -+ case IS_STRING: -+ if (src->value.str.val) { -+ CHECK(dst->value.str.val = apc_string_pmemcpy(src->value.str.val, -+ src->value.str.len+1, -+ pool TSRMLS_CC)); -+ } -+ break; -+ -+ case IS_ARRAY: -+ case IS_CONSTANT_ARRAY: -+ if(APCG(serializer) == NULL || -+ ctxt->copy == APC_COPY_IN_OPCODE || ctxt->copy == APC_COPY_OUT_OPCODE) { -+ -+ CHECK(dst->value.ht = -+ my_copy_hashtable(NULL, -+ src->value.ht, -+ (ht_copy_fun_t) my_copy_zval_ptr, -+ 1, -+ ctxt)); -+ break; -+ } else { -+ /* fall through to object case */ -+ } -+ -+ case IS_OBJECT: -+ -+ dst->type = IS_NULL; -+ if(ctxt->copy == APC_COPY_IN_USER) { -+ dst = my_serialize_object(dst, src, ctxt TSRMLS_CC); -+ } else if(ctxt->copy == APC_COPY_OUT_USER) { -+ dst = my_unserialize_object(dst, src, ctxt TSRMLS_CC); -+ } -+ break; -+ -+ default: -+ assert(0); -+ } -+ -+ return dst; -+} -+/* }}} */ -+ -+#ifdef ZEND_ENGINE_2_4 -+/* {{{ my_copy_znode */ -+static void my_check_znode(zend_uchar op_type, apc_context_t* ctxt TSRMLS_DC) -+{ -+ assert(op_type == IS_CONST || -+ op_type == IS_VAR || -+ op_type == IS_CV || -+ op_type == IS_TMP_VAR || -+ op_type == IS_UNUSED); -+} -+/* }}} */ -+ -+/* {{{ my_copy_zend_op */ -+static zend_op* my_copy_zend_op(zend_op* dst, zend_op* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ assert(dst != NULL); -+ assert(src != NULL); -+ -+ memcpy(dst, src, sizeof(src[0])); -+ -+ my_check_znode(dst->result_type & ~EXT_TYPE_UNUSED, ctxt TSRMLS_CC); -+ my_check_znode(dst->op1_type, ctxt TSRMLS_CC); -+ my_check_znode(dst->op2_type, ctxt TSRMLS_CC); -+ -+ return dst; -+} -+/* }}} */ -+#else -+/* {{{ my_copy_znode */ -+static znode* my_copy_znode(znode* dst, znode* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ assert(dst != NULL); -+ assert(src != NULL); -+ -+ memcpy(dst, src, sizeof(src[0])); -+ -+#ifdef IS_CV -+ assert(dst ->op_type == IS_CONST || -+ dst ->op_type == IS_VAR || -+ dst ->op_type == IS_CV || -+ dst ->op_type == IS_TMP_VAR || -+ dst ->op_type == IS_UNUSED); -+#else -+ assert(dst ->op_type == IS_CONST || -+ dst ->op_type == IS_VAR || -+ dst ->op_type == IS_TMP_VAR || -+ dst ->op_type == IS_UNUSED); -+#endif -+ -+ if (src->op_type == IS_CONST) { -+ if(!my_copy_zval(&dst->u.constant, &src->u.constant, ctxt TSRMLS_CC)) { -+ return NULL; -+ } -+ } -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ my_copy_zend_op */ -+static zend_op* my_copy_zend_op(zend_op* dst, zend_op* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ assert(dst != NULL); -+ assert(src != NULL); -+ -+ memcpy(dst, src, sizeof(src[0])); -+ -+ CHECK(my_copy_znode(&dst->result, &src->result, ctxt TSRMLS_CC)); -+ CHECK(my_copy_znode(&dst->op1, &src->op1, ctxt TSRMLS_CC)); -+ CHECK(my_copy_znode(&dst->op2, &src->op2, ctxt TSRMLS_CC)); -+ -+ return dst; -+} -+/* }}} */ -+#endif -+ -+/* {{{ my_copy_function */ -+static zend_function* my_copy_function(zend_function* dst, zend_function* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ assert(src != NULL); -+ -+ CHECK(dst = my_bitwise_copy_function(dst, src, ctxt TSRMLS_CC)); -+ -+ switch (src->type) { -+ case ZEND_INTERNAL_FUNCTION: -+ case ZEND_OVERLOADED_FUNCTION: -+ /* shallow copy because op_array is internal */ -+ dst->op_array = src->op_array; -+ break; -+ -+ case ZEND_USER_FUNCTION: -+ case ZEND_EVAL_CODE: -+ CHECK(apc_copy_op_array(&dst->op_array, -+ &src->op_array, -+ ctxt TSRMLS_CC)); -+ break; -+ -+ default: -+ assert(0); -+ } -+ /* -+ * op_array bitwise copying overwrites what ever you modified -+ * before apc_copy_op_array - which is why this code is outside -+ * my_bitwise_copy_function. -+ */ -+ -+ /* zend_do_inheritance will re-look this up, because the pointers -+ * in prototype are from a function table of another class. It just -+ * helps if that one is from EG(class_table). -+ */ -+ dst->common.prototype = NULL; -+ -+ /* once a method is marked as ZEND_ACC_IMPLEMENTED_ABSTRACT then you -+ * have to carry around a prototype. Thankfully zend_do_inheritance -+ * sets this properly as well -+ */ -+ dst->common.fn_flags = src->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT); -+ -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ my_copy_function_entry */ -+static zend_function_entry* my_copy_function_entry(zend_function_entry* dst, const zend_function_entry* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ assert(src != NULL); -+ -+ if (!dst) { -+ CHECK(dst = (zend_function_entry*) apc_pool_alloc(ctxt->pool, sizeof(src[0]))); -+ } -+ -+ /* Start with a bitwise copy */ -+ memcpy(dst, src, sizeof(src[0])); -+ -+ dst->fname = NULL; -+ dst->arg_info = NULL; -+ -+ if (src->fname) { -+ CHECK((dst->fname = apc_pstrdup(src->fname, ctxt->pool TSRMLS_CC))); -+ } -+ -+ if (src->arg_info) { -+ CHECK((dst->arg_info = my_copy_arg_info_array(NULL, -+ src->arg_info, -+ src->num_args, -+ ctxt TSRMLS_CC))); -+ } -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ my_copy_property_info */ -+static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ apc_pool* pool = ctxt->pool; -+ -+ assert(src != NULL); -+ -+ if (!dst) { -+ CHECK(dst = (zend_property_info*) apc_pool_alloc(pool, sizeof(*src))); -+ } -+ -+ /* Start with a bitwise copy */ -+ memcpy(dst, src, sizeof(*src)); -+ -+ dst->name = NULL; -+#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0 -+ dst->doc_comment = NULL; -+#endif -+ -+ if (src->name) { -+ /* private members are stored inside property_info as a mangled -+ * string of the form: -+ * \0\0\0 -+ */ -+ CHECK((dst->name = apc_string_pmemcpy(src->name, src->name_length+1, pool TSRMLS_CC))); -+ } -+ -+#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0 -+ if (src->doc_comment) { -+ CHECK((dst->doc_comment = apc_pmemcpy(src->doc_comment, (src->doc_comment_len + 1), pool TSRMLS_CC))); -+ } -+#endif -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ my_copy_property_info_for_execution */ -+static zend_property_info* my_copy_property_info_for_execution(zend_property_info* dst, zend_property_info* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ assert(src != NULL); -+ -+ if (!dst) { -+ CHECK(dst = (zend_property_info*) apc_pool_alloc(ctxt->pool, sizeof(*src))); -+ } -+ -+ /* We need only a shallow copy */ -+ memcpy(dst, src, sizeof(*src)); -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ my_copy_arg_info_array */ -+static zend_arg_info* my_copy_arg_info_array(zend_arg_info* dst, const zend_arg_info* src, uint num_args, apc_context_t* ctxt TSRMLS_DC) -+{ -+ uint i = 0; -+ -+ -+ if (!dst) { -+ CHECK(dst = (zend_arg_info*) apc_pool_alloc(ctxt->pool, (sizeof(*src) * num_args))); -+ } -+ -+ /* Start with a bitwise copy */ -+ memcpy(dst, src, sizeof(*src)*num_args); -+ -+ for(i=0; i < num_args; i++) { -+ CHECK((my_copy_arg_info( &dst[i], &src[i], ctxt TSRMLS_CC))); -+ } -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ my_copy_arg_info */ -+static zend_arg_info* my_copy_arg_info(zend_arg_info* dst, const zend_arg_info* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ apc_pool* pool = ctxt->pool; -+ -+ assert(src != NULL); -+ -+ if (!dst) { -+ CHECK(dst = (zend_arg_info*) apc_pool_alloc(pool, sizeof(*src))); -+ } -+ -+ /* Start with a bitwise copy */ -+ memcpy(dst, src, sizeof(*src)); -+ -+ dst->name = NULL; -+ dst->class_name = NULL; -+ -+ if (src->name) { -+ CHECK((dst->name = apc_string_pmemcpy((char *) src->name, src->name_len+1, pool TSRMLS_CC))); -+ } -+ -+ if (src->class_name) { -+ CHECK((dst->class_name = apc_string_pmemcpy((char *) src->class_name, src->class_name_len+1, pool TSRMLS_CC))); -+ } -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ apc_copy_class_entry */ -+zend_class_entry* apc_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ return my_copy_class_entry(dst, src, ctxt TSRMLS_CC); -+} -+ -+/* {{{ my_copy_class_entry */ -+static zend_class_entry* my_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ int i = 0; -+ apc_pool* pool = ctxt->pool; -+ -+ assert(src != NULL); -+ -+ if (!dst) { -+ CHECK(dst = (zend_class_entry*) apc_pool_alloc(pool, sizeof(*src))); -+ } -+ -+ /* Start with a bitwise copy */ -+ memcpy(dst, src, sizeof(*src)); -+ -+ dst->name = NULL; -+ memset(&dst->function_table, 0, sizeof(dst->function_table)); -+ ZEND_CE_DOC_COMMENT(dst) = NULL; -+ ZEND_CE_FILENAME(dst) = NULL; -+ memset(&dst->properties_info, 0, sizeof(dst->properties_info)); -+ memset(&dst->constants_table, 0, sizeof(dst->constants_table)); -+ -+ if (src->name) { -+ CHECK((dst->name = apc_pstrdup(src->name, pool TSRMLS_CC))); -+ } -+ -+ if(!(my_copy_hashtable_ex(&dst->function_table, -+ &src->function_table TSRMLS_CC, -+ (ht_copy_fun_t) my_copy_function, -+ 0, -+ ctxt, -+ (ht_check_copy_fun_t) my_check_copy_function, -+ src))) { -+ return NULL; -+ } -+ -+ /* the interfaces are populated at runtime using ADD_INTERFACE */ -+ dst->interfaces = NULL; -+ -+ /* the current count includes inherited interfaces as well, -+ the real dynamic ones are the first which are zero'd -+ out in zend_do_end_class_declaration */ -+ for(i = 0 ; (uint)i < src->num_interfaces ; i++) { -+ if(src->interfaces[i]) -+ { -+ dst->num_interfaces = i; -+ break; -+ } -+ } -+ -+ /* these will either be set inside my_fixup_hashtable or -+ * they will be copied out from parent inside zend_do_inheritance -+ */ -+ dst->parent = NULL; -+ dst->constructor = NULL; -+ dst->destructor = NULL; -+ dst->clone = NULL; -+ dst->__get = NULL; -+ dst->__set = NULL; -+ dst->__unset = NULL; -+ dst->__isset = NULL; -+ dst->__call = NULL; -+#ifdef ZEND_ENGINE_2_2 -+ dst->__tostring = NULL; -+#endif -+#ifdef ZEND_ENGINE_2_3 -+ dst->__callstatic = NULL; -+#endif -+ -+ /* unset function proxies */ -+ dst->serialize_func = NULL; -+ dst->unserialize_func = NULL; -+ -+ my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function, src, dst); -+ -+#ifdef ZEND_ENGINE_2_4 -+ dst->default_properties_count = src->default_properties_count; -+ if (src->default_properties_count) { -+ CHECK(dst->default_properties_table = (zval**) apc_pool_alloc(pool, (sizeof(zval*) * src->default_properties_count))); -+ for (i = 0; i < src->default_properties_count; i++) { -+ if (src->default_properties_table[i]) { -+ my_copy_zval_ptr(&dst->default_properties_table[i], (const zval**)&src->default_properties_table[i], ctxt TSRMLS_CC); -+ } else { -+ dst->default_properties_table[i] = NULL; -+ } -+ } -+ } else { -+ dst->default_properties_table = NULL; -+ } -+#else -+ memset(&dst->default_properties, 0, sizeof(dst->default_properties)); -+ CHECK((my_copy_hashtable_ex(&dst->default_properties, -+ &src->default_properties TSRMLS_CC, -+ (ht_copy_fun_t) my_copy_zval_ptr, -+ 1, -+ ctxt, -+ (ht_check_copy_fun_t) my_check_copy_default_property, -+ src))); -+#endif -+ -+ CHECK((my_copy_hashtable_ex(&dst->properties_info, -+ &src->properties_info TSRMLS_CC, -+ (ht_copy_fun_t) my_copy_property_info, -+ 0, -+ ctxt, -+ (ht_check_copy_fun_t) my_check_copy_property_info, -+ src))); -+ -+#ifdef ZEND_ENGINE_2_2 -+ /* php5.2 introduced a scope attribute for property info */ -+ my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst); -+#endif -+ -+#ifdef ZEND_ENGINE_2_4 -+ dst->default_static_members_count = src->default_static_members_count; -+ -+ if (src->default_static_members_count) { -+ CHECK(dst->default_static_members_table = (zval**) apc_pool_alloc(pool, (sizeof(zval*) * src->default_static_members_count))); -+ for (i = 0; i < src->default_static_members_count; i++) { -+ if (src->default_static_members_table[i]) { -+ my_copy_zval_ptr(&dst->default_static_members_table[i], (const zval**)&src->default_static_members_table[i], ctxt TSRMLS_CC); -+ } else { -+ dst->default_static_members_table[i] = NULL; -+ } -+ } -+ } else { -+ dst->default_static_members_table = NULL; -+ } -+ dst->static_members_table = dst->default_static_members_table; -+#else -+ memset(&dst->default_static_members, 0, sizeof(dst->default_static_members)); -+ dst->static_members = NULL; -+ CHECK(my_copy_hashtable_ex(&dst->default_static_members, -+ &src->default_static_members TSRMLS_CC, -+ (ht_copy_fun_t) my_copy_zval_ptr, -+ 1, -+ ctxt, -+ (ht_check_copy_fun_t) my_check_copy_static_member, -+ src, -+ &src->default_static_members)); -+ -+ if(src->static_members != &src->default_static_members) -+ { -+ CHECK((dst->static_members = my_copy_hashtable_ex(NULL, -+ src->static_members TSRMLS_CC, -+ (ht_copy_fun_t) my_copy_zval_ptr, -+ 1, -+ ctxt, -+ (ht_check_copy_fun_t) my_check_copy_static_member, -+ src, -+ src->static_members))); -+ } -+ else -+ { -+ dst->static_members = &dst->default_static_members; -+ } -+#endif -+ -+ CHECK((my_copy_hashtable_ex(&dst->constants_table, -+ &src->constants_table TSRMLS_CC, -+ (ht_copy_fun_t) my_copy_zval_ptr, -+ 1, -+ ctxt, -+ (ht_check_copy_fun_t) my_check_copy_constant, -+ src))); -+ -+ if (src->type == ZEND_USER_CLASS && ZEND_CE_DOC_COMMENT(src)) { -+ CHECK(ZEND_CE_DOC_COMMENT(dst) = -+ apc_pmemcpy(ZEND_CE_DOC_COMMENT(src), (ZEND_CE_DOC_COMMENT_LEN(src) + 1), pool TSRMLS_CC)); -+ } -+ -+ if (src->type == ZEND_INTERNAL_CLASS && ZEND_CE_BUILTIN_FUNCTIONS(src)) { -+ int n; -+ -+ for (n = 0; src->type == ZEND_INTERNAL_CLASS && ZEND_CE_BUILTIN_FUNCTIONS(src)[n].fname != NULL; n++) {} -+ -+ CHECK((ZEND_CE_BUILTIN_FUNCTIONS(dst) = -+ (zend_function_entry*) apc_pool_alloc(pool, ((n + 1) * sizeof(zend_function_entry))))); -+ -+ for (i = 0; i < n; i++) { -+ CHECK(my_copy_function_entry((zend_function_entry*)(&ZEND_CE_BUILTIN_FUNCTIONS(dst)[i]), -+ &ZEND_CE_BUILTIN_FUNCTIONS(src)[i], -+ ctxt TSRMLS_CC)); -+ } -+ *(char**)&(ZEND_CE_BUILTIN_FUNCTIONS(dst)[n].fname) = NULL; -+ } -+ -+ if (src->type == ZEND_USER_CLASS && ZEND_CE_FILENAME(src)) { -+ CHECK((ZEND_CE_FILENAME(dst) = apc_pstrdup(ZEND_CE_FILENAME(src), pool TSRMLS_CC))); -+ } -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ my_copy_hashtable_ex */ -+static APC_HOTSPOT HashTable* my_copy_hashtable_ex(HashTable* dst, -+ HashTable* src TSRMLS_DC, -+ ht_copy_fun_t copy_fn, -+ int holds_ptrs, -+ apc_context_t* ctxt, -+ ht_check_copy_fun_t check_fn, -+ ...) -+{ -+ Bucket* curr = NULL; -+ Bucket* prev = NULL; -+ Bucket* newp = NULL; -+ int first = 1; -+ apc_pool* pool = ctxt->pool; -+ -+ assert(src != NULL); -+ -+ if (!dst) { -+ CHECK(dst = (HashTable*) apc_pool_alloc(pool, sizeof(src[0]))); -+ } -+ -+ memcpy(dst, src, sizeof(src[0])); -+ -+ /* allocate buckets for the new hashtable */ -+ CHECK((dst->arBuckets = apc_pool_alloc(pool, (dst->nTableSize * sizeof(Bucket*))))); -+ -+ memset(dst->arBuckets, 0, dst->nTableSize * sizeof(Bucket*)); -+ dst->pInternalPointer = NULL; -+ dst->pListHead = NULL; -+ -+ for (curr = src->pListHead; curr != NULL; curr = curr->pListNext) { -+ int n = curr->h % dst->nTableSize; -+ -+ if(check_fn) { -+ va_list args; -+ va_start(args, check_fn); -+ -+ /* Call the check_fn to see if the current bucket -+ * needs to be copied out -+ */ -+ if(!check_fn(curr, args)) { -+ dst->nNumOfElements--; -+ va_end(args); -+ continue; -+ } -+ -+ va_end(args); -+ } -+ -+ /* create a copy of the bucket 'curr' */ -+#ifdef ZEND_ENGINE_2_4 -+ if (!curr->nKeyLength) { -+ CHECK((newp = (Bucket*) apc_pmemcpy(curr, sizeof(Bucket), pool TSRMLS_CC))); -+ } else if (IS_INTERNED(curr->arKey)) { -+ CHECK((newp = (Bucket*) apc_pmemcpy(curr, sizeof(Bucket), pool TSRMLS_CC))); -+#ifndef ZTS -+ } else if (pool->type != APC_UNPOOL) { -+ char *arKey; -+ -+ CHECK((newp = (Bucket*) apc_pmemcpy(curr, sizeof(Bucket), pool TSRMLS_CC))); -+ arKey = apc_new_interned_string(curr->arKey, curr->nKeyLength TSRMLS_CC); -+ if (!arKey) { -+ CHECK((newp->arKey = (char*) apc_pmemcpy(curr->arKey, curr->nKeyLength, pool TSRMLS_CC))); -+ } else { -+ newp->arKey = arKey; -+ } -+#endif -+ } else { -+ CHECK((newp = (Bucket*) apc_pmemcpy(curr, sizeof(Bucket), pool TSRMLS_CC))); -+ CHECK((newp->arKey = (char*) apc_pmemcpy(curr->arKey, curr->nKeyLength, pool TSRMLS_CC))); -+ } -+#else -+ CHECK((newp = (Bucket*) apc_pmemcpy(curr, -+ (sizeof(Bucket) + curr->nKeyLength - 1), -+ pool TSRMLS_CC))); -+#endif -+ -+ /* insert 'newp' into the linked list at its hashed index */ -+ if (dst->arBuckets[n]) { -+ newp->pNext = dst->arBuckets[n]; -+ newp->pLast = NULL; -+ newp->pNext->pLast = newp; -+ } -+ else { -+ newp->pNext = newp->pLast = NULL; -+ } -+ -+ dst->arBuckets[n] = newp; -+ -+ /* copy the bucket data using our 'copy_fn' callback function */ -+ CHECK((newp->pData = copy_fn(NULL, curr->pData, ctxt TSRMLS_CC))); -+ -+ if (holds_ptrs) { -+ memcpy(&newp->pDataPtr, newp->pData, sizeof(void*)); -+ } -+ else { -+ newp->pDataPtr = NULL; -+ } -+ -+ /* insert 'newp' into the table-thread linked list */ -+ newp->pListLast = prev; -+ newp->pListNext = NULL; -+ -+ if (prev) { -+ prev->pListNext = newp; -+ } -+ -+ if (first) { -+ dst->pListHead = newp; -+ first = 0; -+ } -+ -+ prev = newp; -+ } -+ -+ dst->pListTail = newp; -+ -+ zend_hash_internal_pointer_reset(dst); -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ my_copy_static_variables */ -+static HashTable* my_copy_static_variables(zend_op_array* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ if (src->static_variables == NULL) { -+ return NULL; -+ } -+ -+ return my_copy_hashtable(NULL, -+ src->static_variables, -+ (ht_copy_fun_t) my_copy_zval_ptr, -+ 1, -+ ctxt); -+} -+/* }}} */ -+ -+/* {{{ apc_copy_zval */ -+zval* apc_copy_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ apc_pool* pool = ctxt->pool; -+ int usegc = (ctxt->copy == APC_COPY_OUT_OPCODE) || (ctxt->copy == APC_COPY_OUT_USER); -+ -+ assert(src != NULL); -+ -+ if (!dst) { -+ if(usegc) { -+ ALLOC_ZVAL(dst); -+ CHECK(dst); -+ } else { -+ CHECK(dst = (zval*) apc_pool_alloc(pool, sizeof(zval))); -+ } -+ } -+ -+ CHECK(dst = my_copy_zval(dst, src, ctxt TSRMLS_CC)); -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ apc_fixup_op_array_jumps */ -+static void apc_fixup_op_array_jumps(zend_op_array *dst, zend_op_array *src ) -+{ -+ uint i; -+ -+ for (i=0; i < dst->last; ++i) { -+ zend_op *zo = &(dst->opcodes[i]); -+ /*convert opline number to jump address*/ -+ switch (zo->opcode) { -+#ifdef ZEND_ENGINE_2_3 -+ case ZEND_GOTO: -+#endif -+ case ZEND_JMP: -+ /*Note: if src->opcodes != dst->opcodes then we need to the opline according to src*/ -+#ifdef ZEND_ENGINE_2_4 -+ zo->op1.jmp_addr = dst->opcodes + (zo->op1.jmp_addr - src->opcodes); -+#else -+ zo->op1.u.jmp_addr = dst->opcodes + (zo->op1.u.jmp_addr - src->opcodes); -+#endif -+ break; -+ case ZEND_JMPZ: -+ case ZEND_JMPNZ: -+ case ZEND_JMPZ_EX: -+ case ZEND_JMPNZ_EX: -+#ifdef ZEND_ENGINE_2_3 -+ case ZEND_JMP_SET: -+#endif -+#ifdef ZEND_ENGINE_2_4 -+ case ZEND_JMP_SET_VAR: -+#endif -+#ifdef ZEND_ENGINE_2_4 -+ zo->op2.jmp_addr = dst->opcodes + (zo->op2.jmp_addr - src->opcodes); -+#else -+ zo->op2.u.jmp_addr = dst->opcodes + (zo->op2.u.jmp_addr - src->opcodes); -+#endif -+ break; -+ default: -+ break; -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ apc_copy_op_array */ -+zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ int i; -+ apc_fileinfo_t *fileinfo = NULL; -+ char canon_path[MAXPATHLEN]; -+ char *fullpath = NULL; -+ apc_opflags_t * flags = NULL; -+ apc_pool* pool = ctxt->pool; -+ -+ assert(src != NULL); -+ -+ if (!dst) { -+ CHECK(dst = (zend_op_array*) apc_pool_alloc(pool, sizeof(src[0]))); -+ } -+ -+ if(APCG(apc_optimize_function)) { -+ APCG(apc_optimize_function)(src TSRMLS_CC); -+ } -+ -+ /* start with a bitwise copy of the array */ -+ memcpy(dst, src, sizeof(src[0])); -+ -+ dst->function_name = NULL; -+ dst->filename = NULL; -+ dst->refcount = NULL; -+ dst->opcodes = NULL; -+ dst->brk_cont_array = NULL; -+ dst->static_variables = NULL; -+ dst->try_catch_array = NULL; -+ dst->arg_info = NULL; -+ dst->doc_comment = NULL; -+#ifdef ZEND_ENGINE_2_1 -+ dst->vars = NULL; -+#endif -+ -+ /* copy the arg types array (if set) */ -+ if (src->arg_info) { -+ CHECK(dst->arg_info = my_copy_arg_info_array(NULL, -+ src->arg_info, -+ src->num_args, -+ ctxt TSRMLS_CC)); -+ } -+ -+ if (src->function_name) { -+ CHECK(dst->function_name = apc_pstrdup(src->function_name, pool TSRMLS_CC)); -+ } -+ if (src->filename) { -+ CHECK(dst->filename = apc_pstrdup(src->filename, pool TSRMLS_CC)); -+ } -+ -+ CHECK(dst->refcount = apc_pmemcpy(src->refcount, -+ sizeof(src->refcount[0]), -+ pool TSRMLS_CC)); -+ -+#ifdef ZEND_ENGINE_2_4 -+ if (src->literals) { -+ zend_literal *p, *q, *end; -+ -+ q = src->literals; -+ p = dst->literals = (zend_literal*) apc_pool_alloc(pool, (sizeof(zend_literal) * src->last_literal)); -+ end = p + src->last_literal; -+ while (p < end) { -+ *p = *q; -+ my_copy_zval(&p->constant, &q->constant, ctxt TSRMLS_CC); -+ p++; -+ q++; -+ } -+ } -+#endif -+ -+ /* deep-copy the opcodes */ -+ CHECK(dst->opcodes = (zend_op*) apc_pool_alloc(pool, (sizeof(zend_op) * src->last))); -+ -+ if(apc_reserved_offset != -1) { -+ /* Insanity alert: the void* pointer is cast into an apc_opflags_t -+ * struct. apc_zend_init() checks to ensure that it fits in a void* */ -+ flags = (apc_opflags_t*) & (dst->reserved[apc_reserved_offset]); -+ memset(flags, 0, sizeof(apc_opflags_t)); -+ /* assert(sizeof(apc_opflags_t) <= sizeof(dst->reserved)); */ -+ } -+ -+ for (i = 0; (uint) i < src->last; i++) { -+ zend_op *zo = &(src->opcodes[i]); -+ /* a lot of files are merely constant arrays with no jumps */ -+ switch (zo->opcode) { -+#ifdef ZEND_ENGINE_2_3 -+ case ZEND_GOTO: -+#endif -+ case ZEND_JMP: -+ case ZEND_JMPZ: -+ case ZEND_JMPNZ: -+ case ZEND_JMPZ_EX: -+ case ZEND_JMPNZ_EX: -+#ifdef ZEND_ENGINE_2_3 -+ case ZEND_JMP_SET: -+#endif -+#ifdef ZEND_ENGINE_2_4 -+ case ZEND_JMP_SET_VAR: -+#endif -+ if(flags != NULL) { -+ flags->has_jumps = 1; -+ } -+ break; -+ /* auto_globals_jit was not in php-4.3.* */ -+ case ZEND_FETCH_R: -+ case ZEND_FETCH_W: -+ case ZEND_FETCH_IS: -+ case ZEND_FETCH_FUNC_ARG: -+ case ZEND_FETCH_RW: -+ case ZEND_FETCH_UNSET: -+ if(PG(auto_globals_jit) && flags != NULL) -+ { -+ /* The fetch is only required if auto_globals_jit=1 */ -+#ifdef ZEND_ENGINE_2_4 -+ if((zo->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_GLOBAL && -+ zo->op1_type == IS_CONST && -+ Z_TYPE_P(zo->op1.zv) == IS_STRING) { -+ if (Z_STRVAL_P(zo->op1.zv)[0] == '_') { -+# define SET_IF_AUTOGLOBAL(member) \ -+ if(!strcmp(Z_STRVAL_P(zo->op1.zv), #member)) \ -+ flags->member = 1 /* no ';' here */ -+#else -+ if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL && -+ zo->op1.op_type == IS_CONST && -+ zo->op1.u.constant.type == IS_STRING) { -+ znode * varname = &zo->op1; -+ if (varname->u.constant.value.str.val[0] == '_') { -+# define SET_IF_AUTOGLOBAL(member) \ -+ if(!strcmp(varname->u.constant.value.str.val, #member)) \ -+ flags->member = 1 /* no ';' here */ -+#endif -+ SET_IF_AUTOGLOBAL(_GET); -+ else SET_IF_AUTOGLOBAL(_POST); -+ else SET_IF_AUTOGLOBAL(_COOKIE); -+ else SET_IF_AUTOGLOBAL(_SERVER); -+ else SET_IF_AUTOGLOBAL(_ENV); -+ else SET_IF_AUTOGLOBAL(_FILES); -+ else SET_IF_AUTOGLOBAL(_REQUEST); -+ else SET_IF_AUTOGLOBAL(_SESSION); -+#ifdef ZEND_ENGINE_2_4 -+ else if(zend_is_auto_global( -+ Z_STRVAL_P(zo->op1.zv), -+ Z_STRLEN_P(zo->op1.zv) -+ TSRMLS_CC)) -+#else -+ else if(zend_is_auto_global( -+ varname->u.constant.value.str.val, -+ varname->u.constant.value.str.len -+ TSRMLS_CC)) -+#endif -+ { -+ flags->unknown_global = 1; -+ } -+#ifdef ZEND_ENGINE_2_4 -+ } else SET_IF_AUTOGLOBAL(GLOBALS); -+#else -+ } -+#endif -+ } -+ } -+ break; -+ case ZEND_RECV_INIT: -+#ifdef ZEND_ENGINE_2_4 -+ if(zo->op2_type == IS_CONST && -+ Z_TYPE_P(zo->op2.zv) == IS_CONSTANT_ARRAY) { -+#else -+ if(zo->op2.op_type == IS_CONST && -+ zo->op2.u.constant.type == IS_CONSTANT_ARRAY) { -+#endif -+ if(flags != NULL) { -+ flags->deep_copy = 1; -+ } -+ } -+ break; -+ default: -+#ifdef ZEND_ENGINE_2_4 -+ if((zo->op1_type == IS_CONST && -+ Z_TYPE_P(zo->op1.zv) == IS_CONSTANT_ARRAY) || -+ (zo->op2_type == IS_CONST && -+ Z_TYPE_P(zo->op2.zv) == IS_CONSTANT_ARRAY)) { -+#else -+ if((zo->op1.op_type == IS_CONST && -+ zo->op1.u.constant.type == IS_CONSTANT_ARRAY) || -+ (zo->op2.op_type == IS_CONST && -+ zo->op2.u.constant.type == IS_CONSTANT_ARRAY)) { -+#endif -+ if(flags != NULL) { -+ flags->deep_copy = 1; -+ } -+ } -+ break; -+ } -+ -+ if(!(my_copy_zend_op(dst->opcodes+i, src->opcodes+i, ctxt TSRMLS_CC))) { -+ return NULL; -+ } -+ -+#ifdef ZEND_ENGINE_2_4 -+ if (zo->op1_type == IS_CONST) { -+ dst->opcodes[i].op1.literal = src->opcodes[i].op1.literal - src->literals + dst->literals; -+ } -+ if (zo->op2_type == IS_CONST) { -+ dst->opcodes[i].op2.literal = src->opcodes[i].op2.literal - src->literals + dst->literals; -+ } -+ if (zo->result_type == IS_CONST) { -+ dst->opcodes[i].result.literal = src->opcodes[i].result.literal - src->literals + dst->literals; -+ } -+#endif -+ -+ /* This code breaks apc's rule#1 - cache what you compile */ -+ if((APCG(fpstat)==0) && APCG(canonicalize)) { -+ /* not pool allocated, because the pool allocations eat up shm space */ -+ fileinfo = (apc_fileinfo_t*) apc_php_malloc(sizeof(apc_fileinfo_t) TSRMLS_CC); -+#ifdef ZEND_ENGINE_2_4 -+ if((zo->opcode == ZEND_INCLUDE_OR_EVAL) && -+ (zo->op1_type == IS_CONST && Z_TYPE_P(zo->op1.zv) == IS_STRING)) { -+ /* constant includes */ -+ if(!IS_ABSOLUTE_PATH(Z_STRVAL_P(zo->op1.zv),Z_STRLEN_P(zo->op1.zv))) { -+ if (apc_search_paths(Z_STRVAL_P(zo->op1.zv), PG(include_path), fileinfo TSRMLS_CC) == 0) { -+#else -+ if((zo->opcode == ZEND_INCLUDE_OR_EVAL) && -+ (zo->op1.op_type == IS_CONST && zo->op1.u.constant.type == IS_STRING)) { -+ /* constant includes */ -+ if(!IS_ABSOLUTE_PATH(Z_STRVAL_P(&zo->op1.u.constant),Z_STRLEN_P(&zo->op1.u.constant))) { -+ if (apc_search_paths(Z_STRVAL_P(&zo->op1.u.constant), PG(include_path), fileinfo TSRMLS_CC) == 0) { -+#endif -+ if((fullpath = realpath(fileinfo->fullpath, canon_path))) { -+ /* everything has to go through a realpath() */ -+ zend_op *dzo = &(dst->opcodes[i]); -+#ifdef ZEND_ENGINE_2_4 -+ dzo->op1.literal = (zend_literal*) apc_pool_alloc(pool, sizeof(zend_literal)); -+ Z_STRLEN_P(dzo->op1.zv) = strlen(fullpath); -+ Z_STRVAL_P(dzo->op1.zv) = apc_pstrdup(fullpath, pool TSRMLS_CC); -+ Z_TYPE_P(dzo->op1.zv) = IS_STRING; -+ Z_SET_REFCOUNT_P(dzo->op1.zv, 2); -+ Z_SET_ISREF_P(dzo->op1.zv); -+ dzo->op1.literal->hash_value = zend_hash_func(Z_STRVAL_P(dzo->op1.zv), Z_STRLEN_P(dzo->op1.zv)+1); -+#else -+ dzo->op1.u.constant.value.str.len = strlen(fullpath); -+ dzo->op1.u.constant.value.str.val = apc_pstrdup(fullpath, pool TSRMLS_CC); -+#endif -+ } -+ } -+ } -+ } -+ apc_php_free(fileinfo TSRMLS_CC); -+ } -+ } -+ -+ if(flags == NULL || flags->has_jumps) { -+ apc_fixup_op_array_jumps(dst,src); -+ } -+ -+ /* copy the break-continue array */ -+ if (src->brk_cont_array) { -+ CHECK(dst->brk_cont_array = apc_pmemcpy(src->brk_cont_array, -+ sizeof(src->brk_cont_array[0]) * src->last_brk_cont, -+ pool TSRMLS_CC)); -+ } -+ -+ /* copy the table of static variables */ -+ if (src->static_variables) { -+ CHECK(dst->static_variables = my_copy_static_variables(src, ctxt TSRMLS_CC)); -+ } -+ -+ if (src->try_catch_array) { -+ CHECK(dst->try_catch_array = apc_pmemcpy(src->try_catch_array, -+ sizeof(src->try_catch_array[0]) * src->last_try_catch, -+ pool TSRMLS_CC)); -+ } -+ -+#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */ -+ if (src->vars) { -+ CHECK(dst->vars = apc_pmemcpy(src->vars, -+ sizeof(src->vars[0]) * src->last_var, -+ pool TSRMLS_CC)); -+ -+ for(i = 0; i < src->last_var; i++) dst->vars[i].name = NULL; -+ -+ for(i = 0; i < src->last_var; i++) { -+ CHECK(dst->vars[i].name = apc_string_pmemcpy(src->vars[i].name, -+ src->vars[i].name_len + 1, -+ pool TSRMLS_CC)); -+ } -+ } -+#endif -+ -+ if (src->doc_comment) { -+ CHECK(dst->doc_comment -+ = apc_pmemcpy(src->doc_comment, (src->doc_comment_len + 1), pool TSRMLS_CC)); -+ } -+ -+ return dst; -+} -+/* }}} */ -+ -+ -+/* {{{ apc_copy_new_functions */ -+apc_function_t* apc_copy_new_functions(int old_count, apc_context_t* ctxt TSRMLS_DC) -+{ -+ apc_function_t* array; -+ int new_count; /* number of new functions in table */ -+ int i; -+ apc_pool* pool = ctxt->pool; -+ -+ new_count = zend_hash_num_elements(CG(function_table)) - old_count; -+ assert(new_count >= 0); -+ -+ CHECK(array = -+ (apc_function_t*) -+ apc_pool_alloc(pool, (sizeof(apc_function_t) * (new_count + 1)))); -+ -+ if (new_count == 0) { -+ array[0].function = NULL; -+ return array; -+ } -+ -+ /* Skip the first `old_count` functions in the table */ -+ zend_hash_internal_pointer_reset(CG(function_table)); -+ for (i = 0; i < old_count; i++) { -+ zend_hash_move_forward(CG(function_table)); -+ } -+ -+ /* Add the next `new_count` functions to our array */ -+ for (i = 0; i < new_count; i++) { -+ char* key; -+ uint key_size; -+ zend_function* fun; -+ -+ zend_hash_get_current_key_ex(CG(function_table), -+ &key, -+ &key_size, -+ NULL, -+ 0, -+ NULL); -+ -+ zend_hash_get_current_data(CG(function_table), (void**) &fun); -+ -+ CHECK(array[i].name = apc_pmemcpy(key, (int) key_size, pool TSRMLS_CC)); -+ array[i].name_len = (int) key_size-1; -+ CHECK(array[i].function = my_copy_function(NULL, fun, ctxt TSRMLS_CC)); -+ zend_hash_move_forward(CG(function_table)); -+ } -+ -+ array[i].function = NULL; -+ return array; -+} -+/* }}} */ -+ -+/* {{{ apc_copy_new_classes */ -+apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_context_t *ctxt TSRMLS_DC) -+{ -+ apc_class_t* array; -+ int new_count; /* number of new classes in table */ -+ int i; -+ apc_pool* pool = ctxt->pool; -+ -+ new_count = zend_hash_num_elements(CG(class_table)) - old_count; -+ assert(new_count >= 0); -+ -+ CHECK(array = -+ (apc_class_t*) -+ apc_pool_alloc(pool, (sizeof(apc_class_t) * (new_count + 1)))); -+ -+ if (new_count == 0) { -+ array[0].class_entry = NULL; -+ return array; -+ } -+ -+ /* Skip the first `old_count` classes in the table */ -+ zend_hash_internal_pointer_reset(CG(class_table)); -+ for (i = 0; i < old_count; i++) { -+ zend_hash_move_forward(CG(class_table)); -+ } -+ -+ /* Add the next `new_count` classes to our array */ -+ for (i = 0; i < new_count; i++) { -+ char* key; -+ uint key_size; -+ zend_class_entry* elem = NULL; -+ -+ array[i].class_entry = NULL; -+ -+ zend_hash_get_current_key_ex(CG(class_table), -+ &key, -+ &key_size, -+ NULL, -+ 0, -+ NULL); -+ -+ zend_hash_get_current_data(CG(class_table), (void**) &elem); -+ -+ -+ elem = *((zend_class_entry**)elem); -+ -+ CHECK(array[i].name = apc_pmemcpy(key, (int) key_size, pool TSRMLS_CC)); -+ array[i].name_len = (int) key_size-1; -+ CHECK(array[i].class_entry = my_copy_class_entry(NULL, elem, ctxt TSRMLS_CC)); -+ -+ /* -+ * If the class has a pointer to its parent class, save the parent -+ * name so that we can enable compile-time inheritance when we reload -+ * the child class; otherwise, set the parent name to null and scan -+ * the op_array to determine if this class inherits from some base -+ * class at execution-time. -+ */ -+ -+ if (elem->parent) { -+ CHECK(array[i].parent_name = apc_pstrdup(elem->parent->name, pool TSRMLS_CC)); -+ } -+ else { -+ array[i].parent_name = NULL; -+ } -+ -+ zend_hash_move_forward(CG(class_table)); -+ } -+ -+ array[i].class_entry = NULL; -+ return array; -+} -+/* }}} */ -+ -+/* Used only by my_prepare_op_array_for_execution */ -+#ifdef ZEND_ENGINE_2_4 -+# define APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION() \ -+ /* The fetch is only required if auto_globals_jit=1 */ \ -+ if((zo->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_GLOBAL && \ -+ zo->op1_type == IS_CONST && \ -+ Z_TYPE_P(zo->op1.zv) == IS_STRING && \ -+ Z_STRVAL_P(zo->op1.zv)[0] == '_') { \ -+ (void)zend_is_auto_global(Z_STRVAL_P(zo->op1.zv), \ -+ Z_STRLEN_P(zo->op1.zv) \ -+ TSRMLS_CC); \ -+ } -+#else -+# define APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION() \ -+ /* The fetch is only required if auto_globals_jit=1 */ \ -+ if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL && \ -+ zo->op1.op_type == IS_CONST && \ -+ zo->op1.u.constant.type == IS_STRING && \ -+ zo->op1.u.constant.value.str.val[0] == '_') { \ -+ \ -+ znode* varname = &zo->op1; \ -+ (void)zend_is_auto_global(varname->u.constant.value.str.val, \ -+ varname->u.constant.value.str.len \ -+ TSRMLS_CC); \ -+ } -+#endif -+ -+/* {{{ my_prepare_op_array_for_execution */ -+static int my_prepare_op_array_for_execution(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ /* combine my_fetch_global_vars and my_copy_data_exceptions. -+ * - Pre-fetch superglobals which would've been pre-fetched in parse phase. -+ * - If the opcode stream contain mutable data, ensure a copy. -+ * - Fixup array jumps in the same loop. -+ */ -+ int i=src->last; -+ zend_op *zo; -+ zend_op *dzo; -+ apc_opflags_t * flags = apc_reserved_offset != -1 ? -+ (apc_opflags_t*) & (src->reserved[apc_reserved_offset]) : NULL; -+ int needcopy = flags ? flags->deep_copy : 1; -+ /* auto_globals_jit was not in php4 */ -+ int do_prepare_fetch_global = PG(auto_globals_jit) && (flags == NULL || flags->unknown_global); -+ -+#define FETCH_AUTOGLOBAL(member) do { \ -+ if(flags && flags->member == 1) { \ -+ zend_is_auto_global(#member,\ -+ (sizeof(#member) - 1)\ -+ TSRMLS_CC);\ -+ } \ -+} while(0); -+ -+ FETCH_AUTOGLOBAL(_GET); -+ FETCH_AUTOGLOBAL(_POST); -+ FETCH_AUTOGLOBAL(_COOKIE); -+ FETCH_AUTOGLOBAL(_SERVER); -+ FETCH_AUTOGLOBAL(_ENV); -+ FETCH_AUTOGLOBAL(_FILES); -+ FETCH_AUTOGLOBAL(_REQUEST); -+ FETCH_AUTOGLOBAL(_SESSION); -+#ifdef ZEND_ENGINE_2_4 -+ FETCH_AUTOGLOBAL(GLOBALS); -+#endif -+ -+ if(needcopy) { -+ -+#ifdef ZEND_ENGINE_2_4 -+ if (src->literals) { -+ zend_literal *p, *q, *end; -+ -+ q = src->literals; -+ p = dst->literals = (zend_literal*) apc_xmemcpy(src->literals, -+ sizeof(zend_literal) * src->last_literal, -+ apc_php_malloc TSRMLS_CC); -+ end = p + src->last_literal; -+ while (p < end) { -+ if (Z_TYPE(q->constant) == IS_CONSTANT_ARRAY) { -+ my_copy_zval(&p->constant, &q->constant, ctxt TSRMLS_CC); -+ } -+ p++; -+ q++; -+ } -+ } -+#endif -+ -+ dst->opcodes = (zend_op*) apc_xmemcpy(src->opcodes, -+ sizeof(zend_op) * src->last, -+ apc_php_malloc TSRMLS_CC); -+ zo = src->opcodes; -+ dzo = dst->opcodes; -+ while(i > 0) { -+ -+#ifdef ZEND_ENGINE_2_4 -+ if(zo->op1_type == IS_CONST) { -+ dzo->op1.literal = zo->op1.literal - src->literals + dst->literals; -+ } -+ if(zo->op2_type == IS_CONST) { -+ dzo->op2.literal = zo->op2.literal - src->literals + dst->literals; -+ } -+ if(zo->result_type == IS_CONST) { -+ dzo->result.literal = zo->result.literal - src->literals + dst->literals; -+ } -+#else -+ if( ((zo->op1.op_type == IS_CONST && -+ zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) || -+ ((zo->op2.op_type == IS_CONST && -+ zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) { -+ -+ if(!(my_copy_zend_op(dzo, zo, ctxt TSRMLS_CC))) { -+ assert(0); /* emalloc failed or a bad constant array */ -+ } -+ } -+#endif -+ -+ switch(zo->opcode) { -+#ifdef ZEND_ENGINE_2_3 -+ case ZEND_GOTO: -+#endif -+ case ZEND_JMP: -+#ifdef ZEND_ENGINE_2_4 -+ dzo->op1.jmp_addr = dst->opcodes + -+ (zo->op1.jmp_addr - src->opcodes); -+#else -+ dzo->op1.u.jmp_addr = dst->opcodes + -+ (zo->op1.u.jmp_addr - src->opcodes); -+#endif -+ break; -+ case ZEND_JMPZ: -+ case ZEND_JMPNZ: -+ case ZEND_JMPZ_EX: -+ case ZEND_JMPNZ_EX: -+#ifdef ZEND_ENGINE_2_3 -+ case ZEND_JMP_SET: -+#endif -+#ifdef ZEND_ENGINE_2_4 -+ case ZEND_JMP_SET_VAR: -+#endif -+#ifdef ZEND_ENGINE_2_4 -+ dzo->op2.jmp_addr = dst->opcodes + -+ (zo->op2.jmp_addr - src->opcodes); -+#else -+ dzo->op2.u.jmp_addr = dst->opcodes + -+ (zo->op2.u.jmp_addr - src->opcodes); -+#endif -+ break; -+ case ZEND_FETCH_R: -+ case ZEND_FETCH_W: -+ case ZEND_FETCH_IS: -+ case ZEND_FETCH_FUNC_ARG: -+ if(do_prepare_fetch_global) -+ { -+ APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION(); -+ } -+ break; -+ default: -+ break; -+ } -+ i--; -+ zo++; -+ dzo++; -+ } -+ } else { /* !needcopy */ -+ /* The fetch is only required if auto_globals_jit=1 */ -+ if(do_prepare_fetch_global) -+ { -+ zo = src->opcodes; -+ while(i > 0) { -+ -+ if(zo->opcode == ZEND_FETCH_R || -+ zo->opcode == ZEND_FETCH_W || -+ zo->opcode == ZEND_FETCH_IS || -+ zo->opcode == ZEND_FETCH_FUNC_ARG -+ ) { -+ APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION(); -+ } -+ -+ i--; -+ zo++; -+ } -+ } -+ } -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ apc_copy_op_array_for_execution */ -+zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ if(dst == NULL) { -+ dst = (zend_op_array*) emalloc(sizeof(src[0])); -+ } -+ memcpy(dst, src, sizeof(src[0])); -+ dst->static_variables = my_copy_static_variables(src, ctxt TSRMLS_CC); -+ -+ /* memory leak */ -+ dst->refcount = apc_pmemcpy(src->refcount, -+ sizeof(src->refcount[0]), -+ ctxt->pool TSRMLS_CC); -+ -+ my_prepare_op_array_for_execution(dst,src, ctxt TSRMLS_CC); -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ apc_copy_function_for_execution */ -+zend_function* apc_copy_function_for_execution(zend_function* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ zend_function* dst; -+ -+ dst = (zend_function*) emalloc(sizeof(src[0])); -+ memcpy(dst, src, sizeof(src[0])); -+ apc_copy_op_array_for_execution(&(dst->op_array), &(src->op_array), ctxt TSRMLS_CC); -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ apc_copy_function_for_execution_ex */ -+zend_function* apc_copy_function_for_execution_ex(void *dummy, zend_function* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+ if(src->type==ZEND_INTERNAL_FUNCTION || src->type==ZEND_OVERLOADED_FUNCTION) return src; -+ return apc_copy_function_for_execution(src, ctxt TSRMLS_CC); -+} -+/* }}} */ -+ -+/* {{{ apc_copy_class_entry_for_execution */ -+zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, apc_context_t* ctxt TSRMLS_DC) -+{ -+#ifdef ZEND_ENGINE_2_4 -+ int i; -+#endif -+ zend_class_entry* dst = (zend_class_entry*) apc_pool_alloc(ctxt->pool, sizeof(src[0])); -+ memcpy(dst, src, sizeof(src[0])); -+ -+ if(src->num_interfaces) -+ { -+ /* These are slots to be populated later by ADD_INTERFACE insns */ -+ dst->interfaces = apc_php_malloc( -+ (sizeof(zend_class_entry*) * src->num_interfaces) TSRMLS_CC); -+ memset(dst->interfaces, 0, -+ sizeof(zend_class_entry*) * src->num_interfaces); -+ } -+ else -+ { -+ /* assert(dst->interfaces == NULL); */ -+ } -+ -+ /* Deep-copy the class properties, because they will be modified */ -+ -+#ifdef ZEND_ENGINE_2_4 -+ dst->name = apc_string_pmemcpy((char*)src->name, src->name_length+1, ctxt->pool TSRMLS_CC); -+ dst->default_properties_count = src->default_properties_count; -+ if (src->default_properties_count) { -+ dst->default_properties_table = (zval**) apc_php_malloc((sizeof(zval*) * src->default_properties_count) TSRMLS_CC); -+ for (i = 0; i < src->default_properties_count; i++) { -+ if (src->default_properties_table[i]) { -+ my_copy_zval_ptr(&dst->default_properties_table[i], (const zval**)&src->default_properties_table[i], ctxt TSRMLS_CC); -+ } else { -+ dst->default_properties_table[i] = NULL; -+ } -+ } -+ } else { -+ dst->default_properties_table = NULL; -+ } -+#else -+ my_copy_hashtable(&dst->default_properties, -+ &src->default_properties, -+ (ht_copy_fun_t) my_copy_zval_ptr, -+ 1, -+ ctxt); -+#endif -+ -+ /* For derived classes, we must also copy the function hashtable (although -+ * we can merely bitwise copy the functions it contains) */ -+ -+ my_copy_hashtable(&dst->function_table, -+ &src->function_table, -+ (ht_copy_fun_t) apc_copy_function_for_execution_ex, -+ 0, -+ ctxt); -+ -+ my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function_for_execution, src, dst); -+ -+ /* zend_do_inheritance merges properties_info. -+ * Need only shallow copying as it doesn't hold the pointers. -+ */ -+ my_copy_hashtable(&dst->properties_info, -+ &src->properties_info, -+ (ht_copy_fun_t) my_copy_property_info_for_execution, -+ 0, -+ ctxt); -+ -+#ifdef ZEND_ENGINE_2_2 -+ /* php5.2 introduced a scope attribute for property info */ -+ my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst); -+#endif -+ -+ /* if inheritance results in a hash_del, it might result in -+ * a pefree() of the pointers here. Deep copying required. -+ */ -+ -+ my_copy_hashtable(&dst->constants_table, -+ &src->constants_table, -+ (ht_copy_fun_t) my_copy_zval_ptr, -+ 1, -+ ctxt); -+ -+#ifdef ZEND_ENGINE_2_4 -+ dst->default_static_members_count = src->default_static_members_count; -+ if (src->default_static_members_count) { -+ dst->default_static_members_table = (zval**) apc_php_malloc((sizeof(zval*) * src->default_static_members_count) TSRMLS_CC); -+ for (i = 0; i < src->default_static_members_count; i++) { -+ if (src->default_static_members_table[i]) { -+ my_copy_zval_ptr(&dst->default_static_members_table[i], (const zval**)&src->default_static_members_table[i], ctxt TSRMLS_CC); -+ } else { -+ dst->default_static_members_table[i] = NULL; -+ } -+ } -+ } else { -+ dst->default_static_members_table = NULL; -+ } -+ dst->static_members_table = dst->default_static_members_table; -+#else -+ my_copy_hashtable(&dst->default_static_members, -+ &src->default_static_members, -+ (ht_copy_fun_t) my_copy_zval_ptr, -+ 1, -+ ctxt); -+ -+ if(src->static_members != &(src->default_static_members)) -+ { -+ dst->static_members = my_copy_hashtable(NULL, -+ src->static_members, -+ (ht_copy_fun_t) my_copy_zval_ptr, -+ 1, -+ ctxt); -+ } -+ else -+ { -+ dst->static_members = &(dst->default_static_members); -+ } -+#endif -+ -+ return dst; -+} -+/* }}} */ -+ -+/* {{{ apc_free_class_entry_after_execution */ -+void apc_free_class_entry_after_execution(zend_class_entry* src TSRMLS_DC) -+{ -+ if(src->num_interfaces > 0 && src->interfaces) { -+ apc_php_free(src->interfaces TSRMLS_CC); -+ src->interfaces = NULL; -+ src->num_interfaces = 0; -+ } -+ /* my_destroy_hashtable() does not play nice with refcounts */ -+ -+#ifdef ZEND_ENGINE_2_4 -+ if (src->default_static_members_table) { -+ int i; -+ -+ for (i = 0; i < src->default_static_members_count; i++) { -+ zval_ptr_dtor(&src->default_static_members_table[i]); -+ } -+ efree(src->default_static_members_table); -+ src->default_static_members_table = NULL; -+ } -+ src->static_members_table = NULL; -+ if (src->default_properties_table) { -+ int i; -+ -+ for (i = 0; i < src->default_properties_count; i++) { -+ if (src->default_properties_table[i]) { -+ zval_ptr_dtor(&src->default_properties_table[i]); -+ } -+ } -+ efree(src->default_properties_table); -+ src->default_properties_table = NULL; -+ } -+#else -+ zend_hash_clean(&src->default_static_members); -+ if(src->static_members != &(src->default_static_members)) -+ { -+ zend_hash_destroy(src->static_members); -+ apc_php_free(src->static_members TSRMLS_CC); -+ src->static_members = NULL; -+ } -+ else -+ { -+ src->static_members = NULL; -+ } -+ -+ zend_hash_clean(&src->default_properties); -+#endif -+ zend_hash_clean(&src->constants_table); -+ -+ /* TODO: more cleanup */ -+} -+/* }}} */ -+ -+/* {{{ apc_file_halt_offset */ -+long apc_file_halt_offset(const char *filename TSRMLS_DC) -+{ -+ zend_constant *c; -+ char *name; -+ int len; -+ char haltoff[] = "__COMPILER_HALT_OFFSET__"; -+ long value = -1; -+ -+ zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, filename, strlen(filename), 0); -+ -+ if (zend_hash_find(EG(zend_constants), name, len+1, (void **) &c) == SUCCESS) { -+ value = Z_LVAL(c->value); -+ } -+ -+ pefree(name, 0); -+ -+ return value; -+} -+/* }}} */ -+ -+/* {{{ apc_do_halt_compiler_register */ -+void apc_do_halt_compiler_register(const char *filename, long halt_offset TSRMLS_DC) -+{ -+ char *name; -+ char haltoff[] = "__COMPILER_HALT_OFFSET__"; -+ int len; -+ -+ if(halt_offset > 0) { -+ -+ zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, -+ filename, strlen(filename), 0); -+ -+ zend_register_long_constant(name, len+1, halt_offset, CONST_CS, 0 TSRMLS_CC); -+ -+ pefree(name, 0); -+ } -+} -+/* }}} */ -+ -+ -+ -+/* {{{ my_fixup_function */ -+static void my_fixup_function(Bucket *p, zend_class_entry *src, zend_class_entry *dst) -+{ -+ zend_function* zf = p->pData; -+ -+ #define SET_IF_SAME_NAME(member) \ -+ do { \ -+ if(src->member && !strcmp(zf->common.function_name, src->member->common.function_name)) { \ -+ dst->member = zf; \ -+ } \ -+ } \ -+ while(0) -+ -+ if(zf->common.scope == src) -+ { -+ -+ /* Fixing up the default functions for objects here since -+ * we need to compare with the newly allocated functions -+ * -+ * caveat: a sub-class method can have the same name as the -+ * parent's constructor and create problems. -+ */ -+ -+ if(zf->common.fn_flags & ZEND_ACC_CTOR) dst->constructor = zf; -+ else if(zf->common.fn_flags & ZEND_ACC_DTOR) dst->destructor = zf; -+ else if(zf->common.fn_flags & ZEND_ACC_CLONE) dst->clone = zf; -+ else -+ { -+ SET_IF_SAME_NAME(__get); -+ SET_IF_SAME_NAME(__set); -+ SET_IF_SAME_NAME(__unset); -+ SET_IF_SAME_NAME(__isset); -+ SET_IF_SAME_NAME(__call); -+#ifdef ZEND_ENGINE_2_2 -+ SET_IF_SAME_NAME(__tostring); -+#endif -+#ifdef ZEND_ENGINE_2_3 -+ SET_IF_SAME_NAME(__callstatic); -+#endif -+ } -+ zf->common.scope = dst; -+ } -+ else -+ { -+ /* no other function should reach here */ -+ assert(0); -+ } -+ -+ #undef SET_IF_SAME_NAME -+} -+/* }}} */ -+ -+#ifdef ZEND_ENGINE_2_2 -+/* {{{ my_fixup_property_info */ -+static void my_fixup_property_info(Bucket *p, zend_class_entry *src, zend_class_entry *dst) -+{ -+ zend_property_info* property_info = (zend_property_info*)p->pData; -+ -+ if(property_info->ce == src) -+ { -+ property_info->ce = dst; -+ } -+ else -+ { -+ assert(0); /* should never happen */ -+ } -+} -+/* }}} */ -+#endif -+ -+/* {{{ my_fixup_hashtable */ -+static void my_fixup_hashtable(HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst) -+{ -+ Bucket *p; -+ uint i; -+ -+ for (i = 0; i < ht->nTableSize; i++) { -+ if(!ht->arBuckets) break; -+ p = ht->arBuckets[i]; -+ while (p != NULL) { -+ fixup(p, src, dst); -+ p = p->pNext; -+ } -+ } -+} -+/* }}} */ -+ -+ -+/* {{{ my_check_copy_function */ -+static int my_check_copy_function(Bucket* p, va_list args) -+{ -+ zend_class_entry* src = va_arg(args, zend_class_entry*); -+ zend_function* zf = (zend_function*)p->pData; -+ -+ return (zf->common.scope == src); -+} -+/* }}} */ -+ -+#ifndef ZEND_ENGINE_2_4 -+/* {{{ my_check_copy_default_property */ -+static int my_check_copy_default_property(Bucket* p, va_list args) -+{ -+ zend_class_entry* src = va_arg(args, zend_class_entry*); -+ zend_class_entry* parent = src->parent; -+ zval ** child_prop = (zval**)p->pData; -+ zval ** parent_prop = NULL; -+ -+ if (parent && -+ zend_hash_quick_find(&parent->default_properties, p->arKey, -+ p->nKeyLength, p->h, (void **) &parent_prop)==SUCCESS) { -+ -+ if((parent_prop && child_prop) && (*parent_prop) == (*child_prop)) -+ { -+ return 0; -+ } -+ } -+ -+ /* possibly not in the parent */ -+ return 1; -+} -+/* }}} */ -+#endif -+ -+/* {{{ my_check_copy_property_info */ -+static int my_check_copy_property_info(Bucket* p, va_list args) -+{ -+ zend_class_entry* src = va_arg(args, zend_class_entry*); -+ zend_class_entry* parent = src->parent; -+ zend_property_info* child_info = (zend_property_info*)p->pData; -+ zend_property_info* parent_info = NULL; -+ -+#ifdef ZEND_ENGINE_2_2 -+ /* so much easier */ -+ return (child_info->ce == src); -+#endif -+ -+ if (parent && -+ zend_hash_quick_find(&parent->properties_info, p->arKey, p->nKeyLength, -+ p->h, (void **) &parent_info)==SUCCESS) { -+ if(parent_info->flags & ZEND_ACC_PRIVATE) -+ { -+ return 1; -+ } -+ if((parent_info->flags & ZEND_ACC_PPP_MASK) != -+ (child_info->flags & ZEND_ACC_PPP_MASK)) -+ { -+ /* TODO: figure out whether ACC_CHANGED is more appropriate -+ * here */ -+ return 1; -+ } -+ return 0; -+ } -+ -+ /* property doesn't exist in parent, copy into cached child */ -+ return 1; -+} -+/* }}} */ -+ -+#ifndef ZEND_ENGINE_2_4 -+/* {{{ my_check_copy_static_member */ -+static int my_check_copy_static_member(Bucket* p, va_list args) -+{ -+ zend_class_entry* src = va_arg(args, zend_class_entry*); -+ HashTable * ht = va_arg(args, HashTable*); -+ zend_class_entry* parent = src->parent; -+ HashTable * parent_ht = NULL; -+ char * member_name; -+ char * class_name = NULL; -+ -+ zend_property_info *parent_info = NULL; -+ zend_property_info *child_info = NULL; -+ zval ** parent_prop = NULL; -+ zval ** child_prop = (zval**)(p->pData); -+ -+ if(!parent) { -+ return 1; -+ } -+ -+ /* these do not need free'ing */ -+#ifdef ZEND_ENGINE_2_2 -+ zend_unmangle_property_name(p->arKey, p->nKeyLength-1, &class_name, &member_name); -+#else -+ zend_unmangle_property_name(p->arKey, &class_name, &member_name); -+#endif -+ -+ /* please refer do_inherit_property_access_check in zend_compile.c -+ * to understand why we lookup in properties_info. -+ */ -+ if((zend_hash_find(&parent->properties_info, member_name, -+ strlen(member_name)+1, (void**)&parent_info) == SUCCESS) -+ && -+ (zend_hash_find(&src->properties_info, member_name, -+ strlen(member_name)+1, (void**)&child_info) == SUCCESS)) -+ { -+ if(ht == &(src->default_static_members)) -+ { -+ parent_ht = &parent->default_static_members; -+ } -+ else -+ { -+ parent_ht = parent->static_members; -+ } -+ -+ if(zend_hash_quick_find(parent_ht, p->arKey, -+ p->nKeyLength, p->h, (void**)&parent_prop) == SUCCESS) -+ { -+ /* they point to the same zval */ -+ if(*parent_prop == *child_prop) -+ { -+ return 0; -+ } -+ } -+ } -+ -+ return 1; -+} -+/* }}} */ -+#endif -+ -+/* {{{ my_check_copy_constant */ -+static int my_check_copy_constant(Bucket* p, va_list args) -+{ -+ zend_class_entry* src = va_arg(args, zend_class_entry*); -+ zend_class_entry* parent = src->parent; -+ zval ** child_const = (zval**)p->pData; -+ zval ** parent_const = NULL; -+ -+ if (parent && -+ zend_hash_quick_find(&parent->constants_table, p->arKey, -+ p->nKeyLength, p->h, (void **) &parent_const)==SUCCESS) { -+ -+ if((parent_const && child_const) && (*parent_const) == (*child_const)) -+ { -+ return 0; -+ } -+ } -+ -+ /* possibly not in the parent */ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ apc_register_optimizer(apc_optimize_function_t optimizer) -+ * register a optimizer callback function, returns the previous callback -+ */ -+apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC) { -+ apc_optimize_function_t old_optimizer = APCG(apc_optimize_function); -+ APCG(apc_optimize_function) = optimizer; -+ return old_optimizer; -+} -+/* }}} */ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_compile.h b/ext/apc/apc_compile.h ---- a/ext/apc/apc_compile.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_compile.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,152 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | Arun C. Murthy | -+ | Gopal Vijayaraghavan | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_compile.h 307185 2011-01-06 21:13:11Z gopalv $ */ -+ -+#ifndef APC_COMPILE_H -+#define APC_COMPILE_H -+ -+/* -+ * This module encapsulates most of the complexity involved in deep-copying -+ * the Zend compiler data structures. The routines are allocator-agnostic, so -+ * the same function can be used for copying to and from shared memory. -+ */ -+ -+#include "apc.h" -+#include "apc_php.h" -+#include "apc_main.h" -+#include "apc_serializer.h" -+ -+/* {{{ struct definition: apc_function_t */ -+typedef struct apc_function_t apc_function_t; -+struct apc_function_t { -+ char* name; /* the function name */ -+ int name_len; /* length of name */ -+ zend_function* function; /* the zend function data structure */ -+}; -+/* }}} */ -+ -+/* {{{ struct definition: apc_class_t */ -+typedef struct apc_class_t apc_class_t; -+struct apc_class_t { -+ char* name; /* the class name */ -+ int name_len; /* length of name */ -+ char* parent_name; /* the parent class name */ -+ zend_class_entry* class_entry; /* the zend class data structure */ -+}; -+/* }}} */ -+ -+/* {{{ struct definition: apc_opflags_t */ -+typedef struct apc_opflags_t apc_opflags_t; -+struct apc_opflags_t { -+ unsigned int has_jumps : 1; /* has jump offsets */ -+ unsigned int deep_copy : 1; /* needs deep copy */ -+ -+ /* autoglobal bits */ -+ unsigned int _POST : 1; -+ unsigned int _GET : 1; -+ unsigned int _COOKIE : 1; -+ unsigned int _SERVER : 1; -+ unsigned int _ENV : 1; -+ unsigned int _FILES : 1; -+ unsigned int _REQUEST : 1; -+ unsigned int _SESSION : 1; -+#ifdef ZEND_ENGINE_2_4 -+ unsigned int GLOBALS : 1; -+#endif -+ unsigned int unknown_global : 1; -+}; -+/* }}} */ -+ -+/* -+ * These are the top-level copy functions. -+ */ -+ -+extern zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC); -+extern zend_class_entry* apc_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_context_t* ctxt TSRMLS_DC); -+extern apc_function_t* apc_copy_new_functions(int old_count, apc_context_t* ctxt TSRMLS_DC); -+extern apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_context_t* ctxt TSRMLS_DC); -+extern zval* apc_copy_zval(zval* dst, const zval* src, apc_context_t* ctxt TSRMLS_DC); -+ -+#if 0 -+/* -+ * Deallocation functions corresponding to the copy functions above. -+ */ -+ -+extern void apc_free_op_array(zend_op_array* src, apc_context_t* ctxt); -+extern void apc_free_functions(apc_function_t* src, apc_context_t* ctxt); -+extern void apc_free_classes(apc_class_t* src, apc_context_t* ctxt); -+extern void apc_free_zval(zval* src, apc_context_t* ctxt); -+#endif -+ -+/* -+ * These "copy-for-execution" functions must be called after retrieving an -+ * object from the shared cache. They do the minimal amount of work necessary -+ * to allow multiple processes to concurrently execute the same VM data -+ * structures. -+ */ -+ -+extern zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC); -+extern zend_function* apc_copy_function_for_execution(zend_function* src, apc_context_t* ctxt TSRMLS_DC); -+extern zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, apc_context_t* ctxt TSRMLS_DC); -+ -+/* -+ * The "free-after-execution" function performs a cursory clean up of the class data -+ * This is required to minimize memory leak warnings and to ensure correct destructor -+ * ordering of some variables. -+ */ -+extern void apc_free_class_entry_after_execution(zend_class_entry* src TSRMLS_DC); -+ -+/* -+ * Optimization callback definition and registration function. -+ */ -+typedef zend_op_array* (*apc_optimize_function_t) (zend_op_array* TSRMLS_DC); -+extern apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC); -+ -+/* -+ * To handle __COMPILER_HALT_OFFSET__ -+ */ -+long apc_file_halt_offset(const char* filename TSRMLS_DC); -+void apc_do_halt_compiler_register(const char *filename, long halt_offset TSRMLS_DC); -+ -+/* -+ * apc serialization functions -+ */ -+int APC_SERIALIZER_NAME(php) (APC_SERIALIZER_ARGS); -+int APC_UNSERIALIZER_NAME(php) (APC_UNSERIALIZER_ARGS); -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_debug.c b/ext/apc/apc_debug.c ---- a/ext/apc/apc_debug.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_debug.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,70 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | Arun C. Murthy | -+ | Gopal Vijayaraghavan | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+*/ -+ -+/* $Id: apc_debug.c 307048 2011-01-03 23:53:17Z kalle $ */ -+#include "apc.h" -+#include -+#include "zend.h" -+#include "zend_compile.h" -+ -+#if defined(__DEBUG_APC__) -+ -+/* keep track of vld_dump_oparray() signature */ -+typedef void (*vld_dump_f) (zend_op_array * TSRMLS_DC); -+ -+#endif -+ -+void dump(zend_op_array *op_array TSRMLS_DC) -+{ -+#if defined(__DEBUG_APC__) -+ vld_dump_f dump_op_array; -+ DL_HANDLE handle = NULL; -+ -+#ifdef PHP_WIN32 -+ handle = GetModuleHandle(NULL); -+ -+ if (!handle) { -+ apc_warning("unable to fetch current module handle." TSRMLS_CC); -+ } -+#endif -+ -+ dump_op_array = (vld_dump_f) DL_FETCH_SYMBOL(handle, "vld_dump_oparray"); -+ -+#ifdef PHP_WIN32 -+ DL_UNLOAD(handle); -+#endif -+ -+ if(dump_op_array) { -+ dump_op_array(op_array TSRMLS_CC); -+ -+ return; -+ } -+ -+ apc_warning("vld is not installed or something even worse." TSRMLS_CC); -+#endif -+} -diff -Naur a/ext/apc/apc_debug.h b/ext/apc/apc_debug.h ---- a/ext/apc/apc_debug.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_debug.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,29 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | Arun C. Murthy | -+ | Gopal Vijayaraghavan | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+*/ -+ -+void dump(zend_op_array * TSRMLS_DC); -diff -Naur a/ext/apc/apc_fcntl.c b/ext/apc/apc_fcntl.c ---- a/ext/apc/apc_fcntl.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_fcntl.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,123 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: George Schlossnagle | -+ | Rasmus Lerdorf | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_fcntl.c 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#include "apc.h" -+ -+#ifdef APC_FCNTL_LOCKS -+ -+#include "apc_fcntl.h" -+#include -+#include -+ -+int apc_fcntl_create(const char* pathname TSRMLS_DC) -+{ -+ int fd; -+ if(pathname == NULL) { -+ char lock_path[] = "/tmp/.apc.XXXXXX"; -+ mktemp(lock_path); -+ fd = open(lock_path, O_RDWR|O_CREAT, 0666); -+ if(fd > 0 ) { -+ unlink(lock_path); -+ return fd; -+ } else { -+ apc_error("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:" TSRMLS_CC, lock_path); -+ return -1; -+ } -+ } -+ fd = open(pathname, O_RDWR|O_CREAT, 0666); -+ if(fd > 0 ) { -+ unlink(pathname); -+ return fd; -+ } -+ apc_error("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:" TSRMLS_CC, pathname); -+ return -1; -+} -+ -+void apc_fcntl_destroy(int fd) -+{ -+ close(fd); -+} -+ -+static int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len) -+{ -+ int ret; -+ struct flock lock; -+ -+ lock.l_type = type; -+ lock.l_start = offset; -+ lock.l_whence = whence; -+ lock.l_len = len; -+ lock.l_pid = 0; -+ -+ do { ret = fcntl(fd, cmd, &lock) ; } -+ while(ret < 0 && errno == EINTR); -+ return(ret); -+} -+ -+void apc_fcntl_lock(int fd TSRMLS_DC) -+{ -+ if(lock_reg(fd, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) { -+ apc_error("apc_fcntl_lock failed:" TSRMLS_CC); -+ } -+} -+ -+void apc_fcntl_rdlock(int fd TSRMLS_DC) -+{ -+ if(lock_reg(fd, F_SETLKW, F_RDLCK, 0, SEEK_SET, 0) < 0) { -+ apc_error("apc_fcntl_rdlock failed:" TSRMLS_CC); -+ } -+} -+ -+zend_bool apc_fcntl_nonblocking_lock(int fd TSRMLS_DC) -+{ -+ if(lock_reg(fd, F_SETLK, F_WRLCK, 0, SEEK_SET, 0) < 0) { -+ if(errno==EACCES||errno==EAGAIN) return 0; -+ else apc_error("apc_fcntl_lock failed:" TSRMLS_CC); -+ } -+ return 1; -+} -+ -+void apc_fcntl_unlock(int fd TSRMLS_DC) -+{ -+ if(lock_reg(fd, F_SETLKW, F_UNLCK, 0, SEEK_SET, 0) < 0) { -+ apc_error("apc_fcntl_unlock failed:" TSRMLS_CC); -+ } -+} -+ -+#endif /* APC_FCNTL_LOCKS */ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_fcntl.h b/ext/apc/apc_fcntl.h ---- a/ext/apc/apc_fcntl.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_fcntl.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,50 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: George Schlossnagle | -+ | Rasmus Lerdorf | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_fcntl.h 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#ifndef APC_FCNTL_H -+#define APC_FCNTL_H -+ -+ -+extern int apc_fcntl_create(const char* pathname TSRMLS_DC); -+extern void apc_fcntl_destroy(int fd); -+extern void apc_fcntl_lock(int fd TSRMLS_DC); -+extern void apc_fcntl_rdlock(int fd TSRMLS_DC); -+extern void apc_fcntl_unlock(int fd TSRMLS_DC); -+extern unsigned char apc_fcntl_nonblocking_lock(int fd TSRMLS_DC); -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_fcntl_win32.c b/ext/apc/apc_fcntl_win32.c ---- a/ext/apc/apc_fcntl_win32.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_fcntl_win32.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,120 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: George Schlossnagle | -+ | Edin Kadribasic | -+ | Pierre Joye | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_fcntl_win32.c 309203 2011-03-14 06:47:16Z pajoye $ */ -+ -+#include "apc.h" -+#include "apc_fcntl.h" -+#include -+#include -+#include -+#include -+#include -+#include -+ -+int apc_fcntl_create(const char* pathname TSRMLS_DC) -+{ -+ char lock_file[MAXPATHLEN]; -+ HANDLE fd; -+ DWORD tmp_dirname_len; -+ char lock_filename_tpl[] = ".apc.XXXXXX"; -+ char *lock_filename; -+ -+ tmp_dirname_len = GetTempPath(MAXPATHLEN, lock_file); -+ if (!tmp_dirname_len) { -+ return -1; -+ } -+ -+ lock_filename = _mktemp(lock_filename_tpl); -+ if (lock_filename == NULL) { -+ return -1; -+ } -+ -+ snprintf(lock_file + tmp_dirname_len, MAXPATHLEN - tmp_dirname_len - 1, "%s", lock_filename); -+ -+ fd = CreateFile(lock_file, -+ GENERIC_READ | GENERIC_WRITE, -+ FILE_SHARE_READ | FILE_SHARE_WRITE, -+ NULL, -+ OPEN_ALWAYS, -+ FILE_ATTRIBUTE_NORMAL, -+ NULL); -+ -+ if (fd == INVALID_HANDLE_VALUE) { -+ apc_error("apc_fcntl_create: could not open %s" TSRMLS_CC, lock_file); -+ return -1; -+ } -+ -+ return (int)fd; -+} -+ -+void apc_fcntl_destroy(int fd) -+{ -+ CloseHandle((HANDLE)fd); -+} -+ -+void apc_fcntl_lock(int fd TSRMLS_DC) -+{ -+ OVERLAPPED offset = {0, 0, 0, 0, NULL}; -+ -+ if (!LockFileEx((HANDLE)fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset)) { -+ apc_error("apc_fcntl_lock failed errno:%d" TSRMLS_CC, GetLastError()); -+ } -+} -+ -+void apc_fcntl_rdlock(int fd TSRMLS_DC) -+{ -+ OVERLAPPED offset = {0, 0, 0, 0, NULL}; -+ -+ if (!LockFileEx((HANDLE)fd, 0, 0, 1, 0, &offset)) { -+ apc_error("apc_fcntl_rdlock failed errno:%d" TSRMLS_CC, GetLastError()); -+ } -+} -+ -+void apc_fcntl_unlock(int fd TSRMLS_DC) -+{ -+ OVERLAPPED offset = {0, 0, 0, 0, NULL}; -+ -+ if (!UnlockFileEx((HANDLE)fd, 0, 1, 0, &offset)) { -+ DWORD error_code = GetLastError(); -+ /* Ignore already unlocked error */ -+ if (error_code != ERROR_NOT_LOCKED) { -+ apc_error("apc_fcntl_unlock failed errno:%d" TSRMLS_CC, error_code); -+ } -+ } -+} -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_globals.h b/ext/apc/apc_globals.h ---- a/ext/apc/apc_globals.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_globals.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,152 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | George Schlossnagle | -+ | Rasmus Lerdorf | -+ | Arun C. Murthy | -+ | Gopal Vijayaraghavan | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_globals.h 307215 2011-01-07 09:54:00Z gopalv $ */ -+ -+#ifndef APC_GLOBALS_H -+#define APC_GLOBALS_H -+ -+#include "apc_cache.h" -+#include "apc_stack.h" -+#include "apc_php.h" -+#include "apc_main.h" -+ -+/* {{{ struct apc_rfc1867_data */ -+ -+typedef struct _apc_rfc1867_data apc_rfc1867_data; -+ -+struct _apc_rfc1867_data { -+ char tracking_key[64]; -+ int key_length; -+ size_t content_length; -+ char filename[128]; -+ char name[64]; -+ char *temp_filename; -+ int cancel_upload; -+ double start_time; -+ size_t bytes_processed; -+ size_t prev_bytes_processed; -+ int update_freq; -+ double rate; -+ int started; -+}; -+/* }}} */ -+ -+ -+ZEND_BEGIN_MODULE_GLOBALS(apc) -+ /* configuration parameters */ -+ zend_bool enabled; /* if true, apc is enabled (defaults to true) */ -+ long shm_segments; /* number of shared memory segments to use */ -+ long shm_size; /* size of each shared memory segment (in MB) */ -+ long num_files_hint; /* parameter to apc_cache_create */ -+ long user_entries_hint; -+ long gc_ttl; /* parameter to apc_cache_create */ -+ long ttl; /* parameter to apc_cache_create */ -+ long user_ttl; -+#if APC_MMAP -+ char *mmap_file_mask; /* mktemp-style file-mask to pass to mmap */ -+#endif -+ char** filters; /* array of regex filters that prevent caching */ -+ void* compiled_filters; /* compiled regex filters */ -+ -+ /* module variables */ -+ zend_bool initialized; /* true if module was initialized */ -+ apc_stack_t* cache_stack; /* the stack of cached executable code */ -+ zend_bool cache_by_default; /* true if files should be cached unless filtered out */ -+ /* false if files should only be cached if filtered in */ -+ long file_update_protection; /* Age in seconds before a file is eligible to be cached - 0 to disable */ -+ zend_bool enable_cli; /* Flag to override turning APC off for CLI */ -+ long max_file_size; /* Maximum size of file, in bytes that APC will be allowed to cache */ -+ zend_bool fpstat; /* true if fullpath includes should be stat'ed */ -+ zend_bool canonicalize; /* true if relative paths should be canonicalized in no-stat mode */ -+ zend_bool stat_ctime; /* true if ctime in addition to mtime should be checked */ -+ zend_bool write_lock; /* true for a global write lock */ -+ zend_bool slam_defense; /* true for user cache slam defense */ -+ zend_bool report_autofilter; /* true for auto-filter warnings */ -+ zend_bool include_once; /* Override the ZEND_INCLUDE_OR_EVAL opcode handler to avoid pointless fopen()s [still experimental] */ -+ apc_optimize_function_t apc_optimize_function; /* optimizer function callback */ -+#ifdef MULTIPART_EVENT_FORMDATA -+ zend_bool rfc1867; /* Flag to enable rfc1867 handler */ -+ char* rfc1867_prefix; /* Key prefix */ -+ char* rfc1867_name; /* Name of hidden field to activate upload progress/key suffix */ -+ double rfc1867_freq; /* Update frequency as percentage or bytes */ -+ long rfc1867_ttl; /* TTL for rfc1867 entries */ -+ apc_rfc1867_data rfc1867_data;/* Per-request data */ -+#endif -+ HashTable copied_zvals; /* my_copy recursion detection list */ -+ zend_bool force_file_update; /* force files to be updated during apc_compile_file */ -+ char canon_path[MAXPATHLEN]; /* canonical path for key data */ -+#ifdef APC_FILEHITS -+ zval *filehits; /* Files that came from the cache for this request */ -+#endif -+ zend_bool coredump_unmap; /* Trap signals that coredump and unmap shared memory */ -+ apc_cache_t *current_cache; /* current cache being modified/read */ -+ char *preload_path; -+ zend_bool file_md5; /* record md5 hash of files */ -+ void *apc_bd_alloc_ptr; /* bindump alloc() ptr */ -+ void *apc_bd_alloc_ubptr; /* bindump alloc() upper bound ptr */ -+ HashTable apc_bd_alloc_list; /* bindump alloc() ptr list */ -+ zend_bool use_request_time; /* use the SAPI request start time for TTL */ -+ zend_bool lazy_functions; /* enable/disable lazy function loading */ -+ HashTable *lazy_function_table; /* lazy function entry table */ -+ zend_bool lazy_classes; /* enable/disable lazy class loading */ -+ HashTable *lazy_class_table; /* lazy class entry table */ -+#ifdef ZEND_ENGINE_2_4 -+ long shm_strings_buffer; -+#endif -+ char *serializer_name; /* the serializer config option */ -+ apc_serializer_t *serializer;/* the actual serializer in use */ -+ZEND_END_MODULE_GLOBALS(apc) -+ -+/* (the following declaration is defined in php_apc.c) */ -+ZEND_EXTERN_MODULE_GLOBALS(apc) -+ -+#ifdef ZTS -+# define APCG(v) TSRMG(apc_globals_id, zend_apc_globals *, v) -+#else -+# define APCG(v) (apc_globals.v) -+#endif -+ -+/* True globals */ -+extern apc_cache_t* apc_cache; /* the global compiler cache */ -+extern apc_cache_t* apc_user_cache; /* the global user content cache */ -+extern void* apc_compiled_filters; /* compiled filters */ -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc.h b/ext/apc/apc.h ---- a/ext/apc/apc.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,136 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | George Schlossnagle | -+ | Rasmus Lerdorf | -+ | Arun C. Murthy | -+ | Gopal Vijayaraghavan | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc.h 307264 2011-01-08 13:20:20Z gopalv $ */ -+ -+#ifndef APC_H -+#define APC_H -+ -+/* -+ * This module defines utilities and helper functions used elsewhere in APC. -+ */ -+ -+/* Commonly needed C library headers. */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* UNIX headers (needed for struct stat) */ -+#include -+#include -+#ifndef PHP_WIN32 -+#include -+#endif -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include "php.h" -+#include "main/php_streams.h" -+ -+/* typedefs for extensible memory allocators */ -+typedef void* (*apc_malloc_t)(size_t TSRMLS_DC); -+typedef void (*apc_free_t) (void * TSRMLS_DC); -+ -+/* wrappers for memory allocation routines */ -+extern void* apc_emalloc(size_t n TSRMLS_DC); -+extern void* apc_erealloc(void* p, size_t n TSRMLS_DC); -+extern void apc_efree(void* p TSRMLS_DC); -+extern char* apc_estrdup(const char* s TSRMLS_DC); -+extern void* apc_xstrdup(const char* s, apc_malloc_t f TSRMLS_DC); -+extern void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f TSRMLS_DC); -+ -+/* console display functions */ -+extern void apc_error(const char *format TSRMLS_DC, ...); -+extern void apc_warning(const char *format TSRMLS_DC, ...); -+extern void apc_notice(const char *format TSRMLS_DC, ...); -+extern void apc_debug(const char *format TSRMLS_DC, ...); -+ -+/* string and text manipulation */ -+extern char* apc_append(const char* s, const char* t TSRMLS_DC); -+extern char* apc_substr(const char* s, int start, int length TSRMLS_DC); -+extern char** apc_tokenize(const char* s, char delim TSRMLS_DC); -+ -+/* filesystem functions */ -+ -+typedef struct apc_fileinfo_t -+{ -+ char *fullpath; -+ char path_buf[MAXPATHLEN]; -+ php_stream_statbuf st_buf; -+} apc_fileinfo_t; -+ -+extern int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo TSRMLS_DC); -+ -+/* regular expression wrapper functions */ -+extern void* apc_regex_compile_array(char* patterns[] TSRMLS_DC); -+extern void apc_regex_destroy_array(void* p TSRMLS_DC); -+extern int apc_regex_match_array(void* p, const char* input); -+ -+/* apc_crc32: returns the CRC-32 checksum of the first len bytes in buf */ -+extern unsigned int apc_crc32(const char* buf, int len); -+ -+/* apc_flip_hash flips keys and values for faster searching */ -+extern HashTable* apc_flip_hash(HashTable *hash); -+ -+#define APC_NEGATIVE_MATCH 1 -+#define APC_POSITIVE_MATCH 2 -+ -+#define apc_time() \ -+ (APCG(use_request_time) ? (time_t) sapi_get_request_time(TSRMLS_C) : time(0)); -+ -+#if defined(__GNUC__) -+# define APC_UNUSED __attribute__((unused)) -+# define APC_USED __attribute__((used)) -+# define APC_ALLOC __attribute__((malloc)) -+# define APC_HOTSPOT __attribute__((hot)) -+#else -+# define APC_UNUSED -+# define APC_USED -+# define APC_ALLOC -+# define APC_HOTSPOT -+#endif -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_iterator.c b/ext/apc/apc_iterator.c ---- a/ext/apc/apc_iterator.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_iterator.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,741 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Brian Shire | -+ +----------------------------------------------------------------------+ -+ -+ */ -+ -+/* $Id: apc_iterator.c 324326 2012-03-18 13:19:50Z pajoye $ */ -+ -+#include "php_apc.h" -+#include "apc_iterator.h" -+#include "apc_cache.h" -+#include "apc_zend.h" -+ -+#include "ext/standard/md5.h" -+ -+#include "zend_interfaces.h" -+ -+zend_class_entry *apc_iterator_ce; -+zend_object_handlers apc_iterator_object_handlers; -+ -+ -+/* {{{ apc_iterator_item */ -+static apc_iterator_item_t* apc_iterator_item_ctor(apc_iterator_t *iterator, slot_t **slot_pp TSRMLS_DC) { -+ zval *zvalue; -+ char md5str[33]; -+ slot_t *slot = *slot_pp; -+ apc_context_t ctxt = {0, }; -+ apc_iterator_item_t *item = ecalloc(1, sizeof(apc_iterator_item_t)); -+ -+ if (slot->key.type == APC_CACHE_KEY_FILE) { -+ /* keys should be unique and with stat=1 we could have multiple files with the same name, so use ' ' instead */ -+#ifdef PHP_WIN32 -+ item->key_len = spprintf(&item->key, 0, "%I64d %I64d", slot->key.data.file.device, slot->key.data.file.inode); -+#else -+ item->key_len = spprintf(&item->key, 0, "%ld %ld", (ulong)slot->key.data.file.device, (ulong)slot->key.data.file.inode); -+#endif -+ item->filename_key = estrdup(slot->value->data.file.filename); -+ } else if (slot->key.type == APC_CACHE_KEY_USER) { -+ item->key = estrndup((char*)slot->key.data.user.identifier, slot->key.data.user.identifier_len); -+ item->key_len = slot->key.data.user.identifier_len; -+ item->filename_key = item->key; -+ } else if (slot->key.type == APC_CACHE_KEY_FPFILE) { -+ item->key = estrndup((char*)slot->key.data.fpfile.fullpath, slot->key.data.fpfile.fullpath_len); -+ item->key_len = slot->key.data.fpfile.fullpath_len; -+ item->filename_key = item->key; -+ } else { -+ apc_error("Internal error, invalid entry type." TSRMLS_CC); -+ } -+ -+ ALLOC_INIT_ZVAL(item->value); -+ array_init(item->value); -+ -+ if (APC_ITER_TYPE & iterator->format) { -+ if(slot->value->type == APC_CACHE_ENTRY_FILE) { -+ add_assoc_string(item->value, "type", "file", 1); -+ } else if(slot->value->type == APC_CACHE_ENTRY_USER) { -+ add_assoc_string(item->value, "type", "user", 1); -+ } -+ } -+ if (APC_ITER_FILENAME & iterator->format) { -+ if(slot->value->type == APC_CACHE_ENTRY_FILE) { -+ if (slot->key.type == APC_CACHE_KEY_FILE) { -+ add_assoc_string(item->value, "filename", slot->value->data.file.filename, 1); -+ } else { /* APC_CACHE_FPFILE */ -+ add_assoc_string(item->value, "filename", (char*)slot->key.data.fpfile.fullpath, 1); -+ } -+ } -+ } -+ if (APC_ITER_DEVICE & iterator->format) { -+ if(slot->key.type == APC_CACHE_KEY_FILE) { -+#ifdef PHP_WIN32 -+ char buf[20]; -+ sprintf(buf, "%I64d", slot->key.data.file.device); -+ add_assoc_string(item->value, "device", buf, 1); -+#else -+ add_assoc_long(item->value, "device", slot->key.data.file.device); -+#endif -+ } -+ } -+ if (APC_ITER_INODE & iterator->format) { -+ if(slot->key.type == APC_CACHE_KEY_FILE) { -+#ifdef PHP_WIN32 -+ char buf[20]; -+ sprintf(buf, "%I64d", slot->key.data.file.device); -+ add_assoc_string(item->value, "device", buf, 1); -+#else -+ add_assoc_long(item->value, "inode", slot->key.data.file.inode); -+#endif -+ } -+ } -+ if (APC_ITER_KEY & iterator->format) { -+ add_assoc_stringl(item->value, "key", item->key, (item->key_len - 1), 1); -+ } -+ if (APC_ITER_VALUE & iterator->format) { -+ if(slot->value->type == APC_CACHE_ENTRY_USER) { -+ -+ ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, NULL, NULL TSRMLS_CC); -+ ctxt.copy = APC_COPY_OUT_USER; -+ -+ MAKE_STD_ZVAL(zvalue); -+ apc_cache_fetch_zval(zvalue, slot->value->data.user.val, &ctxt TSRMLS_CC); -+ apc_pool_destroy(ctxt.pool TSRMLS_CC); -+ add_assoc_zval(item->value, "value", zvalue); -+ } -+ } -+ if (APC_ITER_MD5 & iterator->format) { -+ if(slot->value->type == APC_CACHE_ENTRY_FILE) { -+ if(APCG(file_md5) && slot->key.md5) { -+ make_digest(md5str, slot->key.md5); -+ add_assoc_string(item->value, "md5", md5str, 1); -+ } -+ } -+ } -+ if (APC_ITER_NUM_HITS & iterator->format) { -+ add_assoc_long(item->value, "num_hits", slot->num_hits); -+ } -+ if (APC_ITER_MTIME & iterator->format) { -+ add_assoc_long(item->value, "mtime", slot->key.mtime); -+ } -+ if (APC_ITER_CTIME & iterator->format) { -+ add_assoc_long(item->value, "creation_time", slot->creation_time); -+ } -+ if (APC_ITER_DTIME & iterator->format) { -+ add_assoc_long(item->value, "deletion_time", slot->deletion_time); -+ } -+ if (APC_ITER_ATIME & iterator->format) { -+ add_assoc_long(item->value, "access_time", slot->access_time); -+ } -+ if (APC_ITER_REFCOUNT & iterator->format) { -+ add_assoc_long(item->value, "ref_count", slot->value->ref_count); -+ } -+ if (APC_ITER_MEM_SIZE & iterator->format) { -+ add_assoc_long(item->value, "mem_size", slot->value->mem_size); -+ } -+ if (APC_ITER_TTL & iterator->format) { -+ if(slot->value->type == APC_CACHE_ENTRY_USER) { -+ add_assoc_long(item->value, "ttl", slot->value->data.user.ttl); -+ } -+ } -+ -+ return item; -+} -+/* }}} */ -+ -+/* {{{ apc_iterator_clone */ -+static zend_object_value apc_iterator_clone(zval *zobject TSRMLS_DC) { -+ zend_object_value value = {0}; -+ apc_error("APCIterator object cannot be cloned." TSRMLS_CC); -+ return value; -+} -+/* }}} */ -+ -+/* {{{ apc_iterator_item_dtor */ -+static void apc_iterator_item_dtor(apc_iterator_item_t *item) { -+ if (item->filename_key && item->filename_key != item->key) { -+ efree(item->filename_key); -+ } -+ if (item->key) { -+ efree(item->key); -+ } -+ if (item->value) { -+ zval_ptr_dtor(&item->value); -+ } -+ efree(item); -+} -+/* }}} */ -+ -+/* {{{ apc_iterator_destroy */ -+static void apc_iterator_destroy(void *object, zend_object_handle handle TSRMLS_DC) { -+ apc_iterator_t *iterator = (apc_iterator_t*)object; -+ -+ if (iterator->initialized == 0) { -+ return; -+ } -+ -+ while (apc_stack_size(iterator->stack) > 0) { -+ apc_iterator_item_dtor(apc_stack_pop(iterator->stack)); -+ } -+ if (iterator->regex) { -+ efree(iterator->regex); -+ } -+ if (iterator->search_hash) { -+ zend_hash_destroy(iterator->search_hash); -+ efree(iterator->search_hash); -+ } -+ iterator->initialized = 0; -+ -+} -+/* }}} */ -+ -+/* {{{ acp_iterator_free */ -+static void apc_iterator_free(void *object TSRMLS_DC) { -+ zend_object_std_dtor(object TSRMLS_CC); -+ efree(object); -+} -+/* }}} */ -+ -+/* {{{ apc_iterator_create */ -+static zend_object_value apc_iterator_create(zend_class_entry *ce TSRMLS_DC) { -+ zend_object_value retval; -+ apc_iterator_t *iterator; -+ -+ iterator = emalloc(sizeof(apc_iterator_t)); -+ iterator->obj.ce = ce; -+ ALLOC_HASHTABLE(iterator->obj.properties); -+ zend_hash_init(iterator->obj.properties, 0, NULL, ZVAL_PTR_DTOR, 0); -+#ifdef ZEND_ENGINE_2_4 -+ iterator->obj.properties_table = NULL; -+#endif -+ iterator->obj.guards = NULL; -+ iterator->initialized = 0; -+ retval.handle = zend_objects_store_put(iterator, apc_iterator_destroy, apc_iterator_free, NULL TSRMLS_CC); -+ retval.handlers = &apc_iterator_object_handlers; -+ -+ return retval; -+} -+/* }}} */ -+ -+/* {{{ apc_iterator_search_match -+ * Verify if the key matches oru search parameters -+ */ -+static int apc_iterator_search_match(apc_iterator_t *iterator, slot_t **slot) { -+ char *key; -+ int key_len; -+ char *fname_key = NULL; -+ int fname_key_len = 0; -+ int rval = 1; -+ -+ if ((*slot)->key.type == APC_CACHE_KEY_FILE) { -+ key = (*slot)->value->data.file.filename; -+ key_len = strlen(key); -+ fname_key_len = spprintf(&fname_key, 0, "%ld %ld", (*slot)->key.data.file.device, (*slot)->key.data.file.inode); -+ } else if ((*slot)->key.type == APC_CACHE_KEY_USER) { -+ key = (char*)(*slot)->key.data.user.identifier; -+ key_len = (*slot)->key.data.user.identifier_len; -+ } else if ((*slot)->key.type == APC_CACHE_KEY_FPFILE) { -+ key = (char*)(*slot)->key.data.fpfile.fullpath; -+ key_len = (*slot)->key.data.fpfile.fullpath_len; -+ } else { -+ return 0; -+ } -+ -+#ifdef ITERATOR_PCRE -+ if (iterator->regex) { -+ rval = (pcre_exec(iterator->re, NULL, key, strlen(key), 0, 0, NULL, 0) >= 0); -+ } -+#endif -+ -+ if (iterator->search_hash) { -+ rval = zend_hash_exists(iterator->search_hash, key, key_len); -+ if (!rval && fname_key) { -+ rval = zend_hash_exists(iterator->search_hash, fname_key, fname_key_len+1); -+ } -+ } -+ -+ return rval; -+} -+/* }}} */ -+ -+/* {{{ apc_iterator_check_expiry */ -+static int apc_iterator_check_expiry(apc_cache_t* cache, slot_t **slot, time_t t) -+{ -+ if((*slot)->value->type == APC_CACHE_ENTRY_USER) { -+ if((*slot)->value->data.user.ttl) { -+ if((time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) { -+ return 0; -+ } -+ } else if(cache->ttl) { -+ if((*slot)->creation_time + cache->ttl < t) { -+ return 0; -+ } -+ } -+ } else if((*slot)->access_time < (t - cache->ttl)) { -+ return 0; -+ } -+ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ apc_iterator_fetch_active */ -+static int apc_iterator_fetch_active(apc_iterator_t *iterator TSRMLS_DC) { -+ int count=0; -+ slot_t **slot; -+ apc_iterator_item_t *item; -+ time_t t; -+ -+ t = apc_time(); -+ -+ while (apc_stack_size(iterator->stack) > 0) { -+ apc_iterator_item_dtor(apc_stack_pop(iterator->stack)); -+ } -+ -+ CACHE_LOCK(iterator->cache); -+ while(count <= iterator->chunk_size && iterator->slot_idx < iterator->cache->num_slots) { -+ slot = &iterator->cache->slots[iterator->slot_idx]; -+ while(*slot) { -+ if (apc_iterator_check_expiry(iterator->cache, slot, t)) { -+ if (apc_iterator_search_match(iterator, slot)) { -+ count++; -+ item = apc_iterator_item_ctor(iterator, slot TSRMLS_CC); -+ if (item) { -+ apc_stack_push(iterator->stack, item TSRMLS_CC); -+ } -+ } -+ } -+ slot = &(*slot)->next; -+ } -+ iterator->slot_idx++; -+ } -+ CACHE_UNLOCK(iterator->cache); -+ iterator->stack_idx = 0; -+ return count; -+} -+/* }}} */ -+ -+/* {{{ apc_iterator_fetch_deleted */ -+static int apc_iterator_fetch_deleted(apc_iterator_t *iterator TSRMLS_DC) { -+ int count=0; -+ slot_t **slot; -+ apc_iterator_item_t *item; -+ -+ CACHE_LOCK(iterator->cache); -+ slot = &iterator->cache->header->deleted_list; -+ while ((*slot) && count <= iterator->slot_idx) { -+ count++; -+ slot = &(*slot)->next; -+ } -+ count = 0; -+ while ((*slot) && count < iterator->chunk_size) { -+ if (apc_iterator_search_match(iterator, slot)) { -+ count++; -+ item = apc_iterator_item_ctor(iterator, slot TSRMLS_CC); -+ if (item) { -+ apc_stack_push(iterator->stack, item TSRMLS_CC); -+ } -+ } -+ slot = &(*slot)->next; -+ } -+ CACHE_UNLOCK(iterator->cache); -+ iterator->slot_idx += count; -+ iterator->stack_idx = 0; -+ return count; -+} -+/* }}} */ -+ -+/* {{{ apc_iterator_totals */ -+static void apc_iterator_totals(apc_iterator_t *iterator TSRMLS_DC) { -+ slot_t **slot; -+ int i; -+ -+ CACHE_LOCK(iterator->cache); -+ for (i=0; i < iterator->cache->num_slots; i++) { -+ slot = &iterator->cache->slots[i]; -+ while((*slot)) { -+ if (apc_iterator_search_match(iterator, slot)) { -+ iterator->size += (*slot)->value->mem_size; -+ iterator->hits += (*slot)->num_hits; -+ iterator->count++; -+ } -+ slot = &(*slot)->next; -+ } -+ } -+ CACHE_UNLOCK(iterator->cache); -+ iterator->totals_flag = 1; -+} -+/* }}} */ -+ -+/* {{{ proto object APCIterator::__costruct(string cache [, mixed search [, long format [, long chunk_size [, long list ]]]]) */ -+PHP_METHOD(apc_iterator, __construct) { -+ zval *object = getThis(); -+ apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(object TSRMLS_CC); -+ char *cachetype; -+ int cachetype_len; -+ long format = APC_ITER_ALL; -+ long chunk_size=0; -+ zval *search = NULL; -+ long list = APC_LIST_ACTIVE; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zlll", &cachetype, &cachetype_len, &search, &format, &chunk_size, &list) == FAILURE) { -+ return; -+ } -+ -+ if (!APCG(enabled)) { -+ apc_error("APC must be enabled to use APCIterator." TSRMLS_CC); -+ } -+ -+ if (chunk_size < 0) { -+ apc_error("APCIterator chunk size must be 0 or greater." TSRMLS_CC); -+ return; -+ } -+ -+ if (format > APC_ITER_ALL) { -+ apc_error("APCIterator format is invalid." TSRMLS_CC); -+ return; -+ } -+ -+ if (list == APC_LIST_ACTIVE) { -+ iterator->fetch = apc_iterator_fetch_active; -+ } else if (list == APC_LIST_DELETED) { -+ iterator->fetch = apc_iterator_fetch_deleted; -+ } else { -+ apc_warning("APCIterator invalid list type." TSRMLS_CC); -+ return; -+ } -+ -+ if(!strcasecmp(cachetype,"user")) { -+ iterator->cache = apc_user_cache; -+ } else { -+ iterator->cache = apc_cache; -+ } -+ -+ iterator->slot_idx = 0; -+ iterator->stack_idx = 0; -+ iterator->key_idx = 0; -+ iterator->chunk_size = chunk_size == 0 ? APC_DEFAULT_CHUNK_SIZE : chunk_size; -+ iterator->stack = apc_stack_create(chunk_size TSRMLS_CC); -+ iterator->format = format; -+ iterator->totals_flag = 0; -+ iterator->count = 0; -+ iterator->size = 0; -+ iterator->hits = 0; -+ iterator->regex = NULL; -+ iterator->regex_len = 0; -+ iterator->search_hash = NULL; -+ if (search && Z_TYPE_P(search) == IS_STRING && Z_STRLEN_P(search)) { -+#ifdef ITERATOR_PCRE -+ iterator->regex = estrndup(Z_STRVAL_P(search), Z_STRLEN_P(search)); -+ iterator->regex_len = Z_STRLEN_P(search); -+ iterator->re = pcre_get_compiled_regex(Z_STRVAL_P(search), NULL, NULL TSRMLS_CC); -+ -+ if(!iterator->re) { -+ apc_error("Could not compile regular expression: %s" TSRMLS_CC, Z_STRVAL_P(search)); -+ } -+#else -+ apc_error("Regular expressions support is not enabled, please enable PCRE for APCIterator regex support" TSRMLS_CC); -+#endif -+ } else if (search && Z_TYPE_P(search) == IS_ARRAY) { -+ Z_ADDREF_P(search); -+ iterator->search_hash = apc_flip_hash(Z_ARRVAL_P(search)); -+ } -+ iterator->initialized = 1; -+} -+/* }}} */ -+ -+/* {{{ proto APCIterator::rewind() */ -+PHP_METHOD(apc_iterator, rewind) { -+ apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC); -+ -+ if (zend_parse_parameters_none() == FAILURE) { -+ return; -+ } -+ -+ if (iterator->initialized == 0) { -+ RETURN_FALSE; -+ } -+ -+ iterator->slot_idx = 0; -+ iterator->stack_idx = 0; -+ iterator->key_idx = 0; -+ iterator->fetch(iterator TSRMLS_CC); -+} -+/* }}} */ -+ -+/* {{{ proto boolean APCIterator::valid() */ -+PHP_METHOD(apc_iterator, valid) { -+ apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC); -+ -+ if (zend_parse_parameters_none() == FAILURE) { -+ return; -+ } -+ -+ if (iterator->initialized == 0) { -+ RETURN_FALSE; -+ } -+ -+ if (apc_stack_size(iterator->stack) == iterator->stack_idx) { -+ iterator->fetch(iterator TSRMLS_CC); -+ } -+ -+ RETURN_BOOL(apc_stack_size(iterator->stack) == 0 ? 0 : 1); -+} -+/* }}} */ -+ -+/* {{{ proto mixed APCIterator::current() */ -+PHP_METHOD(apc_iterator, current) { -+ apc_iterator_item_t *item; -+ apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC); -+ -+ if (zend_parse_parameters_none() == FAILURE) { -+ return; -+ } -+ -+ if (iterator->initialized == 0) { -+ RETURN_FALSE; -+ } -+ -+ if (apc_stack_size(iterator->stack) == iterator->stack_idx) { -+ if (iterator->fetch(iterator TSRMLS_CC) == 0) { -+ RETURN_FALSE; -+ } -+ } -+ -+ item = apc_stack_get(iterator->stack, iterator->stack_idx); -+ RETURN_ZVAL(item->value, 1, 0); -+} -+/* }}} */ -+ -+/* {{{ proto string APCIterator::key() */ -+PHP_METHOD(apc_iterator, key) { -+ apc_iterator_item_t *item; -+ apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC); -+ -+ if (zend_parse_parameters_none() == FAILURE) { -+ return; -+ } -+ -+ if (iterator->initialized == 0 || apc_stack_size(iterator->stack) == 0) { -+ RETURN_FALSE; -+ } -+ -+ if (apc_stack_size(iterator->stack) == iterator->stack_idx) { -+ if (iterator->fetch(iterator TSRMLS_CC) == 0) { -+ RETURN_FALSE; -+ } -+ } -+ -+ item = apc_stack_get(iterator->stack, iterator->stack_idx); -+ -+ if (item->key) { -+ RETURN_STRINGL(item->key, (item->key_len-1), 1); -+ } else { -+ RETURN_LONG(iterator->key_idx); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto APCIterator::next() */ -+PHP_METHOD(apc_iterator, next) { -+ apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC); -+ -+ if (zend_parse_parameters_none() == FAILURE) { -+ return; -+ } -+ -+ if (iterator->initialized == 0 || apc_stack_size(iterator->stack) == 0) { -+ RETURN_FALSE; -+ } -+ -+ iterator->stack_idx++; -+ iterator->key_idx++; -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto long APCIterator::getTotalHits() */ -+PHP_METHOD(apc_iterator, getTotalHits) { -+ apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC); -+ -+ if (zend_parse_parameters_none() == FAILURE) { -+ return; -+ } -+ -+ if (iterator->initialized == 0) { -+ RETURN_FALSE; -+ } -+ -+ if (iterator->totals_flag == 0) { -+ apc_iterator_totals(iterator TSRMLS_CC); -+ } -+ -+ RETURN_LONG(iterator->hits); -+} -+/* }}} */ -+ -+/* {{{ proto long APCIterator::getTotalSize() */ -+PHP_METHOD(apc_iterator, getTotalSize) { -+ apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC); -+ -+ if (zend_parse_parameters_none() == FAILURE) { -+ return; -+ } -+ -+ if (iterator->initialized == 0) { -+ RETURN_FALSE; -+ } -+ -+ if (iterator->totals_flag == 0) { -+ apc_iterator_totals(iterator TSRMLS_CC); -+ } -+ -+ RETURN_LONG(iterator->size); -+} -+/* }}} */ -+ -+/* {{{ proto long APCIterator::getTotalCount() */ -+PHP_METHOD(apc_iterator, getTotalCount) { -+ apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(getThis() TSRMLS_CC); -+ -+ if (zend_parse_parameters_none() == FAILURE) { -+ return; -+ } -+ -+ if (iterator->initialized == 0) { -+ RETURN_FALSE; -+ } -+ -+ if (iterator->totals_flag == 0) { -+ apc_iterator_totals(iterator TSRMLS_CC); -+ } -+ -+ RETURN_LONG(iterator->count); -+} -+/* }}} */ -+ -+/* {{{ arginfo */ -+#if (PHP_MAJOR_VERSION >= 6 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3)) -+# define PHP_APC_ARGINFO -+#else -+# define PHP_APC_ARGINFO static -+#endif -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_iterator___construct, 0, 0, 1) -+ ZEND_ARG_INFO(0, cache) -+ ZEND_ARG_INFO(0, search) -+ ZEND_ARG_INFO(0, format) -+ ZEND_ARG_INFO(0, chunk_size) -+ ZEND_ARG_INFO(0, list) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_iterator_void, 0, 0, 0) -+ZEND_END_ARG_INFO() -+/* }}} */ -+ -+/* {{{ apc_iterator_functions */ -+static zend_function_entry apc_iterator_functions[] = { -+ PHP_ME(apc_iterator, __construct, arginfo_apc_iterator___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) -+ PHP_ME(apc_iterator, rewind, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC) -+ PHP_ME(apc_iterator, current, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC) -+ PHP_ME(apc_iterator, key, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC) -+ PHP_ME(apc_iterator, next, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC) -+ PHP_ME(apc_iterator, valid, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC) -+ PHP_ME(apc_iterator, getTotalHits, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC) -+ PHP_ME(apc_iterator, getTotalSize, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC) -+ PHP_ME(apc_iterator, getTotalCount, arginfo_apc_iterator_void, ZEND_ACC_PUBLIC) -+ {NULL, NULL, NULL} -+}; -+/* }}} */ -+ -+/* {{{ apc_iterator_init */ -+int apc_iterator_init(int module_number TSRMLS_DC) { -+ zend_class_entry ce; -+ -+ INIT_CLASS_ENTRY(ce, APC_ITERATOR_NAME, apc_iterator_functions); -+ apc_iterator_ce = zend_register_internal_class(&ce TSRMLS_CC); -+ apc_iterator_ce->create_object = apc_iterator_create; -+ zend_class_implements(apc_iterator_ce TSRMLS_CC, 1, zend_ce_iterator); -+ -+ zend_register_long_constant("APC_LIST_ACTIVE", sizeof("APC_LIST_ACTIVE"), APC_LIST_ACTIVE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_LIST_DELETED", sizeof("APC_LIST_DELETED"), APC_LIST_DELETED, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ -+ zend_register_long_constant("APC_ITER_TYPE", sizeof("APC_ITER_TYPE"), APC_ITER_TYPE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_KEY", sizeof("APC_ITER_KEY"), APC_ITER_KEY, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_FILENAME", sizeof("APC_ITER_FILENAME"), APC_ITER_FILENAME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_DEVICE", sizeof("APC_ITER_DEVICE"), APC_ITER_DEVICE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_INODE", sizeof("APC_ITER_INODE"), APC_ITER_INODE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_VALUE", sizeof("APC_ITER_VALUE"), APC_ITER_VALUE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_MD5", sizeof("APC_ITER_MD5"), APC_ITER_MD5, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_NUM_HITS", sizeof("APC_ITER_NUM_HITS"), APC_ITER_NUM_HITS, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_MTIME", sizeof("APC_ITER_MTIME"), APC_ITER_MTIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_CTIME", sizeof("APC_ITER_CTIME"), APC_ITER_CTIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_DTIME", sizeof("APC_ITER_DTIME"), APC_ITER_DTIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_ATIME", sizeof("APC_ITER_ATIME"), APC_ITER_ATIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_REFCOUNT", sizeof("APC_ITER_REFCOUNT"), APC_ITER_REFCOUNT, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_MEM_SIZE", sizeof("APC_ITER_MEM_SIZE"), APC_ITER_MEM_SIZE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_TTL", sizeof("APC_ITER_TTL"), APC_ITER_TTL, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_NONE", sizeof("APC_ITER_NONE"), APC_ITER_NONE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ zend_register_long_constant("APC_ITER_ALL", sizeof("APC_ITER_ALL"), APC_ITER_ALL, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC); -+ -+ memcpy(&apc_iterator_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); -+ apc_iterator_object_handlers.clone_obj = apc_iterator_clone; -+ -+ return SUCCESS; -+} -+/* }}} */ -+ -+ -+int apc_iterator_delete(zval *zobj TSRMLS_DC) { -+ apc_iterator_t *iterator; -+ zend_class_entry *ce = Z_OBJCE_P(zobj); -+ apc_iterator_item_t *item; -+ -+ if (!ce || !instanceof_function(ce, apc_iterator_ce TSRMLS_CC)) { -+ apc_error("apc_delete object argument must be instance of APCIterator" TSRMLS_CC); -+ return 0; -+ } -+ iterator = (apc_iterator_t*)zend_object_store_get_object(zobj TSRMLS_CC); -+ -+ if (iterator->initialized == 0) { -+ return 0; -+ } -+ -+ while (iterator->fetch(iterator TSRMLS_CC)) { -+ while (iterator->stack_idx < apc_stack_size(iterator->stack)) { -+ item = apc_stack_get(iterator->stack, iterator->stack_idx++); -+ if (iterator->cache == apc_cache) { -+ apc_cache_delete(apc_cache, item->filename_key, strlen(item->filename_key) + 1 TSRMLS_CC); -+ } else { -+ apc_cache_user_delete(apc_user_cache, item->key, item->key_len TSRMLS_CC); -+ } -+ } -+ } -+ -+ return 1; -+} -+ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_iterator.h b/ext/apc/apc_iterator.h ---- a/ext/apc/apc_iterator.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_iterator.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,117 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Brian Shire | -+ +----------------------------------------------------------------------+ -+ -+ */ -+ -+/* $Id: apc_iterator.h 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#ifndef APC_ITERATOR_H -+#define APC_ITERATOR_H -+ -+#include "apc.h" -+#include "apc_stack.h" -+ -+#if HAVE_PCRE || HAVE_BUNDLED_PCRE -+/* Deal with problem present until php-5.2.2 where php_pcre.h was not installed correctly */ -+# if !HAVE_BUNDLED_PCRE && PHP_MAJOR_VERSION == 5 && (PHP_MINOR_VERSION < 2 || (PHP_MINOR_VERSION == 2 && PHP_RELEASE_VERSION < 2)) -+# include "apc_php_pcre.h" -+# else -+# include "ext/pcre/php_pcre.h" -+# endif -+# include "ext/standard/php_smart_str.h" -+# define ITERATOR_PCRE 1 -+#endif -+ -+ -+#define APC_ITERATOR_NAME "APCIterator" -+ -+#define APC_DEFAULT_CHUNK_SIZE 100 -+ -+#define APC_LIST_ACTIVE 0x1 -+#define APC_LIST_DELETED 0x2 -+ -+#define APC_ITER_TYPE (1L << 0) -+#define APC_ITER_KEY (1L << 1) -+#define APC_ITER_FILENAME (1L << 2) -+#define APC_ITER_DEVICE (1L << 3) -+#define APC_ITER_INODE (1L << 4) -+#define APC_ITER_VALUE (1L << 5) -+#define APC_ITER_MD5 (1L << 6) -+#define APC_ITER_NUM_HITS (1L << 7) -+#define APC_ITER_MTIME (1L << 8) -+#define APC_ITER_CTIME (1L << 9) -+#define APC_ITER_DTIME (1L << 10) -+#define APC_ITER_ATIME (1L << 11) -+#define APC_ITER_REFCOUNT (1L << 12) -+#define APC_ITER_MEM_SIZE (1L << 13) -+#define APC_ITER_TTL (1L << 14) -+ -+#define APC_ITER_NONE (0x00000000L) -+#define APC_ITER_ALL (0xffffffffL) -+ -+typedef void* (*apc_iterator_item_cb_t)(slot_t **slot); -+ -+ -+/* {{{ apc_iterator_t */ -+typedef struct _apc_iterator_t { -+ zend_object obj; /* must always be first */ -+ short int initialized; /* sanity check in case __construct failed */ -+ long format; /* format bitmask of the return values ie: key, value, info */ -+ int (*fetch)(struct _apc_iterator_t *iterator TSRMLS_DC); -+ /* fetch callback to fetch items from cache slots or lists */ -+ apc_cache_t *cache; /* cache which we are iterating on */ -+ long slot_idx; /* index to the slot array or linked list */ -+ long chunk_size; /* number of entries to pull down per fetch */ -+ apc_stack_t *stack; /* stack of entries pulled from cache */ -+ int stack_idx; /* index into the current stack */ -+#ifdef ITERATOR_PCRE -+ pcre *re; /* regex filter on entry identifiers */ -+#endif -+ char *regex; /* original regex expression or NULL */ -+ int regex_len; /* regex length */ -+ HashTable *search_hash; /* hash of keys to iterate over */ -+ long key_idx; /* incrementing index for numerical keys */ -+ short int totals_flag; /* flag if totals have been calculated */ -+ long hits; /* hit total */ -+ size_t size; /* size total */ -+ long count; /* count total */ -+} apc_iterator_t; -+/* }}} */ -+ -+/* {{{ apc_iterator_item */ -+typedef struct _apc_iterator_item_t { -+ char *key; /* string key */ -+ long key_len; /* strlen of key */ -+ char *filename_key; /* filename key used for deletion */ -+ zval *value; -+} apc_iterator_item_t; -+/* }}} */ -+ -+ -+extern int apc_iterator_init(int module_number TSRMLS_DC); -+extern int apc_iterator_delete(zval *zobj TSRMLS_DC); -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_lock.h b/ext/apc/apc_lock.h ---- a/ext/apc/apc_lock.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_lock.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,160 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: George Schlossnagle | -+ | Rasmus Lerdorf | -+ | Pierre Joye | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_lock.h 311339 2011-05-22 17:18:49Z gopalv $ */ -+ -+#ifndef APC_LOCK -+#define APC_LOCK -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include "apc.h" -+#include "apc_sem.h" -+#include "apc_fcntl.h" -+#include "apc_pthreadmutex.h" -+#include "apc_pthreadrwlock.h" -+#include "apc_spin.h" -+#include "apc_windows_srwlock_kernel.h" -+ -+/* {{{ generic locking macros */ -+#define CREATE_LOCK(lock) apc_lck_create(NULL, 0, 1, lock) -+#define DESTROY_LOCK(lock) apc_lck_destroy(lock) -+#define LOCK(lock) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(lock); } -+#define RDLOCK(lock) { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(lock); } -+#define UNLOCK(lock) { apc_lck_unlock(lock); HANDLE_UNBLOCK_INTERRUPTIONS(); } -+#define RDUNLOCK(lock) { apc_lck_rdunlock(lock); HANDLE_UNBLOCK_INTERRUPTIONS(); } -+/* }}} */ -+ -+/* atomic operations : rdlocks are impossible without these */ -+#if HAVE_ATOMIC_OPERATIONS -+# ifdef PHP_WIN32 -+# define ATOMIC_INC(a) InterlockedIncrement(&a) -+# define ATOMIC_DEC(a) InterlockedDecrement(&a) -+# else -+# define ATOMIC_INC(a) __sync_add_and_fetch(&a, 1) -+# define ATOMIC_DEC(a) __sync_sub_and_fetch(&a, 1) -+# endif -+#endif -+ -+#if defined(APC_SEM_LOCKS) -+# define APC_LOCK_TYPE "IPC Semaphore" -+# define RDLOCK_AVAILABLE 0 -+# define NONBLOCKING_LOCK_AVAILABLE 1 -+# define apc_lck_t int -+# define apc_lck_create(a,b,c,d) d=apc_sem_create((b),(c) TSRMLS_CC) -+# define apc_lck_destroy(a) apc_sem_destroy(a) -+# define apc_lck_lock(a) apc_sem_lock(a TSRMLS_CC) -+# define apc_lck_nb_lock(a) apc_sem_nonblocking_lock(a TSRMLS_CC) -+# define apc_lck_rdlock(a) apc_sem_lock(a TSRMLS_CC) -+# define apc_lck_unlock(a) apc_sem_unlock(a TSRMLS_CC) -+# define apc_lck_rdunlock(a) apc_sem_unlock(a TSRMLS_CC) -+#elif defined(APC_PTHREADMUTEX_LOCKS) -+# define APC_LOCK_TYPE "pthread mutex Locks" -+# define RDLOCK_AVAILABLE 0 -+# define NONBLOCKING_LOCK_AVAILABLE 1 -+# define apc_lck_t pthread_mutex_t -+# define apc_lck_create(a,b,c,d) apc_pthreadmutex_create((pthread_mutex_t*)&d TSRMLS_CC) -+# define apc_lck_destroy(a) apc_pthreadmutex_destroy(&a) -+# define apc_lck_lock(a) apc_pthreadmutex_lock(&a TSRMLS_CC) -+# define apc_lck_nb_lock(a) apc_pthreadmutex_nonblocking_lock(&a TSRMLS_CC) -+# define apc_lck_rdlock(a) apc_pthreadmutex_lock(&a TSRMLS_CC) -+# define apc_lck_unlock(a) apc_pthreadmutex_unlock(&a TSRMLS_CC) -+# define apc_lck_rdunlock(a) apc_pthreadmutex_unlock(&a TSRMLS_CC) -+#elif defined(APC_PTHREADRW_LOCKS) -+# define APC_LOCK_TYPE "pthread read/write Locks" -+# define RDLOCK_AVAILABLE 1 -+# define NONBLOCKING_LOCK_AVAILABLE 1 -+# define apc_lck_t pthread_rwlock_t -+# define apc_lck_create(a,b,c,d) apc_pthreadrwlock_create((pthread_rwlock_t*)&d TSRMLS_CC) -+# define apc_lck_destroy(a) apc_pthreadrwlock_destroy(&a) -+# define apc_lck_lock(a) apc_pthreadrwlock_lock(&a TSRMLS_CC) -+# define apc_lck_nb_lock(a) apc_pthreadrwlock_nonblocking_lock(&a TSRMLS_CC) -+# define apc_lck_rdlock(a) apc_pthreadrwlock_rdlock(&a TSRMLS_CC) -+# define apc_lck_unlock(a) apc_pthreadrwlock_unlock(&a TSRMLS_CC) -+# define apc_lck_rdunlock(a) apc_pthreadrwlock_unlock(&a TSRMLS_CC) -+#elif defined(APC_SPIN_LOCKS) -+# define APC_LOCK_TYPE "spin Locks" -+# define RDLOCK_AVAILABLE 0 -+# define NONBLOCKING_LOCK_AVAILABLE APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE -+# define apc_lck_t slock_t -+# define apc_lck_create(a,b,c,d) apc_slock_create((slock_t*)&(d)) -+# define apc_lck_destroy(a) apc_slock_destroy(&a) -+# define apc_lck_lock(a) apc_slock_lock(&a TSRMLS_CC) -+# define apc_lck_nb_lock(a) apc_slock_nonblocking_lock(&a) -+# define apc_lck_rdlock(a) apc_slock_lock(&a TSRMLS_CC) -+# define apc_lck_unlock(a) apc_slock_unlock(&a) -+# define apc_lck_rdunlock(a) apc_slock_unlock(&a) -+#elif defined(APC_SRWLOCK_NATIVE) && defined(PHP_WIN32) -+# define APC_LOCK_TYPE "Windows Slim RWLOCK (native)" -+# define RDLOCK_AVAILABLE 1 -+# define NONBLOCKING_LOCK_AVAILABLE 0 -+# define apc_lck_t SRWLOCK -+# define apc_lck_create(a,b,c,d) InitializeSRWLock((SRWLOCK*)&(d)) -+# define apc_lck_destroy(a) -+# define apc_lck_lock(a) AcquireSRWLockExclusive(&a) -+# define apc_lck_rdlock(a) AcquireSRWLockShared(&a) -+# define apc_lck_unlock(a) ReleaseSRWLockExclusive(&a) -+# define apc_lck_rdunlock(a) ReleaseSRWLockShared(&a) -+# if NONBLOCKING_LOCK_AVAILABLE==1 /* Only in win7/2008 */ -+# define apc_lck_nb_lock(a) (TryAcquireSRWLockExclusive(&a TSRMLS_CC) == 0 ? 1 : 0); -+# endif -+#elif defined(APC_SRWLOCK_KERNEL) && defined(PHP_WIN32) -+# define APC_LOCK_TYPE "Windows Slim RWLOCK (kernel)" -+# define RDLOCK_AVAILABLE 1 -+# define NONBLOCKING_LOCK_AVAILABLE 0 -+# define apc_lck_t apc_windows_cs_rwlock_t -+# define apc_lck_create(a,b,c,d) apc_windows_cs_create((apc_windows_cs_rwlock_t*)&(d) TSRMLS_CC) -+# define apc_lck_destroy(a) apc_windows_cs_destroy(&a); -+# define apc_lck_lock(a) apc_windows_cs_lock(&a TSRMLS_CC) -+# define apc_lck_rdlock(a) apc_windows_cs_rdlock(&a TSRMLS_CC) -+# define apc_lck_unlock(a) apc_windows_cs_unlock_wr(&a TSRMLS_CC) -+# define apc_lck_rdunlock(a) apc_windows_cs_unlock_rd(&a TSRMLS_CC) -+#else -+# define APC_LOCK_TYPE "File Locks" -+# ifdef HAVE_ATOMIC_OPERATIONS -+# define RDLOCK_AVAILABLE 1 -+# endif -+# ifdef PHP_WIN32 -+# define NONBLOCKING_LOCK_AVAILABLE 0 -+# else -+# define NONBLOCKING_LOCK_AVAILABLE 1 -+# endif -+# define apc_lck_t int -+# define apc_lck_create(a,b,c,d) d=apc_fcntl_create((a) TSRMLS_CC) -+# define apc_lck_destroy(a) apc_fcntl_destroy(a) -+# define apc_lck_lock(a) apc_fcntl_lock(a TSRMLS_CC) -+# define apc_lck_nb_lock(a) apc_fcntl_nonblocking_lock(a TSRMLS_CC) -+# define apc_lck_rdlock(a) apc_fcntl_rdlock(a TSRMLS_CC) -+# define apc_lck_unlock(a) apc_fcntl_unlock(a TSRMLS_CC) -+# define apc_lck_rdunlock(a) apc_fcntl_unlock(a TSRMLS_CC) -+#endif -+ -+#endif -diff -Naur a/ext/apc/apc_main.c b/ext/apc/apc_main.c ---- a/ext/apc/apc_main.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_main.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,1030 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | Rasmus Lerdorf | -+ | Arun C. Murthy | -+ | Gopal Vijayaraghavan | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_main.c 324326 2012-03-18 13:19:50Z pajoye $ */ -+ -+#include "apc_php.h" -+#include "apc_main.h" -+#include "apc.h" -+#include "apc_lock.h" -+#include "apc_cache.h" -+#include "apc_compile.h" -+#include "apc_globals.h" -+#include "apc_sma.h" -+#include "apc_stack.h" -+#include "apc_zend.h" -+#include "apc_pool.h" -+#include "apc_string.h" -+#include "SAPI.h" -+#include "php_scandir.h" -+#include "ext/standard/php_var.h" -+#include "ext/standard/md5.h" -+ -+#define APC_MAX_SERIALIZERS 16 -+ -+/* {{{ module variables */ -+ -+/* pointer to the original Zend engine compile_file function */ -+typedef zend_op_array* (zend_compile_t)(zend_file_handle*, int TSRMLS_DC); -+static zend_compile_t *old_compile_file; -+static apc_serializer_t apc_serializers[APC_MAX_SERIALIZERS] = {{0,}}; -+ -+/* }}} */ -+ -+/* {{{ get/set old_compile_file (to interact with other extensions that need the compile hook) */ -+static zend_compile_t* set_compile_hook(zend_compile_t *ptr) -+{ -+ zend_compile_t *retval = old_compile_file; -+ -+ if (ptr != NULL) old_compile_file = ptr; -+ return retval; -+} -+/* }}} */ -+ -+/* {{{ install_function */ -+static int install_function(apc_function_t fn, apc_context_t* ctxt, int lazy TSRMLS_DC) -+{ -+ int status; -+ -+#if APC_HAVE_LOOKUP_HOOKS -+ if(lazy && fn.name[0] != '\0' && strncmp(fn.name, "__autoload", fn.name_len) != 0) { -+ status = zend_hash_add(APCG(lazy_function_table), -+ fn.name, -+ fn.name_len+1, -+ &fn, -+ sizeof(apc_function_t), -+ NULL); -+#else -+ if(0) { -+#endif -+ } else { -+ zend_function *func = apc_copy_function_for_execution(fn.function, ctxt TSRMLS_CC); -+ status = zend_hash_add(EG(function_table), -+ fn.name, -+ fn.name_len+1, -+ func, -+ sizeof(fn.function[0]), -+ NULL); -+ efree(func); -+ } -+ -+ if (status == FAILURE) { -+ /* apc_error("Cannot redeclare %s()" TSRMLS_CC, fn.name); */ -+ } -+ -+ return status; -+} -+/* }}} */ -+ -+/* {{{ apc_lookup_function_hook */ -+int apc_lookup_function_hook(char *name, int len, ulong hash, zend_function **fe) { -+ apc_function_t *fn; -+ int status = FAILURE; -+ apc_context_t ctxt = {0,}; -+ TSRMLS_FETCH(); -+ -+ ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, apc_sma_protect, apc_sma_unprotect TSRMLS_CC); -+ ctxt.copy = APC_COPY_OUT_OPCODE; -+ -+ if(zend_hash_quick_find(APCG(lazy_function_table), name, len, hash, (void**)&fn) == SUCCESS) { -+ *fe = apc_copy_function_for_execution(fn->function, &ctxt TSRMLS_CC); -+ status = zend_hash_add(EG(function_table), -+ fn->name, -+ fn->name_len+1, -+ *fe, -+ sizeof(zend_function), -+ NULL); -+ } -+ -+ return status; -+} -+/* }}} */ -+ -+/* {{{ install_class */ -+static int install_class(apc_class_t cl, apc_context_t* ctxt, int lazy TSRMLS_DC) -+{ -+ zend_class_entry* class_entry = cl.class_entry; -+ zend_class_entry* parent = NULL; -+ int status; -+ zend_class_entry** allocated_ce = NULL; -+ -+ /* Special case for mangled names. Mangled names are unique to a file. -+ * There is no way two classes with the same mangled name will occur, -+ * unless a file is included twice. And if in case, a file is included -+ * twice, all mangled name conflicts can be ignored and the class redeclaration -+ * error may be deferred till runtime of the corresponding DECLARE_CLASS -+ * calls. -+ */ -+ -+ if(cl.name_len != 0 && cl.name[0] == '\0') { -+ if(zend_hash_exists(CG(class_table), cl.name, cl.name_len+1)) { -+ return SUCCESS; -+ } -+ } -+ -+ if(lazy && cl.name_len != 0 && cl.name[0] != '\0') { -+ status = zend_hash_add(APCG(lazy_class_table), -+ cl.name, -+ cl.name_len+1, -+ &cl, -+ sizeof(apc_class_t), -+ NULL); -+ if(status == FAILURE) { -+ zend_error(E_ERROR, "Cannot redeclare class %s", cl.name); -+ } -+ return status; -+ } -+ -+ /* -+ * XXX: We need to free this somewhere... -+ */ -+ allocated_ce = apc_php_malloc(sizeof(zend_class_entry*) TSRMLS_CC); -+ -+ if(!allocated_ce) { -+ return FAILURE; -+ } -+ -+ *allocated_ce = -+ class_entry = -+ apc_copy_class_entry_for_execution(cl.class_entry, ctxt TSRMLS_CC); -+ -+ -+ /* restore parent class pointer for compile-time inheritance */ -+ if (cl.parent_name != NULL) { -+ zend_class_entry** parent_ptr = NULL; -+ /* -+ * __autoload brings in the old issues with mixed inheritance. -+ * When a statically inherited class triggers autoload, it runs -+ * afoul of a potential require_once "parent.php" in the previous -+ * line, which when executed provides the parent class, but right -+ * now goes and hits __autoload which could fail. -+ * -+ * missing parent == re-compile. -+ * -+ * whether __autoload is enabled or not, because __autoload errors -+ * cause php to die. -+ * -+ * Aside: Do NOT pass *strlen(cl.parent_name)+1* because -+ * zend_lookup_class_ex does it internally anyway! -+ */ -+ status = zend_lookup_class_ex(cl.parent_name, -+ strlen(cl.parent_name), -+#ifdef ZEND_ENGINE_2_4 -+ NULL, -+#endif -+ 0, -+ &parent_ptr TSRMLS_CC); -+ if (status == FAILURE) { -+ if(APCG(report_autofilter)) { -+ apc_warning("Dynamic inheritance detected for class %s" TSRMLS_CC, cl.name); -+ } -+ class_entry->parent = NULL; -+ return status; -+ } -+ else { -+ parent = *parent_ptr; -+ class_entry->parent = parent; -+ zend_do_inheritance(class_entry, parent TSRMLS_CC); -+ } -+ -+ -+ } -+ -+ status = zend_hash_add(EG(class_table), -+ cl.name, -+ cl.name_len+1, -+ allocated_ce, -+ sizeof(zend_class_entry*), -+ NULL); -+ -+ if (status == FAILURE) { -+ apc_error("Cannot redeclare class %s" TSRMLS_CC, cl.name); -+ } -+ return status; -+} -+/* }}} */ -+ -+/* {{{ apc_lookup_class_hook */ -+int apc_lookup_class_hook(char *name, int len, ulong hash, zend_class_entry ***ce) { -+ -+ apc_class_t *cl; -+ apc_context_t ctxt = {0,}; -+ TSRMLS_FETCH(); -+ -+ if(zend_is_compiling(TSRMLS_C)) { return FAILURE; } -+ -+ if(zend_hash_quick_find(APCG(lazy_class_table), name, len, hash, (void**)&cl) == FAILURE) { -+ return FAILURE; -+ } -+ -+ ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, apc_sma_protect, apc_sma_unprotect TSRMLS_CC); -+ ctxt.copy = APC_COPY_OUT_OPCODE; -+ -+ if(install_class(*cl, &ctxt, 0 TSRMLS_CC) == FAILURE) { -+ apc_warning("apc_lookup_class_hook: could not install %s" TSRMLS_CC, name); -+ return FAILURE; -+ } -+ -+ if(zend_hash_quick_find(EG(class_table), name, len, hash, (void**)ce) == FAILURE) { -+ apc_warning("apc_lookup_class_hook: known error trying to fetch class %s" TSRMLS_CC, name); -+ return FAILURE; -+ } -+ -+ return SUCCESS; -+ -+} -+/* }}} */ -+ -+/* {{{ uninstall_class */ -+static int uninstall_class(apc_class_t cl TSRMLS_DC) -+{ -+ int status; -+ -+ status = zend_hash_del(EG(class_table), -+ cl.name, -+ cl.name_len+1); -+ if (status == FAILURE) { -+ apc_error("Cannot delete class %s" TSRMLS_CC, cl.name); -+ } -+ return status; -+} -+/* }}} */ -+ -+/* {{{ copy_function_name (taken from zend_builtin_functions.c to ensure future compatibility with APC) */ -+static int copy_function_name(apc_function_t *pf TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) -+{ -+ zval *internal_ar = va_arg(args, zval *), -+ *user_ar = va_arg(args, zval *); -+ zend_function *func = pf->function; -+ -+ if (hash_key->nKeyLength == 0 || hash_key->arKey[0] == 0) { -+ return 0; -+ } -+ -+ if (func->type == ZEND_INTERNAL_FUNCTION) { -+ add_next_index_stringl(internal_ar, hash_key->arKey, hash_key->nKeyLength-1, 1); -+ } else if (func->type == ZEND_USER_FUNCTION) { -+ add_next_index_stringl(user_ar, hash_key->arKey, hash_key->nKeyLength-1, 1); -+ } -+ -+ return 0; -+} -+ -+/* {{{ copy_class_or_interface_name (taken from zend_builtin_functions.c to ensure future compatibility with APC) */ -+static int copy_class_or_interface_name(apc_class_t *cl TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) -+{ -+ zval *array = va_arg(args, zval *); -+ zend_uint mask = va_arg(args, zend_uint); -+ zend_uint comply = va_arg(args, zend_uint); -+ zend_uint comply_mask = (comply)? mask:0; -+ zend_class_entry *ce = cl->class_entry; -+ -+ if ((hash_key->nKeyLength==0 || hash_key->arKey[0]!=0) -+ && (comply_mask == (ce->ce_flags & mask))) { -+ add_next_index_stringl(array, ce->name, ce->name_length, 1); -+ } -+ return ZEND_HASH_APPLY_KEEP; -+} -+/* }}} */ -+ -+/* }}} */ -+ -+/* {{{ apc_defined_function_hook */ -+int apc_defined_function_hook(zval *internal, zval *user) { -+ TSRMLS_FETCH(); -+ zend_hash_apply_with_arguments(APCG(lazy_function_table) -+#ifdef ZEND_ENGINE_2_3 -+ TSRMLS_CC -+#endif -+ ,(apply_func_args_t) copy_function_name, 2, internal, user); -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ apc_declared_class_hook */ -+int apc_declared_class_hook(zval *classes, zend_uint mask, zend_uint comply) { -+ TSRMLS_FETCH(); -+ zend_hash_apply_with_arguments(APCG(lazy_class_table) -+#ifdef ZEND_ENGINE_2_3 -+ TSRMLS_CC -+#endif -+ , (apply_func_args_t) copy_class_or_interface_name, 3, classes, mask, comply); -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ cached_compile */ -+static zend_op_array* cached_compile(zend_file_handle* h, -+ int type, -+ apc_context_t* ctxt TSRMLS_DC) -+{ -+ apc_cache_entry_t* cache_entry; -+ int i, ii; -+ -+ cache_entry = (apc_cache_entry_t*) apc_stack_top(APCG(cache_stack)); -+ assert(cache_entry != NULL); -+ -+ if (cache_entry->data.file.classes) { -+ int lazy_classes = APCG(lazy_classes); -+ for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) { -+ if(install_class(cache_entry->data.file.classes[i], ctxt, lazy_classes TSRMLS_CC) == FAILURE) { -+ goto default_compile; -+ } -+ } -+ } -+ -+ if (cache_entry->data.file.functions) { -+ int lazy_functions = APCG(lazy_functions); -+ for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) { -+ install_function(cache_entry->data.file.functions[i], ctxt, lazy_functions TSRMLS_CC); -+ } -+ } -+ -+ apc_do_halt_compiler_register(cache_entry->data.file.filename, cache_entry->data.file.halt_offset TSRMLS_CC); -+ -+ -+ return apc_copy_op_array_for_execution(NULL, cache_entry->data.file.op_array, ctxt TSRMLS_CC); -+ -+default_compile: -+ -+ if(cache_entry->data.file.classes) { -+ for(ii = 0; ii < i ; ii++) { -+ uninstall_class(cache_entry->data.file.classes[ii] TSRMLS_CC); -+ } -+ } -+ -+ apc_stack_pop(APCG(cache_stack)); /* pop out cache_entry */ -+ -+ apc_cache_release(apc_cache, cache_entry TSRMLS_CC); -+ -+ /* cannot free up cache data yet, it maybe in use */ -+ -+ return NULL; -+} -+/* }}} */ -+ -+/* {{{ apc_compile_cache_entry */ -+zend_bool apc_compile_cache_entry(apc_cache_key_t *key, zend_file_handle* h, int type, time_t t, zend_op_array** op_array, apc_cache_entry_t** cache_entry TSRMLS_DC) { -+ int num_functions, num_classes; -+ apc_function_t* alloc_functions; -+ zend_op_array* alloc_op_array; -+ apc_class_t* alloc_classes; -+ char *path; -+ apc_context_t ctxt; -+ -+ /* remember how many functions and classes existed before compilation */ -+ num_functions = zend_hash_num_elements(CG(function_table)); -+ num_classes = zend_hash_num_elements(CG(class_table)); -+ -+ /* compile the file using the default compile function, * -+ * we set *op_array here so we return opcodes during * -+ * a failure. We should not return prior to this line. */ -+ *op_array = old_compile_file(h, type TSRMLS_CC); -+ if (*op_array == NULL) { -+ return FAILURE; -+ } -+ -+ ctxt.pool = apc_pool_create(APC_MEDIUM_POOL, apc_sma_malloc, apc_sma_free, -+ apc_sma_protect, apc_sma_unprotect TSRMLS_CC); -+ if (!ctxt.pool) { -+ apc_warning("Unable to allocate memory for pool." TSRMLS_CC); -+ return FAILURE; -+ } -+ ctxt.copy = APC_COPY_IN_OPCODE; -+ -+ if(APCG(file_md5)) { -+ int n; -+ unsigned char buf[1024]; -+ PHP_MD5_CTX context; -+ php_stream *stream; -+ char *filename; -+ -+ if(h->opened_path) { -+ filename = h->opened_path; -+ } else { -+ filename = h->filename; -+ } -+ stream = php_stream_open_wrapper(filename, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL); -+ if(stream) { -+ PHP_MD5Init(&context); -+ while((n = php_stream_read(stream, (char*)buf, sizeof(buf))) > 0) { -+ PHP_MD5Update(&context, buf, n); -+ } -+ PHP_MD5Final(key->md5, &context); -+ php_stream_close(stream); -+ if(n<0) { -+ apc_warning("Error while reading '%s' for md5 generation." TSRMLS_CC, filename); -+ } -+ } else { -+ apc_warning("Unable to open '%s' for md5 generation." TSRMLS_CC, filename); -+ } -+ } -+ -+ if(!(alloc_op_array = apc_copy_op_array(NULL, *op_array, &ctxt TSRMLS_CC))) { -+ goto freepool; -+ } -+ -+ if(!(alloc_functions = apc_copy_new_functions(num_functions, &ctxt TSRMLS_CC))) { -+ goto freepool; -+ } -+ if(!(alloc_classes = apc_copy_new_classes(*op_array, num_classes, &ctxt TSRMLS_CC))) { -+ goto freepool; -+ } -+ -+ path = h->opened_path; -+ if(!path && key->type == APC_CACHE_KEY_FPFILE) path = (char*)key->data.fpfile.fullpath; -+ if(!path) path=h->filename; -+ -+ apc_debug("2. h->opened_path=[%s] h->filename=[%s]\n" TSRMLS_CC, h->opened_path?h->opened_path:"null",h->filename); -+ -+ if(!(*cache_entry = apc_cache_make_file_entry(path, alloc_op_array, alloc_functions, alloc_classes, &ctxt TSRMLS_CC))) { -+ goto freepool; -+ } -+ -+ return SUCCESS; -+ -+freepool: -+ apc_pool_destroy(ctxt.pool TSRMLS_CC); -+ ctxt.pool = NULL; -+ -+ return FAILURE; -+ -+} -+/* }}} */ -+ -+/* {{{ my_compile_file -+ Overrides zend_compile_file */ -+static zend_op_array* my_compile_file(zend_file_handle* h, -+ int type TSRMLS_DC) -+{ -+ apc_cache_key_t key; -+ apc_cache_entry_t* cache_entry; -+ zend_op_array* op_array = NULL; -+ time_t t; -+ apc_context_t ctxt = {0,}; -+ int bailout=0; -+ const char* filename = NULL; -+ -+ if (!APCG(enabled) || apc_cache_busy(apc_cache)) { -+ return old_compile_file(h, type TSRMLS_CC); -+ } -+ -+ if(h->opened_path) { -+ filename = h->opened_path; -+ } else { -+ filename = h->filename; -+ } -+ -+ /* check our regular expression filters */ -+ if (APCG(filters) && APCG(compiled_filters) && filename) { -+ int ret = apc_regex_match_array(APCG(compiled_filters), filename); -+ -+ if(ret == APC_NEGATIVE_MATCH || (ret != APC_POSITIVE_MATCH && !APCG(cache_by_default))) { -+ return old_compile_file(h, type TSRMLS_CC); -+ } -+ } else if(!APCG(cache_by_default)) { -+ return old_compile_file(h, type TSRMLS_CC); -+ } -+ APCG(current_cache) = apc_cache; -+ -+ -+ t = apc_time(); -+ -+ apc_debug("1. h->opened_path=[%s] h->filename=[%s]\n" TSRMLS_CC, h->opened_path?h->opened_path:"null",h->filename); -+ -+ /* try to create a cache key; if we fail, give up on caching */ -+ if (!apc_cache_make_file_key(&key, h->filename, PG(include_path), t TSRMLS_CC)) { -+ return old_compile_file(h, type TSRMLS_CC); -+ } -+ -+ if(!APCG(force_file_update)) { -+ /* search for the file in the cache */ -+ cache_entry = apc_cache_find(apc_cache, key, t TSRMLS_CC); -+ ctxt.force_update = 0; -+ } else { -+ cache_entry = NULL; -+ ctxt.force_update = 1; -+ } -+ -+ if (cache_entry != NULL) { -+ int dummy = 1; -+ -+ ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, -+ apc_sma_protect, apc_sma_unprotect TSRMLS_CC); -+ if (!ctxt.pool) { -+ apc_warning("Unable to allocate memory for pool." TSRMLS_CC); -+ return old_compile_file(h, type TSRMLS_CC); -+ } -+ ctxt.copy = APC_COPY_OUT_OPCODE; -+ -+ zend_hash_add(&EG(included_files), cache_entry->data.file.filename, -+ strlen(cache_entry->data.file.filename)+1, -+ (void *)&dummy, sizeof(int), NULL); -+ -+ apc_stack_push(APCG(cache_stack), cache_entry TSRMLS_CC); -+ op_array = cached_compile(h, type, &ctxt TSRMLS_CC); -+ -+ if(op_array) { -+#ifdef APC_FILEHITS -+ /* If the file comes from the cache, add it to the global request file list */ -+ add_next_index_string(APCG(filehits), h->filename, 1); -+#endif -+ /* this is an unpool, which has no cleanup - this only free's the pool header */ -+ apc_pool_destroy(ctxt.pool TSRMLS_CC); -+ -+ /* We might leak fds without this hack */ -+ if (h->type != ZEND_HANDLE_FILENAME) { -+ zend_llist_add_element(&CG(open_files), h); -+ } -+ return op_array; -+ } -+ if(APCG(report_autofilter)) { -+ apc_warning("Autofiltering %s" TSRMLS_CC, -+ (h->opened_path ? h->opened_path : h->filename)); -+ apc_warning("Recompiling %s" TSRMLS_CC, cache_entry->data.file.filename); -+ } -+ /* TODO: check what happens with EG(included_files) */ -+ } -+ -+ /* Make sure the mtime reflects the files last known mtime, and we respect max_file_size in the case of fpstat==0 */ -+ if(key.type == APC_CACHE_KEY_FPFILE) { -+ apc_fileinfo_t fileinfo; -+ struct stat *tmp_buf = NULL; -+ if(!strcmp(SG(request_info).path_translated, h->filename)) { -+ tmp_buf = sapi_get_stat(TSRMLS_C); /* Apache has already done this stat() for us */ -+ } -+ if(tmp_buf) { -+ fileinfo.st_buf.sb = *tmp_buf; -+ } else { -+ if (apc_search_paths(h->filename, PG(include_path), &fileinfo TSRMLS_CC) != 0) { -+ apc_debug("Stat failed %s - bailing (%s) (%d)\n" TSRMLS_CC,h->filename,SG(request_info).path_translated); -+ return old_compile_file(h, type TSRMLS_CC); -+ } -+ } -+ if (APCG(max_file_size) < fileinfo.st_buf.sb.st_size) { -+ apc_debug("File is too big %s (%ld) - bailing\n" TSRMLS_CC, h->filename, fileinfo.st_buf.sb.st_size); -+ return old_compile_file(h, type TSRMLS_CC); -+ } -+ key.mtime = fileinfo.st_buf.sb.st_mtime; -+ } -+ -+ HANDLE_BLOCK_INTERRUPTIONS(); -+ -+#if NONBLOCKING_LOCK_AVAILABLE -+ if(APCG(write_lock)) { -+ if(!apc_cache_write_lock(apc_cache TSRMLS_CC)) { -+ HANDLE_UNBLOCK_INTERRUPTIONS(); -+ return old_compile_file(h, type TSRMLS_CC); -+ } -+ } -+#endif -+ -+ zend_try { -+ if (apc_compile_cache_entry(&key, h, type, t, &op_array, &cache_entry TSRMLS_CC) == SUCCESS) { -+ ctxt.pool = cache_entry->pool; -+ ctxt.copy = APC_COPY_IN_OPCODE; -+ if (apc_cache_insert(apc_cache, key, cache_entry, &ctxt, t TSRMLS_CC) != 1) { -+ apc_pool_destroy(ctxt.pool TSRMLS_CC); -+ ctxt.pool = NULL; -+ } -+ } -+ } zend_catch { -+ bailout=1; /* in the event of a bailout, ensure we don't create a dead-lock */ -+ } zend_end_try(); -+ -+ APCG(current_cache) = NULL; -+ -+#if NONBLOCKING_LOCK_AVAILABLE -+ if(APCG(write_lock)) { -+ apc_cache_write_unlock(apc_cache TSRMLS_CC); -+ } -+#endif -+ HANDLE_UNBLOCK_INTERRUPTIONS(); -+ -+ if (bailout) zend_bailout(); -+ -+ return op_array; -+} -+/* }}} */ -+ -+/* {{{ data preload */ -+ -+extern int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC); -+ -+static zval* data_unserialize(const char *filename TSRMLS_DC) -+{ -+ zval* retval; -+ long len = 0; -+ struct stat sb; -+ char *contents, *tmp; -+ FILE *fp; -+ php_unserialize_data_t var_hash; -+ -+ if(VCWD_STAT(filename, &sb) == -1) { -+ return NULL; -+ } -+ -+ fp = fopen(filename, "rb"); -+ -+ len = sizeof(char)*sb.st_size; -+ -+ tmp = contents = malloc(len); -+ -+ if(!contents) { -+ return NULL; -+ } -+ -+ if(fread(contents, 1, len, fp) < 1) { -+ free(contents); -+ return NULL; -+ } -+ -+ MAKE_STD_ZVAL(retval); -+ -+ PHP_VAR_UNSERIALIZE_INIT(var_hash); -+ -+ /* I wish I could use json */ -+ if(!php_var_unserialize(&retval, (const unsigned char**)&tmp, (const unsigned char*)(contents+len), &var_hash TSRMLS_CC)) { -+ zval_ptr_dtor(&retval); -+ return NULL; -+ } -+ -+ PHP_VAR_UNSERIALIZE_DESTROY(var_hash); -+ -+ free(contents); -+ fclose(fp); -+ -+ return retval; -+} -+ -+static int apc_load_data(const char *data_file TSRMLS_DC) -+{ -+ char *p; -+ char key[MAXPATHLEN] = {0,}; -+ unsigned int key_len; -+ zval *data; -+ -+ p = strrchr(data_file, DEFAULT_SLASH); -+ -+ if(p && p[1]) { -+ strlcpy(key, p+1, sizeof(key)); -+ p = strrchr(key, '.'); -+ -+ if(p) { -+ p[0] = '\0'; -+ key_len = strlen(key); -+ -+ data = data_unserialize(data_file TSRMLS_CC); -+ if(data) { -+ _apc_store(key, key_len, data, 0, 1 TSRMLS_CC); -+ } -+ return 1; -+ } -+ } -+ -+ return 0; -+} -+ -+static int apc_walk_dir(const char *path TSRMLS_DC) -+{ -+ char file[MAXPATHLEN]={0,}; -+ int ndir, i; -+ char *p = NULL; -+ struct dirent **namelist = NULL; -+ -+ if ((ndir = php_scandir(path, &namelist, 0, php_alphasort)) > 0) -+ { -+ for (i = 0; i < ndir; i++) -+ { -+ /* check for extension */ -+ if (!(p = strrchr(namelist[i]->d_name, '.')) -+ || (p && strcmp(p, ".data"))) -+ { -+ free(namelist[i]); -+ continue; -+ } -+ snprintf(file, MAXPATHLEN, "%s%c%s", -+ path, DEFAULT_SLASH, namelist[i]->d_name); -+ if(!apc_load_data(file TSRMLS_CC)) -+ { -+ /* print error */ -+ } -+ free(namelist[i]); -+ } -+ free(namelist); -+ } -+ -+ return 1; -+} -+ -+void apc_data_preload(TSRMLS_D) -+{ -+ if(!APCG(preload_path)) return; -+ -+ apc_walk_dir(APCG(preload_path) TSRMLS_CC); -+} -+/* }}} */ -+ -+/* {{{ apc_serializer hooks */ -+static int _apc_register_serializer(const char* name, apc_serialize_t serialize, -+ apc_unserialize_t unserialize, -+ void *config TSRMLS_DC) -+{ -+ int i; -+ apc_serializer_t *serializer; -+ -+ for(i = 0; i < APC_MAX_SERIALIZERS; i++) { -+ serializer = &apc_serializers[i]; -+ if(!serializer->name) { -+ /* empty entry */ -+ serializer->name = name; /* assumed to be const */ -+ serializer->serialize = serialize; -+ serializer->unserialize = unserialize; -+ serializer->config = config; -+ apc_serializers[i+1].name = NULL; -+ return 1; -+ } -+ } -+ -+ return 0; -+} -+ -+apc_serializer_t* apc_find_serializer(const char* name TSRMLS_DC) -+{ -+ int i; -+ apc_serializer_t *serializer; -+ -+ for(i = 0; i < APC_MAX_SERIALIZERS; i++) { -+ serializer = &apc_serializers[i]; -+ if(serializer->name && (strcmp(serializer->name, name) == 0)) { -+ return serializer; -+ } -+ } -+ return NULL; -+} -+ -+apc_serializer_t* apc_get_serializers(TSRMLS_D) -+{ -+ return &(apc_serializers[0]); -+} -+/* }}} */ -+ -+/* {{{ module init and shutdown */ -+ -+int apc_module_init(int module_number TSRMLS_DC) -+{ -+ /* apc initialization */ -+#if APC_MMAP -+ apc_sma_init(APCG(shm_segments), APCG(shm_size), APCG(mmap_file_mask) TSRMLS_CC); -+#else -+ apc_sma_init(APCG(shm_segments), APCG(shm_size), NULL TSRMLS_CC); -+#endif -+ apc_cache = apc_cache_create(APCG(num_files_hint), APCG(gc_ttl), APCG(ttl) TSRMLS_CC); -+ apc_user_cache = apc_cache_create(APCG(user_entries_hint), APCG(gc_ttl), APCG(user_ttl) TSRMLS_CC); -+ -+ /* override compilation */ -+ old_compile_file = zend_compile_file; -+ zend_compile_file = my_compile_file; -+ REGISTER_LONG_CONSTANT("\000apc_magic", (long)&set_compile_hook, CONST_PERSISTENT | CONST_CS); -+ REGISTER_LONG_CONSTANT("\000apc_compile_file", (long)&my_compile_file, CONST_PERSISTENT | CONST_CS); -+ REGISTER_LONG_CONSTANT(APC_SERIALIZER_CONSTANT, (long)&_apc_register_serializer, CONST_PERSISTENT | CONST_CS); -+ -+ /* test out the constant function pointer */ -+ apc_register_serializer("php", APC_SERIALIZER_NAME(php), APC_UNSERIALIZER_NAME(php), NULL TSRMLS_CC); -+ -+ assert(apc_serializers[0].name != NULL); -+ -+ apc_pool_init(); -+ -+ apc_data_preload(TSRMLS_C); -+ -+#if APC_HAVE_LOOKUP_HOOKS -+ if(APCG(lazy_functions)) { -+ zend_set_lookup_function_hook(apc_lookup_function_hook TSRMLS_CC); -+ zend_set_defined_function_hook(apc_defined_function_hook TSRMLS_CC); -+ } -+ if(APCG(lazy_classes)) { -+ zend_set_lookup_class_hook(apc_lookup_class_hook TSRMLS_CC); -+ zend_set_declared_class_hook(apc_declared_class_hook TSRMLS_CC); -+ } -+#else -+ if(APCG(lazy_functions) || APCG(lazy_classes)) { -+ apc_warning("Lazy function/class loading not available with this version of PHP, please disable APC lazy loading." TSRMLS_CC); -+ APCG(lazy_functions) = APCG(lazy_classes) = 0; -+ } -+#endif -+ -+#ifdef ZEND_ENGINE_2_4 -+#ifndef ZTS -+ apc_interned_strings_init(TSRMLS_C); -+#endif -+#endif -+ -+ APCG(initialized) = 1; -+ return 0; -+} -+ -+int apc_module_shutdown(TSRMLS_D) -+{ -+ if (!APCG(initialized)) -+ return 0; -+ -+ /* restore compilation */ -+ zend_compile_file = old_compile_file; -+ -+ /* -+ * In case we got interrupted by a SIGTERM or something else during execution -+ * we may have cache entries left on the stack that we need to check to make -+ * sure that any functions or classes these may have added to the global function -+ * and class tables are removed before we blow away the memory that hold them. -+ * -+ * This is merely to remove memory leak warnings - as the process is terminated -+ * immediately after shutdown. The following while loop can be removed without -+ * affecting anything else. -+ */ -+ while (apc_stack_size(APCG(cache_stack)) > 0) { -+ int i; -+ apc_cache_entry_t* cache_entry = (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack)); -+ if (cache_entry->data.file.functions) { -+ for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) { -+ zend_hash_del(EG(function_table), -+ cache_entry->data.file.functions[i].name, -+ cache_entry->data.file.functions[i].name_len+1); -+ } -+ } -+ if (cache_entry->data.file.classes) { -+ for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) { -+ zend_hash_del(EG(class_table), -+ cache_entry->data.file.classes[i].name, -+ cache_entry->data.file.classes[i].name_len+1); -+ } -+ } -+ apc_cache_release(apc_cache, cache_entry TSRMLS_CC); -+ } -+ -+#ifdef ZEND_ENGINE_2_4 -+#ifndef ZTS -+ apc_interned_strings_shutdown(TSRMLS_C); -+#endif -+#endif -+ -+ apc_cache_destroy(apc_cache TSRMLS_CC); -+ apc_cache_destroy(apc_user_cache TSRMLS_CC); -+ apc_sma_cleanup(TSRMLS_C); -+ -+ APCG(initialized) = 0; -+ return 0; -+} -+ -+/* }}} */ -+ -+/* {{{ process init and shutdown */ -+int apc_process_init(int module_number TSRMLS_DC) -+{ -+ return 0; -+} -+ -+int apc_process_shutdown(TSRMLS_D) -+{ -+ return 0; -+} -+/* }}} */ -+ -+ -+/* {{{ apc_deactivate */ -+static void apc_deactivate(TSRMLS_D) -+{ -+ /* The execution stack was unwound, which prevented us from decrementing -+ * the reference counts on active cache entries in `my_execute`. -+ */ -+ while (apc_stack_size(APCG(cache_stack)) > 0) { -+ int i; -+ zend_class_entry* zce = NULL; -+ void ** centry = (void*)(&zce); -+ zend_class_entry** pzce = NULL; -+ -+ apc_cache_entry_t* cache_entry = -+ (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack)); -+ -+ if (cache_entry->data.file.classes) { -+ for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) { -+ centry = (void**)&pzce; /* a triple indirection to get zend_class_entry*** */ -+ if(zend_hash_find(EG(class_table), -+ cache_entry->data.file.classes[i].name, -+ cache_entry->data.file.classes[i].name_len+1, -+ (void**)centry) == FAILURE) -+ { -+ /* double inclusion of conditional classes ends up failing -+ * this lookup the second time around. -+ */ -+ continue; -+ } -+ -+ zce = *pzce; -+ -+ zend_hash_del(EG(class_table), -+ cache_entry->data.file.classes[i].name, -+ cache_entry->data.file.classes[i].name_len+1); -+ -+ apc_free_class_entry_after_execution(zce TSRMLS_CC); -+ } -+ } -+ apc_cache_release(apc_cache, cache_entry TSRMLS_CC); -+ } -+} -+/* }}} */ -+ -+/* {{{ request init and shutdown */ -+ -+int apc_request_init(TSRMLS_D) -+{ -+ apc_stack_clear(APCG(cache_stack)); -+ if (!APCG(compiled_filters) && APCG(filters)) { -+ /* compile regex filters here to avoid race condition between MINIT of PCRE and APC. -+ * This should be moved to apc_cache_create() if this race condition between modules is resolved */ -+ APCG(compiled_filters) = apc_regex_compile_array(APCG(filters) TSRMLS_CC); -+ } -+ -+ if (!APCG(serializer) && APCG(serializer_name)) { -+ /* Avoid race conditions between MINIT of apc and serializer exts like igbinary */ -+ APCG(serializer) = apc_find_serializer(APCG(serializer_name) TSRMLS_CC); -+ } -+ -+#if APC_HAVE_LOOKUP_HOOKS -+ if(APCG(lazy_functions)) { -+ APCG(lazy_function_table) = emalloc(sizeof(HashTable)); -+ zend_hash_init(APCG(lazy_function_table), 0, NULL, NULL, 0); -+ } -+ if(APCG(lazy_classes)) { -+ APCG(lazy_class_table) = emalloc(sizeof(HashTable)); -+ zend_hash_init(APCG(lazy_class_table), 0, NULL, NULL, 0); -+ } -+#endif -+ -+#ifdef APC_FILEHITS -+ ALLOC_INIT_ZVAL(APCG(filehits)); -+ array_init(APCG(filehits)); -+#endif -+ -+ return 0; -+} -+ -+int apc_request_shutdown(TSRMLS_D) -+{ -+#if APC_HAVE_LOOKUP_HOOKS -+ if(APCG(lazy_class_table)) { -+ zend_hash_destroy(APCG(lazy_class_table)); -+ efree(APCG(lazy_class_table)); -+ } -+ if(APCG(lazy_function_table)) { -+ zend_hash_destroy(APCG(lazy_function_table)); -+ efree(APCG(lazy_function_table)); -+ } -+#endif -+ -+ apc_deactivate(TSRMLS_C); -+ -+#ifdef APC_FILEHITS -+ zval_ptr_dtor(&APCG(filehits)); -+#endif -+ return 0; -+} -+ -+/* }}} */ -+ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_main.h b/ext/apc/apc_main.h ---- a/ext/apc/apc_main.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_main.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,88 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | George Schlossnagle | -+ | Rasmus Lerdorf | -+ | Arun C. Murthy | -+ | Gopal Vijayaraghavan | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_main.h 308594 2011-02-23 12:35:33Z gopalv $ */ -+ -+#ifndef APC_MAIN_H -+#define APC_MAIN_H -+ -+#include "apc_pool.h" -+#include "apc_serializer.h" -+ -+/* -+ * This module provides the primary interface between PHP and APC. -+ */ -+ -+extern int apc_module_init(int module_number TSRMLS_DC); -+extern int apc_module_shutdown(TSRMLS_D); -+extern int apc_process_init(int module_number TSRMLS_DC); -+extern int apc_process_shutdown(TSRMLS_D); -+extern int apc_request_init(TSRMLS_D); -+extern int apc_request_shutdown(TSRMLS_D); -+ -+typedef enum _apc_copy_type { -+ APC_NO_COPY = 0, -+ APC_COPY_IN_OPCODE, -+ APC_COPY_OUT_OPCODE, -+ APC_COPY_IN_USER, -+ APC_COPY_OUT_USER -+} apc_copy_type; -+ -+typedef struct _apc_context_t -+{ -+ apc_pool *pool; -+ apc_copy_type copy; -+ unsigned int force_update:1; -+} apc_context_t; -+ -+/* {{{ struct apc_serializer_t */ -+typedef struct apc_serializer_t apc_serializer_t; -+struct apc_serializer_t { -+ const char *name; -+ apc_serialize_t serialize; -+ apc_unserialize_t unserialize; -+ void *config; -+}; -+/* }}} */ -+ -+apc_serializer_t* apc_get_serializers(TSRMLS_D); -+apc_serializer_t* apc_find_serializer(const char* name TSRMLS_DC); -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_mmap.c b/ext/apc/apc_mmap.c ---- a/ext/apc/apc_mmap.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_mmap.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,177 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Rasmus Lerdorf | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_mmap.c 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#include "apc.h" -+#include "apc_mmap.h" -+#include "apc_lock.h" -+ -+#if APC_MMAP -+ -+#include -+#include -+#include -+ -+/* -+ * Some operating systems (like FreeBSD) have a MAP_NOSYNC flag that -+ * tells whatever update daemons might be running to not flush dirty -+ * vm pages to disk unless absolutely necessary. My guess is that -+ * most systems that don't have this probably default to only synching -+ * to disk when absolutely necessary. -+ */ -+#ifndef MAP_NOSYNC -+#define MAP_NOSYNC 0 -+#endif -+ -+/* support for systems where MAP_ANONYMOUS is defined but not MAP_ANON, ie: HP-UX bug #14615 */ -+#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS) -+# define MAP_ANON MAP_ANONYMOUS -+#endif -+ -+apc_segment_t apc_mmap(char *file_mask, size_t size TSRMLS_DC) -+{ -+ apc_segment_t segment; -+ -+ int fd = -1; -+ int flags = MAP_SHARED | MAP_NOSYNC; -+ int remap = 1; -+ -+ /* If no filename was provided, do an anonymous mmap */ -+ if(!file_mask || (file_mask && !strlen(file_mask))) { -+#if !defined(MAP_ANON) -+ apc_error("Anonymous mmap does not apear to be available on this system (MAP_ANON/MAP_ANONYMOUS). Please see the apc.mmap_file_mask INI option." TSRMLS_CC); -+#else -+ fd = -1; -+ flags = MAP_SHARED | MAP_ANON; -+ remap = 0; -+#endif -+ } else if(!strcmp(file_mask,"/dev/zero")) { -+ fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR); -+ if(fd == -1) { -+ apc_error("apc_mmap: open on /dev/zero failed:" TSRMLS_CC); -+ goto error; -+ } -+ remap = 0; /* cannot remap */ -+ } else if(strstr(file_mask,".shm")) { -+ /* -+ * If the filemask contains .shm we try to do a POSIX-compliant shared memory -+ * backed mmap which should avoid synchs on some platforms. At least on -+ * FreeBSD this implies MAP_NOSYNC and on Linux it is equivalent of mmap'ing -+ * a file in a mounted shmfs. For this to work on Linux you need to make sure -+ * you actually have shmfs mounted. Also on Linux, make sure the file_mask you -+ * pass in has a leading / and no other /'s. eg. /apc.shm.XXXXXX -+ * On FreeBSD these are mapped onto the regular filesystem so you can put whatever -+ * path you want here. -+ */ -+ if(!mktemp(file_mask)) { -+ apc_error("apc_mmap: mktemp on %s failed:" TSRMLS_CC, file_mask); -+ goto error; -+ } -+ fd = shm_open(file_mask, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); -+ if(fd == -1) { -+ apc_error("apc_mmap: shm_open on %s failed:" TSRMLS_CC, file_mask); -+ goto error; -+ } -+ if (ftruncate(fd, size) < 0) { -+ close(fd); -+ shm_unlink(file_mask); -+ apc_error("apc_mmap: ftruncate failed:" TSRMLS_CC); -+ goto error; -+ } -+ shm_unlink(file_mask); -+ } else { -+ /* -+ * Otherwise we do a normal filesystem mmap -+ */ -+ fd = mkstemp(file_mask); -+ if(fd == -1) { -+ apc_error("apc_mmap: mkstemp on %s failed:" TSRMLS_CC, file_mask); -+ goto error; -+ } -+ if (ftruncate(fd, size) < 0) { -+ close(fd); -+ unlink(file_mask); -+ apc_error("apc_mmap: ftruncate failed:" TSRMLS_CC); -+ goto error; -+ } -+ unlink(file_mask); -+ } -+ -+ segment.shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0); -+ segment.size = size; -+ -+#ifdef APC_MEMPROTECT -+ if(remap) { -+ segment.roaddr = (void *)mmap(NULL, size, PROT_READ, flags, fd, 0); -+ } else { -+ segment.roaddr = NULL; -+ } -+#endif -+ -+ if((long)segment.shmaddr == -1) { -+ apc_error("apc_mmap: mmap failed:" TSRMLS_CC); -+ } -+ -+ if(fd != -1) close(fd); -+ -+ return segment; -+ -+error: -+ -+ segment.shmaddr = (void*)-1; -+ segment.size = 0; -+#ifdef APC_MEMPROTECT -+ segment.roaddr = NULL; -+#endif -+ return segment; -+} -+ -+void apc_unmap(apc_segment_t *segment TSRMLS_DC) -+{ -+ if (munmap(segment->shmaddr, segment->size) < 0) { -+ apc_warning("apc_unmap: munmap failed:" TSRMLS_CC); -+ } -+ -+#ifdef APC_MEMPROTECT -+ if (segment->roaddr && munmap(segment->roaddr, segment->size) < 0) { -+ apc_warning("apc_unmap: munmap failed:" TSRMLS_CC); -+ } -+#endif -+ -+} -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_mmap.h b/ext/apc/apc_mmap.h ---- a/ext/apc/apc_mmap.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_mmap.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,54 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Gopal V | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_mmap.h 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#ifndef APC_MMAP_H -+#define APC_MMAP_H -+ -+#include -+ -+#include "apc.h" -+#include "apc_sma.h" -+ -+/* Wrapper functions for shared memory mapped files */ -+ -+#if APC_MMAP -+apc_segment_t apc_mmap(char *file_mask, size_t size TSRMLS_DC); -+void apc_unmap(apc_segment_t* segment TSRMLS_DC); -+#endif -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc.php b/ext/apc/apc.php ---- a/ext/apc/apc.php 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc.php 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,1362 @@ -+ | -+ | Rasmus Lerdorf | -+ | Ilia Alshanetsky | -+ +----------------------------------------------------------------------+ -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+$VERSION='$Id: apc.php 325483 2012-05-01 00:34:04Z rasmus $'; -+ -+////////// READ OPTIONAL CONFIGURATION FILE //////////// -+if (file_exists("apc.conf.php")) include("apc.conf.php"); -+//////////////////////////////////////////////////////// -+ -+////////// BEGIN OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////// -+ -+defaults('USE_AUTHENTICATION',1); // Use (internal) authentication - best choice if -+ // no other authentication is available -+ // If set to 0: -+ // There will be no further authentication. You -+ // will have to handle this by yourself! -+ // If set to 1: -+ // You need to change ADMIN_PASSWORD to make -+ // this work! -+defaults('ADMIN_USERNAME','apc'); // Admin Username -+defaults('ADMIN_PASSWORD','password'); // Admin Password - CHANGE THIS TO ENABLE!!! -+ -+// (beckerr) I'm using a clear text password here, because I've no good idea how to let -+// users generate a md5 or crypt password in a easy way to fill it in above -+ -+//defaults('DATE_FORMAT', "d.m.Y H:i:s"); // German -+defaults('DATE_FORMAT', 'Y/m/d H:i:s'); // US -+ -+defaults('GRAPH_SIZE',200); // Image size -+ -+//defaults('PROXY', 'tcp://127.0.0.1:8080'); -+ -+////////// END OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////// -+ -+ -+// "define if not defined" -+function defaults($d,$v) { -+ if (!defined($d)) define($d,$v); // or just @define(...) -+} -+ -+// rewrite $PHP_SELF to block XSS attacks -+// -+$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],''), ENT_QUOTES, 'UTF-8') : ''; -+$time = time(); -+$host = php_uname('n'); -+if($host) { $host = '('.$host.')'; } -+if (isset($_SERVER['SERVER_ADDR'])) { -+ $host .= ' ('.$_SERVER['SERVER_ADDR'].')'; -+} -+ -+// operation constants -+define('OB_HOST_STATS',1); -+define('OB_SYS_CACHE',2); -+define('OB_USER_CACHE',3); -+define('OB_SYS_CACHE_DIR',4); -+define('OB_VERSION_CHECK',9); -+ -+// check validity of input variables -+$vardom=array( -+ 'OB' => '/^\d+$/', // operational mode switch -+ 'CC' => '/^[01]$/', // clear cache requested -+ 'DU' => '/^.*$/', // Delete User Key -+ 'SH' => '/^[a-z0-9]+$/', // shared object description -+ -+ 'IMG' => '/^[123]$/', // image to generate -+ 'LO' => '/^1$/', // login requested -+ -+ 'COUNT' => '/^\d+$/', // number of line displayed in list -+ 'SCOPE' => '/^[AD]$/', // list view scope -+ 'SORT1' => '/^[AHSMCDTZ]$/', // first sort key -+ 'SORT2' => '/^[DA]$/', // second sort key -+ 'AGGR' => '/^\d+$/', // aggregation by dir level -+ 'SEARCH' => '~^[a-zA-Z0-9/_.-]*$~' // aggregation by dir level -+); -+ -+// default cache mode -+$cache_mode='opcode'; -+ -+// cache scope -+$scope_list=array( -+ 'A' => 'cache_list', -+ 'D' => 'deleted_list' -+); -+ -+// handle POST and GET requests -+if (empty($_REQUEST)) { -+ if (!empty($_GET) && !empty($_POST)) { -+ $_REQUEST = array_merge($_GET, $_POST); -+ } else if (!empty($_GET)) { -+ $_REQUEST = $_GET; -+ } else if (!empty($_POST)) { -+ $_REQUEST = $_POST; -+ } else { -+ $_REQUEST = array(); -+ } -+} -+ -+// check parameter syntax -+foreach($vardom as $var => $dom) { -+ if (!isset($_REQUEST[$var])) { -+ $MYREQUEST[$var]=NULL; -+ } else if (!is_array($_REQUEST[$var]) && preg_match($dom.'D',$_REQUEST[$var])) { -+ $MYREQUEST[$var]=$_REQUEST[$var]; -+ } else { -+ $MYREQUEST[$var]=$_REQUEST[$var]=NULL; -+ } -+} -+ -+// check parameter sematics -+if (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']="A"; -+if (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']="H"; -+if (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']="D"; -+if (empty($MYREQUEST['OB'])) $MYREQUEST['OB']=OB_HOST_STATS; -+if (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20; -+if (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A'; -+ -+$MY_SELF= -+ "$PHP_SELF". -+ "?SCOPE=".$MYREQUEST['SCOPE']. -+ "&SORT1=".$MYREQUEST['SORT1']. -+ "&SORT2=".$MYREQUEST['SORT2']. -+ "&COUNT=".$MYREQUEST['COUNT']; -+$MY_SELF_WO_SORT= -+ "$PHP_SELF". -+ "?SCOPE=".$MYREQUEST['SCOPE']. -+ "&COUNT=".$MYREQUEST['COUNT']; -+ -+// authentication needed? -+// -+if (!USE_AUTHENTICATION) { -+ $AUTHENTICATED=1; -+} else { -+ $AUTHENTICATED=0; -+ if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) { -+ -+ if (!isset($_SERVER['PHP_AUTH_USER']) || -+ !isset($_SERVER['PHP_AUTH_PW']) || -+ $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME || -+ $_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) { -+ Header("WWW-Authenticate: Basic realm=\"APC Login\""); -+ Header("HTTP/1.0 401 Unauthorized"); -+ -+ echo << -+

Rejected!

-+ Wrong Username or Password!
 
  -+ Continue... -+ -+EOB; -+ exit; -+ -+ } else { -+ $AUTHENTICATED=1; -+ } -+ } -+} -+ -+// select cache mode -+if ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) { -+ $cache_mode='user'; -+} -+// clear cache -+if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) { -+ apc_clear_cache($cache_mode); -+} -+ -+if ($AUTHENTICATED && !empty($MYREQUEST['DU'])) { -+ apc_delete($MYREQUEST['DU']); -+} -+ -+if(!function_exists('apc_cache_info') || !($cache=@apc_cache_info($cache_mode))) { -+ echo "No cache info available. APC does not appear to be running."; -+ exit; -+} -+ -+$cache_user = apc_cache_info('user', 1); -+$mem=apc_sma_info(); -+if(!$cache['num_hits']) { $cache['num_hits']=1; $time++; } // Avoid division by 0 errors on a cache clear -+ -+// don't cache this page -+// -+header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1 -+header("Cache-Control: post-check=0, pre-check=0", false); -+header("Pragma: no-cache"); // HTTP/1.0 -+ -+function duration($ts) { -+ global $time; -+ $years = (int)((($time - $ts)/(7*86400))/52.177457); -+ $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400)); -+ $weeks = (int)(($rem)/(7*86400)); -+ $days = (int)(($rem)/86400) - $weeks*7; -+ $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24; -+ $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60; -+ $str = ''; -+ if($years==1) $str .= "$years year, "; -+ if($years>1) $str .= "$years years, "; -+ if($weeks==1) $str .= "$weeks week, "; -+ if($weeks>1) $str .= "$weeks weeks, "; -+ if($days==1) $str .= "$days day,"; -+ if($days>1) $str .= "$days days,"; -+ if($hours == 1) $str .= " $hours hour and"; -+ if($hours>1) $str .= " $hours hours and"; -+ if($mins == 1) $str .= " 1 minute"; -+ else $str .= " $mins minutes"; -+ return $str; -+} -+ -+// create graphics -+// -+function graphics_avail() { -+ return extension_loaded('gd'); -+} -+if (isset($MYREQUEST['IMG'])) -+{ -+ if (!graphics_avail()) { -+ exit(0); -+ } -+ -+ function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) { -+ $r=$diameter/2; -+ $w=deg2rad((360+$start+($end-$start)/2)%360); -+ -+ -+ if (function_exists("imagefilledarc")) { -+ // exists only if GD 2.0.1 is avaliable -+ imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE); -+ imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE); -+ imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED); -+ } else { -+ imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2); -+ imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2); -+ imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2); -+ imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2); -+ imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end)) * $r, $centerY + sin(deg2rad($end)) * $r, $color2); -+ imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2); -+ } -+ if ($text) { -+ if ($placeindex>0) { -+ imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1); -+ imagestring($im,4,$diameter, $placeindex*12,$text,$color1); -+ -+ } else { -+ imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1); -+ } -+ } -+ } -+ -+ function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) { -+ $r=$diameter/2; -+ $w=deg2rad((360+$start+($end-$start)/2)%360); -+ -+ if ($placeindex>0) { -+ imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1); -+ imagestring($im,4,$diameter, $placeindex*12,$text,$color1); -+ -+ } else { -+ imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1); -+ } -+ } -+ -+ function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') { -+ global $col_black; -+ $x1=$x+$w-1; -+ $y1=$y+$h-1; -+ -+ imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black); -+ if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2); -+ else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2); -+ imagerectangle($im, $x, $y1, $x1, $y, $color1); -+ if ($text) { -+ if ($placeindex>0) { -+ -+ if ($placeindex<16) -+ { -+ $px=5; -+ $py=$placeindex*12+6; -+ imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2); -+ imageline($im,$x,$y+$h/2,$px+90,$py,$color2); -+ imagestring($im,2,$px,$py-6,$text,$color1); -+ -+ } else { -+ if ($placeindex<31) { -+ $px=$x+40*2; -+ $py=($placeindex-15)*12+6; -+ } else { -+ $px=$x+40*2+100*intval(($placeindex-15)/15); -+ $py=($placeindex%15)*12+6; -+ } -+ imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2); -+ imageline($im,$x+$w,$y+$h/2,$px,$py,$color2); -+ imagestring($im,2,$px+2,$py-6,$text,$color1); -+ } -+ } else { -+ imagestring($im,4,$x+5,$y1-16,$text,$color1); -+ } -+ } -+ } -+ -+ -+ $size = GRAPH_SIZE; // image size -+ if ($MYREQUEST['IMG']==3) -+ $image = imagecreate(2*$size+150, $size+10); -+ else -+ $image = imagecreate($size+50, $size+10); -+ -+ $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF); -+ $col_red = imagecolorallocate($image, 0xD0, 0x60, 0x30); -+ $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60); -+ $col_black = imagecolorallocate($image, 0, 0, 0); -+ imagecolortransparent($image,$col_white); -+ -+ switch ($MYREQUEST['IMG']) { -+ -+ case 1: -+ $s=$mem['num_seg']*$mem['seg_size']; -+ $a=$mem['avail_mem']; -+ $x=$y=$size/2; -+ $fuzz = 0.000001; -+ -+ // This block of code creates the pie chart. It is a lot more complex than you -+ // would expect because we try to visualize any memory fragmentation as well. -+ $angle_from = 0; -+ $string_placement=array(); -+ for($i=0; $i<$mem['num_seg']; $i++) { -+ $ptr = 0; -+ $free = $mem['block_lists'][$i]; -+ uasort($free, 'block_sort'); -+ foreach($free as $block) { -+ if($block['offset']!=$ptr) { // Used block -+ $angle_to = $angle_from+($block['offset']-$ptr)/$s; -+ if(($angle_to+$fuzz)>1) $angle_to = 1; -+ if( ($angle_to*360) - ($angle_from*360) >= 1) { -+ fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red); -+ if (($angle_to-$angle_from)>0.05) { -+ array_push($string_placement, array($angle_from,$angle_to)); -+ } -+ } -+ $angle_from = $angle_to; -+ } -+ $angle_to = $angle_from+($block['size'])/$s; -+ if(($angle_to+$fuzz)>1) $angle_to = 1; -+ if( ($angle_to*360) - ($angle_from*360) >= 1) { -+ fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green); -+ if (($angle_to-$angle_from)>0.05) { -+ array_push($string_placement, array($angle_from,$angle_to)); -+ } -+ } -+ $angle_from = $angle_to; -+ $ptr = $block['offset']+$block['size']; -+ } -+ if ($ptr < $mem['seg_size']) { // memory at the end -+ $angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s; -+ if(($angle_to+$fuzz)>1) $angle_to = 1; -+ fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red); -+ if (($angle_to-$angle_from)>0.05) { -+ array_push($string_placement, array($angle_from,$angle_to)); -+ } -+ } -+ } -+ foreach ($string_placement as $angle) { -+ text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0]))); -+ } -+ break; -+ -+ case 2: -+ $s=$cache['num_hits']+$cache['num_misses']; -+ $a=$cache['num_hits']; -+ -+ fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s)); -+ fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s)); -+ break; -+ -+ case 3: -+ $s=$mem['num_seg']*$mem['seg_size']; -+ $a=$mem['avail_mem']; -+ $x=130; -+ $y=1; -+ $j=1; -+ -+ // This block of code creates the bar chart. It is a lot more complex than you -+ // would expect because we try to visualize any memory fragmentation as well. -+ for($i=0; $i<$mem['num_seg']; $i++) { -+ $ptr = 0; -+ $free = $mem['block_lists'][$i]; -+ uasort($free, 'block_sort'); -+ foreach($free as $block) { -+ if($block['offset']!=$ptr) { // Used block -+ $h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s; -+ if ($h>0) { -+ $j++; -+ if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j); -+ else fill_box($image,$x,$y,50,$h,$col_black,$col_red); -+ } -+ $y+=$h; -+ } -+ $h=(GRAPH_SIZE-5)*($block['size'])/$s; -+ if ($h>0) { -+ $j++; -+ if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j); -+ else fill_box($image,$x,$y,50,$h,$col_black,$col_green); -+ } -+ $y+=$h; -+ $ptr = $block['offset']+$block['size']; -+ } -+ if ($ptr < $mem['seg_size']) { // memory at the end -+ $h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s; -+ if ($h > 0) { -+ fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++); -+ } -+ } -+ } -+ break; -+ case 4: -+ $s=$cache['num_hits']+$cache['num_misses']; -+ $a=$cache['num_hits']; -+ -+ fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s)); -+ fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s)); -+ break; -+ -+ } -+ header("Content-type: image/png"); -+ imagepng($image); -+ exit; -+} -+ -+// pretty printer for byte values -+// -+function bsize($s) { -+ foreach (array('','K','M','G') as $i => $k) { -+ if ($s < 1024) break; -+ $s/=1024; -+ } -+ return sprintf("%5.1f %sBytes",$s,$k); -+} -+ -+// sortable table header in "scripts for this host" view -+function sortheader($key,$name,$extra='') { -+ global $MYREQUEST, $MY_SELF_WO_SORT; -+ -+ if ($MYREQUEST['SORT1']==$key) { -+ $MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A'; -+ } -+ return "$name"; -+ -+} -+ -+// create menu entry -+function menu_entry($ob,$title) { -+ global $MYREQUEST,$MY_SELF; -+ if ($MYREQUEST['OB']!=$ob) { -+ return "
  • $title
  • "; -+ } else if (empty($MYREQUEST['SH'])) { -+ return "
  • $title
  • "; -+ } else { -+ return "
  • $title
  • "; -+ } -+} -+ -+function put_login_link($s="Login") -+{ -+ global $MY_SELF,$MYREQUEST,$AUTHENTICATED; -+ // needs ADMIN_PASSWORD to be changed! -+ // -+ if (!USE_AUTHENTICATION) { -+ return; -+ } else if (ADMIN_PASSWORD=='password') -+ { -+ print <<$s -+EOB; -+ } else if ($AUTHENTICATED) { -+ print <<$s -+EOB; -+ } -+} -+ -+function block_sort($array1, $array2) -+{ -+ if ($array1['offset'] > $array2['offset']) { -+ return 1; -+ } else { -+ return -1; -+ } -+} -+ -+ -+?> -+ -+ -+APC INFO <?php echo $host ?> -+ -+ -+ -+
    -+

    -+ -+
    Opcode Cache
    -+

    -+ -+
    -+
    -+ -+
  • Refresh Data
  • -+EOB; -+echo -+ menu_entry(1,'View Host Stats'), -+ menu_entry(2,'System Cache Entries'); -+if ($AUTHENTICATED) { -+ echo menu_entry(4,'Per-Directory Entries'); -+} -+echo -+ menu_entry(3,'User Cache Entries'), -+ menu_entry(9,'Version Check'); -+ -+if ($AUTHENTICATED) { -+ echo <<Clear $cache_mode Cache -+EOB; -+} -+echo << -+EOB; -+ -+ -+// CONTENT -+echo << -+EOB; -+ -+// MAIN SWITCH STATEMENT -+ -+switch ($MYREQUEST['OB']) { -+ -+ -+ -+ -+ -+// ----------------------------------------------- -+// Host Stats -+// ----------------------------------------------- -+case OB_HOST_STATS: -+ $mem_size = $mem['num_seg']*$mem['seg_size']; -+ $mem_avail= $mem['avail_mem']; -+ $mem_used = $mem_size-$mem_avail; -+ $seg_size = bsize($mem['seg_size']); -+ $req_rate = sprintf("%.2f",($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time'])); -+ $hit_rate = sprintf("%.2f",($cache['num_hits'])/($time-$cache['start_time'])); -+ $miss_rate = sprintf("%.2f",($cache['num_misses'])/($time-$cache['start_time'])); -+ $insert_rate = sprintf("%.2f",($cache['num_inserts'])/($time-$cache['start_time'])); -+ $req_rate_user = sprintf("%.2f",($cache_user['num_hits']+$cache_user['num_misses'])/($time-$cache_user['start_time'])); -+ $hit_rate_user = sprintf("%.2f",($cache_user['num_hits'])/($time-$cache_user['start_time'])); -+ $miss_rate_user = sprintf("%.2f",($cache_user['num_misses'])/($time-$cache_user['start_time'])); -+ $insert_rate_user = sprintf("%.2f",($cache_user['num_inserts'])/($time-$cache_user['start_time'])); -+ $apcversion = phpversion('apc'); -+ $phpversion = phpversion(); -+ $number_files = $cache['num_entries']; -+ $size_files = bsize($cache['mem_size']); -+ $number_vars = $cache_user['num_entries']; -+ $size_vars = bsize($cache_user['mem_size']); -+ $i=0; -+ echo <<< EOB -+

    General Cache Information

    -+ -+ -+ -+EOB; -+ -+ if(!empty($_SERVER['SERVER_NAME'])) -+ echo "\n"; -+ if(!empty($_SERVER['SERVER_SOFTWARE'])) -+ echo "\n"; -+ -+ echo << -+EOB; -+ echo ''; -+ echo ''; -+ echo ''; -+ echo <<
    APC Version$apcversion
    PHP Version$phpversion
    APC Host{$_SERVER['SERVER_NAME']} $host
    Server Software{$_SERVER['SERVER_SOFTWARE']}
    Shared Memory{$mem['num_seg']} Segment(s) with $seg_size -+
    ({$cache['memory_type']} memory, {$cache['locking_type']} locking) -+
    Start Time',date(DATE_FORMAT,$cache['start_time']),'
    Uptime',duration($cache['start_time']),'
    File Upload Support',$cache['file_upload_progress'],'
    -+
    -+ -+

    File Cache Information

    -+ -+ -+ -+ -+ -+ -+ -+ -+ -+
    Cached Files$number_files ($size_files)
    Hits{$cache['num_hits']}
    Misses{$cache['num_misses']}
    Request Rate (hits, misses)$req_rate cache requests/second
    Hit Rate$hit_rate cache requests/second
    Miss Rate$miss_rate cache requests/second
    Insert Rate$insert_rate cache requests/second
    Cache full count{$cache['expunges']}
    -+
    -+ -+

    User Cache Information

    -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+
    Cached Variables$number_vars ($size_vars)
    Hits{$cache_user['num_hits']}
    Misses{$cache_user['num_misses']}
    Request Rate (hits, misses)$req_rate_user cache requests/second
    Hit Rate$hit_rate_user cache requests/second
    Miss Rate$miss_rate_user cache requests/second
    Insert Rate$insert_rate_user cache requests/second
    Cache full count{$cache_user['expunges']}
    -+
    -+ -+

    Runtime Settings

    -+EOB; -+ -+ $j = 0; -+ foreach (ini_get_all('apc') as $k => $v) { -+ echo "\n"; -+ $j = 1 - $j; -+ } -+ -+ if($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1) -+ $mem_note = "Memory Usage
    (multiple slices indicate fragments)"; -+ else -+ $mem_note = "Memory Usage"; -+ -+ echo <<< EOB -+
    ",$k,"",str_replace(',',',
    ',$v['local_value']),"
    -+
    -+ -+

    Host Status Diagrams

    -+ -+EOB; -+ $size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10); -+ echo << -+ -+ -+ -+EOB; -+ -+ echo -+ graphics_avail() ? -+ ''. -+ "". -+ "\n" -+ : "", -+ '', -+ '\n", -+ '\n", -+ '', -+ '', -+ '\n", -+ '\n"; -+ echo <<< EOB -+ -+
    $mem_noteHits & Misses
    \"\"\"\"
     Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size)," Hits: ',$cache['num_hits'].sprintf(" (%.1f%%)",$cache['num_hits']*100/($cache['num_hits']+$cache['num_misses'])),"
     Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size)," Misses: ',$cache['num_misses'].sprintf(" (%.1f%%)",$cache['num_misses']*100/($cache['num_hits']+$cache['num_misses'])),"
    -+ -+
    -+

    Detailed Memory Usage and Fragmentation

    -+ -+ -+ -+ -+EOB; -+ if(isset($mem['adist'])) { -+ foreach($mem['adist'] as $i=>$v) { -+ $cur = pow(2,$i); $nxt = pow(2,$i+1)-1; -+ if($i==0) $range = "1"; -+ else $range = "$cur - $nxt"; -+ echo "\n"; -+ } -+ } -+ echo <<

    -+EOB; -+ -+ // Fragementation: (freeseg - 1) / total_seg -+ $nseg = $freeseg = $fragsize = $freetotal = 0; -+ for($i=0; $i<$mem['num_seg']; $i++) { -+ $ptr = 0; -+ foreach($mem['block_lists'][$i] as $block) { -+ if ($block['offset'] != $ptr) { -+ ++$nseg; -+ } -+ $ptr = $block['offset'] + $block['size']; -+ /* Only consider blocks <5M for the fragmentation % */ -+ if($block['size']<(5*1024*1024)) $fragsize+=$block['size']; -+ $freetotal+=$block['size']; -+ } -+ $freeseg += count($mem['block_lists'][$i]); -+ } -+ -+ if ($freeseg > 1) { -+ $frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg); -+ } else { -+ $frag = "0%"; -+ } -+ -+ if (graphics_avail()) { -+ $size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10); -+ echo << -+EOB; -+ } -+ echo <<Fragmentation: $frag -+
    $range$v
    -+
    -+EOB; -+ -+ break; -+ -+ -+// ----------------------------------------------- -+// User Cache Entries -+// ----------------------------------------------- -+case OB_USER_CACHE: -+ if (!$AUTHENTICATED) { -+ echo '
    You need to login to see the user values here!
     
    '; -+ put_login_link("Login now!"); -+ echo '
    '; -+ break; -+ } -+ $fieldname='info'; -+ $fieldheading='User Entry Label'; -+ $fieldkey='info'; -+ -+// ----------------------------------------------- -+// System Cache Entries -+// ----------------------------------------------- -+case OB_SYS_CACHE: -+ if (!isset($fieldname)) -+ { -+ $fieldname='filename'; -+ $fieldheading='Script Filename'; -+ if(ini_get("apc.stat")) $fieldkey='inode'; -+ else $fieldkey='filename'; -+ } -+ if (!empty($MYREQUEST['SH'])) -+ { -+ echo <<< EOB -+
    -+ -+EOB; -+ -+ $m=0; -+ foreach($scope_list as $j => $list) { -+ foreach($cache[$list] as $i => $entry) { -+ if (md5($entry[$fieldkey])!=$MYREQUEST['SH']) continue; -+ foreach($entry as $k => $value) { -+ if (!$AUTHENTICATED) { -+ // hide all path entries if not logged in -+ $value=preg_replace('/^.*(\\/|\\\\)/','<hidden>/',$value); -+ } -+ -+ if ($k == "num_hits") { -+ $value=sprintf("%s (%.2f%%)",$value,$value*100/$cache['num_hits']); -+ } -+ if ($k == 'deletion_time') { -+ if(!$entry['deletion_time']) $value = "None"; -+ } -+ echo -+ "", -+ "", -+ "", -+ ""; -+ $m=1-$m; -+ } -+ if($fieldkey=='info') { -+ echo "\n"; -+ } -+ break; -+ } -+ } -+ -+ echo <<
    AttributeValue
    ",ucwords(preg_replace("/_/"," ",$k)),"",(preg_match("/time/",$k) && $value!='None') ? date(DATE_FORMAT,$value) : htmlspecialchars($value, ENT_QUOTES, 'UTF-8'),"
    Stored Value
    ";
    -+					$output = var_export(apc_fetch($entry[$fieldkey]),true);
    -+					echo htmlspecialchars($output, ENT_QUOTES, 'UTF-8');
    -+					echo "
    -+
    -+EOB; -+ break; -+ } -+ -+ $cols=6; -+ echo <<
    Scope: -+ -+ ", -+ ", Sorting:', -+ '', -+ '', -+ '  Search: ', -+ ' ', -+ '
    '; -+ -+ if (isset($MYREQUEST['SEARCH'])) { -+ // Don't use preg_quote because we want the user to be able to specify a -+ // regular expression subpattern. -+ $MYREQUEST['SEARCH'] = '/'.str_replace('/', '\\/', $MYREQUEST['SEARCH']).'/i'; -+ if (preg_match($MYREQUEST['SEARCH'], 'test') === false) { -+ echo '
    Error: enter a valid regular expression as a search query.
    '; -+ break; -+ } -+ } -+ -+ echo -+ '
    ', -+ '', -+ '', -+ '', -+ '', -+ '', -+ '', -+ ''; -+ -+ if($fieldname=='info') { -+ $cols+=2; -+ echo ''; -+ } -+ echo ''; -+ -+ // builds list with alpha numeric sortable keys -+ // -+ $list = array(); -+ foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) { -+ switch($MYREQUEST['SORT1']) { -+ case 'A': $k=sprintf('%015d-',$entry['access_time']); break; -+ case 'H': $k=sprintf('%015d-',$entry['num_hits']); break; -+ case 'Z': $k=sprintf('%015d-',$entry['mem_size']); break; -+ case 'M': $k=sprintf('%015d-',$entry['mtime']); break; -+ case 'C': $k=sprintf('%015d-',$entry['creation_time']); break; -+ case 'T': $k=sprintf('%015d-',$entry['ttl']); break; -+ case 'D': $k=sprintf('%015d-',$entry['deletion_time']); break; -+ case 'S': $k=''; break; -+ } -+ if (!$AUTHENTICATED) { -+ // hide all path entries if not logged in -+ $list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','*hidden*/',$entry); -+ } else { -+ $list[$k.$entry[$fieldname]]=$entry; -+ } -+ } -+ -+ if ($list) { -+ -+ // sort list -+ // -+ switch ($MYREQUEST['SORT2']) { -+ case "A": krsort($list); break; -+ case "D": ksort($list); break; -+ } -+ -+ // output list -+ $i=0; -+ foreach($list as $k => $entry) { -+ if(!$MYREQUEST['SEARCH'] || preg_match($MYREQUEST['SEARCH'], $entry[$fieldname]) != 0) { -+ $field_value = htmlentities(strip_tags($entry[$fieldname],''), ENT_QUOTES, 'UTF-8'); -+ echo -+ '', -+ "', -+ '', -+ '', -+ '', -+ '', -+ ''; -+ -+ if($fieldname=='info') { -+ if($entry['ttl']) -+ echo ''; -+ else -+ echo ''; -+ } -+ if ($entry['deletion_time']) { -+ -+ echo ''; -+ } else if ($MYREQUEST['OB'] == OB_USER_CACHE) { -+ -+ echo ''; -+ } else { -+ echo ''; -+ } -+ echo ''; -+ $i++; -+ if ($i == $MYREQUEST['COUNT']) -+ break; -+ } -+ } -+ -+ } else { -+ echo ''; -+ } -+ echo <<< EOB -+
    ',sortheader('S',$fieldheading, "&OB=".$MYREQUEST['OB']),'',sortheader('H','Hits', "&OB=".$MYREQUEST['OB']),'',sortheader('Z','Size', "&OB=".$MYREQUEST['OB']),'',sortheader('A','Last accessed',"&OB=".$MYREQUEST['OB']),'',sortheader('M','Last modified',"&OB=".$MYREQUEST['OB']),'',sortheader('C','Created at', "&OB=".$MYREQUEST['OB']),'',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'
    ",$field_value,'',$entry['num_hits'],'',$entry['mem_size'],'',date(DATE_FORMAT,$entry['access_time']),'',date(DATE_FORMAT,$entry['mtime']),'',date(DATE_FORMAT,$entry['creation_time']),''.$entry['ttl'].' secondsNone', date(DATE_FORMAT,$entry['deletion_time']), ''; -+ echo '[Delete Now]'; -+ echo '  
    No data
    -+EOB; -+ -+ if ($list && $i < count($list)) { -+ echo "",count($list)-$i,' more available...'; -+ } -+ -+ echo <<< EOB -+
    -+EOB; -+ break; -+ -+ -+// ----------------------------------------------- -+// Per-Directory System Cache Entries -+// ----------------------------------------------- -+case OB_SYS_CACHE_DIR: -+ if (!$AUTHENTICATED) { -+ break; -+ } -+ -+ echo <<
    Scope: -+ -+ ", -+ ", Sorting:', -+ '', -+ '', -+ ", Group By Dir Level:', -+ ' ', -+ '
    ', -+ -+ '
    ', -+ '', -+ '', -+ '', -+ '', -+ '', -+ '', -+ '', -+ ''; -+ -+ // builds list with alpha numeric sortable keys -+ // -+ $tmp = $list = array(); -+ foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $entry) { -+ $n = dirname($entry['filename']); -+ if ($MYREQUEST['AGGR'] > 0) { -+ $n = preg_replace("!^(/?(?:[^/\\\\]+[/\\\\]){".($MYREQUEST['AGGR']-1)."}[^/\\\\]*).*!", "$1", $n); -+ } -+ if (!isset($tmp[$n])) { -+ $tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0); -+ } -+ $tmp[$n]['hits'] += $entry['num_hits']; -+ $tmp[$n]['size'] += $entry['mem_size']; -+ ++$tmp[$n]['ents']; -+ } -+ -+ foreach ($tmp as $k => $v) { -+ switch($MYREQUEST['SORT1']) { -+ case 'A': $kn=sprintf('%015d-',$v['size'] / $v['ents']);break; -+ case 'T': $kn=sprintf('%015d-',$v['ents']); break; -+ case 'H': $kn=sprintf('%015d-',$v['hits']); break; -+ case 'Z': $kn=sprintf('%015d-',$v['size']); break; -+ case 'C': $kn=sprintf('%015d-',$v['hits'] / $v['ents']);break; -+ case 'S': $kn = $k; break; -+ } -+ $list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']); -+ } -+ -+ if ($list) { -+ -+ // sort list -+ // -+ switch ($MYREQUEST['SORT2']) { -+ case "A": krsort($list); break; -+ case "D": ksort($list); break; -+ } -+ -+ // output list -+ $i = 0; -+ foreach($list as $entry) { -+ echo -+ '', -+ "', -+ '', -+ '', -+ '', -+ '', -+ '', -+ ''; -+ -+ if (++$i == $MYREQUEST['COUNT']) break; -+ } -+ -+ } else { -+ echo ''; -+ } -+ echo <<< EOB -+
    ',sortheader('S','Directory Name', "&OB=".$MYREQUEST['OB']),'',sortheader('T','Number of Files',"&OB=".$MYREQUEST['OB']),'',sortheader('H','Total Hits', "&OB=".$MYREQUEST['OB']),'',sortheader('Z','Total Size', "&OB=".$MYREQUEST['OB']),'',sortheader('C','Avg. Hits', "&OB=".$MYREQUEST['OB']),'',sortheader('A','Avg. Size', "&OB=".$MYREQUEST['OB']),'
    ",$entry[0],'',$entry[1],'',$entry[2],'',$entry[3],'',round($entry[2] / $entry[1]),'',round($entry[3] / $entry[1]),'
    No data
    -+EOB; -+ -+ if ($list && $i < count($list)) { -+ echo "",count($list)-$i,' more available...'; -+ } -+ -+ echo <<< EOB -+
    -+EOB; -+ break; -+ -+// ----------------------------------------------- -+// Version check -+// ----------------------------------------------- -+case OB_VERSION_CHECK: -+ echo <<

    APC Version Information

    -+ -+ -+ -+ -+EOB; -+ if (defined('PROXY')) { -+ $ctxt = stream_context_create( array( 'http' => array( 'proxy' => PROXY, 'request_fulluri' => True ) ) ); -+ $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss", False, $ctxt); -+ } else { -+ $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss"); -+ } -+ if (!$rss) { -+ echo ''; -+ } else { -+ $apcversion = phpversion('apc'); -+ -+ preg_match('!APC ([0-9.]+)!', $rss, $match); -+ echo ''; -+ echo ''; -+ } -+ echo <<< EOB -+
    Unable to fetch version information.
    '; -+ if (version_compare($apcversion, $match[1], '>=')) { -+ echo '
    You are running the latest version of APC ('.$apcversion.')
    '; -+ $i = 3; -+ } else { -+ echo '
    You are running an older version of APC ('.$apcversion.'), -+ newer version '.$match[1].' is available at -+ http://pecl.php.net/package/APC/'.$match[1].' -+
    '; -+ $i = -1; -+ } -+ echo '

    Change Log:


    '; -+ -+ preg_match_all('!<(title|description)>([^<]+)!', $rss, $match); -+ next($match[2]); next($match[2]); -+ -+ while (list(,$v) = each($match[2])) { -+ list(,$ver) = explode(' ', $v, 2); -+ if ($i < 0 && version_compare($apcversion, $ver, '>=')) { -+ break; -+ } else if (!$i--) { -+ break; -+ } -+ echo "".htmlspecialchars($v, ENT_QUOTES, 'UTF-8')."
    "; -+ echo nl2br(htmlspecialchars(current($match[2]), ENT_QUOTES, 'UTF-8'))."
    "; -+ next($match[2]); -+ } -+ echo '
    -+ -+EOB; -+ break; -+ -+} -+ -+echo <<< EOB -+ -+EOB; -+ -+?> -+ -+ -+ -+ -diff -Naur a/ext/apc/apc_php.h b/ext/apc/apc_php.h ---- a/ext/apc/apc_php.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_php.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,81 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | George Schlossnagle | -+ | Rasmus Lerdorf | -+ | Arun C. Murthy | -+ | Gopal Vijayaraghavan | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_php.h 313808 2011-07-28 06:17:10Z gopalv $ */ -+ -+#ifndef APC_PHP_H -+#define APC_PHP_H -+ -+/* -+ * The purpose of this header file is to include all PHP and Zend headers that -+ * are typically needed elsewhere in APC. This makes it easy to insure that -+ * all required headers are available. -+ */ -+ -+#include "php.h" -+#include "zend.h" -+#include "zend_API.h" -+#include "zend_compile.h" -+#include "zend_hash.h" -+#include "zend_extensions.h" -+ -+#if ZEND_MODULE_API_NO >= 20100409 -+#define ZEND_ENGINE_2_4 -+#endif -+#if ZEND_MODULE_API_NO > 20060613 -+#define ZEND_ENGINE_2_3 -+#endif -+#if ZEND_MODULE_API_NO > 20050922 -+#define ZEND_ENGINE_2_2 -+#endif -+#if ZEND_MODULE_API_NO > 20050921 -+#define ZEND_ENGINE_2_1 -+#endif -+#ifdef ZEND_ENGINE_2_1 -+#include "zend_vm.h" -+#endif -+ -+#ifndef IS_CONSTANT_TYPE_MASK -+#define IS_CONSTANT_TYPE_MASK (~IS_CONSTANT_INDEX) -+#endif -+ -+#include "rfc1867.h" -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_php_pcre.h b/ext/apc/apc_php_pcre.h ---- a/ext/apc/apc_php_pcre.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_php_pcre.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,98 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC/PHP Version 5 | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 1997-2011 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. | -+ +----------------------------------------------------------------------+ -+ | Author: Andrei Zmievski | -+ +----------------------------------------------------------------------+ -+ */ -+ -+/* $Id: apc_php_pcre.h 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#ifndef PHP_PCRE_H -+#define PHP_PCRE_H -+ -+#if HAVE_PCRE || HAVE_BUNDLED_PCRE -+ -+#if HAVE_BUNDLED_PCRE -+#include "ext/pcre/pcrelib/pcre.h" -+#else -+#include "pcre.h" -+#endif -+ -+#if HAVE_LOCALE_H -+#include -+#endif -+ -+PHP_FUNCTION(preg_match); -+PHP_FUNCTION(preg_match_all); -+PHP_FUNCTION(preg_replace); -+PHP_FUNCTION(preg_replace_callback); -+PHP_FUNCTION(preg_split); -+PHP_FUNCTION(preg_quote); -+PHP_FUNCTION(preg_grep); -+ -+PHPAPI char *php_pcre_replace(char *regex, int regex_len, char *subject, int subject_len, zval *replace_val, int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC); -+PHPAPI pcre* pcre_get_compiled_regex(char *regex, pcre_extra **extra, int *options TSRMLS_DC); -+PHPAPI pcre* pcre_get_compiled_regex_ex(char *regex, pcre_extra **extra, int *preg_options, int *coptions TSRMLS_DC); -+ -+extern zend_module_entry pcre_module_entry; -+#define pcre_module_ptr &pcre_module_entry -+ -+typedef struct { -+ pcre *re; -+ pcre_extra *extra; -+ int preg_options; -+#if HAVE_SETLOCALE -+ char *locale; -+ unsigned const char *tables; -+#endif -+ int compile_options; -+ int refcount; -+} pcre_cache_entry; -+ -+PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_len TSRMLS_DC); -+ -+PHPAPI void php_pcre_match_impl( pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value, -+ zval *subpats, int global, int use_flags, long flags, long start_offset TSRMLS_DC); -+ -+PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value, -+ int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC); -+ -+PHPAPI void php_pcre_split_impl( pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value, -+ long limit_val, long flags TSRMLS_DC); -+ -+PHPAPI void php_pcre_grep_impl( pcre_cache_entry *pce, zval *input, zval *return_value, -+ long flags TSRMLS_DC); -+ -+ZEND_BEGIN_MODULE_GLOBALS(pcre) -+ HashTable pcre_cache; -+ long backtrack_limit; -+ long recursion_limit; -+ int error_code; -+ZEND_END_MODULE_GLOBALS(pcre) -+ -+#ifdef ZTS -+# define PCRE_G(v) TSRMG(pcre_globals_id, zend_pcre_globals *, v) -+#else -+# define PCRE_G(v) (pcre_globals.v) -+#endif -+ -+#else -+ -+#define pcre_module_ptr NULL -+ -+#endif /* HAVE_PCRE || HAVE_BUNDLED_PCRE */ -+ -+#define phpext_pcre_ptr pcre_module_ptr -+ -+#endif /* PHP_PCRE_H */ -diff -Naur a/ext/apc/apc_pool.c b/ext/apc/apc_pool.c ---- a/ext/apc/apc_pool.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_pool.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,507 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Gopal Vijayaraghavan | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Yahoo! Inc. in 2008. -+ -+ Future revisions and derivatives of this source code must acknowledge -+ Yahoo! Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_pool.c 307555 2011-01-18 07:17:21Z gopalv $ */ -+ -+ -+#include "apc_pool.h" -+#include -+ -+#ifdef HAVE_VALGRIND_MEMCHECK_H -+#include -+#endif -+ -+ -+/* {{{ forward references */ -+static apc_pool* apc_unpool_create(apc_pool_type type, apc_malloc_t, apc_free_t, apc_protect_t, apc_unprotect_t TSRMLS_DC); -+static apc_pool* apc_realpool_create(apc_pool_type type, apc_malloc_t, apc_free_t, apc_protect_t, apc_unprotect_t TSRMLS_DC); -+/* }}} */ -+ -+/* {{{ apc_pool_create */ -+apc_pool* apc_pool_create(apc_pool_type pool_type, -+ apc_malloc_t allocate, -+ apc_free_t deallocate, -+ apc_protect_t protect, -+ apc_unprotect_t unprotect -+ TSRMLS_DC) -+{ -+ if(pool_type == APC_UNPOOL) { -+ return apc_unpool_create(pool_type, allocate, deallocate, -+ protect, unprotect TSRMLS_CC); -+ } -+ -+ return apc_realpool_create(pool_type, allocate, deallocate, -+ protect, unprotect TSRMLS_CC); -+} -+/* }}} */ -+ -+/* {{{ apc_pool_destroy */ -+void apc_pool_destroy(apc_pool *pool TSRMLS_DC) -+{ -+ apc_free_t deallocate = pool->deallocate; -+ apc_pcleanup_t cleanup = pool->cleanup; -+ -+ cleanup(pool TSRMLS_CC); -+ deallocate(pool TSRMLS_CC); -+} -+/* }}} */ -+ -+/* {{{ apc_unpool implementation */ -+ -+typedef struct _apc_unpool apc_unpool; -+ -+struct _apc_unpool { -+ apc_pool parent; -+ /* apc_unpool is a lie! */ -+}; -+ -+static void* apc_unpool_alloc(apc_pool* pool, size_t size TSRMLS_DC) -+{ -+ apc_unpool *upool = (apc_unpool*)pool; -+ -+ apc_malloc_t allocate = upool->parent.allocate; -+ -+ upool->parent.size += size; -+ upool->parent.used += size; -+ -+ return allocate(size TSRMLS_CC); -+} -+ -+static void apc_unpool_free(apc_pool* pool, void *ptr TSRMLS_DC) -+{ -+ apc_unpool *upool = (apc_unpool*) pool; -+ -+ apc_free_t deallocate = upool->parent.deallocate; -+ -+ deallocate(ptr TSRMLS_CC); -+} -+ -+static void apc_unpool_cleanup(apc_pool* pool TSRMLS_DC) -+{ -+} -+ -+static apc_pool* apc_unpool_create(apc_pool_type type, -+ apc_malloc_t allocate, apc_free_t deallocate, -+ apc_protect_t protect, apc_unprotect_t unprotect -+ TSRMLS_DC) -+{ -+ apc_unpool* upool = allocate(sizeof(apc_unpool) TSRMLS_CC); -+ -+ if (!upool) { -+ return NULL; -+ } -+ -+ upool->parent.type = type; -+ upool->parent.allocate = allocate; -+ upool->parent.deallocate = deallocate; -+ -+ upool->parent.protect = protect; -+ upool->parent.unprotect = unprotect; -+ -+ upool->parent.palloc = apc_unpool_alloc; -+ upool->parent.pfree = apc_unpool_free; -+ -+ upool->parent.cleanup = apc_unpool_cleanup; -+ -+ upool->parent.used = 0; -+ upool->parent.size = 0; -+ -+ return &(upool->parent); -+} -+/* }}} */ -+ -+ -+/*{{{ apc_realpool implementation */ -+ -+/* {{{ typedefs */ -+typedef struct _pool_block -+{ -+ size_t avail; -+ size_t capacity; -+ unsigned char *mark; -+ struct _pool_block *next; -+ unsigned :0; /* this should align to word */ -+ /* data comes here */ -+}pool_block; -+ -+/* -+ parts in ? are optional and turned on for fun, memory loss, -+ and for something else that I forgot about ... ah, debugging -+ -+ |--------> data[] |<-- non word boundary (too) -+ +-------------+--------------+-----------+-------------+-------------->>> -+ | pool_block | ?sizeinfo<1> | block<1> | ?redzone<1> | ?sizeinfo<2> -+ | | (size_t) | | padded left | -+ +-------------+--------------+-----------+-------------+-------------->>> -+ */ -+ -+typedef struct _apc_realpool apc_realpool; -+ -+struct _apc_realpool -+{ -+ struct _apc_pool parent; -+ -+ size_t dsize; -+ void *owner; -+ -+ unsigned long count; -+ -+ pool_block *head; -+ pool_block first; -+}; -+ -+/* }}} */ -+ -+/* {{{ redzone code */ -+static const unsigned char decaff[] = { -+ 0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad, -+ 0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad, -+ 0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad, -+ 0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad -+}; -+ -+/* a redzone is at least 4 (0xde,0xca,0xc0,0xff) bytes */ -+#define REDZONE_SIZE(size) \ -+ ((ALIGNWORD((size)) > ((size) + 4)) ? \ -+ (ALIGNWORD((size)) - (size)) : /* does not change realsize */\ -+ ALIGNWORD((size)) - (size) + ALIGNWORD((sizeof(char)))) /* adds 1 word to realsize */ -+ -+#define SIZEINFO_SIZE ALIGNWORD(sizeof(size_t)) -+ -+#define MARK_REDZONE(block, redsize) do {\ -+ memcpy(block, decaff, redsize );\ -+ } while(0) -+ -+#define CHECK_REDZONE(block, redsize) (memcmp(block, decaff, redsize) == 0) -+ -+/* }}} */ -+ -+#define INIT_POOL_BLOCK(rpool, entry, size) do {\ -+ (entry)->avail = (entry)->capacity = (size);\ -+ (entry)->mark = ((unsigned char*)(entry)) + ALIGNWORD(sizeof(pool_block));\ -+ (entry)->next = (rpool)->head;\ -+ (rpool)->head = (entry);\ -+} while(0) -+ -+/* {{{ create_pool_block */ -+static pool_block* create_pool_block(apc_realpool *rpool, size_t size TSRMLS_DC) -+{ -+ apc_malloc_t allocate = rpool->parent.allocate; -+ -+ size_t realsize = sizeof(pool_block) + ALIGNWORD(size); -+ -+ pool_block* entry = allocate(realsize TSRMLS_CC); -+ -+ if (!entry) { -+ return NULL; -+ } -+ -+ INIT_POOL_BLOCK(rpool, entry, size); -+ -+ rpool->parent.size += realsize; -+ -+ rpool->count++; -+ -+ return entry; -+} -+/* }}} */ -+ -+/* {{{ apc_realpool_alloc */ -+static void* apc_realpool_alloc(apc_pool *pool, size_t size TSRMLS_DC) -+{ -+ apc_realpool *rpool = (apc_realpool*)pool; -+ unsigned char *p = NULL; -+ size_t realsize = ALIGNWORD(size); -+ size_t poolsize; -+ unsigned char *redzone = NULL; -+ size_t redsize = 0; -+ size_t *sizeinfo= NULL; -+ pool_block *entry = NULL; -+ unsigned long i; -+ -+ if(APC_POOL_HAS_REDZONES(pool)) { -+ redsize = REDZONE_SIZE(size); /* redsize might be re-using word size padding */ -+ realsize = size + redsize; /* recalculating realsize */ -+ } else { -+ redsize = realsize - size; /* use padding space */ -+ } -+ -+ if(APC_POOL_HAS_SIZEINFO(pool)) { -+ realsize += ALIGNWORD(sizeof(size_t)); -+ } -+ -+ /* minimize look-back, a value of 8 seems to give similar fill-ratios (+2%) -+ * as looping through the entire list. And much faster in allocations. */ -+ for(entry = rpool->head, i = 0; entry != NULL && (i < 8); entry = entry->next, i++) { -+ if(entry->avail >= realsize) { -+ goto found; -+ } -+ } -+ -+ /* upgrade the pool type to reduce overhead */ -+ if(rpool->count > 4 && rpool->dsize < 4096) { -+ rpool->dsize = 4096; -+ } else if(rpool->count > 8 && rpool->dsize < 8192) { -+ rpool->dsize = 8192; -+ } -+ -+ poolsize = ALIGNSIZE(realsize, rpool->dsize); -+ -+ entry = create_pool_block(rpool, poolsize TSRMLS_CC); -+ -+ if(!entry) { -+ return NULL; -+ } -+ -+found: -+ p = entry->mark; -+ -+ if(APC_POOL_HAS_SIZEINFO(pool)) { -+ sizeinfo = (size_t*)p; -+ p += SIZEINFO_SIZE; -+ *sizeinfo = size; -+ } -+ -+ redzone = p + size; -+ -+ if(APC_POOL_HAS_REDZONES(pool)) { -+ MARK_REDZONE(redzone, redsize); -+ } -+ -+#ifdef VALGRIND_MAKE_MEM_NOACCESS -+ if(redsize != 0) { -+ VALGRIND_MAKE_MEM_NOACCESS(redzone, redsize); -+ } -+#endif -+ -+ entry->avail -= realsize; -+ entry->mark += realsize; -+ pool->used += realsize; -+ -+#ifdef VALGRIND_MAKE_MEM_UNDEFINED -+ /* need to write before reading data off this */ -+ VALGRIND_MAKE_MEM_UNDEFINED(p, size); -+#endif -+ -+ return (void*)p; -+} -+/* }}} */ -+ -+/* {{{ apc_realpool_check_integrity */ -+/* -+ * Checking integrity at runtime, does an -+ * overwrite check only when the sizeinfo -+ * is set. -+ * -+ * Marked as used in gcc, so that this function -+ * is accessible from gdb, eventhough it is never -+ * used in code in non-debug builds. -+ */ -+static APC_USED int apc_realpool_check_integrity(apc_realpool *rpool) -+{ -+ apc_pool *pool = &(rpool->parent); -+ pool_block *entry; -+ size_t *sizeinfo = NULL; -+ unsigned char *start; -+ size_t realsize; -+ unsigned char *redzone; -+ size_t redsize; -+ -+ for(entry = rpool->head; entry != NULL; entry = entry->next) { -+ start = (unsigned char *)entry + ALIGNWORD(sizeof(pool_block)); -+ if((entry->mark - start) != (entry->capacity - entry->avail)) { -+ return 0; -+ } -+ } -+ -+ if(!APC_POOL_HAS_REDZONES(pool) || -+ !APC_POOL_HAS_SIZEINFO(pool)) { -+ (void)pool; /* remove unused warning */ -+ return 1; -+ } -+ -+ for(entry = rpool->head; entry != NULL; entry = entry->next) { -+ start = (unsigned char *)entry + ALIGNWORD(sizeof(pool_block)); -+ -+ while(start < entry->mark) { -+ sizeinfo = (size_t*)start; -+ /* redzone starts where real data ends, in a non-word boundary -+ * redsize is at least 4 bytes + whatever's needed to make it -+ * to another word boundary. -+ */ -+ redzone = start + SIZEINFO_SIZE + (*sizeinfo); -+ redsize = REDZONE_SIZE(*sizeinfo); -+#ifdef VALGRIND_MAKE_MEM_DEFINED -+ VALGRIND_MAKE_MEM_DEFINED(redzone, redsize); -+#endif -+ if(!CHECK_REDZONE(redzone, redsize)) -+ { -+ /* -+ fprintf(stderr, "Redzone check failed for %p\n", -+ start + ALIGNWORD(sizeof(size_t)));*/ -+ return 0; -+ } -+#ifdef VALGRIND_MAKE_MEM_NOACCESS -+ VALGRIND_MAKE_MEM_NOACCESS(redzone, redsize); -+#endif -+ realsize = SIZEINFO_SIZE + *sizeinfo + redsize; -+ start += realsize; -+ } -+ } -+ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ apc_realpool_free */ -+/* -+ * free does not do anything other than -+ * check for redzone values when free'ing -+ * data areas. -+ */ -+static void apc_realpool_free(apc_pool *pool, void *p TSRMLS_DC) -+{ -+} -+/* }}} */ -+ -+static void apc_realpool_cleanup(apc_pool *pool TSRMLS_DC) -+{ -+ pool_block *entry; -+ pool_block *tmp; -+ apc_realpool *rpool = (apc_realpool*)pool; -+ apc_free_t deallocate = pool->deallocate; -+ -+ assert(apc_realpool_check_integrity(rpool)!=0); -+ -+ entry = rpool->head; -+ -+ while(entry->next != NULL) { -+ tmp = entry->next; -+ deallocate(entry TSRMLS_CC); -+ entry = tmp; -+ } -+} -+ -+/* {{{ apc_realpool_create */ -+static apc_pool* apc_realpool_create(apc_pool_type type, apc_malloc_t allocate, apc_free_t deallocate, -+ apc_protect_t protect, apc_unprotect_t unprotect -+ TSRMLS_DC) -+{ -+ -+ size_t dsize = 0; -+ apc_realpool *rpool; -+ -+ switch(type & APC_POOL_SIZE_MASK) { -+ case APC_SMALL_POOL: -+ dsize = 512; -+ break; -+ -+ case APC_LARGE_POOL: -+ dsize = 8192; -+ break; -+ -+ case APC_MEDIUM_POOL: -+ dsize = 4096; -+ break; -+ -+ default: -+ return NULL; -+ } -+ -+ rpool = (apc_realpool*)allocate((sizeof(apc_realpool) + ALIGNWORD(dsize)) TSRMLS_CC); -+ -+ if(!rpool) { -+ return NULL; -+ } -+ -+ rpool->parent.type = type; -+ -+ rpool->parent.allocate = allocate; -+ rpool->parent.deallocate = deallocate; -+ -+ rpool->parent.size = sizeof(apc_realpool) + ALIGNWORD(dsize); -+ -+ rpool->parent.palloc = apc_realpool_alloc; -+ rpool->parent.pfree = apc_realpool_free; -+ -+ rpool->parent.protect = protect; -+ rpool->parent.unprotect = unprotect; -+ -+ rpool->parent.cleanup = apc_realpool_cleanup; -+ -+ rpool->dsize = dsize; -+ rpool->head = NULL; -+ rpool->count = 0; -+ -+ INIT_POOL_BLOCK(rpool, &(rpool->first), dsize); -+ -+ return &(rpool->parent); -+} -+ -+ -+/* }}} */ -+ -+/* {{{ apc_pool_init */ -+void apc_pool_init() -+{ -+ /* put all ye sanity checks here */ -+ assert(sizeof(decaff) > REDZONE_SIZE(ALIGNWORD(sizeof(char)))); -+ assert(sizeof(pool_block) == ALIGNWORD(sizeof(pool_block))); -+#if APC_POOL_DEBUG -+ assert((APC_POOL_SIZE_MASK & (APC_POOL_SIZEINFO | APC_POOL_REDZONES)) == 0); -+#endif -+} -+/* }}} */ -+ -+/* {{{ apc_pstrdup */ -+void* APC_ALLOC apc_pstrdup(const char* s, apc_pool* pool TSRMLS_DC) -+{ -+ return s != NULL ? apc_pmemcpy(s, (strlen(s) + 1), pool TSRMLS_CC) : NULL; -+} -+/* }}} */ -+ -+/* {{{ apc_pmemcpy */ -+void* APC_ALLOC apc_pmemcpy(const void* p, size_t n, apc_pool* pool TSRMLS_DC) -+{ -+ void* q; -+ -+ if (p != NULL && (q = apc_pool_alloc(pool, n)) != NULL) { -+ memcpy(q, p, n); -+ return q; -+ } -+ return NULL; -+} -+/* }}} */ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_pool.h b/ext/apc/apc_pool.h ---- a/ext/apc/apc_pool.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_pool.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,114 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Gopal Vijayaraghavan | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Yahoo! Inc. in 2008. -+ -+ Future revisions and derivatives of this source code must acknowledge -+ Yahoo! Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_pool.h 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#ifndef APC_POOL_H -+#define APC_POOL_H -+ -+#include "apc.h" -+#include "apc_sma.h" -+ -+/* #define APC_POOL_DEBUG 1 */ -+ -+typedef enum { -+ APC_UNPOOL = 0x0, -+ APC_SMALL_POOL = 0x1, -+ APC_MEDIUM_POOL = 0x2, -+ APC_LARGE_POOL = 0x3, -+ APC_POOL_SIZE_MASK = 0x7, /* waste a bit */ -+#if APC_POOL_DEBUG -+ APC_POOL_REDZONES = 0x08, -+ APC_POOL_SIZEINFO = 0x10, -+ APC_POOL_OPT_MASK = 0x18 -+#endif -+} apc_pool_type; -+ -+#if APC_POOL_DEBUG -+#define APC_POOL_HAS_SIZEINFO(pool) ((pool->type & APC_POOL_SIZEINFO)!=0) -+#define APC_POOL_HAS_REDZONES(pool) ((pool->type & APC_POOL_REDZONES)!=0) -+#else -+/* let gcc optimize away the optional features */ -+#define APC_POOL_HAS_SIZEINFO(pool) (0) -+#define APC_POOL_HAS_REDZONES(pool) (0) -+#endif -+ -+ -+typedef struct _apc_pool apc_pool; -+ -+typedef void (*apc_pcleanup_t)(apc_pool *pool TSRMLS_DC); -+ -+typedef void* (*apc_palloc_t)(apc_pool *pool, size_t size TSRMLS_DC); -+typedef void (*apc_pfree_t) (apc_pool *pool, void* p TSRMLS_DC); -+ -+typedef void* (*apc_protect_t) (void *p); -+typedef void* (*apc_unprotect_t)(void *p); -+ -+struct _apc_pool { -+ apc_pool_type type; -+ -+ apc_malloc_t allocate; -+ apc_free_t deallocate; -+ -+ apc_palloc_t palloc; -+ apc_pfree_t pfree; -+ -+ apc_protect_t protect; -+ apc_unprotect_t unprotect; -+ -+ apc_pcleanup_t cleanup; -+ -+ size_t size; -+ size_t used; -+ -+ /* apc_realpool and apc_unpool add more here */ -+}; -+ -+#define apc_pool_alloc(pool, size) ((void *) pool->palloc(pool, size TSRMLS_CC)) -+#define apc_pool_free(pool, ptr) ((void) pool->pfree (pool, ptr TSRMLS_CC)) -+ -+#define apc_pool_protect(pool, ptr) (pool->protect ? \ -+ (pool)->protect((ptr)) : (ptr)) -+ -+#define apc_pool_unprotect(pool, ptr) (pool->unprotect ? \ -+ (pool)->unprotect((ptr)) : (ptr)) -+ -+extern void apc_pool_init(); -+ -+extern apc_pool* apc_pool_create(apc_pool_type pool_type, -+ apc_malloc_t allocate, -+ apc_free_t deallocate, -+ apc_protect_t protect, -+ apc_unprotect_t unprotect -+ TSRMLS_DC); -+ -+extern void apc_pool_destroy(apc_pool* pool TSRMLS_DC); -+ -+extern void* apc_pmemcpy(const void* p, size_t n, apc_pool* pool TSRMLS_DC); -+extern void* apc_pstrdup(const char* s, apc_pool* pool TSRMLS_DC); -+ -+#endif -diff -Naur a/ext/apc/apc_pthreadmutex.c b/ext/apc/apc_pthreadmutex.c ---- a/ext/apc/apc_pthreadmutex.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_pthreadmutex.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,111 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Brian Shire | -+ +----------------------------------------------------------------------+ -+ -+ */ -+ -+/* $Id: apc_pthreadmutex.c 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#include "apc_pthreadmutex.h" -+ -+#ifdef APC_PTHREADMUTEX_LOCKS -+ -+pthread_mutex_t *apc_pthreadmutex_create(pthread_mutex_t *lock TSRMLS_DC) -+{ -+ int result; -+ pthread_mutexattr_t* attr; -+ attr = malloc(sizeof(pthread_mutexattr_t)); -+ -+ result = pthread_mutexattr_init(attr); -+ if(result == ENOMEM) { -+ apc_error("pthread mutex error: Insufficient memory exists to create the mutex attribute object." TSRMLS_CC); -+ } else if(result == EINVAL) { -+ apc_error("pthread mutex error: attr does not point to writeable memory." TSRMLS_CC); -+ } else if(result == EFAULT) { -+ apc_error("pthread mutex error: attr is an invalid pointer." TSRMLS_CC); -+ } -+ -+#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP -+ result = pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ADAPTIVE_NP); -+ if (result == EINVAL) { -+ apc_error("pthread_mutexattr_settype: unable to set adaptive mutexes" TSRMLS_CC); -+ } -+#endif -+ -+ /* pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ERRORCHECK); */ -+ result = pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED); -+ if(result == EINVAL) { -+ apc_error("pthread mutex error: attr is not an initialized mutex attribute object, or pshared is not a valid process-shared state setting." TSRMLS_CC); -+ } else if(result == EFAULT) { -+ apc_error("pthread mutex error: attr is an invalid pointer." TSRMLS_CC); -+ } else if(result == ENOTSUP) { -+ apc_error("pthread mutex error: pshared was set to PTHREAD_PROCESS_SHARED." TSRMLS_CC); -+ } -+ -+ if(pthread_mutex_init(lock, attr)) { -+ apc_error("unable to initialize pthread lock" TSRMLS_CC); -+ } -+ return lock; -+} -+ -+void apc_pthreadmutex_destroy(pthread_mutex_t *lock) -+{ -+ return; /* we don't actually destroy the mutex, as it would destroy it for all processes */ -+} -+ -+void apc_pthreadmutex_lock(pthread_mutex_t *lock TSRMLS_DC) -+{ -+ int result; -+ result = pthread_mutex_lock(lock); -+ if(result == EINVAL) { -+ apc_error("unable to obtain pthread lock (EINVAL)" TSRMLS_CC); -+ } else if(result == EDEADLK) { -+ apc_error("unable to obtain pthread lock (EDEADLK)" TSRMLS_CC); -+ } -+} -+ -+void apc_pthreadmutex_unlock(pthread_mutex_t *lock TSRMLS_DC) -+{ -+ if(pthread_mutex_unlock(lock)) { -+ apc_error("unable to unlock pthread lock" TSRMLS_CC); -+ } -+} -+ -+zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock TSRMLS_DC) -+{ -+ int rval; -+ rval = pthread_mutex_trylock(lock); -+ if(rval == EBUSY) { /* Lock is already held */ -+ return 0; -+ } else if(rval == 0) { /* Obtained lock */ -+ return 1; -+ } else { /* Other error */ -+ apc_error("unable to obtain pthread trylock" TSRMLS_CC); -+ return 0; -+ } -+} -+ -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_pthreadmutex.h b/ext/apc/apc_pthreadmutex.h ---- a/ext/apc/apc_pthreadmutex.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_pthreadmutex.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,48 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Brian Shire | -+ +----------------------------------------------------------------------+ -+ -+ */ -+ -+/* $Id: apc_pthreadmutex.h 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#ifndef APC_PTHREADMUTEX_H -+#define APC_PTHREADMUTEX_H -+ -+#include "apc.h" -+ -+#ifdef APC_PTHREADMUTEX_LOCKS -+ -+#include -+ -+pthread_mutex_t *apc_pthreadmutex_create(pthread_mutex_t *lock TSRMLS_DC); -+void apc_pthreadmutex_destroy(pthread_mutex_t *lock); -+void apc_pthreadmutex_lock(pthread_mutex_t *lock TSRMLS_DC); -+void apc_pthreadmutex_unlock(pthread_mutex_t *lock TSRMLS_DC); -+zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock TSRMLS_DC); -+ -+#endif -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_pthreadrwlock.c b/ext/apc/apc_pthreadrwlock.c ---- a/ext/apc/apc_pthreadrwlock.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_pthreadrwlock.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,120 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Gopal V | -+ +----------------------------------------------------------------------+ -+ -+ */ -+ -+/* $Id: $ */ -+ -+#include "apc_pthreadrwlock.h" -+ -+#ifdef APC_PTHREADRW_LOCKS -+ -+pthread_rwlock_t *apc_pthreadrwlock_create(pthread_rwlock_t *lock TSRMLS_DC) -+{ -+ int result; -+ pthread_rwlockattr_t attr; -+ -+ result = pthread_rwlockattr_init(&attr); -+ if(result == ENOMEM) { -+ apc_error("pthread rwlock error: Insufficient memory exists to create the rwlock attribute object." TSRMLS_CC); -+ } else if(result == EINVAL) { -+ apc_error("pthread rwlock error: attr does not point to writeable memory." TSRMLS_CC); -+ } else if(result == EFAULT) { -+ apc_error("pthread rwlock error: attr is an invalid pointer." TSRMLS_CC); -+ } -+ -+#ifdef __USE_UNIX98 -+ pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); -+#endif -+ -+ result = pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); -+ if(result == EINVAL) { -+ apc_error("pthread rwlock error: attr is not an initialized rwlock attribute object, or pshared is not a valid process-shared state setting." TSRMLS_CC); -+ } else if(result == EFAULT) { -+ apc_error("pthread rwlock error: attr is an invalid pointer." TSRMLS_CC); -+ } else if(result == ENOTSUP) { -+ apc_error("pthread rwlock error: pshared was set to PTHREAD_PROCESS_SHARED." TSRMLS_CC); -+ } -+ -+ if(pthread_rwlock_init(lock, &attr)) { -+ apc_error("unable to initialize pthread rwlock" TSRMLS_CC); -+ } -+ -+ pthread_rwlockattr_destroy(&attr); -+ -+ return lock; -+} -+ -+void apc_pthreadrwlock_destroy(pthread_rwlock_t *lock) -+{ -+ return; /* we don't actually destroy the rwlock, as it would destroy it for all processes */ -+} -+ -+void apc_pthreadrwlock_lock(pthread_rwlock_t *lock TSRMLS_DC) -+{ -+ int result; -+ result = pthread_rwlock_wrlock(lock); -+ if(result == EINVAL) { -+ apc_error("unable to obtain pthread lock (EINVAL)" TSRMLS_CC); -+ } else if(result == EDEADLK) { -+ apc_error("unable to obtain pthread lock (EDEADLK)" TSRMLS_CC); -+ } -+} -+ -+void apc_pthreadrwlock_rdlock(pthread_rwlock_t *lock TSRMLS_DC) -+{ -+ int result; -+ result = pthread_rwlock_rdlock(lock); -+ if(result == EINVAL) { -+ apc_error("unable to obtain pthread lock (EINVAL)" TSRMLS_CC); -+ } else if(result == EDEADLK) { -+ apc_error("unable to obtain pthread lock (EDEADLK)" TSRMLS_CC); -+ } -+} -+ -+void apc_pthreadrwlock_unlock(pthread_rwlock_t *lock TSRMLS_DC) -+{ -+ if(pthread_rwlock_unlock(lock)) { -+ apc_error("unable to unlock pthread lock" TSRMLS_CC); -+ } -+} -+ -+zend_bool apc_pthreadrwlock_nonblocking_lock(pthread_rwlock_t *lock TSRMLS_DC) -+{ -+ int rval; -+ rval = pthread_rwlock_trywrlock(lock); -+ if(rval == EBUSY) { /* Lock is already held */ -+ return 0; -+ } else if(rval == 0) { /* Obtained lock */ -+ return 1; -+ } else { /* Other error */ -+ apc_error("unable to obtain pthread trylock" TSRMLS_CC); -+ return 0; -+ } -+} -+ -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_pthreadrwlock.h b/ext/apc/apc_pthreadrwlock.h ---- a/ext/apc/apc_pthreadrwlock.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_pthreadrwlock.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,49 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Gopal V | -+ +----------------------------------------------------------------------+ -+ -+ */ -+ -+/* $Id: apc_pthreadrwlock.h 302175 2010-08-13 06:20:28Z kalle $ */ -+ -+#ifndef APC_PTHREADRWLOCK_H -+#define APC_PTHREADRWLOCK_H -+ -+#include "apc.h" -+ -+#ifdef APC_PTHREADRW_LOCKS -+ -+#include -+ -+pthread_rwlock_t *apc_pthreadrwlock_create(pthread_rwlock_t *lock TSRMLS_DC); -+void apc_pthreadrwlock_destroy(pthread_rwlock_t *lock); -+void apc_pthreadrwlock_lock(pthread_rwlock_t *lock TSRMLS_DC); -+void apc_pthreadrwlock_rdlock(pthread_rwlock_t *lock TSRMLS_DC); -+void apc_pthreadrwlock_unlock(pthread_rwlock_t *lock TSRMLS_DC); -+zend_bool apc_pthreadrwlock_nonblocking_lock(pthread_rwlock_t *lock TSRMLS_DC); -+ -+#endif -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_rfc1867.c b/ext/apc/apc_rfc1867.c ---- a/ext/apc/apc_rfc1867.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_rfc1867.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,236 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Rasmus Lerdorf | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_rfc1867.c 309694 2011-03-25 18:47:38Z rasmus $*/ -+ -+#include "apc.h" -+#include "apc_globals.h" -+#include "rfc1867.h" -+ -+#ifdef PHP_WIN32 -+#include "win32/time.h" -+#endif -+ -+#ifdef MULTIPART_EVENT_FORMDATA -+extern int _apc_store(char *strkey, int strkey_len, const zval *val, const uint ttl, const int exclusive TSRMLS_DC); -+extern int _apc_update(char *strkey, int strkey_len, apc_cache_updater_t updater, void* data TSRMLS_DC); -+ -+static int update_bytes_processed(apc_cache_t* cache, apc_cache_entry_t* entry, void* data) { -+ int *bytes_ptr = (int*)data; -+ zval* val = entry->data.user.val; -+ -+ if(Z_TYPE_P(val) == IS_ARRAY) { -+ HashTable *ht = val->value.ht; -+ Bucket* curr = NULL; -+ for (curr = ht->pListHead; curr != NULL; curr = curr->pListNext) { -+ if(curr->nKeyLength == 8 && -+ (!memcmp(curr->arKey, "current", curr->nKeyLength))) { -+ zval* current = ((zval**)curr->pData)[0]; -+ current->value.lval = *bytes_ptr; -+ return 1; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static double my_time() { -+ struct timeval a; -+ double t; -+ gettimeofday(&a, NULL); -+ t = a.tv_sec + (a.tv_usec/1000000.00); -+ return t; -+} -+ -+ -+#define RFC1867_DATA(name) \ -+ ((request_data)->name) -+ -+int apc_rfc1867_progress(uint event, void *event_data, void **extra TSRMLS_DC) { -+ apc_rfc1867_data *request_data = &APCG(rfc1867_data); -+ zval *track = NULL; -+ -+ switch (event) { -+ case MULTIPART_EVENT_START: -+ { -+ multipart_event_start *data = (multipart_event_start *) event_data; -+ -+ RFC1867_DATA(content_length) = data->content_length; -+ RFC1867_DATA(tracking_key)[0] = '\0'; -+ RFC1867_DATA(name)[0] = '\0'; -+ RFC1867_DATA(cancel_upload) = 0; -+ RFC1867_DATA(temp_filename) = NULL; -+ RFC1867_DATA(filename)[0] = '\0'; -+ RFC1867_DATA(key_length) = 0; -+ RFC1867_DATA(start_time) = my_time(); -+ RFC1867_DATA(bytes_processed) = 0; -+ RFC1867_DATA(prev_bytes_processed) = 0; -+ RFC1867_DATA(rate) = 0; -+ RFC1867_DATA(update_freq) = (int) APCG(rfc1867_freq); -+ RFC1867_DATA(started) = 0; -+ -+ if(RFC1867_DATA(update_freq) < 0) { // frequency is a percentage, not bytes -+ RFC1867_DATA(update_freq) = (int) (RFC1867_DATA(content_length) * APCG(rfc1867_freq) / 100); -+ } -+ } -+ break; -+ -+ case MULTIPART_EVENT_FORMDATA: -+ { -+ int prefix_len = strlen(APCG(rfc1867_prefix)); -+ multipart_event_formdata *data = (multipart_event_formdata *) event_data; -+ if(data->name && !strncasecmp(data->name, APCG(rfc1867_name), strlen(APCG(rfc1867_name))) -+ && data->value && data->length) { -+ -+ if(data->length >= sizeof(RFC1867_DATA(tracking_key)) - prefix_len) { -+ apc_warning("Key too long for '%s'. Maximum size is '%d' characters." TSRMLS_CC, -+ APCG(rfc1867_name), -+ sizeof(RFC1867_DATA(tracking_key)) - prefix_len); -+ break; -+ } -+ -+ if(RFC1867_DATA(started)) { -+ apc_warning("Upload progress key '%s' should be before the file upload entry in the form." TSRMLS_CC, -+ APCG(rfc1867_name)); -+ break; -+ } -+ -+ strlcat(RFC1867_DATA(tracking_key), APCG(rfc1867_prefix), 63); -+ strlcat(RFC1867_DATA(tracking_key), *data->value, 63); -+ RFC1867_DATA(key_length) = data->length + prefix_len; -+ RFC1867_DATA(bytes_processed) = data->post_bytes_processed; -+ } -+ } -+ break; -+ -+ case MULTIPART_EVENT_FILE_START: -+ { -+ RFC1867_DATA(started) = 1; -+ if(*RFC1867_DATA(tracking_key)) { -+ multipart_event_file_start *data = (multipart_event_file_start *) event_data; -+ -+ RFC1867_DATA(bytes_processed) = data->post_bytes_processed; -+ strlcpy(RFC1867_DATA(filename),*data->filename,128); -+ RFC1867_DATA(temp_filename) = NULL; -+ strlcpy(RFC1867_DATA(name),data->name,64); -+ ALLOC_INIT_ZVAL(track); -+ array_init(track); -+ add_assoc_long(track, "total", RFC1867_DATA(content_length)); -+ add_assoc_long(track, "current", RFC1867_DATA(bytes_processed)); -+ add_assoc_string(track, "filename", RFC1867_DATA(filename), 1); -+ add_assoc_string(track, "name", RFC1867_DATA(name), 1); -+ add_assoc_long(track, "done", 0); -+ add_assoc_double(track, "start_time", RFC1867_DATA(start_time)); -+ _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length)+1, track, APCG(rfc1867_ttl), 0 TSRMLS_CC); -+ zval_ptr_dtor(&track); -+ } -+ } -+ break; -+ -+ case MULTIPART_EVENT_FILE_DATA: -+ if(*RFC1867_DATA(tracking_key)) { -+ multipart_event_file_data *data = (multipart_event_file_data *) event_data; -+ RFC1867_DATA(bytes_processed) = data->post_bytes_processed; -+ if(RFC1867_DATA(bytes_processed) - RFC1867_DATA(prev_bytes_processed) > (uint) RFC1867_DATA(update_freq)) { -+ if(!_apc_update(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length), update_bytes_processed, &RFC1867_DATA(bytes_processed) TSRMLS_CC)) { -+ ALLOC_INIT_ZVAL(track); -+ array_init(track); -+ add_assoc_long(track, "total", RFC1867_DATA(content_length)); -+ add_assoc_long(track, "current", RFC1867_DATA(bytes_processed)); -+ add_assoc_string(track, "filename", RFC1867_DATA(filename), 1); -+ add_assoc_string(track, "name", RFC1867_DATA(name), 1); -+ add_assoc_long(track, "done", 0); -+ add_assoc_double(track, "start_time", RFC1867_DATA(start_time)); -+ _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length)+1, track, APCG(rfc1867_ttl), 0 TSRMLS_CC); -+ zval_ptr_dtor(&track); -+ } -+ RFC1867_DATA(prev_bytes_processed) = RFC1867_DATA(bytes_processed); -+ } -+ } -+ break; -+ -+ case MULTIPART_EVENT_FILE_END: -+ if(*RFC1867_DATA(tracking_key)) { -+ multipart_event_file_end *data = (multipart_event_file_end *) event_data; -+ RFC1867_DATA(bytes_processed) = data->post_bytes_processed; -+ RFC1867_DATA(cancel_upload) = data->cancel_upload; -+ if(data->temp_filename) { -+ RFC1867_DATA(temp_filename) = data->temp_filename; -+ } else { -+ RFC1867_DATA(temp_filename) = ""; -+ } -+ ALLOC_INIT_ZVAL(track); -+ array_init(track); -+ add_assoc_long(track, "total", RFC1867_DATA(content_length)); -+ add_assoc_long(track, "current", RFC1867_DATA(bytes_processed)); -+ add_assoc_string(track, "filename", RFC1867_DATA(filename), 1); -+ add_assoc_string(track, "name", RFC1867_DATA(name), 1); -+ add_assoc_string(track, "temp_filename", RFC1867_DATA(temp_filename), 1); -+ add_assoc_long(track, "cancel_upload", RFC1867_DATA(cancel_upload)); -+ add_assoc_long(track, "done", 0); -+ add_assoc_double(track, "start_time", RFC1867_DATA(start_time)); -+ _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length)+1, track, APCG(rfc1867_ttl), 0 TSRMLS_CC); -+ zval_ptr_dtor(&track); -+ } -+ break; -+ -+ case MULTIPART_EVENT_END: -+ if(*RFC1867_DATA(tracking_key)) { -+ double now = my_time(); -+ multipart_event_end *data = (multipart_event_end *) event_data; -+ RFC1867_DATA(bytes_processed) = data->post_bytes_processed; -+ if(now>RFC1867_DATA(start_time)) RFC1867_DATA(rate) = 8.0*RFC1867_DATA(bytes_processed)/(now-RFC1867_DATA(start_time)); -+ else RFC1867_DATA(rate) = 8.0*RFC1867_DATA(bytes_processed); /* Too quick */ -+ ALLOC_INIT_ZVAL(track); -+ array_init(track); -+ add_assoc_long(track, "total", RFC1867_DATA(content_length)); -+ add_assoc_long(track, "current", RFC1867_DATA(bytes_processed)); -+ add_assoc_double(track, "rate", RFC1867_DATA(rate)); -+ add_assoc_string(track, "filename", RFC1867_DATA(filename), 1); -+ add_assoc_string(track, "name", RFC1867_DATA(name), 1); -+ add_assoc_long(track, "cancel_upload", RFC1867_DATA(cancel_upload)); -+ add_assoc_long(track, "done", 1); -+ add_assoc_double(track, "start_time", RFC1867_DATA(start_time)); -+ _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length)+1, track, APCG(rfc1867_ttl), 0 TSRMLS_CC); -+ zval_ptr_dtor(&track); -+ } -+ break; -+ } -+ -+ return SUCCESS; -+} -+ -+#endif -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_sem.c b/ext/apc/apc_sem.c ---- a/ext/apc/apc_sem.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_sem.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,192 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_sem.c 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#include "apc.h" -+ -+#ifdef APC_SEM_LOCKS -+ -+#include "apc_sem.h" -+#include "php.h" -+#include -+#include -+#include -+#include -+#include -+ -+#if HAVE_SEMUN -+/* we have semun, no need to define */ -+#else -+#undef HAVE_SEMUN -+union semun { -+ int val; /* value for SETVAL */ -+ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ -+ unsigned short *array; /* array for GETALL, SETALL */ -+ /* Linux specific part: */ -+ struct seminfo *__buf; /* buffer for IPC_INFO */ -+}; -+#define HAVE_SEMUN 1 -+#endif -+ -+#ifndef SEM_R -+# define SEM_R 0444 -+#endif -+#ifndef SEM_A -+# define SEM_A 0222 -+#endif -+ -+/* always use SEM_UNDO, otherwise we risk deadlock */ -+#define USE_SEM_UNDO -+ -+#ifdef USE_SEM_UNDO -+# define UNDO SEM_UNDO -+#else -+# define UNDO 0 -+#endif -+ -+int apc_sem_create(int proj, int initval TSRMLS_DC) -+{ -+ int semid; -+ int perms = 0777; -+ union semun arg; -+ key_t key = IPC_PRIVATE; -+ -+ if ((semid = semget(key, 1, IPC_CREAT | IPC_EXCL | perms)) >= 0) { -+ /* sempahore created for the first time, initialize now */ -+ arg.val = initval; -+ if (semctl(semid, 0, SETVAL, arg) < 0) { -+ apc_error("apc_sem_create: semctl(%d,...) failed:" TSRMLS_CC, semid); -+ } -+ } -+ else if (errno == EEXIST) { -+ /* sempahore already exists, don't initialize */ -+ if ((semid = semget(key, 1, perms)) < 0) { -+ apc_error("apc_sem_create: semget(%u,...) failed:" TSRMLS_CC, key); -+ } -+ /* insert here */ -+ } -+ else { -+ apc_error("apc_sem_create: semget(%u,...) failed:" TSRMLS_CC, key); -+ } -+ -+ return semid; -+} -+ -+void apc_sem_destroy(int semid) -+{ -+ /* we expect this call to fail often, so we do not check */ -+ union semun arg; -+ semctl(semid, 0, IPC_RMID, arg); -+} -+ -+void apc_sem_lock(int semid TSRMLS_DC) -+{ -+ struct sembuf op; -+ -+ op.sem_num = 0; -+ op.sem_op = -1; -+ op.sem_flg = UNDO; -+ -+ if (semop(semid, &op, 1) < 0) { -+ if (errno != EINTR) { -+ apc_error("apc_sem_lock: semop(%d) failed:" TSRMLS_CC, semid); -+ } -+ } -+} -+ -+int apc_sem_nonblocking_lock(int semid TSRMLS_DC) -+{ -+ struct sembuf op; -+ -+ op.sem_num = 0; -+ op.sem_op = -1; -+ op.sem_flg = UNDO | IPC_NOWAIT; -+ -+ if (semop(semid, &op, 1) < 0) { -+ if (errno == EAGAIN) { -+ return 0; /* Lock is already held */ -+ } else if (errno != EINTR) { -+ apc_error("apc_sem_lock: semop(%d) failed:" TSRMLS_CC, semid); -+ } -+ } -+ -+ return 1; /* Lock obtained */ -+} -+ -+void apc_sem_unlock(int semid TSRMLS_DC) -+{ -+ struct sembuf op; -+ -+ op.sem_num = 0; -+ op.sem_op = 1; -+ op.sem_flg = UNDO; -+ -+ if (semop(semid, &op, 1) < 0) { -+ if (errno != EINTR) { -+ apc_error("apc_sem_unlock: semop(%d) failed:" TSRMLS_CC, semid); -+ } -+ } -+} -+ -+void apc_sem_wait_for_zero(int semid TSRMLS_DC) -+{ -+ struct sembuf op; -+ -+ op.sem_num = 0; -+ op.sem_op = 0; -+ op.sem_flg = UNDO; -+ -+ if (semop(semid, &op, 1) < 0) { -+ if (errno != EINTR) { -+ apc_error("apc_sem_waitforzero: semop(%d) failed:" TSRMLS_CC, semid); -+ } -+ } -+} -+ -+int apc_sem_get_value(int semid TSRMLS_DC) -+{ -+ union semun arg; -+ unsigned short val[1]; -+ -+ arg.array = val; -+ if (semctl(semid, 0, GETALL, arg) < 0) { -+ apc_error("apc_sem_getvalue: semctl(%d,...) failed:" TSRMLS_CC, semid); -+ } -+ return val[0]; -+} -+ -+#endif /* APC_SEM_LOCKS */ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_sem.h b/ext/apc/apc_sem.h ---- a/ext/apc/apc_sem.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_sem.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,52 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_sem.h 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#ifndef APC_SEM_H -+#define APC_SEM_H -+ -+/* Wrapper functions for SysV sempahores */ -+ -+extern int apc_sem_create(int proj, int initval TSRMLS_DC); -+extern void apc_sem_destroy(int semid); -+extern void apc_sem_lock(int semid TSRMLS_DC); -+extern int apc_sem_nonblocking_lock(int semid TSRMLS_DC); -+extern void apc_sem_unlock(int semid TSRMLS_DC); -+extern void apc_sem_wait_for_zero(int semid TSRMLS_DC); -+extern int apc_sem_get_value(int semid TSRMLS_DC); -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_serializer.h b/ext/apc/apc_serializer.h ---- a/ext/apc/apc_serializer.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_serializer.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,84 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Gopal Vijayaraghavan | -+ +----------------------------------------------------------------------+ -+ -+ */ -+ -+/* $Id: $ */ -+ -+#ifndef APC_SERIALIZER_H -+#define APC_SERIALIZER_H -+ -+/* this is a shipped .h file, do not include any other header in this file */ -+#define APC_SERIALIZER_NAME(module) module##_apc_serializer -+#define APC_UNSERIALIZER_NAME(module) module##_apc_unserializer -+ -+#define APC_SERIALIZER_ARGS unsigned char **buf, size_t *buf_len, const zval *value, void *config TSRMLS_DC -+#define APC_UNSERIALIZER_ARGS zval **value, unsigned char *buf, size_t buf_len, void *config TSRMLS_DC -+ -+typedef int (*apc_serialize_t)(APC_SERIALIZER_ARGS); -+typedef int (*apc_unserialize_t)(APC_UNSERIALIZER_ARGS); -+ -+typedef int (*apc_register_serializer_t)(const char* name, -+ apc_serialize_t serialize, -+ apc_unserialize_t unserialize, -+ void *config TSRMLS_DC); -+ -+/* -+ * ABI version for constant hooks. Increment this any time you make any changes -+ * to any function in this file. -+ */ -+#define APC_SERIALIZER_ABI "0" -+#define APC_SERIALIZER_CONSTANT "\000apc_register_serializer-" APC_SERIALIZER_ABI -+ -+#if !defined(APC_UNUSED) -+# if defined(__GNUC__) -+# define APC_UNUSED __attribute__((unused)) -+# else -+# define APC_UNUSED -+# endif -+#endif -+ -+static APC_UNUSED int apc_register_serializer(const char* name, -+ apc_serialize_t serialize, -+ apc_unserialize_t unserialize, -+ void *config TSRMLS_DC) -+{ -+ zval apc_magic_constant; -+ int retval = 0; -+ -+ /* zend_get_constant will return 1 on success, otherwise apc_magic_constant wouldn't be touched at all */ -+ if (zend_get_constant(APC_SERIALIZER_CONSTANT, sizeof(APC_SERIALIZER_CONSTANT)-1, &apc_magic_constant TSRMLS_CC)) { -+ apc_register_serializer_t register_func = (apc_register_serializer_t)(Z_LVAL(apc_magic_constant)); -+ if(register_func) { -+ retval = register_func(name, serialize, unserialize, NULL TSRMLS_CC); -+ } -+ zval_dtor(&apc_magic_constant); -+ } -+ -+ return retval; -+} -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_shm.c b/ext/apc/apc_shm.c ---- a/ext/apc/apc_shm.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_shm.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,116 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | Rasmus Lerdorf | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_shm.c 307259 2011-01-08 12:05:24Z gopalv $ */ -+ -+#include "apc_shm.h" -+#include "apc.h" -+#ifdef PHP_WIN32 -+/* shm functions are available in TSRM */ -+#include -+#define key_t long -+#else -+#include -+#include -+#include -+#endif -+ -+#ifndef SHM_R -+# define SHM_R 0444 /* read permission */ -+#endif -+#ifndef SHM_A -+# define SHM_A 0222 /* write permission */ -+#endif -+ -+int apc_shm_create(int proj, size_t size TSRMLS_DC) -+{ -+ int shmid; /* shared memory id */ -+ int oflag; /* permissions on shm */ -+ key_t key = IPC_PRIVATE; /* shm key */ -+ -+ oflag = IPC_CREAT | SHM_R | SHM_A; -+ if ((shmid = shmget(key, size, oflag)) < 0) { -+ apc_error("apc_shm_create: shmget(%d, %d, %d) failed: %s. It is possible that the chosen SHM segment size is higher than the operation system allows. Linux has usually a default limit of 32MB per segment." TSRMLS_CC, key, size, oflag, strerror(errno)); -+ } -+ -+ return shmid; -+} -+ -+void apc_shm_destroy(int shmid) -+{ -+ /* we expect this call to fail often, so we do not check */ -+ shmctl(shmid, IPC_RMID, 0); -+} -+ -+apc_segment_t apc_shm_attach(int shmid, size_t size TSRMLS_DC) -+{ -+ apc_segment_t segment; /* shm segment */ -+ -+ if ((long)(segment.shmaddr = shmat(shmid, 0, 0)) == -1) { -+ apc_error("apc_shm_attach: shmat failed:" TSRMLS_CC); -+ } -+ -+#ifdef APC_MEMPROTECT -+ -+ if ((long)(segment.roaddr = shmat(shmid, 0, SHM_RDONLY)) == -1) { -+ segment.roaddr = NULL; -+ } -+ -+#endif -+ -+ segment.size = size; -+ -+ /* -+ * We set the shmid for removal immediately after attaching to it. The -+ * segment won't disappear until all processes have detached from it. -+ */ -+ apc_shm_destroy(shmid); -+ return segment; -+} -+ -+void apc_shm_detach(apc_segment_t* segment TSRMLS_DC) -+{ -+ if (shmdt(segment->shmaddr) < 0) { -+ apc_error("apc_shm_detach: shmdt failed:" TSRMLS_CC); -+ } -+ -+#ifdef APC_MEMPROTECT -+ if (segment->roaddr && shmdt(segment->roaddr) < 0) { -+ apc_error("apc_shm_detach: shmdt failed:" TSRMLS_CC); -+ } -+#endif -+} -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_shm.h b/ext/apc/apc_shm.h ---- a/ext/apc/apc_shm.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_shm.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,56 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_shm.h 307259 2011-01-08 12:05:24Z gopalv $ */ -+ -+#ifndef APC_SHM_H -+#define APC_SHM_H -+ -+#include -+#ifdef PHP_WIN32 -+#include -+#endif -+ -+#include "apc_sma.h" -+ -+/* Wrapper functions for unix shared memory */ -+ -+extern int apc_shm_create(int proj, size_t size TSRMLS_DC); -+extern void apc_shm_destroy(int shmid); -+extern apc_segment_t apc_shm_attach(int shmid, size_t size TSRMLS_DC); -+extern void apc_shm_detach(apc_segment_t* segment TSRMLS_DC); -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_signal.c b/ext/apc/apc_signal.c ---- a/ext/apc/apc_signal.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_signal.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,197 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Lucas Nealan | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Facebook Inc. in 2007. -+ -+ Future revisions and derivatives of this source code must acknowledge -+ Facebook Inc. as the original contributor of this module by leaving -+ this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ */ -+ -+ /* $Id: apc_signal.c 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+ /* Allows apc to install signal handlers and maintain signalling -+ to already registered handlers. Registers all signals that -+ coredump by default and unmaps the shared memory segment -+ before the coredump. Note: PHP module init is called before -+ signals are set by Apache and thus apc_set_signals should -+ be called in request init (RINIT) -+ */ -+ -+#include "apc.h" -+ -+#if HAVE_SIGACTION -+#include -+#include "apc_globals.h" -+#include "apc_sma.h" -+#include "apc_signal.h" -+ -+static apc_signal_info_t apc_signal_info = {0}; -+ -+static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*) TSRMLS_DC); -+static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context); -+static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context); -+ -+/* {{{ apc_core_unmap -+ * Coredump signal handler, unmaps shm and calls previously installed handlers -+ */ -+static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context) -+{ -+ TSRMLS_FETCH(); -+ -+ apc_sma_cleanup(TSRMLS_C); -+ apc_rehandle_signal(signo, siginfo, context); -+ -+#if !defined(WIN32) && !defined(NETWARE) -+ kill(getpid(), signo); -+#else -+ raise(signo); -+#endif -+} /* }}} */ -+ -+/* {{{ apc_rehandle_signal -+ * Call the previously registered handler for a signal -+ */ -+static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context) -+{ -+ int i; -+ apc_signal_entry_t p_sig = {0}; -+ -+ for (i=0; (i < apc_signal_info.installed && p_sig.signo != signo); i++) { -+ p_sig = *apc_signal_info.prev[i]; -+ if (p_sig.signo == signo) { -+ if (p_sig.siginfo) { -+ (*(void (*)(int, siginfo_t*, void*))p_sig.handler)(signo, siginfo, context); -+ } else { -+ (*(void (*)(int))p_sig.handler)(signo); -+ } -+ } -+ } -+ -+} /* }}} */ -+ -+/* {{{ apc_register_signal -+ * Set a handler for a previously installed signal and save so we can -+ * callback when handled -+ */ -+static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*) TSRMLS_DC) -+{ -+ struct sigaction sa = {{0}}; -+ apc_signal_entry_t p_sig = {0}; -+ -+ if (sigaction(signo, NULL, &sa) == 0) { -+ if ((void*)sa.sa_handler == (void*)handler) { -+ return SUCCESS; -+ } -+ -+ if (sa.sa_handler != SIG_ERR && sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN) { -+ p_sig.signo = signo; -+ p_sig.siginfo = ((sa.sa_flags & SA_SIGINFO) == SA_SIGINFO); -+ p_sig.handler = (void *)sa.sa_handler; -+ -+ apc_signal_info.prev = (apc_signal_entry_t **)apc_erealloc(apc_signal_info.prev, (apc_signal_info.installed+1)*sizeof(apc_signal_entry_t *) TSRMLS_CC); -+ apc_signal_info.prev[apc_signal_info.installed] = (apc_signal_entry_t *)apc_emalloc(sizeof(apc_signal_entry_t) TSRMLS_CC); -+ *apc_signal_info.prev[apc_signal_info.installed++] = p_sig; -+ } else { -+ /* inherit flags and mask if already set */ -+ sigemptyset(&sa.sa_mask); -+ sa.sa_flags = 0; -+ sa.sa_flags |= SA_SIGINFO; /* we'll use a siginfo handler */ -+#if defined(SA_ONESHOT) -+ sa.sa_flags = SA_ONESHOT; -+#elif defined(SA_RESETHAND) -+ sa.sa_flags = SA_RESETHAND; -+#endif -+ } -+ sa.sa_handler = (void*)handler; -+ -+ if (sigaction(signo, &sa, NULL) < 0) { -+ apc_warning("Error installing apc signal handler for %d" TSRMLS_CC, signo); -+ } -+ -+ return SUCCESS; -+ } -+ return FAILURE; -+} /* }}} */ -+ -+/* {{{ apc_set_signals -+ * Install our signal handlers */ -+void apc_set_signals(TSRMLS_D) -+{ -+ if (APCG(coredump_unmap) && apc_signal_info.installed == 0) { -+ /* ISO C standard signals that coredump */ -+ apc_register_signal(SIGSEGV, apc_core_unmap TSRMLS_CC); -+ apc_register_signal(SIGABRT, apc_core_unmap TSRMLS_CC); -+ apc_register_signal(SIGFPE, apc_core_unmap TSRMLS_CC); -+ apc_register_signal(SIGILL, apc_core_unmap TSRMLS_CC); -+ /* extended signals that coredump */ -+#ifdef SIGBUS -+ apc_register_signal(SIGBUS, apc_core_unmap TSRMLS_CC); -+#endif -+#ifdef SIGABORT -+ apc_register_signal(SIGABORT, apc_core_unmap TSRMLS_CC); -+#endif -+#ifdef SIGEMT -+ apc_register_signal(SIGEMT, apc_core_unmap TSRMLS_CC); -+#endif -+#ifdef SIGIOT -+ apc_register_signal(SIGIOT, apc_core_unmap TSRMLS_CC); -+#endif -+#ifdef SIGQUIT -+ apc_register_signal(SIGQUIT, apc_core_unmap TSRMLS_CC); -+#endif -+#ifdef SIGSYS -+ apc_register_signal(SIGSYS, apc_core_unmap TSRMLS_CC); -+#endif -+#ifdef SIGTRAP -+ apc_register_signal(SIGTRAP, apc_core_unmap TSRMLS_CC); -+#endif -+#ifdef SIGXCPU -+ apc_register_signal(SIGXCPU, apc_core_unmap TSRMLS_CC); -+#endif -+#ifdef SIGXFSZ -+ apc_register_signal(SIGXFSZ, apc_core_unmap TSRMLS_CC); -+#endif -+ } -+} /* }}} */ -+ -+/* {{{ apc_set_signals -+ * cleanup signals for shutdown */ -+void apc_shutdown_signals(TSRMLS_D) -+{ -+ int i=0; -+ if (apc_signal_info.installed > 0) { -+ for (i=0; (i < apc_signal_info.installed); i++) { -+ apc_efree(apc_signal_info.prev[i] TSRMLS_CC); -+ } -+ apc_efree(apc_signal_info.prev TSRMLS_CC); -+ apc_signal_info.installed = 0; /* just in case */ -+ } -+} -+ -+#endif /* HAVE_SIGACTION */ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_signal.h b/ext/apc/apc_signal.h ---- a/ext/apc/apc_signal.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_signal.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,51 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Lucas Nealan | -+ +----------------------------------------------------------------------+ -+ -+ */ -+ -+/* $Id: apc_signal.h 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#ifndef APC_SIGNAL_H -+#define APC_SIGNAL_H -+ -+#include "apc.h" -+#include "apc_php.h" -+ -+typedef struct apc_signal_entry_t { -+ int signo; /* signal number */ -+ int siginfo; /* siginfo style handler calling */ -+ void* handler; /* signal handler */ -+} apc_signal_entry_t; -+ -+typedef struct apc_signal_info_t { -+ int installed; /* How many signals we've installed handles for */ -+ apc_signal_entry_t **prev; /* Previous signal handlers */ -+} apc_signal_info_t; -+ -+void apc_set_signals(TSRMLS_D); -+void apc_shutdown_signals(TSRMLS_D); -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_sma.c b/ext/apc/apc_sma.c ---- a/ext/apc/apc_sma.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_sma.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,765 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | Rasmus Lerdorf | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_sma.c 309489 2011-03-21 00:00:54Z pajoye $ */ -+ -+#include "apc_sma.h" -+#include "apc.h" -+#include "apc_globals.h" -+#include "apc_lock.h" -+#include "apc_shm.h" -+#include "apc_cache.h" -+ -+#include -+#include "apc_mmap.h" -+ -+#ifdef HAVE_VALGRIND_MEMCHECK_H -+#include -+#endif -+ -+enum { DEFAULT_NUMSEG=1, DEFAULT_SEGSIZE=30*1024*1024 }; -+ -+static int sma_initialized = 0; /* true if the sma has been initialized */ -+static uint sma_numseg; /* number of shm segments to allow */ -+static size_t sma_segsize; /* size of each shm segment */ -+static apc_segment_t* sma_segments; /* array of shm segments */ -+static int sma_lastseg = 0; /* index of MRU segment */ -+ -+typedef struct sma_header_t sma_header_t; -+struct sma_header_t { -+ apc_lck_t sma_lock; /* segment lock, MUST BE ALIGNED for futex locks */ -+ size_t segsize; /* size of entire segment */ -+ size_t avail; /* bytes available (not necessarily contiguous) */ -+#if ALLOC_DISTRIBUTION -+ size_t adist[30]; -+#endif -+}; -+ -+#define SMA_HDR(i) ((sma_header_t*)((sma_segments[i]).shmaddr)) -+#define SMA_ADDR(i) ((char*)(SMA_HDR(i))) -+#define SMA_RO(i) ((char*)(sma_segments[i]).roaddr) -+#define SMA_LCK(i) ((SMA_HDR(i))->sma_lock) -+ -+ -+/* do not enable for threaded http servers */ -+/* #define __APC_SMA_DEBUG__ 1 */ -+ -+#ifdef __APC_SMA_DEBUG__ -+/* global counter for identifying blocks -+ * Technically it is possible to do the same -+ * using offsets, but double allocations of the -+ * same offset can happen. */ -+static volatile size_t block_id = 0; -+#endif -+ -+#define APC_SMA_CANARIES 1 -+ -+typedef struct block_t block_t; -+struct block_t { -+ size_t size; /* size of this block */ -+ size_t prev_size; /* size of sequentially previous block, 0 if prev is allocated */ -+ size_t fnext; /* offset in segment of next free block */ -+ size_t fprev; /* offset in segment of prev free block */ -+#ifdef APC_SMA_CANARIES -+ size_t canary; /* canary to check for memory overwrites */ -+#endif -+#ifdef __APC_SMA_DEBUG__ -+ size_t id; /* identifier for the memory block */ -+#endif -+}; -+ -+/* The macros BLOCKAT and OFFSET are used for convenience throughout this -+ * module. Both assume the presence of a variable shmaddr that points to the -+ * beginning of the shared memory segment in question. */ -+ -+#define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset)) -+#define OFFSET(block) ((size_t)(((char*)block) - (char*)shmaddr)) -+ -+/* macros for getting the next or previous sequential block */ -+#define NEXT_SBLOCK(block) ((block_t*)((char*)block + block->size)) -+#define PREV_SBLOCK(block) (block->prev_size ? ((block_t*)((char*)block - block->prev_size)) : NULL) -+ -+/* Canary macros for setting, checking and resetting memory canaries */ -+#ifdef APC_SMA_CANARIES -+ #define SET_CANARY(v) (v)->canary = 0x42424242 -+ #define CHECK_CANARY(v) assert((v)->canary == 0x42424242) -+ #define RESET_CANARY(v) (v)->canary = -42 -+#else -+ #define SET_CANARY(v) -+ #define CHECK_CANARY(v) -+ #define RESET_CANARY(v) -+#endif -+ -+ -+/* {{{ MINBLOCKSIZE */ -+#define MINBLOCKSIZE (ALIGNWORD(1) + ALIGNWORD(sizeof(block_t))) -+/* }}} */ -+ -+#if 0 -+/* {{{ sma_debug_state(apc_sma_segment_t *segment, int canary_check, int verbose) -+ * useful for debuging state of memory blocks and free list, and sanity checking -+ */ -+static void sma_debug_state(void* shmaddr, int canary_check, int verbose TSRMLS_DC) { -+ sma_header_t *header = (sma_header_t*)shmaddr; -+ block_t *cur = BLOCKAT(ALIGNWORD(sizeof(sma_header_t))); -+ block_t *prv = NULL; -+ size_t avail; -+ -+ /* Verify free list */ -+ if (verbose) apc_warning("Free List: " TSRMLS_CC); -+ while(1) { -+ if (verbose) apc_warning(" 0x%x[%d] (s%d)" TSRMLS_CC, cur, OFFSET(cur), cur->size); -+ if (canary_check) CHECK_CANARY(cur); -+ if (!cur->fnext) break; -+ cur = BLOCKAT(cur->fnext); -+ avail += cur->size; -+ if (prv == cur) { -+ apc_warning("Circular list detected!" TSRMLS_CC); -+ assert(0); -+ } -+ if (prv && cur->fprev != OFFSET(prv)) { -+ apc_warning("Previous pointer does not point to previous!" TSRMLS_CC); -+ assert(0); -+ } -+ prv = cur; -+ } -+ assert(avail == header->avail); -+ -+ /* Verify each block */ -+ if (verbose) apc_warning("Block List: " TSRMLS_CC); -+ cur = BLOCKAT(ALIGNWORD(sizeof(sma_header_t))); -+ while(1) { -+ if(!cur->fnext) { -+ if (verbose) apc_warning(" 0x%x[%d] (s%d) (u)" TSRMLS_CC, cur, OFFSET(cur), cur->size); -+ } else { -+ if (verbose) apc_warning(" 0x%x[%d] (s%d) (f)" TSRMLS_CC, cur, OFFSET(cur), cur->size); -+ } -+ if (canary_check) CHECK_CANARY(cur); -+ if (!cur->size && !cur->fnext) break; -+ if (!cur->size) { -+ cur = BLOCKAT(OFFSET(cur) + ALIGNWORD(sizeof(block_t))); -+ } else { -+ cur = NEXT_SBLOCK(cur); -+ } -+ if (prv == cur) { -+ apc_warning("Circular list detected!" TSRMLS_CC); -+ assert(0); -+ } -+ prv = cur; -+ } -+} -+/* }}} */ -+#endif -+ -+/* {{{ sma_allocate: tries to allocate at least size bytes in a segment */ -+static APC_HOTSPOT size_t sma_allocate(sma_header_t* header, size_t size, size_t fragment, size_t *allocated) -+{ -+ void* shmaddr; /* header of shared memory segment */ -+ block_t* prv; /* block prior to working block */ -+ block_t* cur; /* working block in list */ -+ block_t* prvnextfit; /* block before next fit */ -+ size_t realsize; /* actual size of block needed, including header */ -+ const size_t block_size = ALIGNWORD(sizeof(struct block_t)); -+ -+ realsize = ALIGNWORD(size + block_size); -+ -+ /* -+ * First, insure that the segment contains at least realsize free bytes, -+ * even if they are not contiguous. -+ */ -+ shmaddr = header; -+ -+ if (header->avail < realsize) { -+ return -1; -+ } -+ -+ prvnextfit = 0; /* initially null (no fit) */ -+ prv = BLOCKAT(ALIGNWORD(sizeof(sma_header_t))); -+ CHECK_CANARY(prv); -+ -+ while (prv->fnext != 0) { -+ cur = BLOCKAT(prv->fnext); -+#ifdef __APC_SMA_DEBUG__ -+ CHECK_CANARY(cur); -+#endif -+ /* If it can fit realsize bytes in cur block, stop searching */ -+ if (cur->size >= realsize) { -+ prvnextfit = prv; -+ break; -+ } -+ prv = cur; -+ } -+ -+ if (prvnextfit == 0) { -+ return -1; -+ } -+ -+ prv = prvnextfit; -+ cur = BLOCKAT(prv->fnext); -+ -+ CHECK_CANARY(prv); -+ CHECK_CANARY(cur); -+ -+ if (cur->size == realsize || (cur->size > realsize && cur->size < (realsize + (MINBLOCKSIZE + fragment)))) { -+ /* cur is big enough for realsize, but too small to split - unlink it */ -+ *(allocated) = cur->size - block_size; -+ prv->fnext = cur->fnext; -+ BLOCKAT(cur->fnext)->fprev = OFFSET(prv); -+ NEXT_SBLOCK(cur)->prev_size = 0; /* block is alloc'd */ -+ } else { -+ /* nextfit is too big; split it into two smaller blocks */ -+ block_t* nxt; /* the new block (chopped part of cur) */ -+ size_t oldsize; /* size of cur before split */ -+ -+ oldsize = cur->size; -+ cur->size = realsize; -+ *(allocated) = cur->size - block_size; -+ nxt = NEXT_SBLOCK(cur); -+ nxt->prev_size = 0; /* block is alloc'd */ -+ nxt->size = oldsize - realsize; /* and fix the size */ -+ NEXT_SBLOCK(nxt)->prev_size = nxt->size; /* adjust size */ -+ SET_CANARY(nxt); -+ -+ /* replace cur with next in free list */ -+ nxt->fnext = cur->fnext; -+ nxt->fprev = cur->fprev; -+ BLOCKAT(nxt->fnext)->fprev = OFFSET(nxt); -+ BLOCKAT(nxt->fprev)->fnext = OFFSET(nxt); -+#ifdef __APC_SMA_DEBUG__ -+ nxt->id = -1; -+#endif -+ } -+ -+ cur->fnext = 0; -+ -+ /* update the block header */ -+ header->avail -= cur->size; -+#if ALLOC_DISTRIBUTION -+ header->adist[(int)(log(size)/log(2))]++; -+#endif -+ -+ SET_CANARY(cur); -+#ifdef __APC_SMA_DEBUG__ -+ cur->id = ++block_id; -+ fprintf(stderr, "allocate(realsize=%d,size=%d,id=%d)\n", (int)(size), (int)(cur->size), cur->id); -+#endif -+ -+ return OFFSET(cur) + block_size; -+} -+/* }}} */ -+ -+/* {{{ sma_deallocate: deallocates the block at the given offset */ -+static APC_HOTSPOT size_t sma_deallocate(void* shmaddr, size_t offset) -+{ -+ sma_header_t* header; /* header of shared memory segment */ -+ block_t* cur; /* the new block to insert */ -+ block_t* prv; /* the block before cur */ -+ block_t* nxt; /* the block after cur */ -+ size_t size; /* size of deallocated block */ -+ -+ offset -= ALIGNWORD(sizeof(struct block_t)); -+ assert(offset >= 0); -+ -+ /* find position of new block in free list */ -+ cur = BLOCKAT(offset); -+ -+ /* update the block header */ -+ header = (sma_header_t*) shmaddr; -+ header->avail += cur->size; -+ size = cur->size; -+ -+ if (cur->prev_size != 0) { -+ /* remove prv from list */ -+ prv = PREV_SBLOCK(cur); -+ BLOCKAT(prv->fnext)->fprev = prv->fprev; -+ BLOCKAT(prv->fprev)->fnext = prv->fnext; -+ /* cur and prv share an edge, combine them */ -+ prv->size +=cur->size; -+ RESET_CANARY(cur); -+ cur = prv; -+ } -+ -+ nxt = NEXT_SBLOCK(cur); -+ if (nxt->fnext != 0) { -+ assert(NEXT_SBLOCK(NEXT_SBLOCK(cur))->prev_size == nxt->size); -+ /* cur and nxt shared an edge, combine them */ -+ BLOCKAT(nxt->fnext)->fprev = nxt->fprev; -+ BLOCKAT(nxt->fprev)->fnext = nxt->fnext; -+ cur->size += nxt->size; -+#ifdef __APC_SMA_DEBUG__ -+ CHECK_CANARY(nxt); -+ nxt->id = -1; /* assert this or set it ? */ -+#endif -+ RESET_CANARY(nxt); -+ } -+ -+ NEXT_SBLOCK(cur)->prev_size = cur->size; -+ -+ /* insert new block after prv */ -+ prv = BLOCKAT(ALIGNWORD(sizeof(sma_header_t))); -+ cur->fnext = prv->fnext; -+ prv->fnext = OFFSET(cur); -+ cur->fprev = OFFSET(prv); -+ BLOCKAT(cur->fnext)->fprev = OFFSET(cur); -+ -+ return size; -+} -+/* }}} */ -+ -+/* {{{ apc_sma_init */ -+ -+void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask TSRMLS_DC) -+{ -+ uint i; -+ -+ if (sma_initialized) { -+ return; -+ } -+ sma_initialized = 1; -+ -+#if APC_MMAP -+ /* -+ * I don't think multiple anonymous mmaps makes any sense -+ * so force sma_numseg to 1 in this case -+ */ -+ if(!mmap_file_mask || -+ (mmap_file_mask && !strlen(mmap_file_mask)) || -+ (mmap_file_mask && !strcmp(mmap_file_mask, "/dev/zero"))) { -+ sma_numseg = 1; -+ } else { -+ sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG; -+ } -+#else -+ sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG; -+#endif -+ -+ sma_segsize = segsize > 0 ? segsize : DEFAULT_SEGSIZE; -+ -+ sma_segments = (apc_segment_t*) apc_emalloc((sma_numseg * sizeof(apc_segment_t)) TSRMLS_CC); -+ -+ for (i = 0; i < sma_numseg; i++) { -+ sma_header_t* header; -+ block_t *first, *empty, *last; -+ void* shmaddr; -+ -+#if APC_MMAP -+ sma_segments[i] = apc_mmap(mmap_file_mask, sma_segsize TSRMLS_CC); -+ if(sma_numseg != 1) memcpy(&mmap_file_mask[strlen(mmap_file_mask)-6], "XXXXXX", 6); -+#else -+ sma_segments[i] = apc_shm_attach(apc_shm_create(i, sma_segsize TSRMLS_CC), sma_segsize TSRMLS_CC); -+#endif -+ -+ sma_segments[i].size = sma_segsize; -+ -+ shmaddr = sma_segments[i].shmaddr; -+ -+ header = (sma_header_t*) shmaddr; -+ apc_lck_create(NULL, 0, 1, header->sma_lock); -+ header->segsize = sma_segsize; -+ header->avail = sma_segsize - ALIGNWORD(sizeof(sma_header_t)) - ALIGNWORD(sizeof(block_t)) - ALIGNWORD(sizeof(block_t)); -+#if ALLOC_DISTRIBUTION -+ { -+ int j; -+ for(j=0; j<30; j++) header->adist[j] = 0; -+ } -+#endif -+ first = BLOCKAT(ALIGNWORD(sizeof(sma_header_t))); -+ first->size = 0; -+ first->fnext = ALIGNWORD(sizeof(sma_header_t)) + ALIGNWORD(sizeof(block_t)); -+ first->fprev = 0; -+ first->prev_size = 0; -+ SET_CANARY(first); -+#ifdef __APC_SMA_DEBUG__ -+ block->id = -1; -+#endif -+ empty = BLOCKAT(first->fnext); -+ empty->size = header->avail - ALIGNWORD(sizeof(block_t)); -+ empty->fnext = OFFSET(empty) + empty->size; -+ empty->fprev = ALIGNWORD(sizeof(sma_header_t)); -+ empty->prev_size = 0; -+ SET_CANARY(empty); -+#ifdef __APC_SMA_DEBUG__ -+ empty->id = -1; -+#endif -+ last = BLOCKAT(empty->fnext); -+ last->size = 0; -+ last->fnext = 0; -+ last->fprev = OFFSET(empty); -+ last->prev_size = empty->size; -+ SET_CANARY(last); -+#ifdef __APC_SMA_DEBUG__ -+ last->id = -1; -+#endif -+ } -+} -+/* }}} */ -+ -+/* {{{ apc_sma_cleanup */ -+void apc_sma_cleanup(TSRMLS_D) -+{ -+ uint i; -+ -+ assert(sma_initialized); -+ -+ for (i = 0; i < sma_numseg; i++) { -+ apc_lck_destroy(SMA_LCK(i)); -+#if APC_MMAP -+ apc_unmap(&sma_segments[i] TSRMLS_CC); -+#else -+ apc_shm_detach(&sma_segments[i] TSRMLS_CC); -+#endif -+ } -+ sma_initialized = 0; -+ apc_efree(sma_segments TSRMLS_CC); -+} -+/* }}} */ -+ -+/* {{{ apc_sma_malloc_ex */ -+void* apc_sma_malloc_ex(size_t n, size_t fragment, size_t* allocated TSRMLS_DC) -+{ -+ size_t off; -+ uint i; -+ int nuked = 0; -+ -+restart: -+ assert(sma_initialized); -+ LOCK(SMA_LCK(sma_lastseg)); -+ -+ off = sma_allocate(SMA_HDR(sma_lastseg), n, fragment, allocated); -+ -+ if(off == -1 && APCG(current_cache)) { -+ /* retry failed allocation after we expunge */ -+ UNLOCK(SMA_LCK(sma_lastseg)); -+ APCG(current_cache)->expunge_cb(APCG(current_cache), (n+fragment) TSRMLS_CC); -+ LOCK(SMA_LCK(sma_lastseg)); -+ off = sma_allocate(SMA_HDR(sma_lastseg), n, fragment, allocated); -+ } -+ -+ if (off != -1) { -+ void* p = (void *)(SMA_ADDR(sma_lastseg) + off); -+ UNLOCK(SMA_LCK(sma_lastseg)); -+#ifdef VALGRIND_MALLOCLIKE_BLOCK -+ VALGRIND_MALLOCLIKE_BLOCK(p, n, 0, 0); -+#endif -+ return p; -+ } -+ -+ UNLOCK(SMA_LCK(sma_lastseg)); -+ -+ for (i = 0; i < sma_numseg; i++) { -+ if (i == sma_lastseg) { -+ continue; -+ } -+ LOCK(SMA_LCK(i)); -+ off = sma_allocate(SMA_HDR(i), n, fragment, allocated); -+ if(off == -1 && APCG(current_cache)) { -+ /* retry failed allocation after we expunge */ -+ UNLOCK(SMA_LCK(i)); -+ APCG(current_cache)->expunge_cb(APCG(current_cache), (n+fragment) TSRMLS_CC); -+ LOCK(SMA_LCK(i)); -+ off = sma_allocate(SMA_HDR(i), n, fragment, allocated); -+ } -+ if (off != -1) { -+ void* p = (void *)(SMA_ADDR(i) + off); -+ UNLOCK(SMA_LCK(i)); -+ sma_lastseg = i; -+#ifdef VALGRIND_MALLOCLIKE_BLOCK -+ VALGRIND_MALLOCLIKE_BLOCK(p, n, 0, 0); -+#endif -+ return p; -+ } -+ UNLOCK(SMA_LCK(i)); -+ } -+ -+ /* I've tried being nice, but now you're just asking for it */ -+ if(!nuked) { -+ apc_cache->expunge_cb(apc_cache, (n+fragment) TSRMLS_CC); -+ apc_user_cache->expunge_cb(apc_user_cache, (n+fragment) TSRMLS_CC); -+ nuked = 1; -+ goto restart; -+ } -+ -+ /* now, I've truly and well given up */ -+ -+ return NULL; -+} -+/* }}} */ -+ -+/* {{{ apc_sma_malloc */ -+void* apc_sma_malloc(size_t n TSRMLS_DC) -+{ -+ size_t allocated; -+ void *p = apc_sma_malloc_ex(n, MINBLOCKSIZE, &allocated TSRMLS_CC); -+ -+ return p; -+} -+/* }}} */ -+ -+/* {{{ apc_sma_realloc */ -+void* apc_sma_realloc(void *p, size_t n TSRMLS_DC) -+{ -+ apc_sma_free(p TSRMLS_CC); -+ return apc_sma_malloc(n TSRMLS_CC); -+} -+/* }}} */ -+ -+/* {{{ apc_sma_strdup */ -+char* apc_sma_strdup(const char* s TSRMLS_DC) -+{ -+ void* q; -+ int len; -+ -+ if(!s) return NULL; -+ -+ len = strlen(s)+1; -+ q = apc_sma_malloc(len TSRMLS_CC); -+ if(!q) return NULL; -+ memcpy(q, s, len); -+ return q; -+} -+/* }}} */ -+ -+/* {{{ apc_sma_free */ -+void apc_sma_free(void* p TSRMLS_DC) -+{ -+ uint i; -+ size_t offset; -+ size_t d_size; -+ -+ if (p == NULL) { -+ return; -+ } -+ -+ assert(sma_initialized); -+ -+ -+ for (i = 0; i < sma_numseg; i++) { -+ offset = (size_t)((char *)p - SMA_ADDR(i)); -+ if (p >= (void*)SMA_ADDR(i) && offset < sma_segsize) { -+ LOCK(SMA_LCK(i)); -+ d_size = sma_deallocate(SMA_HDR(i), offset); -+ UNLOCK(SMA_LCK(i)); -+#ifdef VALGRIND_FREELIKE_BLOCK -+ VALGRIND_FREELIKE_BLOCK(p, 0); -+#endif -+ return; -+ } -+ } -+ -+ apc_error("apc_sma_free: could not locate address %p" TSRMLS_CC, p); -+} -+/* }}} */ -+ -+#ifdef APC_MEMPROTECT -+/* {{{ */ -+void* apc_sma_protect(void *p) -+{ -+ unsigned int i = 0; -+ size_t offset; -+ -+ if (p == NULL) { -+ return NULL; -+ } -+ -+ if(SMA_RO(sma_lastseg) == NULL) return p; -+ -+ offset = (size_t)((char *)p - SMA_ADDR(sma_lastseg)); -+ -+ if(p >= (void*)SMA_ADDR(sma_lastseg) && offset < sma_segsize) { -+ return SMA_RO(sma_lastseg) + offset; -+ } -+ -+ for (i = 0; i < sma_numseg; i++) { -+ offset = (size_t)((char *)p - SMA_ADDR(i)); -+ if (p >= (void*)SMA_ADDR(i) && offset < sma_segsize) { -+ return SMA_RO(i) + offset; -+ } -+ } -+ -+ return NULL; -+} -+/* }}} */ -+ -+/* {{{ */ -+void* apc_sma_unprotect(void *p) -+{ -+ unsigned int i = 0; -+ size_t offset; -+ -+ if (p == NULL) { -+ return NULL; -+ } -+ -+ if(SMA_RO(sma_lastseg) == NULL) return p; -+ -+ offset = (size_t)((char *)p - SMA_RO(sma_lastseg)); -+ -+ if(p >= (void*)SMA_RO(sma_lastseg) && offset < sma_segsize) { -+ return SMA_ADDR(sma_lastseg) + offset; -+ } -+ -+ for (i = 0; i < sma_numseg; i++) { -+ offset = (size_t)((char *)p - SMA_RO(i)); -+ if (p >= (void*)SMA_RO(i) && offset < sma_segsize) { -+ return SMA_ADDR(i) + offset; -+ } -+ } -+ -+ return NULL; -+} -+/* }}} */ -+#else -+/* {{{ */ -+void* apc_sma_protect(void *p) { return p; } -+void* apc_sma_unprotect(void *p) { return p; } -+/* }}} */ -+#endif -+ -+/* {{{ apc_sma_info */ -+apc_sma_info_t* apc_sma_info(zend_bool limited TSRMLS_DC) -+{ -+ apc_sma_info_t* info; -+ apc_sma_link_t** link; -+ uint i; -+ char* shmaddr; -+ block_t* prv; -+ -+ if (!sma_initialized) { -+ return NULL; -+ } -+ -+ info = (apc_sma_info_t*) apc_emalloc(sizeof(apc_sma_info_t) TSRMLS_CC); -+ info->num_seg = sma_numseg; -+ info->seg_size = sma_segsize - (ALIGNWORD(sizeof(sma_header_t)) + ALIGNWORD(sizeof(block_t)) + ALIGNWORD(sizeof(block_t))); -+ -+ info->list = apc_emalloc(info->num_seg * sizeof(apc_sma_link_t*) TSRMLS_CC); -+ for (i = 0; i < sma_numseg; i++) { -+ info->list[i] = NULL; -+ } -+ -+ if(limited) return info; -+ -+ /* For each segment */ -+ for (i = 0; i < sma_numseg; i++) { -+ RDLOCK(SMA_LCK(i)); -+ shmaddr = SMA_ADDR(i); -+ prv = BLOCKAT(ALIGNWORD(sizeof(sma_header_t))); -+ -+ link = &info->list[i]; -+ -+ /* For each block in this segment */ -+ while (BLOCKAT(prv->fnext)->fnext != 0) { -+ block_t* cur = BLOCKAT(prv->fnext); -+#ifdef __APC_SMA_DEBUG__ -+ CHECK_CANARY(cur); -+#endif -+ -+ *link = apc_emalloc(sizeof(apc_sma_link_t) TSRMLS_CC); -+ (*link)->size = cur->size; -+ (*link)->offset = prv->fnext; -+ (*link)->next = NULL; -+ link = &(*link)->next; -+ -+ prv = cur; -+ -+#if ALLOC_DISTRIBUTION -+ sma_header_t* header = (sma_header_t*) segment->shmaddr; -+ memcpy(info->seginfo[i].adist, header->adist, sizeof(size_t) * 30); -+#endif -+ -+ } -+ RDUNLOCK(SMA_LCK(i)); -+ } -+ -+ return info; -+} -+/* }}} */ -+ -+/* {{{ apc_sma_free_info */ -+void apc_sma_free_info(apc_sma_info_t* info TSRMLS_DC) -+{ -+ int i; -+ -+ for (i = 0; i < info->num_seg; i++) { -+ apc_sma_link_t* p = info->list[i]; -+ while (p) { -+ apc_sma_link_t* q = p; -+ p = p->next; -+ apc_efree(q TSRMLS_CC); -+ } -+ } -+ apc_efree(info->list TSRMLS_CC); -+ apc_efree(info TSRMLS_CC); -+} -+/* }}} */ -+ -+/* {{{ apc_sma_get_avail_mem */ -+size_t apc_sma_get_avail_mem() -+{ -+ size_t avail_mem = 0; -+ uint i; -+ -+ for (i = 0; i < sma_numseg; i++) { -+ sma_header_t* header = SMA_HDR(i); -+ avail_mem += header->avail; -+ } -+ return avail_mem; -+} -+/* }}} */ -+ -+/* {{{ apc_sma_get_avail_size */ -+zend_bool apc_sma_get_avail_size(size_t size) -+{ -+ uint i; -+ -+ for (i = 0; i < sma_numseg; i++) { -+ sma_header_t* header = SMA_HDR(i); -+ if (header->avail > size) { -+ return 1; -+ } -+ } -+ return 0; -+} -+/* }}} */ -+ -+ -+#if ALLOC_DISTRIBUTION -+size_t *apc_sma_get_alloc_distribution(void) { -+ sma_header_t* header = (sma_header_t*) segment->sma_shmaddr; -+ return header->adist; -+} -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_sma.h b/ext/apc/apc_sma.h ---- a/ext/apc/apc_sma.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_sma.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,103 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_sma.h 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#ifndef APC_SMA_H -+#define APC_SMA_H -+ -+#define ALLOC_DISTRIBUTION 0 -+ -+#include "apc.h" -+ -+/* Simple shared memory allocator */ -+ -+typedef struct _apc_segment_t apc_segment_t; -+ -+struct _apc_segment_t { -+ size_t size; -+ void* shmaddr; -+#ifdef APC_MEMPROTECT -+ void* roaddr; -+#endif -+}; -+ -+extern void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask TSRMLS_DC); -+extern void apc_sma_cleanup(TSRMLS_D); -+extern void* apc_sma_malloc(size_t size TSRMLS_DC); -+extern void* apc_sma_malloc_ex(size_t size, size_t fragment, size_t* allocated TSRMLS_DC); -+extern void* apc_sma_realloc(void* p, size_t size TSRMLS_DC); -+extern char* apc_sma_strdup(const char *s TSRMLS_DC); -+extern void apc_sma_free(void* p TSRMLS_DC); -+#if ALLOC_DISTRIBUTION -+extern size_t *apc_sma_get_alloc_distribution(); -+#endif -+ -+extern void* apc_sma_protect(void *p); -+extern void* apc_sma_unprotect(void *p); -+ -+/* {{{ struct definition: apc_sma_link_t */ -+typedef struct apc_sma_link_t apc_sma_link_t; -+struct apc_sma_link_t { -+ long size; /* size of this free block */ -+ long offset; /* offset in segment of this block */ -+ apc_sma_link_t* next; /* link to next free block */ -+}; -+/* }}} */ -+ -+/* {{{ struct definition: apc_sma_info_t */ -+typedef struct apc_sma_info_t apc_sma_info_t; -+struct apc_sma_info_t { -+ int num_seg; /* number of shared memory segments */ -+ size_t seg_size; /* size of each shared memory segment */ -+ apc_sma_link_t** list; /* there is one list per segment */ -+}; -+/* }}} */ -+ -+extern apc_sma_info_t* apc_sma_info(zend_bool limited TSRMLS_DC); -+extern void apc_sma_free_info(apc_sma_info_t* info TSRMLS_DC); -+ -+extern size_t apc_sma_get_avail_mem(); -+extern zend_bool apc_sma_get_avail_size(size_t size); -+extern void apc_sma_check_integrity(); -+ -+/* {{{ ALIGNWORD: pad up x, aligned to the system's word boundary */ -+typedef union { void* p; int i; long l; double d; void (*f)(); } apc_word_t; -+#define ALIGNSIZE(x, size) ((size) * (1 + (((x)-1)/(size)))) -+#define ALIGNWORD(x) ALIGNSIZE(x, sizeof(apc_word_t)) -+/* }}} */ -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_spin.c b/ext/apc/apc_spin.c ---- a/ext/apc/apc_spin.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_spin.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,66 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Brian Shire | -+ +----------------------------------------------------------------------+ -+ -+ */ -+ -+/* $Id: apc_spin.c 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#include "apc_spin.h" -+ -+#ifdef APC_SPIN_LOCKS -+ -+slock_t *apc_slock_create(slock_t *lock) -+{ -+ S_INIT_LOCK(lock); -+ return lock; -+} -+ -+void apc_slock_destroy(slock_t *lock) -+{ -+ return; -+} -+ -+void apc_slock_lock(slock_t *lock TSRMLS_DC) -+{ -+ S_LOCK(lock); -+} -+ -+void apc_slock_unlock(slock_t *lock) -+{ -+ S_UNLOCK(lock); -+} -+ -+zend_bool apc_slock_nonblocking_lock(slock_t *lock) -+{ -+ /* Technically we aren't supposed to call this directly, but the original -+ * code provides no method for absolute non-blocking locks, so we'll call into -+ * the TAS (test and set) functionality directly -+ */ -+ return !(TAS(lock)); /* if TAS returns 0 we obtained the lock, otherwise we failed */ -+} -+ -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_spin.h b/ext/apc/apc_spin.h ---- a/ext/apc/apc_spin.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_spin.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,48 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Brian Shire | -+ +----------------------------------------------------------------------+ -+ -+ */ -+ -+/* $Id: apc_spin.h 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#ifndef APC_SPIN_H -+#define APC_SPIN_H -+ -+#include "apc.h" -+ -+#ifdef APC_SPIN_LOCKS -+ -+#include "pgsql_s_lock.h" -+ -+slock_t *apc_slock_create(slock_t *lock); -+void apc_slock_destroy(slock_t *lock); -+void apc_slock_lock(slock_t *lock TSRMLS_DC); -+zend_bool apc_slock_nonblocking_lock(slock_t *lock); -+void apc_slock_unlock(slock_t *lock); -+ -+#endif -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_stack.c b/ext/apc/apc_stack.c ---- a/ext/apc/apc_stack.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_stack.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,106 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_stack.c 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#include "apc.h" -+#include "apc_stack.h" -+ -+struct apc_stack_t { -+ void** data; -+ int capacity; -+ int size; -+}; -+ -+apc_stack_t* apc_stack_create(int size_hint TSRMLS_DC) -+{ -+ apc_stack_t* stack = (apc_stack_t*) apc_emalloc(sizeof(apc_stack_t) TSRMLS_CC); -+ -+ stack->capacity = (size_hint > 0) ? size_hint : 10; -+ stack->size = 0; -+ stack->data = (void**) apc_emalloc(sizeof(void*) * stack->capacity TSRMLS_CC); -+ -+ return stack; -+} -+ -+void apc_stack_destroy(apc_stack_t* stack TSRMLS_DC) -+{ -+ if (stack != NULL) { -+ apc_efree(stack->data TSRMLS_CC); -+ apc_efree(stack TSRMLS_CC); -+ } -+} -+ -+void apc_stack_clear(apc_stack_t* stack) -+{ -+ assert(stack != NULL); -+ stack->size = 0; -+} -+ -+void apc_stack_push(apc_stack_t* stack, void* item TSRMLS_DC) -+{ -+ assert(stack != NULL); -+ if (stack->size == stack->capacity) { -+ stack->capacity *= 2; -+ stack->data = apc_erealloc(stack->data, sizeof(void*)*stack->capacity TSRMLS_CC); -+ } -+ stack->data[stack->size++] = item; -+} -+ -+void* apc_stack_pop(apc_stack_t* stack) -+{ -+ assert(stack != NULL && stack->size > 0); -+ return stack->data[--stack->size]; -+} -+ -+void* apc_stack_top(apc_stack_t* stack) -+{ -+ assert(stack != NULL && stack->size > 0); -+ return stack->data[stack->size-1]; -+} -+ -+void* apc_stack_get(apc_stack_t* stack, int n) -+{ -+ assert(stack != NULL && stack->size > n); -+ return stack->data[n]; -+} -+ -+int apc_stack_size(apc_stack_t* stack) -+{ -+ assert(stack != NULL); -+ return stack->size; -+} -+ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_stack.h b/ext/apc/apc_stack.h ---- a/ext/apc/apc_stack.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_stack.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,58 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | George Schlossnagle | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_stack.h 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#ifndef APC_STACK_H -+#define APC_STACK_H -+ -+/* Basic stack datatype */ -+ -+#define T apc_stack_t* -+typedef struct apc_stack_t apc_stack_t; /* opaque stack type */ -+ -+extern T apc_stack_create(int size_hint TSRMLS_DC); -+extern void apc_stack_destroy(T stack TSRMLS_DC); -+extern void apc_stack_clear(T stack); -+extern void apc_stack_push(T stack, void* item TSRMLS_DC); -+extern void* apc_stack_pop(T stack); -+extern void* apc_stack_top(T stack); -+extern void* apc_stack_get(T stack, int n); -+extern int apc_stack_size(T stack); -+ -+#undef T -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_string.c b/ext/apc/apc_string.c ---- a/ext/apc/apc_string.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_string.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,261 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Dmitry Stogov | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_string.c 326089 2012-06-11 04:29:57Z rasmus $ */ -+ -+#include "apc.h" -+#include "apc_globals.h" -+#include "apc_php.h" -+#include "apc_lock.h" -+ -+#ifdef ZEND_ENGINE_2_4 -+ -+#ifndef ZTS -+typedef struct _apc_interned_strings_data_t { -+ char *interned_strings_start; -+ char *interned_strings_end; -+ char *interned_strings_top; -+ apc_lck_t lock; -+ HashTable interned_strings; -+} apc_interned_strings_data_t; -+ -+apc_interned_strings_data_t *apc_interned_strings_data = NULL; -+ -+#define APCSG(v) (apc_interned_strings_data->v) -+ -+static char *old_interned_strings_start; -+static char *old_interned_strings_end; -+static const char *(*old_new_interned_string)(const char *str, int len, int free_src TSRMLS_DC); -+static void (*old_interned_strings_snapshot)(TSRMLS_D); -+static void (*old_interned_strings_restore)(TSRMLS_D); -+ -+static const char *apc_dummy_new_interned_string_for_php(const char *str, int len, int free_src TSRMLS_DC) -+{ -+ return str; -+} -+ -+static void apc_dummy_interned_strings_snapshot_for_php(TSRMLS_D) -+{ -+} -+ -+static void apc_dummy_interned_strings_restore_for_php(TSRMLS_D) -+{ -+} -+#endif -+ -+const char *apc_new_interned_string(const char *arKey, int nKeyLength TSRMLS_DC) -+{ -+#ifndef ZTS -+ ulong h; -+ uint nIndex; -+ Bucket *p; -+ -+ if (arKey >= APCSG(interned_strings_start) && arKey < APCSG(interned_strings_end)) { -+ return arKey; -+ } -+ -+ h = zend_inline_hash_func(arKey, nKeyLength); -+ nIndex = h & APCSG(interned_strings).nTableMask; -+ -+ p = APCSG(interned_strings).arBuckets[nIndex]; -+ while (p != NULL) { -+ if ((p->h == h) && (p->nKeyLength == nKeyLength)) { -+ if (!memcmp(p->arKey, arKey, nKeyLength)) { -+ return p->arKey; -+ } -+ } -+ p = p->pNext; -+ } -+ -+ if (APCSG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength + 1) >= -+ APCSG(interned_strings_end)) { -+ /* no memory */ -+ return NULL; -+ } -+ -+ p = (Bucket *) APCSG(interned_strings_top); -+ APCSG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength + 1); -+ -+ p->arKey = (char*)(p+1); -+ memcpy(p->arKey, arKey, nKeyLength); -+ ((char *)p->arKey)[nKeyLength] = '\0'; -+ p->nKeyLength = nKeyLength; -+ p->h = h; -+ p->pData = &p->pDataPtr; -+ p->pDataPtr = p; -+ -+ p->pNext = APCSG(interned_strings).arBuckets[nIndex]; -+ p->pLast = NULL; -+ if (p->pNext) { -+ p->pNext->pLast = p; -+ } -+ APCSG(interned_strings).arBuckets[nIndex] = p; -+ -+ p->pListLast = APCSG(interned_strings).pListTail; -+ APCSG(interned_strings).pListTail = p; -+ p->pListNext = NULL; -+ if (p->pListLast != NULL) { -+ p->pListLast->pListNext = p; -+ } -+ if (!APCSG(interned_strings).pListHead) { -+ APCSG(interned_strings).pListHead = p; -+ } -+ -+ APCSG(interned_strings).nNumOfElements++; -+ -+ return p->arKey; -+#else -+ return zend_new_interned_string(arKey, nKeyLength, 0 TSRMLS_CC); -+#endif -+} -+ -+#ifndef ZTS -+static void apc_copy_internal_strings(TSRMLS_D) -+{ -+ Bucket *p, *q; -+ -+ p = CG(function_table)->pListHead; -+ while (p) { -+ if (p->nKeyLength) { -+ p->arKey = apc_new_interned_string(p->arKey, p->nKeyLength TSRMLS_CC); -+ } -+ p = p->pListNext; -+ } -+ -+ p = CG(class_table)->pListHead; -+ while (p) { -+ zend_class_entry *ce = (zend_class_entry*)(p->pDataPtr); -+ -+ if (p->nKeyLength) { -+ p->arKey = apc_new_interned_string(p->arKey, p->nKeyLength TSRMLS_CC); -+ } -+ -+ if (ce->name) { -+ ce->name = apc_new_interned_string(ce->name, ce->name_length+1 TSRMLS_CC); -+ } -+ -+ q = ce->properties_info.pListHead; -+ while (q) { -+ zend_property_info *info = (zend_property_info*)(q->pData); -+ -+ if (q->nKeyLength) { -+ q->arKey = apc_new_interned_string(q->arKey, q->nKeyLength TSRMLS_CC); -+ } -+ -+ if (info->name) { -+ info->name = apc_new_interned_string(info->name, info->name_length+1 TSRMLS_CC); -+ } -+ -+ q = q->pListNext; -+ } -+ -+ q = ce->function_table.pListHead; -+ while (q) { -+ if (q->nKeyLength) { -+ q->arKey = apc_new_interned_string(q->arKey, q->nKeyLength TSRMLS_CC); -+ } -+ q = q->pListNext; -+ } -+ -+ q = ce->constants_table.pListHead; -+ while (q) { -+ if (q->nKeyLength) { -+ q->arKey = apc_new_interned_string(q->arKey, q->nKeyLength TSRMLS_CC); -+ } -+ q = q->pListNext; -+ } -+ -+ p = p->pListNext; -+ } -+ -+ p = EG(zend_constants)->pListHead; -+ while (p) { -+ if (p->nKeyLength) { -+ p->arKey = apc_new_interned_string(p->arKey, p->nKeyLength TSRMLS_CC); -+ } -+ p = p->pListNext; -+ } -+} -+ -+void apc_interned_strings_init(TSRMLS_D) -+{ -+ int count = APCG(shm_strings_buffer) / (sizeof(Bucket) + sizeof(Bucket*) * 2); -+ -+ apc_interned_strings_data = (apc_interned_strings_data_t*) apc_sma_malloc(APCG(shm_strings_buffer) TSRMLS_CC); -+ memset((void *)apc_interned_strings_data, 0, APCG(shm_strings_buffer)); -+ -+ CREATE_LOCK(APCSG(lock)); -+ -+ zend_hash_init(&APCSG(interned_strings), count, NULL, NULL, 1); -+ APCSG(interned_strings).nTableMask = APCSG(interned_strings).nTableSize - 1; -+ APCSG(interned_strings).arBuckets = (Bucket**)((char*)apc_interned_strings_data + sizeof(apc_interned_strings_data_t)); -+ -+ APCSG(interned_strings_start) = (char*)APCSG(interned_strings).arBuckets + APCSG(interned_strings).nTableSize * sizeof(Bucket *); -+ APCSG(interned_strings_end) = (char*)apc_interned_strings_data + APCG(shm_strings_buffer); -+ APCSG(interned_strings_top) = APCSG(interned_strings_start); -+ -+ old_interned_strings_start = CG(interned_strings_start); -+ old_interned_strings_end = CG(interned_strings_end); -+ old_new_interned_string = zend_new_interned_string; -+ old_interned_strings_snapshot = zend_interned_strings_snapshot; -+ old_interned_strings_restore = zend_interned_strings_restore; -+ -+ CG(interned_strings_start) = APCSG(interned_strings_start); -+ CG(interned_strings_end) = APCSG(interned_strings_end); -+ zend_new_interned_string = apc_dummy_new_interned_string_for_php; -+ zend_interned_strings_snapshot = apc_dummy_interned_strings_snapshot_for_php; -+ zend_interned_strings_restore = apc_dummy_interned_strings_restore_for_php; -+ -+ apc_copy_internal_strings(TSRMLS_C); -+} -+ -+void apc_interned_strings_shutdown(TSRMLS_D) -+{ -+ zend_hash_clean(CG(function_table)); -+ zend_hash_clean(CG(class_table)); -+ zend_hash_clean(EG(zend_constants)); -+ -+ CG(interned_strings_start) = old_interned_strings_start; -+ CG(interned_strings_end) = old_interned_strings_end; -+ zend_new_interned_string = old_new_interned_string; -+ zend_interned_strings_snapshot = old_interned_strings_snapshot; -+ zend_interned_strings_restore = old_interned_strings_restore; -+ -+ DESTROY_LOCK(APCSG(lock)); -+} -+#endif -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_string.h b/ext/apc/apc_string.h ---- a/ext/apc/apc_string.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_string.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,51 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Dmitry Stogov | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_string.h 324145 2012-03-12 11:38:28Z pajoye $ */ -+ -+#ifndef APC_STRING -+#define APC_STRING -+ -+#include "apc.h" -+ -+#ifndef ZTS -+void apc_interned_strings_init(TSRMLS_D); -+void apc_interned_strings_shutdown(TSRMLS_D); -+#endif -+ -+const char *apc_new_interned_string(const char *arKey, int nKeyLength TSRMLS_DC); -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_windows_srwlock_kernel.c b/ext/apc/apc_windows_srwlock_kernel.c ---- a/ext/apc/apc_windows_srwlock_kernel.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_windows_srwlock_kernel.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,133 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Pierre Joye | -+ +----------------------------------------------------------------------+ -+ */ -+/* $Id$ */ -+/* -+ These APIs are not actually exposed nor documented. But should work fine -+ from a binary as available since XP without signature changes. -+*/ -+/* -+TODOs: -+non blocking could be possible using the fWait argument (to 0). However -+I'm not sure whether the wait handlers is actually implemented in all -+supported platforms (xp+). could be enabled later once really tested. -+ */ -+/* $Id: $ */ -+ -+#include -+ -+#ifdef APC_SRWLOCK_KERNEL -+#include "apc_windows_srwlock_kernel.h" -+ -+/* -+For references: -+void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl); -+void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl); -+BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait); -+BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait); -+void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl); -+*/ -+typedef void (WINAPI *tRtlInitializeResource)(LPRTL_RWLOCK rwl); -+typedef void (WINAPI *tRtlDeleteResource)(LPRTL_RWLOCK rwl); -+typedef BYTE (WINAPI *tRtlAcquireResourceExclusive)(LPRTL_RWLOCK rwl, BYTE fWait); -+typedef BYTE (WINAPI *tRtlAcquireResourceShared)(LPRTL_RWLOCK rwl, BYTE fWait); -+typedef void (WINAPI *tRtlReleaseResource)(LPRTL_RWLOCK rwl); -+typedef void (WINAPI *tRtlDumpResource)(LPRTL_RWLOCK rwl); -+ -+tRtlInitializeResource pRtlInitializeResource = 0; -+tRtlDeleteResource pRtlDeleteResource = 0; -+tRtlAcquireResourceExclusive pRtlAcquireResourceExclusive = 0; -+tRtlAcquireResourceShared pRtlAcquireResourceShared = 0; -+tRtlReleaseResource pRtlReleaseResource = 0; -+tRtlDumpResource pRtlDumpResource = 0; -+ -+HINSTANCE ntdll; -+ -+void apc_windows_cs_status(apc_windows_cs_rwlock_t *lock ); -+apc_windows_cs_rwlock_t *apc_windows_cs_create(apc_windows_cs_rwlock_t *lock TSRMLS_DC) -+{ -+ ntdll = LoadLibrary("ntdll.dll"); -+ if (ntdll == 0) { -+ return NULL; -+ } -+ -+ pRtlInitializeResource = (tRtlInitializeResource) GetProcAddress(ntdll, "RtlInitializeResource"); -+ pRtlDeleteResource = (tRtlDeleteResource) GetProcAddress(ntdll, "RtlDeleteResource"); -+ pRtlAcquireResourceExclusive = (tRtlAcquireResourceExclusive) GetProcAddress(ntdll, "RtlAcquireResourceExclusive"); -+ pRtlAcquireResourceShared = (tRtlAcquireResourceShared) GetProcAddress(ntdll, "RtlAcquireResourceShared"); -+ pRtlReleaseResource = (tRtlReleaseResource) GetProcAddress(ntdll, "RtlReleaseResource"); -+ pRtlDumpResource = (tRtlReleaseResource) GetProcAddress(ntdll, "RtlDumpResource"); -+ if (pRtlInitializeResource == 0 || pRtlDeleteResource == 0 || pRtlAcquireResourceExclusive == 0 || -+ pRtlAcquireResourceShared == 0 || pRtlReleaseResource == 0 || pRtlDumpResource == 0) { -+ return NULL; -+ } -+ pRtlInitializeResource(lock); -+ return lock; -+} -+ -+void apc_windows_cs_destroy(apc_windows_cs_rwlock_t *lock) -+{ -+ __try -+ { -+ pRtlDeleteResource(lock); -+ } -+ __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? -+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) -+ { -+ /* Ignore exception (resource was freed during shutdown of another thread) */ -+ } -+ FreeLibrary(ntdll); -+ return; -+} -+ -+void apc_windows_cs_lock(apc_windows_cs_rwlock_t *lock TSRMLS_DC) -+{ -+ pRtlAcquireResourceExclusive(lock, 1); -+} -+ -+void apc_windows_cs_rdlock(apc_windows_cs_rwlock_t *lock TSRMLS_DC) -+{ -+ pRtlAcquireResourceShared(lock, 1); -+} -+ -+void apc_windows_cs_unlock_rd(apc_windows_cs_rwlock_t *lock TSRMLS_DC) -+{ -+ pRtlReleaseResource(lock); -+} -+ -+void apc_windows_cs_unlock_wr(apc_windows_cs_rwlock_t *lock TSRMLS_DC) -+{ -+ pRtlReleaseResource(lock); -+} -+ -+/* debugging purposes, output using trace msgs */ -+void apc_windows_cs_status(apc_windows_cs_rwlock_t *lock) -+{ -+ pRtlDumpResource(lock); -+ return; -+} -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_windows_srwlock_kernel.h b/ext/apc/apc_windows_srwlock_kernel.h ---- a/ext/apc/apc_windows_srwlock_kernel.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_windows_srwlock_kernel.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,74 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Pierre Joye | -+ +----------------------------------------------------------------------+ -+ */ -+/* $Id$ */ -+ -+#ifndef APC_WINDOWS_CS_RWLOCK_H -+#define APC_WINDOWS_CS_RWLOCK_H -+ -+#include "apc.h" -+ -+#ifdef APC_SRWLOCK_KERNEL -+ -+typedef struct _RTL_RWLOCK { -+ RTL_CRITICAL_SECTION rtlCS; -+ -+ HANDLE hSharedReleaseSemaphore; -+ UINT uSharedWaiters; -+ -+ HANDLE hExclusiveReleaseSemaphore; -+ UINT uExclusiveWaiters; -+ -+ INT iNumberActive; -+ HANDLE hOwningThreadId; -+ DWORD dwTimeoutBoost; -+ PVOID pDebugInfo; -+} RTL_RWLOCK, *LPRTL_RWLOCK; -+ -+#define apc_windows_cs_rwlock_t RTL_RWLOCK -+ -+struct apc_windows_cs_rwlock_t { -+ CRITICAL_SECTION cs; -+ LONG writers_waiting_count; -+ LONG readers_waiting_count; -+ DWORD active_writers_readers_flag; -+ HANDLE ready_to_read; -+ HANDLE ready_to_write; -+ DWORD reader_races_lost; -+}; -+ -+apc_windows_cs_rwlock_t *apc_windows_cs_create(apc_windows_cs_rwlock_t *lock TSRMLS_DC); -+void apc_windows_cs_destroy(apc_windows_cs_rwlock_t *lock); -+void apc_windows_cs_lock(apc_windows_cs_rwlock_t *lock TSRMLS_DC); -+void apc_windows_cs_rdlock(apc_windows_cs_rwlock_t *lock TSRMLS_DC); -+void apc_windows_cs_unlock_rd(apc_windows_cs_rwlock_t *lock TSRMLS_DC); -+void apc_windows_cs_unlock_wr(apc_windows_cs_rwlock_t *lock TSRMLS_DC); -+# if NONBLOCKING_LOCK_AVAILABLE==1 /* Only in win7/2008 */ -+zend_bool apc_pthreadrwlock_nonblocking_lock(apc_windows_cs_rwlock_t *lock TSRMLS_DC); -+# endif -+#endif -+ -+#endif -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_zend.c b/ext/apc/apc_zend.c ---- a/ext/apc/apc_zend.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_zend.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,271 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_zend.c 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+#include "apc_zend.h" -+#include "apc_globals.h" -+ -+/* true global */ -+int apc_reserved_offset; -+ -+void* apc_php_malloc(size_t n TSRMLS_DC) -+{ -+ return emalloc(n); -+} -+ -+void apc_php_free(void* p TSRMLS_DC) -+{ -+ efree(p); -+} -+ -+#ifdef APC_OPCODE_OVERRIDE -+ -+static opcode_handler_t *apc_original_opcode_handlers; -+static opcode_handler_t apc_opcode_handlers[APC_OPCODE_HANDLER_COUNT]; -+ -+#define APC_EX_T(offset) (*(temp_variable *)((char*)execute_data->Ts + offset)) -+ -+#ifdef ZEND_ENGINE_2_4 -+static zval *apc_get_zval_ptr(zend_uchar op_type, znode_op *node, zval **freeval, zend_execute_data *execute_data TSRMLS_DC) -+{ -+ *freeval = NULL; -+ -+ switch (op_type) { -+ case IS_CONST: -+ return node->zv; -+ case IS_VAR: -+ return APC_EX_T(node->var).var.ptr; -+ case IS_TMP_VAR: -+ return (*freeval = &APC_EX_T(node->var).tmp_var); -+ case IS_CV: -+ { -+ zval ***ret = &execute_data->CVs[node->var]; -+ -+ if (!*ret) { -+ zend_compiled_variable *cv = &EG(active_op_array)->vars[node->var]; -+ -+ if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void**)ret)==FAILURE) { -+ apc_notice("Undefined variable: %s" TSRMLS_CC, cv->name); -+ return &EG(uninitialized_zval); -+ } -+ } -+ return **ret; -+ } -+ case IS_UNUSED: -+ default: -+ return NULL; -+ } -+} -+#else -+static zval *apc_get_zval_ptr(znode *node, zval **freeval, zend_execute_data *execute_data TSRMLS_DC) -+{ -+ *freeval = NULL; -+ -+ switch (node->op_type) { -+ case IS_CONST: -+ return &(node->u.constant); -+ case IS_VAR: -+ return APC_EX_T(node->u.var).var.ptr; -+ case IS_TMP_VAR: -+ return (*freeval = &APC_EX_T(node->u.var).tmp_var); -+#ifdef ZEND_ENGINE_2_1 -+ case IS_CV: -+ { -+ zval ***ret = &execute_data->CVs[node->u.var]; -+ -+ if (!*ret) { -+ zend_compiled_variable *cv = &EG(active_op_array)->vars[node->u.var]; -+ -+ if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void**)ret)==FAILURE) { -+ apc_notice("Undefined variable: %s" TSRMLS_CC, cv->name); -+ return &EG(uninitialized_zval); -+ } -+ } -+ return **ret; -+ } -+#endif -+ case IS_UNUSED: -+ default: -+ return NULL; -+ } -+} -+#endif -+ -+static int ZEND_FASTCALL apc_op_ZEND_INCLUDE_OR_EVAL(ZEND_OPCODE_HANDLER_ARGS) -+{ -+ APC_ZEND_OPLINE -+ zval *freeop1 = NULL; -+ zval *inc_filename = NULL, tmp_inc_filename; -+ char realpath[MAXPATHLEN]; -+ php_stream_wrapper *wrapper; -+ char *path_for_open; -+ char *full_path = NULL; -+ int ret = 0; -+ apc_opflags_t* flags = NULL; -+ -+#ifdef ZEND_ENGINE_2_4 -+ if (opline->extended_value != ZEND_INCLUDE_ONCE && -+ opline->extended_value != ZEND_REQUIRE_ONCE) { -+ return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -+ } -+ -+ inc_filename = apc_get_zval_ptr(opline->op1_type, &opline->op1, &freeop1, execute_data TSRMLS_CC); -+#else -+ if (Z_LVAL(opline->op2.u.constant) != ZEND_INCLUDE_ONCE && -+ Z_LVAL(opline->op2.u.constant) != ZEND_REQUIRE_ONCE) { -+ return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -+ } -+ -+ inc_filename = apc_get_zval_ptr(&opline->op1, &freeop1, execute_data TSRMLS_CC); -+#endif -+ -+ if (Z_TYPE_P(inc_filename) != IS_STRING) { -+ tmp_inc_filename = *inc_filename; -+ zval_copy_ctor(&tmp_inc_filename); -+ convert_to_string(&tmp_inc_filename); -+ inc_filename = &tmp_inc_filename; -+ } -+ -+ wrapper = php_stream_locate_url_wrapper(Z_STRVAL_P(inc_filename), &path_for_open, 0 TSRMLS_CC); -+ -+ if (wrapper != &php_plain_files_wrapper || !(IS_ABSOLUTE_PATH(path_for_open, strlen(path_for_open)) || (full_path = expand_filepath(path_for_open, realpath TSRMLS_CC)))) { -+ /* Fallback to original handler */ -+ if (inc_filename == &tmp_inc_filename) { -+ zval_dtor(&tmp_inc_filename); -+ } -+ return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -+ } -+ -+ if (!full_path) { -+ full_path = path_for_open; -+ } -+ if (zend_hash_exists(&EG(included_files), realpath, strlen(realpath) + 1)) { -+#ifdef ZEND_ENGINE_2_4 -+ if (!(opline->result_type & EXT_TYPE_UNUSED)) { -+ ALLOC_INIT_ZVAL(APC_EX_T(opline->result.var).var.ptr); -+ ZVAL_TRUE(APC_EX_T(opline->result.var).var.ptr); -+ } -+#else -+ if (!(opline->result.u.EA.type & EXT_TYPE_UNUSED)) { -+ ALLOC_INIT_ZVAL(APC_EX_T(opline->result.u.var).var.ptr); -+ ZVAL_TRUE(APC_EX_T(opline->result.u.var).var.ptr); -+ } -+#endif -+ if (inc_filename == &tmp_inc_filename) { -+ zval_dtor(&tmp_inc_filename); -+ } -+ if (freeop1) { -+ zval_dtor(freeop1); -+ } -+ execute_data->opline++; -+ return 0; -+ } -+ -+ if (inc_filename == &tmp_inc_filename) { -+ zval_dtor(&tmp_inc_filename); -+ } -+ -+ if(apc_reserved_offset != -1) { -+ /* Insanity alert: look into apc_compile.c for why a void** is cast to a apc_opflags_t* */ -+ flags = (apc_opflags_t*) & (execute_data->op_array->reserved[apc_reserved_offset]); -+ } -+ -+ if(flags && flags->deep_copy == 1) { -+ /* Since the op array is a local copy, we can cheat our way through the file inclusion by temporarily -+ * changing the op to a plain require/include, calling its handler and finally restoring the opcode. -+ */ -+#ifdef ZEND_ENGINE_2_4 -+ opline->extended_value = (opline->extended_value == ZEND_INCLUDE_ONCE) ? ZEND_INCLUDE : ZEND_REQUIRE; -+ ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -+ opline->extended_value = (opline->extended_value == ZEND_INCLUDE) ? ZEND_INCLUDE_ONCE : ZEND_REQUIRE_ONCE; -+#else -+ Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE_ONCE) ? ZEND_INCLUDE : ZEND_REQUIRE; -+ ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -+ Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE) ? ZEND_INCLUDE_ONCE : ZEND_REQUIRE_ONCE; -+#endif -+ } else { -+ ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -+ } -+ -+ return ret; -+} -+ -+void apc_zend_init(TSRMLS_D) -+{ -+ zend_extension dummy_ext; -+ apc_reserved_offset = zend_get_resource_handle(&dummy_ext); -+ assert(apc_reserved_offset == dummy_ext.resource_number); -+ assert(apc_reserved_offset != -1); -+ assert(sizeof(apc_opflags_t) <= sizeof(void*)); -+ if (!APCG(include_once)) { -+ /* If we're not overriding the INCLUDE_OR_EVAL handler, then just skip this malarkey */ -+ return; -+ } -+ -+ memcpy(apc_opcode_handlers, zend_opcode_handlers, sizeof(apc_opcode_handlers)); -+ -+ /* 5.0 exposes zend_opcode_handlers differently than 5.1 and later */ -+#ifdef ZEND_ENGINE_2_1 -+ apc_original_opcode_handlers = zend_opcode_handlers; -+ zend_opcode_handlers = apc_opcode_handlers; -+#else -+ apc_original_opcode_handlers = apc_opcode_handlers; -+#endif -+ -+ APC_REPLACE_OPCODE(ZEND_INCLUDE_OR_EVAL); -+} -+ -+void apc_zend_shutdown(TSRMLS_D) -+{ -+ if (!APCG(include_once)) { -+ /* Nothing changed, nothing to restore */ -+ return; -+ } -+ -+#ifdef ZEND_ENGINE_2_1 -+ zend_opcode_handlers = apc_original_opcode_handlers; -+#else -+ memcpy(zend_opcode_handlers, apc_original_opcode_handlers, sizeof(apc_opcode_handlers)); -+#endif -+} -+ -+#else /* Opcode Overrides unavailable */ -+ -+void apc_zend_init(TSRMLS_D) { } -+void apc_zend_shutdown(TSRMLS_D) { } -+ -+#endif /* APC_OPCODE_OVERRIDE */ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/apc_zend.h b/ext/apc/apc_zend.h ---- a/ext/apc/apc_zend.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/apc_zend.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,191 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: apc_zend.h 326712 2012-07-19 21:33:27Z rasmus $ */ -+ -+#ifndef APC_ZEND_H -+#define APC_ZEND_H -+ -+/* Utilities for interfacing with the zend engine */ -+ -+#include "apc.h" -+#include "apc_php.h" -+ -+#ifndef Z_REFCOUNT_P -+#define Z_REFCOUNT_P(pz) (pz)->refcount -+#define Z_REFCOUNT_PP(ppz) Z_REFCOUNT_P(*(ppz)) -+#endif -+ -+#ifndef Z_SET_REFCOUNT_P -+#define Z_SET_REFCOUNT_P(pz, rc) (pz)->refcount = rc -+#define Z_SET_REFCOUNT_PP(ppz, rc) Z_SET_REFCOUNT_P(*(ppz), rc) -+#endif -+ -+#ifndef Z_ADDREF_P -+#define Z_ADDREF_P(pz) (pz)->refcount++ -+#define Z_ADDREF_PP(ppz) Z_ADDREF_P(*(ppz)) -+#endif -+ -+#ifndef Z_DELREF_P -+#define Z_DELREF_P(pz) (pz)->refcount-- -+#define Z_DELREF_PP(ppz) Z_DELREF_P(*(ppz)) -+#endif -+ -+#ifndef Z_ISREF_P -+#define Z_ISREF_P(pz) (pz)->is_ref -+#define Z_ISREF_PP(ppz) Z_ISREF_P(*(ppz)) -+#endif -+ -+#ifndef Z_SET_ISREF_P -+#define Z_SET_ISREF_P(pz) (pz)->is_ref = 1 -+#define Z_SET_ISREF_PP(ppz) Z_SET_ISREF_P(*(ppz)) -+#endif -+ -+#ifndef Z_UNSET_ISREF_P -+#define Z_UNSET_ISREF_P(pz) (pz)->is_ref = 0 -+#define Z_UNSET_ISREF_PP(ppz) Z_UNSET_ISREF_P(*(ppz)) -+#endif -+ -+#ifndef Z_SET_ISREF_TO_P -+#define Z_SET_ISREF_TO_P(pz, isref) (pz)->is_ref = isref -+#define Z_SET_ISREF_TO_PP(ppz, isref) Z_SET_ISREF_TO_P(*(ppz), isref) -+#endif -+ -+ -+extern void* apc_php_malloc(size_t n TSRMLS_DC); -+extern void apc_php_free(void* p TSRMLS_DC); -+ -+extern void apc_zend_init(TSRMLS_D); -+extern void apc_zend_shutdown(TSRMLS_D); -+ -+ -+/* offset for apc info in op_array->reserved */ -+extern int apc_reserved_offset; -+ -+#ifndef ZEND_VM_KIND_CALL /* Not currently defined by any ZE version */ -+# define ZEND_VM_KIND_CALL 1 -+#endif -+ -+#ifndef ZEND_VM_KIND /* Indicates PHP < 5.1 */ -+# define ZEND_VM_KIND ZEND_VM_KIND_CALL -+#endif -+ -+#if defined(ZEND_ENGINE_2) && (ZEND_VM_KIND == ZEND_VM_KIND_CALL) -+# define APC_OPCODE_OVERRIDE -+#endif -+ -+#ifdef APC_OPCODE_OVERRIDE -+ -+#ifdef ZEND_ENGINE_2_1 -+/* Taken from Zend/zend_vm_execute.h */ -+#define _CONST_CODE 0 -+#define _TMP_CODE 1 -+#define _VAR_CODE 2 -+#define _UNUSED_CODE 3 -+#define _CV_CODE 4 -+static inline int _apc_opcode_handler_decode(zend_op *opline) -+{ -+ static const int apc_vm_decode[] = { -+ _UNUSED_CODE, /* 0 */ -+ _CONST_CODE, /* 1 = IS_CONST */ -+ _TMP_CODE, /* 2 = IS_TMP_VAR */ -+ _UNUSED_CODE, /* 3 */ -+ _VAR_CODE, /* 4 = IS_VAR */ -+ _UNUSED_CODE, /* 5 */ -+ _UNUSED_CODE, /* 6 */ -+ _UNUSED_CODE, /* 7 */ -+ _UNUSED_CODE, /* 8 = IS_UNUSED */ -+ _UNUSED_CODE, /* 9 */ -+ _UNUSED_CODE, /* 10 */ -+ _UNUSED_CODE, /* 11 */ -+ _UNUSED_CODE, /* 12 */ -+ _UNUSED_CODE, /* 13 */ -+ _UNUSED_CODE, /* 14 */ -+ _UNUSED_CODE, /* 15 */ -+ _CV_CODE /* 16 = IS_CV */ -+ }; -+#ifdef ZEND_ENGINE_2_4 -+ return (opline->opcode * 25) + (apc_vm_decode[opline->op1_type] * 5) + apc_vm_decode[opline->op2_type]; -+#else -+ return (opline->opcode * 25) + (apc_vm_decode[opline->op1.op_type] * 5) + apc_vm_decode[opline->op2.op_type]; -+#endif -+} -+ -+# define APC_ZEND_OPLINE zend_op *opline = execute_data->opline; -+# define APC_OPCODE_HANDLER_DECODE(opline) _apc_opcode_handler_decode(opline) -+# if PHP_MAJOR_VERSION >= 6 -+# define APC_OPCODE_HANDLER_COUNT ((25 * 152) + 1) -+# elif defined(ZEND_ENGINE_2_4) -+# define APC_OPCODE_HANDLER_COUNT ((25 * 159) + 1) /* 5 new opcodes in 5.4 - qm_assign_var, jmp_set_var, separate, bind_trais, add_trait */ -+# elif PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 3 -+# define APC_OPCODE_HANDLER_COUNT ((25 * 154) + 1) /* 3 new opcodes in 5.3 - unused, lambda, jmp_set */ -+# else -+# define APC_OPCODE_HANDLER_COUNT ((25 * 151) + 1) -+# endif -+# define APC_REPLACE_OPCODE(opname) { int i; for(i = 0; i < 25; i++) if (zend_opcode_handlers[(opname*25) + i]) zend_opcode_handlers[(opname*25) + i] = apc_op_##opname; } -+ -+#else /* ZE2.0 */ -+# define APC_ZEND_ONLINE -+# define APC_OPCODE_HANDLER_DECODE(opline) (opline->opcode) -+# define APC_OPCODE_HANDLER_COUNT 512 -+# define APC_REPLACE_OPCODE(opname) zend_opcode_handlers[opname] = apc_op_##opname; -+#endif -+ -+#ifndef ZEND_FASTCALL /* Added in ZE2.3.0 */ -+#define ZEND_FASTCALL -+#endif -+ -+/* Added in ZE2.3.0 */ -+#ifndef zend_parse_parameters_none -+# define zend_parse_parameters_none() zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") -+#endif -+ -+ -+#endif /* APC_OPCODE_OVERRIDE */ -+ -+#ifdef ZEND_ENGINE_2_4 -+# define ZEND_CE_FILENAME(ce) (ce)->info.user.filename -+# define ZEND_CE_DOC_COMMENT(ce) (ce)->info.user.doc_comment -+# define ZEND_CE_DOC_COMMENT_LEN(ce) (ce)->info.user.doc_comment_len -+# define ZEND_CE_BUILTIN_FUNCTIONS(ce) (ce)->info.internal.builtin_functions -+#else -+# define ZEND_CE_FILENAME(ce) (ce)->filename -+# define ZEND_CE_DOC_COMMENT(ce) (ce)->doc_comment -+# define ZEND_CE_DOC_COMMENT_LEN(ce) (ce)->doc_comment_len -+# define ZEND_CE_BUILTIN_FUNCTIONS(ce) (ce)->builtin_functions -+#endif -+ -+#endif /* APC_ZEND_H */ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/CHANGELOG b/ext/apc/CHANGELOG ---- a/ext/apc/CHANGELOG 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/CHANGELOG 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,249 @@ -+ -+3.1.2 : 2008-12-12 -+ -+- pecl package.xml/build fixes (bjori) -+ -+3.1.1 : 2008-12-12 -+ -+- PHP4 compatibilty break -+- apc_pool allocator (Gopal) -+- doubly-linked sma allocator (Shire) -+- php 5.3 gc compatibility (Gopal) -+- APCIterator for easy access (Shire) -+- apc_delete_file (Shire) -+- apc_inc/apc_dec/apc_cas functions (Shire) -+- apc.canonicalize (Gopal) -+- apc.preload_path (Gopal) -+- apc.rfc1867_ttl (Shire) -+- apc.file_md5 (Shire) -+- consolidate locking macros (Shire) -+- remove futex/TSRM locks (Shire) -+- non-blocking semaphore locks (Shire) -+- zval* object rework (Gopal) -+ -+3.0.19: 2008-05-14 -+- Safe-mode and fast-cgi fixes -+- Fix double-free of builtin_functions -+- php 5.3 fixes -+ -+3.0.18: 2008-03-29 -+- Revert apc_expunge_cb bug-fix -+- Misc memleaks -+ -+3.0.17: 2008-03-26 -+- Crash fixes -+- Fix apc_add() cache expunge bug (Rasmus) -+- Added parameter to apc_fetch to determine success/failure when fetching booleans (shire) -+- Fix misc. memleaks (shire) -+ -+3.0.16: 2007-12-26 -+- Fix for longstanding cache-full crash (Christian Seiler) -+ http://news.php.net/php.pecl.dev/4951 for the details -+- Added optional shm unmap on a fatal signal feature (Lucas Nealan) -+- Added PTHREAD_MUTEX_ADAPTIVE_NP option pthread locks (Paul Saab) -+- Minor cleanups (Lucas Nealan) -+- Added configure option to enable apc_cache_info('filehits') (Shire) -+ -+3.0.15: 2007-10-18 -+- Eliminate a per-request time() syscall (Rasmus) -+- Added rfc1867 prefix, name, and freq ini options (Shire) -+- Allow deletion of individual user cache entries via apc.php (Sara) -+- Fix overzealous cleanup during RSHUTDOWN (Gopal) -+- Fix memory alignment and locking issues (Gopal) -+- Make apc_compile insert/replace entries (Shire) -+- Make mixed inheritance recompile & cache afresh (Gopal) -+- Make nostat mode search include_path for canonicalization (Gopal) -+- ZTS & other compile fixes (Gopal, Edin, Shire) -+ -+3.0.14: 2007-03-21 -+- Build fix (Shire) -+- Don't hook the upload hook if APC is disabled (Rasmus) -+- Local shadow cache support (Gopal) -+- Avoid uneccessary loops over op_arrays for "known" auto-globals (Gopal) -+- Fix apc_add() to overwrite timed out user entries (Rasmus) -+- Fix double inclusion of files with conditional classes in php4 (Gopal) -+- Allocator fixes to reduce fragmentation (Gopal) -+ -+3.0.13: 2007-02-24 -+- File upload progress (Rasmus) -+- Pthread mutex and spin locks (Shire) -+- Recursive zval support for apc_fetch/_store (Shire, Gopal) -+- apc.stat_ctime flag for ctime checks (Rasmus) -+- Multiple key fetches with apc_fetch (Shire) -+- Canary checks for shm memory deallocation (Gopal) -+- Add hooks for external optimizer (Shire) -+- Obsolete and remove apc optimizer (Gopal) -+- APC info changes - cache insert rate, hit and miss rates (Shire) -+- Fix apc_load_constants (Gopal) -+- Rewrite dump opcode code to use vld (Gopal) -+- Use apc_[ewn]print functions for error reporting (Shire) -+- Auto global fixes and refactoring (Gopal, Shire) -+- Fix memory leaks in object serialization (Ilia) -+- Memory cleanup code for destructor order (Gopal) -+- Win32 build fixes (Ilia, Wez) -+- ZTS and Php 4 build fixes (Bjori) -+- Add apc_add() function (Rasmus) -+- Add optional limited flag to apc_sma_info() (Rasmus) -+ -+3.0.12p2: 2006-09-05 -+- Package version up -+ -+3.0,12p1: 2006-09-05 -+- PHP4 build fixes -+ -+3.0.12: 2006-09-05 -+- PHP 5.2 compatibility (Gopal) -+- TSRM fixes (Gopal) -+- Add extra flags to op_array->reserved to improve op array -+ processing code (Gopal) -+- Fix crashes in optimizer and cli mode (Ilia) -+- Optimizer fixes for PHP5 (Ilia, Gopal) -+- Allow multiple inclusions of a file with a dynamic class (Gopal) -+- Php 4 function table and properties fixes (Gopal) -+- Fix memory leaks in apc_cache_info (Gopal) -+ -+3.0.11: 2006-08-16 -+- Made --enable-apc-mmap the default compile option (for real this time) -+- Add an optional flag to apc_cache_info() and some apc.php tweaks to make it -+ only fetch header information to make it useful when you have tens of -+ thousands of entries. (Brian Shire) -+- 64-bit fixes (George) -+- Don't mix Full Path and Inode keys (George) -+- Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of -+ require_once() and include_once() statements. (Sara) -+- Add a non-blocking write_lock for cache inserts. This is a better approach -+ to prevent cache slams and deprecates the slam_defense setting. (Rasmus) -+- A bit of work on the optimizer. (Sara) -+- Various memory issues resolved. (Gopal) -+ -+3.0.10: 2006-03-11 -+- Add apc.stat ini flag which defaults to 1. If set to 0, the main script and any fullpath -+ includes will not be stat'ed for any changes. You will have to restart the server if you -+ change anything. This mode increases performance quite a bit, especially if you have a -+ lot of includes. -+ -+- Get rid of the lock safety net hack I added in 3.0.9. It seems to cause more problems -+ than it solves. I'll need to revisit locking and signal handling at some point soon. -+ -+3.0.9: 2006-03-04 -+- Eliminate rand() call when slam_defense is not set (Rasmus) -+- Fix for __isset problem (Gopal) -+- Rewrite allocator from a "best fit" to a "next fit" algorithm (Rasmus) -+- Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus) -+- Report back the correct number of available bytes in the segment instead of the allocated bytes. (Rasmus) -+- Add cache busy flag which is set when an expunge is underway (Rasmus) -+- Add automatic serialization of objects in apc_store() (Marcus) -+- 64-bit .ini flag fix (Rasmus) -+- Static members fix (Gopal) -+- sma_cleanup() mem leak fix (Rasmus) -+- Fix for http://pecl.php.net/bugs/5311 (Rasmus) -+- Fix autoglobals JIT bug (Gopal) -+- Fix instance bug (Gopal) -+- Add a lock cleanup safety net to request shutdown (Rasmus) -+- Fix apc.slam_defense edge-case bug (Rasmus) -+- User entry memory usage tracking support (Ilia) -+- Allow keys used in apc_store/apc_fetch/apc_delete to be binary safe and prevent conflicts between keys that are found at the start of other keys. (Ilia) -+ -+3.0.8: 2005-08-24 -+Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus) -+Cache corruption fix in cache-full cleanup code (Gopal) -+ -+3.0.7: 2005-08-16 -+- Fix to apc.php to show final segment in frag chart. (Ilia) -+- A couple of win32 fixes. (Frank) -+- Add apc.enable_cli ini directive. (Rasmus) -+- Add test cases. (Marcus) -+- Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus) -+- Simplify user cache handling by removing the user_cache_stack (Rasmus) -+- Fix apc_fetch() memory corruption (Andrei,Rasmus) -+- Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia) -+ -+3.0.6: 2005-07-30 -+- Added apc.php to package.xml file. -+- Track per-entry memory usage. (Val) -+- Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus) -+- fcntl locking robustness fixes. (Rasmus) -+- Shared read-locks where possible. (Rasmus) -+- Added file_update_protection configuration parameter. (Rasmus) -+- Windows ZTS fixes (Frank) -+ -+3.0.5: 2005-07-27 -+- Make it easier for sapis that only populate file_handle->filename to use APC. (Rasmus) -+- Support extensions such as bcompiler that need to hook into compile_file. (Val) -+- Ralf Becker's apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia) -+- Segfault in cache cleanup code (Ilia, Rasmus) -+ -+3.0.4: 2005-07-18 -+- Add win32 support (Edin ) -+- Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches (Rasmus) -+- A couple of other minor fixes -+ -+3.0.3: 2005-07-05 -+- Fix compile problem against PHP 5.0.x -+ -+3.0.2: 2005-07-05 -+- Better shm error message -+ -+3.0.1: 2005-07-05 -+- PHP4 build fix -+ -+3.0: 2005-06-23 -+- PHP 5.1 support (Arun, Gopal, Rasmus) -+- Major Inheritance bug fix (Arun, Gopal) -+ -+2.0: 2003-02-10 -+- ground-up rewrite sharing none of the original source code (djc) -+ -+1.0.10: -+- merge mmap / shm code to be in one file, module supports both modes now [mpb 2001-05-15] -+- added apc.mode config parameter [mpb 2001-05-15] NOTE: You'll have to add -+ this parameter to your php.ini file to activate apc shm or mmap caching -+- generic source cleanup (missing includes, PATH_MAX usage etc) [mpb -+ 2001-05-15] -+- fixed: realpath return result checking in generate_key [mpb 2001-05-15] -+- updated: gui updated (extras/apc_gui-1.0.2.tar.gz) -+- experminental 'fast' cache-retrieval [djc 2001-05-20] -+- fixed regex support [gws 2001-05-16] -+- enhanced reader-writer lock support [rg 2001-05-07] -+ -+1.0.9: -+- fixed (?) memory alignment bug on 64 bit archiecures -+- added many cache visibiliy functions -+- added opional fcntl locks under shm version -+- numerous bug fixes -+ -+1.0.8: -+- added ability to detect and decompile compiled files placed as 'source' -+ [gws,dw 2001-01-30] -+- fixed apc_rstat bug [gws 2001-01-29] -+- added hack to support included urls [gws 2001-01-30] -+- fixed apc_cache_index [mb 2001-01-31] -+- added multiple regex support [gs 2001-02-03] -+- added apc_cache_info [mb,gs 2001-02-03] -+ -+1.0.7: -+- partially fixed for Solaris [gws 2001-01-29] -+- fixed mtime support for relative includes [gws 2001-01-29] -+- code cleanup [yg,ta,gws 2001-01-29] -+ -+1.0.6: -+- support for mtime in mmap [yg,gws 2001-01-27] -+- fixed indexed-array initialization bug [djc,gws 2001-01-27] -+ -+1.0.5: -+- support for relative include paths [djc,gws 2001-01-19] -+- class member array support fixed [djc 2001-01-18] -+- added apc_cache_index [gws 2001-01-18] -+ -+1.0.4: -+- support for class hierarchies greater than two levels deep [djc 2001-01-17] -+ -+1.0.3: -+- fixed support for class inheritance [djc 2001-01-16] -+ -+1.0.2: -+- support for inherited classes [gws 2001-01-15] -+- support for intialization of class variables and objects [gws 2001-01-13] -+ -+1.0.1: -+- added optional file modification time check [djc 2001-01-12] -diff -Naur a/ext/apc/config.m4 b/ext/apc/config.m4 ---- a/ext/apc/config.m4 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/config.m4 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,404 @@ -+dnl -+dnl $Id: config.m4 326700 2012-07-19 11:56:57Z ab $ -+dnl -+ -+PHP_ARG_ENABLE(apc, whether to enable APC support, -+[ --enable-apc Enable APC support]) -+ -+AC_ARG_ENABLE(apc-debug, -+[ --enable-apc-debug Enable APC debugging], -+[ -+ PHP_APC_DEBUG=$enableval -+], -+[ -+ PHP_APC_DEBUG=no -+]) -+ -+AC_MSG_CHECKING(whether we should enable cache request file info) -+AC_ARG_ENABLE(apc-filehits, -+[ --enable-apc-filehits Enable per request file info about files used from the APC cache (ie: apc_cache_info('filehits')) ], -+[ -+ PHP_APC_FILEHITS=$enableval -+ AC_MSG_RESULT($enableval) -+], -+[ -+ PHP_APC_FILEHITS=no -+ AC_MSG_RESULT(no) -+]) -+ -+AC_MSG_CHECKING(whether we should use mmap) -+AC_ARG_ENABLE(apc-mmap, -+[ --disable-apc-mmap -+ Disable mmap support and use IPC shm instead], -+[ -+ PHP_APC_MMAP=$enableval -+ AC_MSG_RESULT($enableval) -+], [ -+ PHP_APC_MMAP=yes -+ AC_MSG_RESULT(yes) -+]) -+ -+AC_MSG_CHECKING(whether we should use semaphore locking instead of fcntl) -+AC_ARG_ENABLE(apc-sem, -+[ --enable-apc-sem -+ Enable semaphore locks instead of fcntl], -+[ -+ PHP_APC_SEM=$enableval -+ AC_MSG_RESULT($enableval) -+], [ -+ PHP_APC_SEM=no -+ AC_MSG_RESULT(no) -+]) -+ -+AC_MSG_CHECKING(whether we should use pthread mutex locking) -+AC_ARG_ENABLE(apc-pthreadmutex, -+[ --disable-apc-pthreadmutex -+ Disable pthread mutex locking ], -+[ -+ PHP_APC_PTHREADMUTEX=$enableval -+ AC_MSG_RESULT($enableval) -+], -+[ -+ PHP_APC_PTHREADMUTEX=yes -+ AC_MSG_RESULT(yes) -+]) -+ -+if test "$PHP_APC_PTHREADMUTEX" != "no"; then -+ orig_LIBS="$LIBS" -+ LIBS="$LIBS -lpthread" -+ AC_TRY_RUN( -+ [ -+ #include -+ #include -+ main() { -+ pthread_mutex_t mutex; -+ pthread_mutexattr_t attr; -+ -+ if(pthread_mutexattr_init(&attr)) { -+ puts("Unable to initialize pthread attributes (pthread_mutexattr_init)."); -+ return -1; -+ } -+ if(pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) { -+ puts("Unable to set PTHREAD_PROCESS_SHARED (pthread_mutexattr_setpshared), your system may not support shared mutex's."); -+ return -1; -+ } -+ if(pthread_mutex_init(&mutex, &attr)) { -+ puts("Unable to initialize the mutex (pthread_mutex_init)."); -+ return -1; -+ } -+ if(pthread_mutexattr_destroy(&attr)) { -+ puts("Unable to destroy mutex attributes (pthread_mutexattr_destroy)."); -+ return -1; -+ } -+ if(pthread_mutex_destroy(&mutex)) { -+ puts("Unable to destroy mutex (pthread_mutex_destroy)."); -+ return -1; -+ } -+ -+ puts("pthread mutexs are supported!"); -+ return 0; -+ } -+ ], -+ [ dnl -Success- -+ PHP_ADD_LIBRARY(pthread) -+ ], -+ [ dnl -Failure- -+ AC_MSG_WARN([It doesn't appear that pthread mutexes are supported on your system]) -+ PHP_APC_PTHREADMUTEX=no -+ ], -+ [ -+ PHP_ADD_LIBRARY(pthread) -+ ] -+ ) -+ LIBS="$orig_LIBS" -+fi -+ -+AC_MSG_CHECKING(whether we should use pthread read/write locking) -+AC_ARG_ENABLE(apc-pthreadrwlocks, -+[ --enable-apc-pthreadrwlocks -+ Enable pthread read/write locking ], -+[ -+ PHP_APC_PTHREADRWLOCK=$enableval -+ AC_MSG_RESULT($enableval) -+], -+[ -+ PHP_APC_PTHREADRWLOCK=no -+ AC_MSG_RESULT(no) -+]) -+ -+if test "$PHP_APC_PTHREADRWLOCK" != "no"; then -+ orig_LIBS="$LIBS" -+ LIBS="$LIBS -lpthread" -+ AC_TRY_RUN( -+ [ -+ #include -+ #include -+ main() { -+ pthread_rwlock_t rwlock; -+ pthread_rwlockattr_t attr; -+ -+ if(pthread_rwlockattr_init(&attr)) { -+ puts("Unable to initialize pthread attributes (pthread_rwlockattr_init)."); -+ return -1; -+ } -+ if(pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) { -+ puts("Unable to set PTHREAD_PROCESS_SHARED (pthread_rwlockattr_setpshared), your system may not support shared rwlock's."); -+ return -1; -+ } -+ if(pthread_rwlock_init(&rwlock, &attr)) { -+ puts("Unable to initialize the rwlock (pthread_rwlock_init)."); -+ return -1; -+ } -+ if(pthread_rwlockattr_destroy(&attr)) { -+ puts("Unable to destroy rwlock attributes (pthread_rwlockattr_destroy)."); -+ return -1; -+ } -+ if(pthread_rwlock_destroy(&rwlock)) { -+ puts("Unable to destroy rwlock (pthread_rwlock_destroy)."); -+ return -1; -+ } -+ -+ puts("pthread rwlocks are supported!"); -+ return 0; -+ } -+ ], -+ [ dnl -Success- -+ PHP_ADD_LIBRARY(pthread) -+ APC_CFLAGS="-D_GNU_SOURCE" -+ ], -+ [ dnl -Failure- -+ AC_MSG_WARN([It doesn't appear that pthread rwlocks are supported on your system]) -+ PHP_APC_PTHREADRWLOCK=no -+ ], -+ [ -+ PHP_ADD_LIBRARY(pthread) -+ ] -+ ) -+ LIBS="$orig_LIBS" -+fi -+ -+ AC_CACHE_CHECK([whether the target compiler supports builtin atomics], PHP_cv_APC_GCC_ATOMICS, [ -+ -+ AC_TRY_LINK([],[ -+ int foo = 0; -+ __sync_fetch_and_add(&foo, 1); -+ __sync_bool_compare_and_swap(&foo, 0, 1); -+ return __sync_fetch_and_add(&foo, 1); -+ ], -+ [PHP_cv_APC_GCC_ATOMICS=yes], -+ [PHP_cv_APC_GCC_ATOMICS=no]) -+ ]) -+ -+ if test "x${PHP_cv_APC_GCC_ATOMICS}" != "xno"; then -+ AC_DEFINE(HAVE_ATOMIC_OPERATIONS, 1, -+ [Define this if your target compiler supports builtin atomics]) -+ else -+ if test "$PHP_APC_PTHREADRWLOCK" != "no"; then -+ AC_MSG_WARN([Disabling pthread rwlocks, because of missing atomic operations]) -+ dnl - fall back would most likely be pthread mutexes -+ PHP_APC_PTHREADRWLOCK=no -+ fi -+ fi -+ -+AC_MSG_CHECKING(whether we should use spin locks) -+AC_ARG_ENABLE(apc-spinlocks, -+[ --enable-apc-spinlocks -+ Enable spin locks EXPERIMENTAL ], -+[ -+ PHP_APC_SPINLOCKS=$enableval -+ AC_MSG_RESULT($enableval) -+], -+[ -+ PHP_APC_SPINLOCKS=no -+ AC_MSG_RESULT(no) -+]) -+ -+ -+AC_MSG_CHECKING(whether we should enable memory protection) -+AC_ARG_ENABLE(apc-memprotect, -+[ --enable-apc-memprotect -+ Enable mmap/shm memory protection], -+[ -+ PHP_APC_MEMPROTECT=$enableval -+ AC_MSG_RESULT($enableval) -+], [ -+ PHP_APC_MEMPROTECT=no -+ AC_MSG_RESULT(no) -+]) -+ -+if test "$PHP_APC" != "no"; then -+ test "$PHP_APC_MMAP" != "no" && AC_DEFINE(APC_MMAP, 1, [ ]) -+ test "$PHP_APC_FILEHITS" != "no" && AC_DEFINE(APC_FILEHITS, 1, [ ]) -+ -+ if test "$PHP_APC_DEBUG" != "no"; then -+ AC_DEFINE(__DEBUG_APC__, 1, [ ]) -+ fi -+ -+ if test "$PHP_APC_SEM" != "no"; then -+ AC_DEFINE(APC_SEM_LOCKS, 1, [ ]) -+ elif test "$PHP_APC_SPINLOCKS" != "no"; then -+ AC_DEFINE(APC_SPIN_LOCKS, 1, [ ]) -+ elif test "$PHP_APC_PTHREADRWLOCK" != "no"; then -+ AC_DEFINE(APC_PTHREADRW_LOCKS, 1, [ ]) -+ elif test "$PHP_APC_PTHREADMUTEX" != "no"; then -+ AC_DEFINE(APC_PTHREADMUTEX_LOCKS, 1, [ ]) -+ else -+ AC_DEFINE(APC_FCNTL_LOCKS, 1, [ ]) -+ fi -+ -+ if test "$PHP_APC_MEMPROTECT" != "no"; then -+ AC_DEFINE(APC_MEMPROTECT, 1, [ shm/mmap memory protection ]) -+ fi -+ -+ AC_CACHE_CHECK(for zend_set_lookup_function_hook, php_cv_zend_set_lookup_function_hook, -+ [ -+ orig_cflags=$CFLAGS -+ CFLAGS="$INCLUDES $EXTRA_INCLUDES" -+ AC_TRY_COMPILE([ -+#include "main/php.h" -+#include "Zend/zend_API.h" -+ ], [#ifndef zend_set_lookup_function_hook -+ (void) zend_set_lookup_function_hook; -+#endif], [ -+ php_cv_zend_set_lookup_function_hook=yes -+ ],[ -+ php_cv_zend_set_lookup_function_hook=no -+ ]) -+ CFLAGS=$orig_cflags -+ ]) -+ if test "$php_cv_zend_set_lookup_function_hook" = "yes"; then -+ AC_DEFINE(APC_HAVE_LOOKUP_HOOKS, 1, [ ]) -+ else -+ AC_DEFINE(APC_HAVE_LOOKUP_HOOKS, 0, [ ]) -+ fi -+ -+ AC_CHECK_FUNCS(sigaction) -+ AC_CACHE_CHECK(for union semun, php_cv_semun, -+ [ -+ AC_TRY_COMPILE([ -+#include -+#include -+#include -+ ], [union semun x; x.val=1], [ -+ php_cv_semun=yes -+ ],[ -+ php_cv_semun=no -+ ]) -+ ]) -+ if test "$php_cv_semun" = "yes"; then -+ AC_DEFINE(HAVE_SEMUN, 1, [ ]) -+ else -+ AC_DEFINE(HAVE_SEMUN, 0, [ ]) -+ fi -+ -+ AC_MSG_CHECKING(whether we should enable valgrind support) -+ AC_ARG_ENABLE(valgrind-checks, -+ [ --disable-valgrind-checks -+ Disable valgrind based memory checks], -+ [ -+ PHP_APC_VALGRIND=$enableval -+ AC_MSG_RESULT($enableval) -+ ], [ -+ PHP_APC_VALGRIND=yes -+ AC_MSG_RESULT(yes) -+ AC_CHECK_HEADER(valgrind/memcheck.h, -+ [AC_DEFINE([HAVE_VALGRIND_MEMCHECK_H],1, [enable valgrind memchecks])]) -+ ]) -+ -+ apc_sources="apc.c php_apc.c \ -+ apc_cache.c \ -+ apc_compile.c \ -+ apc_debug.c \ -+ apc_fcntl.c \ -+ apc_main.c \ -+ apc_mmap.c \ -+ apc_sem.c \ -+ apc_shm.c \ -+ apc_pthreadmutex.c \ -+ apc_pthreadrwlock.c \ -+ apc_spin.c \ -+ pgsql_s_lock.c \ -+ apc_sma.c \ -+ apc_stack.c \ -+ apc_zend.c \ -+ apc_rfc1867.c \ -+ apc_signal.c \ -+ apc_pool.c \ -+ apc_iterator.c \ -+ apc_bin.c \ -+ apc_string.c " -+ -+ PHP_CHECK_LIBRARY(rt, shm_open, [PHP_ADD_LIBRARY(rt,,APC_SHARED_LIBADD)]) -+ PHP_NEW_EXTENSION(apc, $apc_sources, $ext_shared,, \\$(APC_CFLAGS)) -+ PHP_SUBST(APC_SHARED_LIBADD) -+ PHP_SUBST(APC_CFLAGS) -+ PHP_INSTALL_HEADERS(ext/apc, [apc_serializer.h]) -+ AC_DEFINE(HAVE_APC, 1, [ ]) -+fi -+ -+PHP_ARG_ENABLE(coverage, whether to include code coverage symbols, -+[ --enable-coverage DEVELOPERS ONLY!!], no, no) -+ -+if test "$PHP_COVERAGE" = "yes"; then -+ -+ if test "$GCC" != "yes"; then -+ AC_MSG_ERROR([GCC is required for --enable-coverage]) -+ fi -+ -+ dnl Check if ccache is being used -+ case `$php_shtool path $CC` in -+ *ccache*[)] gcc_ccache=yes;; -+ *[)] gcc_ccache=no;; -+ esac -+ -+ if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then -+ AC_MSG_ERROR([ccache must be disabled when --enable-coverage option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.]) -+ fi -+ -+ lcov_version_list="1.5 1.6 1.7 1.9" -+ -+ AC_CHECK_PROG(LCOV, lcov, lcov) -+ AC_CHECK_PROG(GENHTML, genhtml, genhtml) -+ PHP_SUBST(LCOV) -+ PHP_SUBST(GENHTML) -+ -+ if test "$LCOV"; then -+ AC_CACHE_CHECK([for lcov version], php_cv_lcov_version, [ -+ php_cv_lcov_version=invalid -+ lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'` #' -+ for lcov_check_version in $lcov_version_list; do -+ if test "$lcov_version" = "$lcov_check_version"; then -+ php_cv_lcov_version="$lcov_check_version (ok)" -+ fi -+ done -+ ]) -+ else -+ lcov_msg="To enable code coverage reporting you must have one of the following LCOV versions installed: $lcov_version_list" -+ AC_MSG_ERROR([$lcov_msg]) -+ fi -+ -+ case $php_cv_lcov_version in -+ ""|invalid[)] -+ lcov_msg="You must have one of the following versions of LCOV: $lcov_version_list (found: $lcov_version)." -+ AC_MSG_ERROR([$lcov_msg]) -+ LCOV="exit 0;" -+ ;; -+ esac -+ -+ if test -z "$GENHTML"; then -+ AC_MSG_ERROR([Could not find genhtml from the LCOV package]) -+ fi -+ -+ PHP_ADD_MAKEFILE_FRAGMENT -+ -+ dnl Remove all optimization flags from CFLAGS -+ changequote({,}) -+ CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9s]*//g'` -+ CXXFLAGS=`echo "$CXXFLAGS" | $SED -e 's/-O[0-9s]*//g'` -+ changequote([,]) -+ -+ dnl Add the special gcc flags -+ CFLAGS="$CFLAGS -O0 -ggdb -fprofile-arcs -ftest-coverage" -+ CXXFLAGS="$CXXFLAGS -ggdb -O0 -fprofile-arcs -ftest-coverage" -+fi -+dnl vim: set ts=2 -diff -Naur a/ext/apc/config.w32 b/ext/apc/config.w32 ---- a/ext/apc/config.w32 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/config.w32 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,60 @@ -+// $Id: config.w32 309203 2011-03-14 06:47:16Z pajoye $ -+// vim:ft=javascript -+ -+ARG_ENABLE('apc', 'Whether to enable APC support', 'no'); -+ARG_ENABLE('apc-debug', 'Whether to enable APC debugging', 'no'); -+ARG_ENABLE('apc-filehits', 'Whether to enable cache request file info', 'no'); -+ARG_ENABLE('apc-spinlocks', 'Whether to use spin locks (experimental)', 'no'); -+ARG_ENABLE('apc-memprotect', 'Whether to enable memory protection (experimental)', 'no'); -+ARG_ENABLE('apc-srwlock-native', 'Whether to use SRWLOCK locks native (win7/2008 only)', 'no'); -+ARG_ENABLE('apc-srwlock-kernel', 'Whether to use SRWLOCK locks (loaded at runtime)', 'no'); -+ -+if(PHP_APC != 'no') -+{ -+ var apc_sources = 'apc.c php_apc.c apc_cache.c apc_compile.c apc_debug.c ' + -+ 'apc_fcntl_win32.c apc_iterator.c apc_main.c apc_shm.c ' + -+ 'apc_sma.c apc_stack.c apc_rfc1867.c apc_zend.c apc_pool.c ' + -+ 'apc_bin.c apc_string.c'; -+ -+ if(PHP_APC_DEBUG != 'no') -+ { -+ ADD_FLAG('CFLAGS_APC', '/D __DEBUG_APC__=1'); -+ } -+ -+ if(PHP_APC_FILEHITS != 'no') -+ { -+ AC_DEFINE('APC_FILEHITS', 1); -+ } -+ -+ if(PHP_APC_MEMPROTECT != 'no') -+ { -+ AC_DEFINE('APC_MEMPROTECT', 1); -+ } -+ -+ if(PHP_APC_SRWLOCK_NATIVE != 'no') { -+ AC_DEFINE('APC_SRWLOCK_NATIVE', 1); -+ } else { -+ if(PHP_APC_SRWLOCK_KERNEL != 'no') { -+ AC_DEFINE('APC_SRWLOCK_KERNEL', 1); -+ ADD_FLAG('CFLAGS_APC', '/D WIN32_ONLY_COMPILER=1'); -+ -+ apc_sources += ' apc_windows_srwlock_kernel.c'; -+ } else { -+ if(PHP_APC_SPINLOCKS != 'no') { -+ AC_DEFINE('APC_SPIN_LOCKS', 1); -+ ADD_FLAG('CFLAGS_APC', '/D WIN32_ONLY_COMPILER=1'); -+ -+ apc_sources += ' apc_spin.c pgsql_s_lock.c'; -+ } else { -+ AC_DEFINE('APC_FCNTL_LOCKS', 1); -+ } -+ } -+ } -+ -+ AC_DEFINE('HAVE_APC', 1); -+ AC_DEFINE('HAVE_ATOMIC_OPERATIONS', 1); -+ -+ PHP_INSTALL_HEADERS("ext/apc", "apc_serializer.h"); -+ -+ EXTENSION('apc', apc_sources); -+} -diff -Naur a/ext/apc/INSTALL b/ext/apc/INSTALL ---- a/ext/apc/INSTALL 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/INSTALL 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,407 @@ -+Installation Instructions for APC -+--------------------------------- -+ -+This version of APC should work on PHP 4.3.0 - 4.4.x and -+5.1.0 - 5.2.x. Yes, that means PHP 5.0.x is no longer -+supported. Upgrade to PHP 5.1.x or 5.2.x and you will -+notice all sorts of performance increases. -+ -+CVS Instructions -+---------------- -+Building from CVS can be done like this: -+ -+ svn co http://svn.php.net/repository/pecl/apc/trunk apc -+ cd apc -+ phpize -+ ./configure --with-php-config=/usr/local/php/bin/php-config -+ make -+ export TEST_PHP_ARGS='-n' -+ make test -+ make install -+ -+Suggested Configuration (in your php.ini file) -+---------------------------------------------- -+ extension=apc.so -+ apc.enabled=1 -+ apc.shm_size=128M -+ apc.ttl=7200 -+ apc.user_ttl=7200 -+ apc.enable_cli=1 -+ -+These are fully described at the bottom of this file. -+ -++---------------------+ -+| QUICK INSTALL (DSO) | -++---------------------+ -+ -+These instructions assume your PHP installation is located in /usr/local/php and you -+want Apache optimizations (--with-apxs). -+ -+$ gunzip -c apc_x.y.tar.gz | tar xf - -+$ cd apc_x.y -+$ /usr/local/php/bin/phpize -+$ ./configure --with-php-config=/usr/local/php/bin/php-config -+$ make -+$ make install -+ -+You will probably need to run the final command (make install) as root. -+ -+The above sequence of commands will install a .so file in your PHP -+installation extension directory. The output of make install should display -+that path to the screen. -+ -+Next you must edit your php.ini file, which is normally located in -+/usr/local/php/lib/php.ini, and add the following line: -+ -+ extension="apc.so" -+ -+Replace "/path/to/php/extensions" with whatever path was displayed when you -+ran make install above. -+ -+Then restart your web server and consult the output of phpinfo(). If there is -+an informational section for APC, the installation was successful. -+ -++------------------------+ -+| QUICK INSTALL (Static) | -++------------------------+ -+ -+APC will not successfully compile on all systems as a DSO. If you run into -+problems using the DSO quick install, you can try to compile it statically -+into PHP. (The DSO install is recommended, though.) -+ -+These instructions assume the current directory is the root of the PHP source -+tree, and that you have already configured PHP by running its bundled -+configure script. -+ -+$ cd ext -+$ gunzip -c apc_x.y.tar.gz | tar xf - -+$ cd .. -+$ ./buildconf -+$ ./config.nice -+$ make -+$ make install -+ -+Once this is complete, simply restart your web server. You do not need to -+modify your php.ini file to enable APC. -+ -++-----------------+ -+| VERBOSE INSTALL | -++-----------------+ -+ -+These instructions assume your PHP installation is located in /usr/local/php. -+ -+1. Unpack your distribution file. -+ -+ You will have downloaded a file named something like apc_x.y.tar.gz. -+ Unzip this file with a command like -+ -+ gunzip apc_x.y.tar.gz -+ -+ Next you have to untar it with -+ -+ tar xvf apc_x.y.tar -+ -+ This will create an apc_x.y directory. cd into this new directory: -+ -+ cd apc_x.y -+ -+2. Run phpize. -+ -+ phpize is a script that should have been installed with PHP, and is -+ normally located in /usr/local/php/bin assuming you installed PHP in -+ /usr/local/php. (If you do not have the phpize script, you must reinstall -+ PHP and be sure not to disable PEAR.) -+ -+ Run the phpize command: -+ -+ /usr/local/php/bin/phpize -+ -+ Its output should resemble this: -+ -+ autoheader: `config.h.in' is created -+ You should update your `aclocal.m4' by running aclocal. -+ Configuring for: -+ PHP Api Version: 20020918 -+ Zend Module Api No: 20020429 -+ Zend Extension Api No: 20021010 -+ -+ phpize should create a configure script in the current directory. If you -+ get errors instead, you might be missing some required development tools, -+ such as autoconf or libtool. You can try downloading the latest versions -+ of those tools and running phpize again. -+ -+3. Run the configure script. -+ -+ phpize creates a configure script. The only option you need to specify is -+ the location of your php-config script: -+ -+ ./configure --enable-apc -+ -+ php-config should be located in the same directory as phpize. -+ -+ If you prefer to use mmap instead of the default IPC shared memory support, -+ add --enable-apc-mmap to your configure line. -+ -+ If you prefer to use sysv IPC semaphores over the safer fcntl() locks, add -+ --enable-sem to your configure line. If you don't have a problem -+ with your server segaulting, or any other unnatural accumulation of -+ semaphores on your system, the semaphore based locking is slightly faster. -+ -+4. Compile and install the files. Simply type: make install -+ -+ (You may need to be root in order to install) -+ -+ If you encounter errors from libtool or gcc during this step, please -+ contact the project maintainer (dcowgill@php.net). -+ -+5. Edit your php.ini -+ -+ make install should have printed a line resembling the following: -+ -+ Installing shared extensions: /path/to/extension/ -+ -+ Copy the path /path/to/extension/ and add the following line to your -+ php.ini file (normally located in /usr/local/php/lib/php.ini): -+ -+ extension="apc.so" -+ -+ If you don't have a php.ini file in that location, you can create it now. -+ -+6. Restart the web server and test the installation. -+ -+ Restart your web server now (for apache, it's apachectl restart) and -+ create a small test PHP file in your document root. The file should -+ contain just the following line: -+ -+ -+ -+ Request that file in a web browser. If there is an entry for APC in the -+ list of installed modules, the installation was successful. -+ -+ If APC is not listed, consult your web server error log. If it contains an -+ error message saying that it can't load the APC extension, your system -+ might not be able to load shared libraries created with PHP's build -+ system. One alternative would be to compile APC statically into PHP. See -+ the Quick Install (Static) instructions above. -+ -+ You should consult your error log anyway to see if APC generated any -+ errors. On BSD-based platforms, it is typical for APC to be unable to -+ allocate the default-sized shared memory segment. See below for hints on -+ raising your system's shared memory limitations. -+ -++-----------------+ -+| CONFIGURING APC | -++-----------------+ -+ -+Although the default APC settings are fine for many installations, serious -+users should consider tuning the following parameters: -+ -+ OPTION DESCRIPTION -+ ------------------ -------------------------------------------------- -+ apc.enabled This can be set to 0 to disable APC. This is -+ primarily useful when APC is statically compiled -+ into PHP, since there is no other way to disable -+ it (when compiled as a DSO, the zend_extension -+ line can just be commented-out). -+ (Default: 1) -+ -+ apc.shm_segments The number of shared memory segments to allocate -+ for the compiler cache. If APC is running out of -+ shared memory but you have already set -+ apc.shm_size as high as your system allows, you -+ can try raising this value. Setting this to a -+ value other than 1 has no effect in mmap mode -+ since mmap'ed shm segments don't have size limits. -+ (Default: 1) -+ -+ apc.shm_size The size of each shared memory segment in MB. -+ By default, some systems (including most BSD -+ variants) have very low limits on the size of a -+ shared memory segment. M/G suffixes must be used. -+ (Default: 30) -+ -+ -+ apc.optimization This option has been deprecated. -+ (Default: 0) -+ -+ apc.num_files_hint A "hint" about the number of distinct source files -+ that will be included or requested on your web -+ server. Set to zero or omit if you're not sure; -+ this setting is mainly useful for sites that have -+ many thousands of source files. -+ (Default: 1000) -+ -+ apc.user_entries_hint Just like num_files_hint, a "hint" about the number -+ of distinct user cache variables to store. -+ Set to zero or omit if you're not sure; -+ (Default: 4096) -+ -+ apc.ttl The number of seconds a cache entry is allowed to -+ idle in a slot in case this cache entry slot is -+ needed by another entry. Leaving this at zero -+ means that your cache could potentially fill up -+ with stale entries while newer entries won't be -+ cached. -+ (Default: 0) -+ -+ apc.user_ttl The number of seconds a user cache entry is allowed -+ to idle in a slot in case this cache entry slot is -+ needed by another entry. Leaving this at zero -+ means that your cache could potentially fill up -+ with stale entries while newer entries won't be -+ cached. -+ (Default: 0) -+ -+ -+ apc.gc_ttl The number of seconds that a cache entry may -+ remain on the garbage-collection list. This value -+ provides a failsafe in the event that a server -+ process dies while executing a cached source file; -+ if that source file is modified, the memory -+ allocated for the old version will not be -+ reclaimed until this TTL reached. Set to zero to -+ disable this feature. -+ (Default: 3600) -+ -+ apc.cache_by_default On by default, but can be set to off and used in -+ conjunction with positive apc.filters so that files -+ are only cached if matched by a positive filter. -+ (Default: On) -+ -+ apc.filters A comma-separated list of POSIX extended regular -+ expressions. If any pattern matches the source -+ filename, the file will not be cached. Note that -+ the filename used for matching is the one passed -+ to include/require, not the absolute path. If the -+ first character of the expression is a + then the -+ expression will be additive in the sense that any -+ files matched by the expression will be cached, and -+ if the first character is a - then anything matched -+ will not be cached. The - case is the default, so -+ it can be left off. -+ (Default: "") -+ -+ apc.mmap_file_mask If compiled with MMAP support by using --enable-mmap -+ this is the mktemp-style file_mask to pass to the -+ mmap module for determing whether your mmap'ed memory -+ region is going to be file-backed or shared memory -+ backed. For straight file-backed mmap, set it to -+ something like /tmp/apc.XXXXXX (exactly 6 X's). -+ To use POSIX-style shm_open/mmap put a ".shm" -+ somewhere in your mask. eg. "/apc.shm.XXXXXX" -+ You can also set it to "/dev/zero" to use your -+ kernel's /dev/zero interface to anonymous mmap'ed -+ memory. Leaving it undefined will force an -+ anonymous mmap. -+ (Default: "") -+ -+ apc.slam_defense ** DEPRECATED - Use apc.write_lock instead ** -+ On very busy servers whenever you start the server or -+ modify files you can create a race of many processes -+ all trying to cache the same file at the same time. -+ This option sets the percentage of processes that will -+ skip trying to cache an uncached file. Or think of it -+ as the probability of a single process to skip caching. -+ For example, setting this to 75 would mean that there is -+ a 75% chance that the process will not cache an uncached -+ file. So the higher the setting the greater the defense -+ against cache slams. Setting this to 0 disables this -+ feature. -+ (Default: 0) -+ -+ apc.file_update_protection -+ When you modify a file on a live web server you really -+ should do so in an atomic manner. That is, write to a -+ temporary file and rename (mv) the file into its permanent -+ position when it is ready. Many text editors, cp, tar and -+ other such programs don't do this. This means that there -+ is a chance that a file is accessed (and cached) while it -+ is still being written to. This file_update_protection -+ setting puts a delay on caching brand new files. The -+ default is 2 seconds which means that if the modification -+ timestamp (mtime) on a file shows that it is less than 2 -+ seconds old when it is accessed, it will not be cached. -+ The unfortunate person who accessed this half-written file -+ will still see weirdness, but at least it won't persist. -+ If you are certain you always atomically update your files -+ by using something like rsync which does this correctly, you -+ can turn this protection off by setting it to 0. If you -+ have a system that is flooded with io causing some update -+ procedure to take longer than 2 seconds, you may want to -+ increase this a bit. -+ (Default: 2) -+ -+ apc.enable_cli Mostly for testing and debugging. Setting this enables APC -+ for the CLI version of PHP. Normally you wouldn't want to -+ create, populate and tear down the APC cache on every CLI -+ request, but for various test scenarios it is handy to be -+ able to enable APC for the CLI version of APC easily. -+ (Default: 0) -+ -+ apc.max_file_size Prevents large files from being cached. -+ (Default: 1M) -+ -+ apc.stat Whether to stat the main script file and the fullpath -+ includes. If you turn this off you will need to restart -+ your server in order to update scripts. -+ (Default: 1) -+ -+ apc.canonicalize Whether to canonicalize paths in stat=0 mode or -+ fall back to stat behaviour if set to 0 -+ (Default: 0) -+ -+ apc.write_lock On busy servers when you first start up the server, or when -+ many files are modified, you can end up with all your processes -+ trying to compile and cache the same files. With write_lock -+ enabled, only one process at a time will try to compile an -+ uncached script while the other processes will run uncached -+ instead of sitting around waiting on a lock. -+ (Default: 1) -+ -+ apc.report_autofilter Logs any scripts that were automatically excluded from being -+ cached due to early/late binding issues. -+ (Default: 0) -+ -+ apc.rfc1867 RFC1867 File Upload Progress hook handler is only available -+ if you compiled APC against PHP 5.2.0 or later. When enabled -+ any file uploads which includes a field called -+ APC_UPLOAD_PROGRESS before the file field in an upload form -+ will cause APC to automatically create an upload_ -+ user cache entry where is the value of the -+ APC_UPLOAD_PROGRESS form entry. -+ -+ Note that the file upload tracking is not threadsafe at this -+ point, so new uploads that happen while a previous one is -+ still going will disable the tracking for the previous. -+ (Default: 0) -+ -+ apc.rfc1867_prefix Key prefix to use for the user cache entry generated by -+ rfc1867 upload progress functionality. -+ (Default: "upload_") -+ -+ apc.rfc1867_name Specify the hidden form entry name that activates APC upload -+ progress and specifies the user cache key suffix. -+ (Default: "APC_UPLOAD_PROGRESS") -+ -+ apc.rfc1867_freq The frequency that updates should be made to the user cache -+ entry for upload progress. This can take the form of a -+ percentage of the total file size or a size in bytes -+ optionally suffixed with 'k', 'm', or 'g' for kilobytes, -+ megabytes, or gigabytes respectively (case insensitive). -+ A setting of 0 updates as often as possible, which may cause -+ slower uploads. -+ (Default: 0) -+ -+ apc.localcache ** REMOVED -+ apc.localcache.size ** REMOVED -+ -+ apc.include_once_override -+ Optimize include_once and require_once calls and avoid the -+ expensive system calls used. -+ (Default: 0) -+ -+ apc.serializer -+ Defines which serializer should be used. Default is the -+ standard PHP serializer. Other can be used without having -+ to re compile apc, like igbinary for example. -+ (apc.serializer=igbinary) -diff -Naur a/ext/apc/LICENSE b/ext/apc/LICENSE ---- a/ext/apc/LICENSE 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/LICENSE 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,68 @@ -+-------------------------------------------------------------------- -+ The PHP License, version 3.01 -+Copyright (c) 1999 - 2011 The PHP Group. All rights reserved. -+-------------------------------------------------------------------- -+ -+Redistribution and use in source and binary forms, with or without -+modification, is permitted provided that the following conditions -+are met: -+ -+ 1. Redistributions of source code must retain the above copyright -+ notice, this list of conditions and the following disclaimer. -+ -+ 2. Redistributions in binary form must reproduce the above copyright -+ notice, this list of conditions and the following disclaimer in -+ the documentation and/or other materials provided with the -+ distribution. -+ -+ 3. The name "PHP" must not be used to endorse or promote products -+ derived from this software without prior written permission. For -+ written permission, please contact group@php.net. -+ -+ 4. Products derived from this software may not be called "PHP", nor -+ may "PHP" appear in their name, without prior written permission -+ from group@php.net. You may indicate that your software works in -+ conjunction with PHP by saying "Foo for PHP" instead of calling -+ it "PHP Foo" or "phpfoo" -+ -+ 5. The PHP Group may publish revised and/or new versions of the -+ license from time to time. Each version will be given a -+ distinguishing version number. -+ Once covered code has been published under a particular version -+ of the license, you may always continue to use it under the terms -+ of that version. You may also choose to use such covered code -+ under the terms of any subsequent version of the license -+ published by the PHP Group. No one other than the PHP Group has -+ the right to modify the terms applicable to covered code created -+ under this License. -+ -+ 6. Redistributions of any form whatsoever must retain the following -+ acknowledgment: -+ "This product includes PHP software, freely available from -+ ". -+ -+THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND -+ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP -+DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -+OF THE POSSIBILITY OF SUCH DAMAGE. -+ -+-------------------------------------------------------------------- -+ -+This software consists of voluntary contributions made by many -+individuals on behalf of the PHP Group. -+ -+The PHP Group can be contacted via Email at group@php.net. -+ -+For more information on the PHP Group and the PHP project, -+please see . -+ -+PHP includes the Zend Engine, freely available at -+. -diff -Naur a/ext/apc/NOTICE b/ext/apc/NOTICE ---- a/ext/apc/NOTICE 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/NOTICE 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,43 @@ -+This is the NOTICE file that holds acknowledgements and stuff. -+ -+The Alternative PHP Cache (APC) is a free and open opcode cache for PHP. -+This extension is being released under the PHP License for complete compliance -+with PHP and to encourage wide-spread use. It is our intention that this -+project be kept open source and that all commercial spin-offs contribute their -+modifications back into the public source-tree. -+ -+Creators: -+ Daniel Cowgill -+ George Schlossnagle -+ -+PHP5 support and major features by: -+ Arun C. Murthy -+ Gopal Vijayaraghavan -+ Rasmus Lerdorf -+ -+This software was contributed to PHP by Community Connect Inc. in 2002 -+and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+Future revisions and derivatives of this source code must acknowledge -+Community Connect Inc. as the original contributor of this module by -+leaving this note intact in the source code. -+ -+All other licensing and usage conditions are those of the PHP Group. -+ -+We would like to thank Community Connect Inc. and Yahoo! Inc. for supporting -+this project and providing a challenging and stimulating environment in -+which exciting projects can happen. -+ -+Contributors: -+ Mike Bretz bug fixes, GUI, and lots of work -+ Ricardo Galli changed read-write locks to prefer readers -+ Yann Grossel bug fixes -+ Thies Arntzen bug fixes -+ Sara Golemon optimizer work -+ -+Special Thanks: -+ Florian Baumert help debugging phplib problems -+ Thomas Duffey help debugging inheritance issues -+ Vibol Hou help debugging phplib problems -+ Angel Li diffs for ANSI comment compliance -+ Christian Rishøj help debugging phplib problems -+ Sascha Schumann memory error bug fix -diff -Naur a/ext/apc/pgsql_s_lock.c b/ext/apc/pgsql_s_lock.c ---- a/ext/apc/pgsql_s_lock.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/pgsql_s_lock.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,391 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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. | -+ +----------------------------------------------------------------------+ -+ | The following code was ported from the PostgreSQL project, please | -+ | see appropriate copyright notices that follow. | -+ | Initial conversion by Brian Shire | -+ +----------------------------------------------------------------------+ -+ -+ */ -+ -+/* $Id: pgsql_s_lock.c 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+/*------------------------------------------------------------------------- -+ * -+ * s_lock.c -+ * Hardware-dependent implementation of spinlocks. -+ * -+ * -+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group -+ * Portions Copyright (c) 1994, Regents of the University of California -+ * -+ * -+ * IDENTIFICATION -+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.47 2006/10/04 00:29:58 momjian Exp $ -+ * -+ *------------------------------------------------------------------------- -+ */ -+/* #include "postgres.h" -- Removed for APC */ -+ -+/* -- Added for APC -- */ -+#include "apc.h" -+#ifdef APC_SPIN_LOCKS -+ -+#ifdef S_LOCK_TEST -+#include -+#endif -+#ifndef WIN32 -+#include -+#endif -+/* ---- */ -+ -+#include -+#ifdef WIN32 -+#include "win32/unistd.h" -+#else -+#include -+#endif -+ -+/* #include "storage/s_lock.h" -- Removed for APC */ -+#include "pgsql_s_lock.h" -+ -+static int spins_per_delay = DEFAULT_SPINS_PER_DELAY; -+ -+ -+/* -- APC specific additions ------------------------------*/ -+/* The following dependencies have been copied from -+ * other pgsql source files. The original locations -+ * have been noted. -+ */ -+ -+/* -- from include/c.h -- */ -+#ifndef TRUE -+#define TRUE 1 -+#endif -+ -+#ifndef FALSE -+#define FALSE 0 -+#endif -+ -+/* -- from include/pg_config_manual.h -- */ -+#define MAX_RANDOM_VALUE (0x7FFFFFFF) -+ -+/* -+ * Max -+ * Return the maximum of two numbers. -+ */ -+#define Max(x, y) ((x) > (y) ? (x) : (y)) -+ -+/* -- from include/c.h -- */ -+/* -+ * Min -+ * Return the minimum of two numbers. -+ */ -+#define Min(x, y) ((x) < (y) ? (x) : (y)) -+ -+ -+/* -- from backend/port/win32/signal.c -- */ -+/* -+ * pg_usleep --- delay the specified number of microseconds. -+ * -+ * NOTE: although the delay is specified in microseconds, the effective -+ * resolution is only 1/HZ, or 10 milliseconds, on most Unixen. Expect -+ * the requested delay to be rounded up to the next resolution boundary. -+ * -+ * On machines where "long" is 32 bits, the maximum delay is ~2000 seconds. -+ */ -+void -+pg_usleep(long microsec) -+{ -+ if (microsec > 0) -+ { -+#ifndef WIN32 -+ struct timeval delay; -+ -+ delay.tv_sec = microsec / 1000000L; -+ delay.tv_usec = microsec % 1000000L; -+ (void) select(0, NULL, NULL, NULL, &delay); -+#else -+ SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE); -+#endif -+ } -+} -+ -+/* -- End APC specific additions ------------------------------*/ -+ -+ -+/* -+ * s_lock_stuck() - complain about a stuck spinlock -+ */ -+static void -+s_lock_stuck(volatile slock_t *lock, const char *file, int line TSRMLS_DC) -+{ -+#if defined(S_LOCK_TEST) -+ fprintf(stderr, -+ "\nStuck spinlock (%p) detected at %s:%d.\n", -+ lock, file, line); -+ exit(1); -+#else -+ /* -- Removed for APC -+ elog(PANIC, "stuck spinlock (%p) detected at %s:%d", -+ lock, file, line); -+ */ -+ apc_error("Stuck spinlock (%p) detected" TSRMLS_CC, lock); -+#endif -+} -+ -+ -+/* -+ * s_lock(lock) - platform-independent portion of waiting for a spinlock. -+ */ -+void -+s_lock(volatile slock_t *lock, const char *file, int line TSRMLS_DC) -+{ -+ /* -+ * We loop tightly for awhile, then delay using pg_usleep() and try again. -+ * Preferably, "awhile" should be a small multiple of the maximum time we -+ * expect a spinlock to be held. 100 iterations seems about right as an -+ * initial guess. However, on a uniprocessor the loop is a waste of -+ * cycles, while in a multi-CPU scenario it's usually better to spin a bit -+ * longer than to call the kernel, so we try to adapt the spin loop count -+ * depending on whether we seem to be in a uniprocessor or multiprocessor. -+ * -+ * Note: you might think MIN_SPINS_PER_DELAY should be just 1, but you'd -+ * be wrong; there are platforms where that can result in a "stuck -+ * spinlock" failure. This has been seen particularly on Alphas; it seems -+ * that the first TAS after returning from kernel space will always fail -+ * on that hardware. -+ * -+ * Once we do decide to block, we use randomly increasing pg_usleep() -+ * delays. The first delay is 1 msec, then the delay randomly increases to -+ * about one second, after which we reset to 1 msec and start again. The -+ * idea here is that in the presence of heavy contention we need to -+ * increase the delay, else the spinlock holder may never get to run and -+ * release the lock. (Consider situation where spinlock holder has been -+ * nice'd down in priority by the scheduler --- it will not get scheduled -+ * until all would-be acquirers are sleeping, so if we always use a 1-msec -+ * sleep, there is a real possibility of starvation.) But we can't just -+ * clamp the delay to an upper bound, else it would take a long time to -+ * make a reasonable number of tries. -+ * -+ * We time out and declare error after NUM_DELAYS delays (thus, exactly -+ * that many tries). With the given settings, this will usually take 2 or -+ * so minutes. It seems better to fix the total number of tries (and thus -+ * the probability of unintended failure) than to fix the total time -+ * spent. -+ * -+ * The pg_usleep() delays are measured in milliseconds because 1 msec is a -+ * common resolution limit at the OS level for newer platforms. On older -+ * platforms the resolution limit is usually 10 msec, in which case the -+ * total delay before timeout will be a bit more. -+ */ -+#define MIN_SPINS_PER_DELAY 10 -+#define MAX_SPINS_PER_DELAY 1000 -+#define NUM_DELAYS 1000 -+#define MIN_DELAY_MSEC 1 -+#define MAX_DELAY_MSEC 1000 -+ -+ int spins = 0; -+ int delays = 0; -+ int cur_delay = 0; -+ -+ while (TAS(lock)) -+ { -+ /* CPU-specific delay each time through the loop */ -+ SPIN_DELAY(); -+ -+ /* Block the process every spins_per_delay tries */ -+ if (++spins >= spins_per_delay) -+ { -+ if (++delays > NUM_DELAYS) -+ s_lock_stuck(lock, file, line TSRMLS_CC); -+ -+ if (cur_delay == 0) /* first time to delay? */ -+ cur_delay = MIN_DELAY_MSEC; -+ -+ pg_usleep(cur_delay * 1000L); -+ -+#if defined(S_LOCK_TEST) -+ fprintf(stdout, "*"); -+ fflush(stdout); -+#endif -+ -+ /* increase delay by a random fraction between 1X and 2X */ -+ cur_delay += (int) (cur_delay * -+ ((double) rand() / (double) MAX_RANDOM_VALUE) + 0.5); -+ /* wrap back to minimum delay when max is exceeded */ -+ if (cur_delay > MAX_DELAY_MSEC) -+ cur_delay = MIN_DELAY_MSEC; -+ -+ spins = 0; -+ } -+ } -+ -+ /* -+ * If we were able to acquire the lock without delaying, it's a good -+ * indication we are in a multiprocessor. If we had to delay, it's a sign -+ * (but not a sure thing) that we are in a uniprocessor. Hence, we -+ * decrement spins_per_delay slowly when we had to delay, and increase it -+ * rapidly when we didn't. It's expected that spins_per_delay will -+ * converge to the minimum value on a uniprocessor and to the maximum -+ * value on a multiprocessor. -+ * -+ * Note: spins_per_delay is local within our current process. We want to -+ * average these observations across multiple backends, since it's -+ * relatively rare for this function to even get entered, and so a single -+ * backend might not live long enough to converge on a good value. That -+ * is handled by the two routines below. -+ */ -+ if (cur_delay == 0) -+ { -+ /* we never had to delay */ -+ if (spins_per_delay < MAX_SPINS_PER_DELAY) -+ spins_per_delay = Min(spins_per_delay + 100, MAX_SPINS_PER_DELAY); -+ } -+ else -+ { -+ if (spins_per_delay > MIN_SPINS_PER_DELAY) -+ spins_per_delay = Max(spins_per_delay - 1, MIN_SPINS_PER_DELAY); -+ } -+} -+ -+ -+#if 0 /* -- APC doesn't use the set_spins_per_delay or update_spins_per_delay -- */ -+/* -+ * Set local copy of spins_per_delay during backend startup. -+ * -+ * NB: this has to be pretty fast as it is called while holding a spinlock -+ */ -+void -+set_spins_per_delay(int shared_spins_per_delay) -+{ -+ spins_per_delay = shared_spins_per_delay; -+} -+ -+/* -+ * Update shared estimate of spins_per_delay during backend exit. -+ * -+ * NB: this has to be pretty fast as it is called while holding a spinlock -+ */ -+int -+update_spins_per_delay(int shared_spins_per_delay) -+{ -+ /* -+ * We use an exponential moving average with a relatively slow adaption -+ * rate, so that noise in any one backend's result won't affect the shared -+ * value too much. As long as both inputs are within the allowed range, -+ * the result must be too, so we need not worry about clamping the result. -+ * -+ * We deliberately truncate rather than rounding; this is so that single -+ * adjustments inside a backend can affect the shared estimate (see the -+ * asymmetric adjustment rules above). -+ */ -+ return (shared_spins_per_delay * 15 + spins_per_delay) / 16; -+} -+#endif -+ -+/* -+ * Various TAS implementations that cannot live in s_lock.h as no inline -+ * definition exists (yet). -+ * In the future, get rid of tas.[cso] and fold it into this file. -+ * -+ * If you change something here, you will likely need to modify s_lock.h too, -+ * because the definitions for these are split between this file and s_lock.h. -+ */ -+ -+ -+#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */ -+ -+ -+#if defined(__GNUC__) -+ -+/* -+ * All the gcc flavors that are not inlined -+ */ -+ -+ -+/* -+ * Note: all the if-tests here probably ought to be testing gcc version -+ * rather than platform, but I don't have adequate info to know what to -+ * write. Ideally we'd flush all this in favor of the inline version. -+ */ -+#if defined(__m68k__) && !defined(__linux__) -+/* really means: extern int tas(slock_t* **lock); */ -+static void -+tas_dummy() -+{ -+ __asm__ __volatile__( -+#if defined(__NetBSD__) && defined(__ELF__) -+/* no underscore for label and % for registers */ -+ "\ -+.global tas \n\ -+tas: \n\ -+ movel %sp@(0x4),%a0 \n\ -+ tas %a0@ \n\ -+ beq _success \n\ -+ moveq #-128,%d0 \n\ -+ rts \n\ -+_success: \n\ -+ moveq #0,%d0 \n\ -+ rts \n" -+#else -+ "\ -+.global _tas \n\ -+_tas: \n\ -+ movel sp@(0x4),a0 \n\ -+ tas a0@ \n\ -+ beq _success \n\ -+ moveq #-128,d0 \n\ -+ rts \n\ -+_success: \n\ -+ moveq #0,d0 \n\ -+ rts \n" -+#endif /* __NetBSD__ && __ELF__ */ -+ ); -+} -+#endif /* __m68k__ && !__linux__ */ -+#else /* not __GNUC__ */ -+ -+/* -+ * All non gcc -+ */ -+ -+ -+#if defined(sun3) -+static void -+tas_dummy() /* really means: extern int tas(slock_t -+ * *lock); */ -+{ -+ asm("LLA0:"); -+ asm(" .data"); -+ asm(" .text"); -+ asm("|#PROC# 04"); -+ asm(" .globl _tas"); -+ asm("_tas:"); -+ asm("|#PROLOGUE# 1"); -+ asm(" movel sp@(0x4),a0"); -+ asm(" tas a0@"); -+ asm(" beq LLA1"); -+ asm(" moveq #-128,d0"); -+ asm(" rts"); -+ asm("LLA1:"); -+ asm(" moveq #0,d0"); -+ asm(" rts"); -+ asm(" .data"); -+} -+#endif /* sun3 */ -+#endif /* not __GNUC__ */ -+#endif /* HAVE_SPINLOCKS */ -+ -+#endif /* APC_SPIN_LOCKS */ -diff -Naur a/ext/apc/pgsql_s_lock.h b/ext/apc/pgsql_s_lock.h ---- a/ext/apc/pgsql_s_lock.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/pgsql_s_lock.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,928 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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. | -+ +----------------------------------------------------------------------+ -+ | The following code was ported from the PostgreSQL project, please | -+ | see appropriate copyright notices that follow. | -+ | Initial conversion by Brian Shire | -+ +----------------------------------------------------------------------+ -+ -+ */ -+ -+/* $Id: pgsql_s_lock.h 307048 2011-01-03 23:53:17Z kalle $ */ -+ -+/*------------------------------------------------------------------------- -+ * -+ * s_lock.h -+ * Hardware-dependent implementation of spinlocks. -+ * -+ * NOTE: none of the macros in this file are intended to be called directly. -+ * Call them through the hardware-independent macros in spin.h. -+ * -+ * The following hardware-dependent macros must be provided for each -+ * supported platform: -+ * -+ * void S_INIT_LOCK(slock_t *lock) -+ * Initialize a spinlock (to the unlocked state). -+ * -+ * void S_LOCK(slock_t *lock) -+ * Acquire a spinlock, waiting if necessary. -+ * Time out and abort() if unable to acquire the lock in a -+ * "reasonable" amount of time --- typically ~ 1 minute. -+ * -+ * void S_UNLOCK(slock_t *lock) -+ * Unlock a previously acquired lock. -+ * -+ * bool S_LOCK_FREE(slock_t *lock) -+ * Tests if the lock is free. Returns TRUE if free, FALSE if locked. -+ * This does *not* change the state of the lock. -+ * -+ * void SPIN_DELAY(void) -+ * Delay operation to occur inside spinlock wait loop. -+ * -+ * Note to implementors: there are default implementations for all these -+ * macros at the bottom of the file. Check if your platform can use -+ * these or needs to override them. -+ * -+ * Usually, S_LOCK() is implemented in terms of an even lower-level macro -+ * TAS(): -+ * -+ * int TAS(slock_t *lock) -+ * Atomic test-and-set instruction. Attempt to acquire the lock, -+ * but do *not* wait. Returns 0 if successful, nonzero if unable -+ * to acquire the lock. -+ * -+ * TAS() is NOT part of the API, and should never be called directly. -+ * -+ * CAUTION: on some platforms TAS() may sometimes report failure to acquire -+ * a lock even when the lock is not locked. For example, on Alpha TAS() -+ * will "fail" if interrupted. Therefore TAS() should always be invoked -+ * in a retry loop, even if you are certain the lock is free. -+ * -+ * ANOTHER CAUTION: be sure that TAS() and S_UNLOCK() represent sequence -+ * points, ie, loads and stores of other values must not be moved across -+ * a lock or unlock. In most cases it suffices to make the operation be -+ * done through a "volatile" pointer. -+ * -+ * On most supported platforms, TAS() uses a tas() function written -+ * in assembly language to execute a hardware atomic-test-and-set -+ * instruction. Equivalent OS-supplied mutex routines could be used too. -+ * -+ * If no system-specific TAS() is available (ie, HAVE_SPINLOCKS is not -+ * defined), then we fall back on an emulation that uses SysV semaphores -+ * (see spin.c). This emulation will be MUCH MUCH slower than a proper TAS() -+ * implementation, because of the cost of a kernel call per lock or unlock. -+ * An old report is that Postgres spends around 40% of its time in semop(2) -+ * when using the SysV semaphore code. -+ * -+ * -+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group -+ * Portions Copyright (c) 1994, Regents of the University of California -+ * -+ * $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.157 2006/06/07 22:24:45 momjian Exp $ -+ * -+ *------------------------------------------------------------------------- -+ */ -+#ifndef S_LOCK_H -+#define S_LOCK_H -+ -+/** APC namespace protection ************************************************/ -+/* hack to protect against any possible runtime namespace collisions...*/ -+#define pg_usleep apc_spin_pg_usleep -+#define s_lock apc_spin_s_lock -+#define spins_per_delay apc_spin_spins_per_delay -+/****************************************************************************/ -+ -+ -+/* #include "storage/pg_sema.h" -- Removed for APC */ -+ -+#define HAVE_SPINLOCKS 1 /* -- Added for APC */ -+ -+#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */ -+ -+ -+#if defined(__GNUC__) || defined(__ICC) -+/************************************************************************* -+ * All the gcc inlines -+ * Gcc consistently defines the CPU as __cpu__. -+ * Other compilers use __cpu or __cpu__ so we test for both in those cases. -+ */ -+ -+/*---------- -+ * Standard gcc asm format (assuming "volatile slock_t *lock"): -+ -+ __asm__ __volatile__( -+ " instruction \n" -+ " instruction \n" -+ " instruction \n" -+: "=r"(_res), "+m"(*lock) // return register, in/out lock value -+: "r"(lock) // lock pointer, in input register -+: "memory", "cc"); // show clobbered registers here -+ -+ * The output-operands list (after first colon) should always include -+ * "+m"(*lock), whether or not the asm code actually refers to this -+ * operand directly. This ensures that gcc believes the value in the -+ * lock variable is used and set by the asm code. Also, the clobbers -+ * list (after third colon) should always include "memory"; this prevents -+ * gcc from thinking it can cache the values of shared-memory fields -+ * across the asm code. Add "cc" if your asm code changes the condition -+ * code register, and also list any temp registers the code uses. -+ *---------- -+ */ -+ -+ -+#ifdef __i386__ /* 32-bit i386 */ -+#define HAS_TEST_AND_SET -+ -+typedef unsigned char slock_t; -+ -+#define TAS(lock) tas(lock) -+ -+static __inline__ int -+tas(volatile slock_t *lock) -+{ -+ register slock_t _res = 1; -+ -+ /* -+ * Use a non-locking test before asserting the bus lock. Note that the -+ * extra test appears to be a small loss on some x86 platforms and a small -+ * win on others; it's by no means clear that we should keep it. -+ */ -+ __asm__ __volatile__( -+ " cmpb $0,%1 \n" -+ " jne 1f \n" -+ " lock \n" -+ " xchgb %0,%1 \n" -+ "1: \n" -+: "+q"(_res), "+m"(*lock) -+: -+: "memory", "cc"); -+ return (int) _res; -+} -+ -+#define SPIN_DELAY() spin_delay() -+ -+static __inline__ void -+spin_delay(void) -+{ -+ /* -+ * This sequence is equivalent to the PAUSE instruction ("rep" is -+ * ignored by old IA32 processors if the following instruction is -+ * not a string operation); the IA-32 Architecture Software -+ * Developer's Manual, Vol. 3, Section 7.7.2 describes why using -+ * PAUSE in the inner loop of a spin lock is necessary for good -+ * performance: -+ * -+ * The PAUSE instruction improves the performance of IA-32 -+ * processors supporting Hyper-Threading Technology when -+ * executing spin-wait loops and other routines where one -+ * thread is accessing a shared lock or semaphore in a tight -+ * polling loop. When executing a spin-wait loop, the -+ * processor can suffer a severe performance penalty when -+ * exiting the loop because it detects a possible memory order -+ * violation and flushes the core processor's pipeline. The -+ * PAUSE instruction provides a hint to the processor that the -+ * code sequence is a spin-wait loop. The processor uses this -+ * hint to avoid the memory order violation and prevent the -+ * pipeline flush. In addition, the PAUSE instruction -+ * de-pipelines the spin-wait loop to prevent it from -+ * consuming execution resources excessively. -+ */ -+ __asm__ __volatile__( -+ " rep; nop \n"); -+} -+ -+#endif /* __i386__ */ -+ -+ -+#ifdef __x86_64__ /* AMD Opteron, Intel EM64T */ -+#define HAS_TEST_AND_SET -+ -+typedef unsigned char slock_t; -+ -+#define TAS(lock) tas(lock) -+ -+static __inline__ int -+tas(volatile slock_t *lock) -+{ -+ register slock_t _res = 1; -+ -+ /* -+ * On Opteron, using a non-locking test before the locking instruction -+ * is a huge loss. On EM64T, it appears to be a wash or small loss, -+ * so we needn't bother to try to distinguish the sub-architectures. -+ */ -+ __asm__ __volatile__( -+ " lock \n" -+ " xchgb %0,%1 \n" -+: "+q"(_res), "+m"(*lock) -+: -+: "memory", "cc"); -+ return (int) _res; -+} -+ -+#define SPIN_DELAY() spin_delay() -+ -+static __inline__ void -+spin_delay(void) -+{ -+ /* -+ * Adding a PAUSE in the spin delay loop is demonstrably a no-op on -+ * Opteron, but it may be of some use on EM64T, so we keep it. -+ */ -+ __asm__ __volatile__( -+ " rep; nop \n"); -+} -+ -+#endif /* __x86_64__ */ -+ -+ -+#if defined(__ia64__) || defined(__ia64) /* Intel Itanium */ -+#define HAS_TEST_AND_SET -+ -+typedef unsigned int slock_t; -+ -+#define TAS(lock) tas(lock) -+ -+#ifndef __INTEL_COMPILER -+ -+static __inline__ int -+tas(volatile slock_t *lock) -+{ -+ long int ret; -+ -+ __asm__ __volatile__( -+ " xchg4 %0=%1,%2 \n" -+: "=r"(ret), "+m"(*lock) -+: "r"(1) -+: "memory"); -+ return (int) ret; -+} -+ -+#else /* __INTEL_COMPILER */ -+ -+static __inline__ int -+tas(volatile slock_t *lock) -+{ -+ int ret; -+ -+ ret = _InterlockedExchange(lock,1); /* this is a xchg asm macro */ -+ -+ return ret; -+} -+ -+#endif /* __INTEL_COMPILER */ -+#endif /* __ia64__ || __ia64 */ -+ -+ -+#if defined(__arm__) || defined(__arm) -+#define HAS_TEST_AND_SET -+ -+typedef unsigned char slock_t; -+ -+#define TAS(lock) tas(lock) -+ -+static __inline__ int -+tas(volatile slock_t *lock) -+{ -+ register slock_t _res = 1; -+ -+ __asm__ __volatile__( -+ " swpb %0, %0, [%2] \n" -+: "+r"(_res), "+m"(*lock) -+: "r"(lock) -+: "memory"); -+ return (int) _res; -+} -+ -+#endif /* __arm__ */ -+ -+ -+/* S/390 and S/390x Linux (32- and 64-bit zSeries) */ -+#if defined(__s390__) || defined(__s390x__) -+#define HAS_TEST_AND_SET -+ -+typedef unsigned int slock_t; -+ -+#define TAS(lock) tas(lock) -+ -+static __inline__ int -+tas(volatile slock_t *lock) -+{ -+ int _res = 0; -+ -+ __asm__ __volatile__( -+ " cs %0,%3,0(%2) \n" -+: "+d"(_res), "+m"(*lock) -+: "a"(lock), "d"(1) -+: "memory", "cc"); -+ return _res; -+} -+ -+#endif /* __s390__ || __s390x__ */ -+ -+ -+#if defined(__sparc__) /* Sparc */ -+#define HAS_TEST_AND_SET -+ -+typedef unsigned char slock_t; -+ -+#define TAS(lock) tas(lock) -+ -+static __inline__ int -+tas(volatile slock_t *lock) -+{ -+ register slock_t _res; -+ -+ /* -+ * See comment in /pg/backend/port/tas/solaris_sparc.s for why this -+ * uses "ldstub", and that file uses "cas". gcc currently generates -+ * sparcv7-targeted binaries, so "cas" use isn't possible. -+ */ -+ __asm__ __volatile__( -+ " ldstub [%2], %0 \n" -+: "=r"(_res), "+m"(*lock) -+: "r"(lock) -+: "memory"); -+ return (int) _res; -+} -+ -+#endif /* __sparc__ */ -+ -+ -+/* PowerPC */ -+#if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__) -+#define HAS_TEST_AND_SET -+ -+#if defined(__ppc64__) || defined(__powerpc64__) -+typedef unsigned long slock_t; -+#else -+typedef unsigned int slock_t; -+#endif -+ -+#define TAS(lock) tas(lock) -+/* -+ * NOTE: per the Enhanced PowerPC Architecture manual, v1.0 dated 7-May-2002, -+ * an isync is a sufficient synchronization barrier after a lwarx/stwcx loop. -+ */ -+static __inline__ int -+tas(volatile slock_t *lock) -+{ -+ slock_t _t; -+ int _res; -+ -+ __asm__ __volatile__( -+" lwarx %0,0,%3 \n" -+" cmpwi %0,0 \n" -+" bne 1f \n" -+" addi %0,%0,1 \n" -+" stwcx. %0,0,%3 \n" -+" beq 2f \n" -+"1: li %1,1 \n" -+" b 3f \n" -+"2: \n" -+" isync \n" -+" li %1,0 \n" -+"3: \n" -+ -+: "=&r"(_t), "=r"(_res), "+m"(*lock) -+: "r"(lock) -+: "memory", "cc"); -+ return _res; -+} -+ -+/* PowerPC S_UNLOCK is almost standard but requires a "sync" instruction */ -+#define S_UNLOCK(lock) \ -+do \ -+{ \ -+ __asm__ __volatile__ (" sync \n"); \ -+ *((volatile slock_t *) (lock)) = 0; \ -+} while (0) -+ -+#endif /* powerpc */ -+ -+ -+/* Linux Motorola 68k */ -+#if (defined(__mc68000__) || defined(__m68k__)) && defined(__linux__) -+#define HAS_TEST_AND_SET -+ -+typedef unsigned char slock_t; -+ -+#define TAS(lock) tas(lock) -+ -+static __inline__ int -+tas(volatile slock_t *lock) -+{ -+ register int rv; -+ -+ __asm__ __volatile__( -+ " clrl %0 \n" -+ " tas %1 \n" -+ " sne %0 \n" -+: "=d"(rv), "+m"(*lock) -+: -+: "memory", "cc"); -+ return rv; -+} -+ -+#endif /* (__mc68000__ || __m68k__) && __linux__ */ -+ -+ -+/* -+ * VAXen -- even multiprocessor ones -+ * (thanks to Tom Ivar Helbekkmo) -+ */ -+#if defined(__vax__) -+#define HAS_TEST_AND_SET -+ -+typedef unsigned char slock_t; -+ -+#define TAS(lock) tas(lock) -+ -+static __inline__ int -+tas(volatile slock_t *lock) -+{ -+ register int _res; -+ -+ __asm__ __volatile__( -+ " movl $1, %0 \n" -+ " bbssi $0, (%2), 1f \n" -+ " clrl %0 \n" -+ "1: \n" -+: "=&r"(_res), "+m"(*lock) -+: "r"(lock) -+: "memory"); -+ return _res; -+} -+ -+#endif /* __vax__ */ -+ -+ -+#if defined(__ns32k__) /* National Semiconductor 32K */ -+#define HAS_TEST_AND_SET -+ -+typedef unsigned char slock_t; -+ -+#define TAS(lock) tas(lock) -+ -+static __inline__ int -+tas(volatile slock_t *lock) -+{ -+ register int _res; -+ -+ __asm__ __volatile__( -+ " sbitb 0, %1 \n" -+ " sfsd %0 \n" -+: "=r"(_res), "+m"(*lock) -+: -+: "memory"); -+ return _res; -+} -+ -+#endif /* __ns32k__ */ -+ -+ -+#if defined(__alpha) || defined(__alpha__) /* Alpha */ -+/* -+ * Correct multi-processor locking methods are explained in section 5.5.3 -+ * of the Alpha AXP Architecture Handbook, which at this writing can be -+ * found at ftp://ftp.netbsd.org/pub/NetBSD/misc/dec-docs/index.html. -+ * For gcc we implement the handbook's code directly with inline assembler. -+ */ -+#define HAS_TEST_AND_SET -+ -+typedef unsigned long slock_t; -+ -+#define TAS(lock) tas(lock) -+ -+static __inline__ int -+tas(volatile slock_t *lock) -+{ -+ register slock_t _res; -+ -+ __asm__ __volatile__( -+ " ldq $0, %1 \n" -+ " bne $0, 2f \n" -+ " ldq_l %0, %1 \n" -+ " bne %0, 2f \n" -+ " mov 1, $0 \n" -+ " stq_c $0, %1 \n" -+ " beq $0, 2f \n" -+ " mb \n" -+ " br 3f \n" -+ "2: mov 1, %0 \n" -+ "3: \n" -+: "=&r"(_res), "+m"(*lock) -+: -+: "memory", "0"); -+ return (int) _res; -+} -+ -+#define S_UNLOCK(lock) \ -+do \ -+{\ -+ __asm__ __volatile__ (" mb \n"); \ -+ *((volatile slock_t *) (lock)) = 0; \ -+} while (0) -+ -+#endif /* __alpha || __alpha__ */ -+ -+ -+#if defined(__mips__) && !defined(__sgi) /* non-SGI MIPS */ -+/* Note: on SGI we use the OS' mutex ABI, see below */ -+/* Note: R10000 processors require a separate SYNC */ -+#define HAS_TEST_AND_SET -+ -+typedef unsigned int slock_t; -+ -+#define TAS(lock) tas(lock) -+ -+static __inline__ int -+tas(volatile slock_t *lock) -+{ -+ register volatile slock_t *_l = lock; -+ register int _res; -+ register int _tmp; -+ -+ __asm__ __volatile__( -+ " .set push \n" -+ " .set mips2 \n" -+ " .set noreorder \n" -+ " .set nomacro \n" -+ " ll %0, %2 \n" -+ " or %1, %0, 1 \n" -+ " sc %1, %2 \n" -+ " xori %1, 1 \n" -+ " or %0, %0, %1 \n" -+ " sync \n" -+ " .set pop " -+: "=&r" (_res), "=&r" (_tmp), "+R" (*_l) -+: -+: "memory"); -+ return _res; -+} -+ -+/* MIPS S_UNLOCK is almost standard but requires a "sync" instruction */ -+#define S_UNLOCK(lock) \ -+do \ -+{ \ -+ __asm__ __volatile__( \ -+ " .set push \n" \ -+ " .set mips2 \n" \ -+ " .set noreorder \n" \ -+ " .set nomacro \n" \ -+ " sync \n" \ -+ " .set pop "); \ -+ *((volatile slock_t *) (lock)) = 0; \ -+} while (0) -+ -+#endif /* __mips__ && !__sgi */ -+ -+ -+/* These live in s_lock.c, but only for gcc */ -+ -+ -+#if defined(__m68k__) && !defined(__linux__) /* non-Linux Motorola 68k */ -+#define HAS_TEST_AND_SET -+ -+typedef unsigned char slock_t; -+#endif -+ -+ -+#endif /* __GNUC__ */ -+ -+ -+ -+/* -+ * --------------------------------------------------------------------- -+ * Platforms that use non-gcc inline assembly: -+ * --------------------------------------------------------------------- -+ */ -+ -+#if !defined(HAS_TEST_AND_SET) /* We didn't trigger above, let's try here */ -+ -+ -+#if defined(USE_UNIVEL_CC) /* Unixware compiler */ -+#define HAS_TEST_AND_SET -+ -+typedef unsigned char slock_t; -+ -+#define TAS(lock) tas(lock) -+ -+asm int -+tas(volatile slock_t *s_lock) -+{ -+/* UNIVEL wants %mem in column 1, so we don't pg_indent this file */ -+%mem s_lock -+ pushl %ebx -+ movl s_lock, %ebx -+ movl $255, %eax -+ lock -+ xchgb %al, (%ebx) -+ popl %ebx -+} -+ -+#endif /* defined(USE_UNIVEL_CC) */ -+ -+ -+#if defined(__alpha) || defined(__alpha__) /* Tru64 Unix Alpha compiler */ -+/* -+ * The Tru64 compiler doesn't support gcc-style inline asm, but it does -+ * have some builtin functions that accomplish much the same results. -+ * For simplicity, slock_t is defined as long (ie, quadword) on Alpha -+ * regardless of the compiler in use. LOCK_LONG and UNLOCK_LONG only -+ * operate on an int (ie, longword), but that's OK as long as we define -+ * S_INIT_LOCK to zero out the whole quadword. -+ */ -+#define HAS_TEST_AND_SET -+ -+typedef unsigned long slock_t; -+ -+#include -+#define S_INIT_LOCK(lock) (*(lock) = 0) -+#define TAS(lock) (__LOCK_LONG_RETRY((lock), 1) == 0) -+#define S_UNLOCK(lock) __UNLOCK_LONG(lock) -+ -+#endif /* __alpha || __alpha__ */ -+ -+ -+#if defined(__hppa) || defined(__hppa__) /* HP PA-RISC, GCC and HP compilers */ -+/* -+ * HP's PA-RISC -+ * -+ * See src/backend/port/hpux/tas.c.template for details about LDCWX. Because -+ * LDCWX requires a 16-byte-aligned address, we declare slock_t as a 16-byte -+ * struct. The active word in the struct is whichever has the aligned address; -+ * the other three words just sit at -1. -+ * -+ * When using gcc, we can inline the required assembly code. -+ */ -+#define HAS_TEST_AND_SET -+ -+typedef struct -+{ -+ int sema[4]; -+} slock_t; -+ -+#define TAS_ACTIVE_WORD(lock) ((volatile int *) (((long) (lock) + 15) & ~15)) -+ -+#if defined(__GNUC__) -+ -+static __inline__ int -+tas(volatile slock_t *lock) -+{ -+ volatile int *lockword = TAS_ACTIVE_WORD(lock); -+ register int lockval; -+ -+ __asm__ __volatile__( -+ " ldcwx 0(0,%2),%0 \n" -+: "=r"(lockval), "+m"(*lockword) -+: "r"(lockword) -+: "memory"); -+ return (lockval == 0); -+} -+ -+#endif /* __GNUC__ */ -+ -+#define S_UNLOCK(lock) (*TAS_ACTIVE_WORD(lock) = -1) -+ -+#define S_INIT_LOCK(lock) \ -+ do { \ -+ volatile slock_t *lock_ = (lock); \ -+ lock_->sema[0] = -1; \ -+ lock_->sema[1] = -1; \ -+ lock_->sema[2] = -1; \ -+ lock_->sema[3] = -1; \ -+ } while (0) -+ -+#define S_LOCK_FREE(lock) (*TAS_ACTIVE_WORD(lock) != 0) -+ -+#endif /* __hppa || __hppa__ */ -+ -+ -+#if defined(__hpux) && defined(__ia64) && !defined(__GNUC__) -+ -+#define HAS_TEST_AND_SET -+ -+typedef unsigned int slock_t; -+ -+#include -+#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE) -+ -+#endif /* HPUX on IA64, non gcc */ -+ -+ -+#if defined(__sgi) /* SGI compiler */ -+/* -+ * SGI IRIX 5 -+ * slock_t is defined as a unsigned long. We use the standard SGI -+ * mutex API. -+ * -+ * The following comment is left for historical reasons, but is probably -+ * not a good idea since the mutex ABI is supported. -+ * -+ * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II -+ * assembly from his NECEWS SVR4 port, but we probably ought to retain this -+ * for the R3000 chips out there. -+ */ -+#define HAS_TEST_AND_SET -+ -+typedef unsigned long slock_t; -+ -+#include "mutex.h" -+#define TAS(lock) (test_and_set(lock,1)) -+#define S_UNLOCK(lock) (test_then_and(lock,0)) -+#define S_INIT_LOCK(lock) (test_then_and(lock,0)) -+#define S_LOCK_FREE(lock) (test_then_add(lock,0) == 0) -+#endif /* __sgi */ -+ -+ -+#if defined(sinix) /* Sinix */ -+/* -+ * SINIX / Reliant UNIX -+ * slock_t is defined as a struct abilock_t, which has a single unsigned long -+ * member. (Basically same as SGI) -+ */ -+#define HAS_TEST_AND_SET -+ -+#include "abi_mutex.h" -+typedef abilock_t slock_t; -+ -+#define TAS(lock) (!acquire_lock(lock)) -+#define S_UNLOCK(lock) release_lock(lock) -+#define S_INIT_LOCK(lock) init_lock(lock) -+#define S_LOCK_FREE(lock) (stat_lock(lock) == UNLOCKED) -+#endif /* sinix */ -+ -+ -+#if defined(_AIX) /* AIX */ -+/* -+ * AIX (POWER) -+ */ -+#define HAS_TEST_AND_SET -+ -+typedef unsigned int slock_t; -+ -+#define TAS(lock) _check_lock(lock, 0, 1) -+#define S_UNLOCK(lock) _clear_lock(lock, 0) -+#endif /* _AIX */ -+ -+ -+#if defined (nextstep) /* Nextstep */ -+#define HAS_TEST_AND_SET -+ -+typedef struct mutex slock_t; -+ -+#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 0 /* -- APC: non-blocking lock not available in this case -- */ -+ -+#define S_LOCK(lock) mutex_lock(lock) -+#define S_UNLOCK(lock) mutex_unlock(lock) -+#define S_INIT_LOCK(lock) mutex_init(lock) -+/* For Mach, we have to delve inside the entrails of `struct mutex'. Ick! */ -+#define S_LOCK_FREE(alock) ((alock)->lock == 0) -+#endif /* nextstep */ -+ -+ -+/* These are in s_lock.c */ -+ -+ -+#if defined(sun3) /* Sun3 */ -+#define HAS_TEST_AND_SET -+ -+typedef unsigned char slock_t; -+#endif -+ -+ -+#if defined(__sun) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc)) -+#define HAS_TEST_AND_SET -+ -+#if defined(__i386) || defined(__x86_64__) || defined(__sparcv9) || defined(__sparcv8plus) -+typedef unsigned int slock_t; -+#else -+typedef unsigned char slock_t; -+#endif -+ -+extern slock_t pg_atomic_cas(volatile slock_t *lock, slock_t with, -+ slock_t cmp); -+ -+#define TAS(a) (pg_atomic_cas((a), 1, 0) != 0) -+#endif -+ -+ -+#ifdef WIN32_ONLY_COMPILER -+typedef LONG slock_t; -+ -+#define HAS_TEST_AND_SET -+#define TAS(lock) (InterlockedCompareExchange(lock, 1, 0)) -+ -+#define SPIN_DELAY() spin_delay() -+ -+static __forceinline void -+spin_delay(void) -+{ -+ /* See comment for gcc code. Same code, MASM syntax */ -+ __asm rep nop; -+} -+ -+#endif -+ -+ -+#endif /* !defined(HAS_TEST_AND_SET) */ -+ -+ -+/* Blow up if we didn't have any way to do spinlocks */ -+#ifndef HAS_TEST_AND_SET -+/* -- APC: We have better options in APC than this, that should be specified explicitly so just fail out and notify the user -- */ -+#error Spin locking is not available on your platform, please select another locking method (see ./configure --help). -+/* #error PostgreSQL does not have native spinlock support on this platform. To continue the compilation, rerun configure using --disable-spinlocks. However, performance will be poor. Please report this to pgsql-bugs@postgresql.org. */ -+#endif -+ -+ -+#else /* !HAVE_SPINLOCKS */ -+ -+ -+/* -+ * Fake spinlock implementation using semaphores --- slow and prone -+ * to fall foul of kernel limits on number of semaphores, so don't use this -+ * unless you must! The subroutines appear in spin.c. -+ */ -+ -+/* -- Removed for APC -+typedef PGSemaphoreData slock_t; -+ -+extern bool s_lock_free_sema(volatile slock_t *lock); -+extern void s_unlock_sema(volatile slock_t *lock); -+extern void s_init_lock_sema(volatile slock_t *lock); -+extern int tas_sema(volatile slock_t *lock); -+ -+#define S_LOCK_FREE(lock) s_lock_free_sema(lock) -+#define S_UNLOCK(lock) s_unlock_sema(lock) -+#define S_INIT_LOCK(lock) s_init_lock_sema(lock) -+#define TAS(lock) tas_sema(lock) -+*/ -+ -+#endif /* HAVE_SPINLOCKS */ -+ -+ -+/* -+ * Default Definitions - override these above as needed. -+ */ -+ -+#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 1 /* -- APC: Non-blocking lock available for this case -- */ -+ -+#if !defined(S_LOCK) -+#define S_LOCK(lock) \ -+ do { \ -+ if (TAS(lock)) \ -+ s_lock((lock), __FILE__, __LINE__ TSRMLS_CC); \ -+ } while (0) -+#endif /* S_LOCK */ -+ -+#if !defined(S_LOCK_FREE) -+#define S_LOCK_FREE(lock) (*(lock) == 0) -+#endif /* S_LOCK_FREE */ -+ -+#if !defined(S_UNLOCK) -+#define S_UNLOCK(lock) (*((volatile slock_t *) (lock)) = 0) -+#endif /* S_UNLOCK */ -+ -+#if !defined(S_INIT_LOCK) -+#define S_INIT_LOCK(lock) S_UNLOCK(lock) -+#endif /* S_INIT_LOCK */ -+ -+#if !defined(SPIN_DELAY) -+#define SPIN_DELAY() ((void) 0) -+#endif /* SPIN_DELAY */ -+ -+#if !defined(TAS) -+extern int tas(volatile slock_t *lock); /* in port/.../tas.s, or -+ * s_lock.c */ -+ -+#define TAS(lock) tas(lock) -+#endif /* TAS */ -+ -+ -+/* -+ * Platform-independent out-of-line support routines -+ */ -+extern void s_lock(volatile slock_t *lock, const char *file, int line TSRMLS_DC); -+ -+/* Support for dynamic adjustment of spins_per_delay */ -+#define DEFAULT_SPINS_PER_DELAY 100 -+ -+#if 0 /* -- Removed from APC use -- */ -+extern void set_spins_per_delay(int shared_spins_per_delay); -+extern int update_spins_per_delay(int shared_spins_per_delay); -+#endif -+ -+#endif /* S_LOCK_H */ -diff -Naur a/ext/apc/php_apc.c b/ext/apc/php_apc.c ---- a/ext/apc/php_apc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/php_apc.c 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,1716 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | Rasmus Lerdorf | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: php_apc.c 325875 2012-05-27 17:15:26Z felipe $ */ -+ -+#include "apc_zend.h" -+#include "apc_cache.h" -+#include "apc_iterator.h" -+#include "apc_main.h" -+#include "apc_sma.h" -+#include "apc_lock.h" -+#include "apc_bin.h" -+#include "php_globals.h" -+#include "php_ini.h" -+#include "ext/standard/info.h" -+#include "ext/standard/file.h" -+#include "ext/standard/flock_compat.h" -+#ifdef HAVE_SYS_FILE_H -+#include -+#endif -+#include "SAPI.h" -+#include "rfc1867.h" -+#include "php_apc.h" -+#include "ext/standard/md5.h" -+ -+#if HAVE_SIGACTION -+#include "apc_signal.h" -+#endif -+ -+/* {{{ PHP_FUNCTION declarations */ -+PHP_FUNCTION(apc_cache_info); -+PHP_FUNCTION(apc_clear_cache); -+PHP_FUNCTION(apc_sma_info); -+PHP_FUNCTION(apc_store); -+PHP_FUNCTION(apc_fetch); -+PHP_FUNCTION(apc_delete); -+PHP_FUNCTION(apc_delete_file); -+PHP_FUNCTION(apc_compile_file); -+PHP_FUNCTION(apc_define_constants); -+PHP_FUNCTION(apc_load_constants); -+PHP_FUNCTION(apc_add); -+PHP_FUNCTION(apc_inc); -+PHP_FUNCTION(apc_dec); -+PHP_FUNCTION(apc_cas); -+PHP_FUNCTION(apc_bin_dump); -+PHP_FUNCTION(apc_bin_load); -+PHP_FUNCTION(apc_bin_dumpfile); -+PHP_FUNCTION(apc_bin_loadfile); -+PHP_FUNCTION(apc_exists); -+/* }}} */ -+ -+/* {{{ ZEND_DECLARE_MODULE_GLOBALS(apc) */ -+ZEND_DECLARE_MODULE_GLOBALS(apc) -+ -+/* True globals */ -+apc_cache_t* apc_cache = NULL; -+apc_cache_t* apc_user_cache = NULL; -+ -+static void php_apc_init_globals(zend_apc_globals* apc_globals TSRMLS_DC) -+{ -+ apc_globals->filters = NULL; -+ apc_globals->compiled_filters = NULL; -+ apc_globals->initialized = 0; -+ apc_globals->cache_stack = apc_stack_create(0 TSRMLS_CC); -+ apc_globals->cache_by_default = 1; -+ apc_globals->fpstat = 1; -+ apc_globals->canonicalize = 1; -+ apc_globals->stat_ctime = 0; -+ apc_globals->write_lock = 1; -+ apc_globals->slam_defense = 1; -+ apc_globals->report_autofilter = 0; -+ apc_globals->include_once = 0; -+ apc_globals->apc_optimize_function = NULL; -+#ifdef MULTIPART_EVENT_FORMDATA -+ apc_globals->rfc1867 = 0; -+ memset(&(apc_globals->rfc1867_data), 0, sizeof(apc_rfc1867_data)); -+#endif -+ memset(&apc_globals->copied_zvals, 0, sizeof(HashTable)); -+ apc_globals->force_file_update = 0; -+ apc_globals->coredump_unmap = 0; -+ apc_globals->preload_path = NULL; -+ apc_globals->use_request_time = 1; -+ apc_globals->lazy_class_table = NULL; -+ apc_globals->lazy_function_table = NULL; -+ apc_globals->serializer_name = NULL; -+ apc_globals->serializer = NULL; -+} -+ -+static void php_apc_shutdown_globals(zend_apc_globals* apc_globals TSRMLS_DC) -+{ -+ /* deallocate the ignore patterns */ -+ if (apc_globals->filters != NULL) { -+ int i; -+ for (i=0; apc_globals->filters[i] != NULL; i++) { -+ apc_efree(apc_globals->filters[i] TSRMLS_CC); -+ } -+ apc_efree(apc_globals->filters TSRMLS_CC); -+ } -+ -+ /* the stack should be empty */ -+ assert(apc_stack_size(apc_globals->cache_stack) == 0); -+ -+ /* apc cleanup */ -+ apc_stack_destroy(apc_globals->cache_stack TSRMLS_CC); -+ -+ /* the rest of the globals are cleaned up in apc_module_shutdown() */ -+} -+ -+static long apc_atol(const char *str, int str_len) -+{ -+#if PHP_MAJOR_VERSION >= 6 || PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3 -+ return zend_atol(str, str_len); -+#else -+ /* Re-implement zend_atol() for 5.2.x */ -+ long retval; -+ -+ if (!str_len) { -+ str_len = strlen(str); -+ } -+ -+ retval = strtol(str, NULL, 0); -+ -+ if (str_len > 0) { -+ switch (str[str_len - 1]) { -+ case 'g': -+ case 'G': -+ retval *= 1024; -+ /* break intentionally missing */ -+ case 'm': -+ case 'M': -+ retval *= 1024; -+ /* break intentionally missing */ -+ case 'k': -+ case 'K': -+ retval *= 1024; -+ break; -+ } -+ } -+ -+ return retval; -+#endif -+} -+ -+/* }}} */ -+ -+/* {{{ PHP_INI */ -+ -+static PHP_INI_MH(OnUpdate_filters) /* {{{ */ -+{ -+ APCG(filters) = apc_tokenize(new_value, ',' TSRMLS_CC); -+ return SUCCESS; -+} -+/* }}} */ -+ -+static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */ -+{ -+#if APC_MMAP -+ if(zend_atoi(new_value, new_value_length)!=1) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_segments setting ignored in MMAP mode"); -+ } -+ APCG(shm_segments) = 1; -+#else -+ APCG(shm_segments) = zend_atoi(new_value, new_value_length); -+#endif -+ return SUCCESS; -+} -+/* }}} */ -+ -+static PHP_INI_MH(OnUpdateShmSize) /* {{{ */ -+{ -+ long s = apc_atol(new_value, new_value_length); -+ -+ if(s <= 0) { -+ return FAILURE; -+ } -+ -+ if(s < 1048576L) { -+ /* if it's less than 1Mb, they are probably using the old syntax */ -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_size now uses M/G suffixes, please update your ini files"); -+ s = s * 1048576L; -+ } -+ -+ APCG(shm_size) = s; -+ -+ return SUCCESS; -+} -+/* }}} */ -+ -+#ifdef MULTIPART_EVENT_FORMDATA -+static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */ -+{ -+ int tmp; -+ tmp = zend_atoi(new_value, new_value_length); -+ if(tmp < 0) { -+ apc_error("rfc1867_freq must be greater than or equal to zero." TSRMLS_CC); -+ return FAILURE; -+ } -+ if(new_value[new_value_length-1] == '%') { -+ if(tmp > 100) { -+ apc_error("rfc1867_freq cannot be over 100%%" TSRMLS_CC); -+ return FAILURE; -+ } -+ APCG(rfc1867_freq) = tmp / 100.0; -+ } else { -+ APCG(rfc1867_freq) = tmp; -+ } -+ return SUCCESS; -+} -+/* }}} */ -+#endif -+ -+PHP_INI_BEGIN() -+STD_PHP_INI_BOOLEAN("apc.enabled", "1", PHP_INI_SYSTEM, OnUpdateBool, enabled, zend_apc_globals, apc_globals) -+STD_PHP_INI_ENTRY("apc.shm_segments", "1", PHP_INI_SYSTEM, OnUpdateShmSegments, shm_segments, zend_apc_globals, apc_globals) -+STD_PHP_INI_ENTRY("apc.shm_size", "32M", PHP_INI_SYSTEM, OnUpdateShmSize, shm_size, zend_apc_globals, apc_globals) -+#ifdef ZEND_ENGINE_2_4 -+STD_PHP_INI_ENTRY("apc.shm_strings_buffer", "4M", PHP_INI_SYSTEM, OnUpdateLong, shm_strings_buffer, zend_apc_globals, apc_globals) -+#endif -+STD_PHP_INI_BOOLEAN("apc.include_once_override", "0", PHP_INI_SYSTEM, OnUpdateBool, include_once, zend_apc_globals, apc_globals) -+STD_PHP_INI_ENTRY("apc.num_files_hint", "1000", PHP_INI_SYSTEM, OnUpdateLong, num_files_hint, zend_apc_globals, apc_globals) -+STD_PHP_INI_ENTRY("apc.user_entries_hint", "4096", PHP_INI_SYSTEM, OnUpdateLong, user_entries_hint, zend_apc_globals, apc_globals) -+STD_PHP_INI_ENTRY("apc.gc_ttl", "3600", PHP_INI_SYSTEM, OnUpdateLong, gc_ttl, zend_apc_globals, apc_globals) -+STD_PHP_INI_ENTRY("apc.ttl", "0", PHP_INI_SYSTEM, OnUpdateLong, ttl, zend_apc_globals, apc_globals) -+STD_PHP_INI_ENTRY("apc.user_ttl", "0", PHP_INI_SYSTEM, OnUpdateLong, user_ttl, zend_apc_globals, apc_globals) -+#if APC_MMAP -+STD_PHP_INI_ENTRY("apc.mmap_file_mask", NULL, PHP_INI_SYSTEM, OnUpdateString, mmap_file_mask, zend_apc_globals, apc_globals) -+#endif -+PHP_INI_ENTRY("apc.filters", NULL, PHP_INI_SYSTEM, OnUpdate_filters) -+STD_PHP_INI_BOOLEAN("apc.cache_by_default", "1", PHP_INI_ALL, OnUpdateBool, cache_by_default, zend_apc_globals, apc_globals) -+STD_PHP_INI_ENTRY("apc.file_update_protection", "2", PHP_INI_SYSTEM, OnUpdateLong,file_update_protection, zend_apc_globals, apc_globals) -+STD_PHP_INI_BOOLEAN("apc.enable_cli", "0", PHP_INI_SYSTEM, OnUpdateBool, enable_cli, zend_apc_globals, apc_globals) -+STD_PHP_INI_ENTRY("apc.max_file_size", "1M", PHP_INI_SYSTEM, OnUpdateLong, max_file_size, zend_apc_globals, apc_globals) -+STD_PHP_INI_BOOLEAN("apc.stat", "1", PHP_INI_SYSTEM, OnUpdateBool, fpstat, zend_apc_globals, apc_globals) -+STD_PHP_INI_BOOLEAN("apc.canonicalize", "1", PHP_INI_SYSTEM, OnUpdateBool, canonicalize, zend_apc_globals, apc_globals) -+STD_PHP_INI_BOOLEAN("apc.stat_ctime", "0", PHP_INI_SYSTEM, OnUpdateBool, stat_ctime, zend_apc_globals, apc_globals) -+STD_PHP_INI_BOOLEAN("apc.write_lock", "1", PHP_INI_SYSTEM, OnUpdateBool, write_lock, zend_apc_globals, apc_globals) -+STD_PHP_INI_BOOLEAN("apc.slam_defense", "1", PHP_INI_SYSTEM, OnUpdateBool, slam_defense, zend_apc_globals, apc_globals) -+STD_PHP_INI_BOOLEAN("apc.report_autofilter", "0", PHP_INI_SYSTEM, OnUpdateBool, report_autofilter,zend_apc_globals, apc_globals) -+#ifdef MULTIPART_EVENT_FORMDATA -+STD_PHP_INI_BOOLEAN("apc.rfc1867", "0", PHP_INI_SYSTEM, OnUpdateBool, rfc1867, zend_apc_globals, apc_globals) -+STD_PHP_INI_ENTRY("apc.rfc1867_prefix", "upload_", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_prefix, zend_apc_globals, apc_globals) -+STD_PHP_INI_ENTRY("apc.rfc1867_name", "APC_UPLOAD_PROGRESS", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_name, zend_apc_globals, apc_globals) -+STD_PHP_INI_ENTRY("apc.rfc1867_freq", "0", PHP_INI_SYSTEM, OnUpdateRfc1867Freq, rfc1867_freq, zend_apc_globals, apc_globals) -+STD_PHP_INI_ENTRY("apc.rfc1867_ttl", "3600", PHP_INI_SYSTEM, OnUpdateLong, rfc1867_ttl, zend_apc_globals, apc_globals) -+#endif -+STD_PHP_INI_BOOLEAN("apc.coredump_unmap", "0", PHP_INI_SYSTEM, OnUpdateBool, coredump_unmap, zend_apc_globals, apc_globals) -+STD_PHP_INI_ENTRY("apc.preload_path", (char*)NULL, PHP_INI_SYSTEM, OnUpdateString, preload_path, zend_apc_globals, apc_globals) -+STD_PHP_INI_BOOLEAN("apc.file_md5", "0", PHP_INI_SYSTEM, OnUpdateBool, file_md5, zend_apc_globals, apc_globals) -+STD_PHP_INI_BOOLEAN("apc.use_request_time", "1", PHP_INI_ALL, OnUpdateBool, use_request_time, zend_apc_globals, apc_globals) -+STD_PHP_INI_BOOLEAN("apc.lazy_functions", "0", PHP_INI_SYSTEM, OnUpdateBool, lazy_functions, zend_apc_globals, apc_globals) -+STD_PHP_INI_BOOLEAN("apc.lazy_classes", "0", PHP_INI_SYSTEM, OnUpdateBool, lazy_classes, zend_apc_globals, apc_globals) -+STD_PHP_INI_ENTRY("apc.serializer", "default", PHP_INI_SYSTEM, OnUpdateStringUnempty, serializer_name, zend_apc_globals, apc_globals) -+PHP_INI_END() -+ -+/* }}} */ -+ -+/* {{{ PHP_MINFO_FUNCTION(apc) */ -+static PHP_MINFO_FUNCTION(apc) -+{ -+ apc_serializer_t *serializer = NULL; -+ smart_str names = {0,}; -+ int i; -+ -+ php_info_print_table_start(); -+ php_info_print_table_header(2, "APC Support", APCG(enabled) ? "enabled" : "disabled"); -+ php_info_print_table_row(2, "Version", PHP_APC_VERSION); -+#ifdef __DEBUG_APC__ -+ php_info_print_table_row(2, "APC Debugging", "Enabled"); -+#else -+ php_info_print_table_row(2, "APC Debugging", "Disabled"); -+#endif -+#if APC_MMAP -+ php_info_print_table_row(2, "MMAP Support", "Enabled"); -+ php_info_print_table_row(2, "MMAP File Mask", APCG(mmap_file_mask)); -+#else -+ php_info_print_table_row(2, "MMAP Support", "Disabled"); -+#endif -+ php_info_print_table_row(2, "Locking type", APC_LOCK_TYPE); -+ -+ for( i = 0, serializer = apc_get_serializers(TSRMLS_C); -+ serializer->name != NULL; -+ serializer++, i++) { -+ if(i != 0) smart_str_appends(&names, ", "); -+ smart_str_appends(&names, serializer->name); -+ } -+ -+ if(names.c) { -+ smart_str_0(&names); -+ php_info_print_table_row(2, "Serialization Support", names.c); -+ smart_str_free(&names); -+ } else { -+ php_info_print_table_row(2, "Serialization Support", "broken"); -+ } -+ -+ php_info_print_table_row(2, "Revision", "$Revision: 325875 $"); -+ php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__); -+ php_info_print_table_end(); -+ DISPLAY_INI_ENTRIES(); -+} -+/* }}} */ -+ -+#ifdef MULTIPART_EVENT_FORMDATA -+extern int apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC); -+#endif -+ -+/* {{{ PHP_MINIT_FUNCTION(apc) */ -+static PHP_MINIT_FUNCTION(apc) -+{ -+ ZEND_INIT_MODULE_GLOBALS(apc, php_apc_init_globals, php_apc_shutdown_globals); -+ -+ REGISTER_INI_ENTRIES(); -+ -+ /* Disable APC in cli mode unless overridden by apc.enable_cli */ -+ if(!APCG(enable_cli) && !strcmp(sapi_module.name, "cli")) { -+ APCG(enabled) = 0; -+ } -+ -+ if (APCG(enabled)) { -+ if(APCG(initialized)) { -+ apc_process_init(module_number TSRMLS_CC); -+ } else { -+ apc_module_init(module_number TSRMLS_CC); -+ apc_zend_init(TSRMLS_C); -+ apc_process_init(module_number TSRMLS_CC); -+#ifdef MULTIPART_EVENT_FORMDATA -+ /* File upload progress tracking */ -+ if(APCG(rfc1867)) { -+ php_rfc1867_callback = apc_rfc1867_progress; -+ } -+#endif -+ apc_iterator_init(module_number TSRMLS_CC); -+ } -+ -+ zend_register_long_constant("APC_BIN_VERIFY_MD5", sizeof("APC_BIN_VERIFY_MD5"), APC_BIN_VERIFY_MD5, (CONST_CS | CONST_PERSISTENT), module_number TSRMLS_CC); -+ zend_register_long_constant("APC_BIN_VERIFY_CRC32", sizeof("APC_BIN_VERIFY_CRC32"), APC_BIN_VERIFY_CRC32, (CONST_CS | CONST_PERSISTENT), module_number TSRMLS_CC); -+ } -+ -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ PHP_MSHUTDOWN_FUNCTION(apc) */ -+static PHP_MSHUTDOWN_FUNCTION(apc) -+{ -+ if(APCG(enabled)) { -+ apc_process_shutdown(TSRMLS_C); -+ apc_zend_shutdown(TSRMLS_C); -+ apc_module_shutdown(TSRMLS_C); -+#ifndef ZTS -+ php_apc_shutdown_globals(&apc_globals); -+#endif -+#if HAVE_SIGACTION -+ apc_shutdown_signals(TSRMLS_C); -+#endif -+ } -+#ifdef ZTS -+ ts_free_id(apc_globals_id); -+#endif -+ UNREGISTER_INI_ENTRIES(); -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ PHP_RINIT_FUNCTION(apc) */ -+static PHP_RINIT_FUNCTION(apc) -+{ -+ if(APCG(enabled)) { -+ apc_request_init(TSRMLS_C); -+ -+#if HAVE_SIGACTION -+ apc_set_signals(TSRMLS_C); -+#endif -+ } -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ PHP_RSHUTDOWN_FUNCTION(apc) */ -+static PHP_RSHUTDOWN_FUNCTION(apc) -+{ -+ if(APCG(enabled)) { -+ apc_request_shutdown(TSRMLS_C); -+ } -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ proto array apc_cache_info([string type [, bool limited]]) */ -+PHP_FUNCTION(apc_cache_info) -+{ -+ zval* info; -+ char *cache_type; -+ int ct_len; -+ zend_bool limited = 0; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &cache_type, &ct_len, &limited) == FAILURE) { -+ return; -+ } -+ -+ if(ZEND_NUM_ARGS()) { -+ if(!strcasecmp(cache_type,"user")) { -+ info = apc_cache_info(apc_user_cache, limited TSRMLS_CC); -+ } else if(!strcasecmp(cache_type,"filehits")) { -+#ifdef APC_FILEHITS -+ RETVAL_ZVAL(APCG(filehits), 1, 0); -+ return; -+#else -+ RETURN_FALSE; -+#endif -+ } else { -+ info = apc_cache_info(apc_cache, limited TSRMLS_CC); -+ } -+ } else { -+ info = apc_cache_info(apc_cache, limited TSRMLS_CC); -+ } -+ -+ if(!info) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC info available. Perhaps APC is not enabled? Check apc.enabled in your ini file"); -+ RETURN_FALSE; -+ } -+ -+ RETURN_ZVAL(info, 0, 1); -+ -+} -+/* }}} */ -+ -+/* {{{ proto void apc_clear_cache([string cache]) */ -+PHP_FUNCTION(apc_clear_cache) -+{ -+ char *cache_type; -+ int ct_len = 0; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache_type, &ct_len) == FAILURE) { -+ return; -+ } -+ -+ if(ct_len) { -+ if(!strcasecmp(cache_type, "user")) { -+ apc_cache_clear(apc_user_cache TSRMLS_CC); -+ RETURN_TRUE; -+ } -+ } -+ apc_cache_clear(apc_cache TSRMLS_CC); -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto array apc_sma_info([bool limited]) */ -+PHP_FUNCTION(apc_sma_info) -+{ -+ apc_sma_info_t* info; -+ zval* block_lists; -+ int i; -+ zend_bool limited = 0; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &limited) == FAILURE) { -+ return; -+ } -+ -+ info = apc_sma_info(limited TSRMLS_CC); -+ -+ if(!info) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC SMA info available. Perhaps APC is disabled via apc.enabled?"); -+ RETURN_FALSE; -+ } -+ -+ array_init(return_value); -+ add_assoc_long(return_value, "num_seg", info->num_seg); -+ add_assoc_double(return_value, "seg_size", (double)info->seg_size); -+ add_assoc_double(return_value, "avail_mem", (double)apc_sma_get_avail_mem()); -+ -+ if(limited) { -+ apc_sma_free_info(info TSRMLS_CC); -+ return; -+ } -+ -+#if ALLOC_DISTRIBUTION -+ { -+ size_t *adist = apc_sma_get_alloc_distribution(); -+ zval* list; -+ ALLOC_INIT_ZVAL(list); -+ array_init(list); -+ for(i=0; i<30; i++) { -+ add_next_index_long(list, adist[i]); -+ } -+ add_assoc_zval(return_value, "adist", list); -+ } -+#endif -+ ALLOC_INIT_ZVAL(block_lists); -+ array_init(block_lists); -+ -+ for (i = 0; i < info->num_seg; i++) { -+ apc_sma_link_t* p; -+ zval* list; -+ -+ ALLOC_INIT_ZVAL(list); -+ array_init(list); -+ -+ for (p = info->list[i]; p != NULL; p = p->next) { -+ zval* link; -+ -+ ALLOC_INIT_ZVAL(link); -+ array_init(link); -+ -+ add_assoc_long(link, "size", p->size); -+ add_assoc_long(link, "offset", p->offset); -+ add_next_index_zval(list, link); -+ } -+ add_next_index_zval(block_lists, list); -+ } -+ add_assoc_zval(return_value, "block_lists", block_lists); -+ apc_sma_free_info(info TSRMLS_CC); -+} -+/* }}} */ -+ -+/* {{{ */ -+int _apc_update(char *strkey, int strkey_len, apc_cache_updater_t updater, void* data TSRMLS_DC) -+{ -+ if(!APCG(enabled)) { -+ return 0; -+ } -+ -+ if (!APCG(serializer) && APCG(serializer_name)) { -+ /* Avoid race conditions between MINIT of apc and serializer exts like igbinary */ -+ APCG(serializer) = apc_find_serializer(APCG(serializer_name) TSRMLS_CC); -+ } -+ -+ HANDLE_BLOCK_INTERRUPTIONS(); -+ APCG(current_cache) = apc_user_cache; -+ -+ if (!_apc_cache_user_update(apc_user_cache, strkey, strkey_len + 1, updater, data TSRMLS_CC)) { -+ HANDLE_UNBLOCK_INTERRUPTIONS(); -+ return 0; -+ } -+ -+ APCG(current_cache) = NULL; -+ HANDLE_UNBLOCK_INTERRUPTIONS(); -+ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ _apc_store */ -+int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC) { -+ apc_cache_entry_t *entry; -+ apc_cache_key_t key; -+ time_t t; -+ apc_context_t ctxt={0,}; -+ int ret = 1; -+ -+ t = apc_time(); -+ -+ if(!APCG(enabled)) return 0; -+ -+ if (!APCG(serializer) && APCG(serializer_name)) { -+ /* Avoid race conditions between MINIT of apc and serializer exts like igbinary */ -+ APCG(serializer) = apc_find_serializer(APCG(serializer_name) TSRMLS_CC); -+ } -+ -+ HANDLE_BLOCK_INTERRUPTIONS(); -+ -+ APCG(current_cache) = apc_user_cache; -+ -+ ctxt.pool = apc_pool_create(APC_SMALL_POOL, apc_sma_malloc, apc_sma_free, apc_sma_protect, apc_sma_unprotect TSRMLS_CC); -+ if (!ctxt.pool) { -+ apc_warning("Unable to allocate memory for pool." TSRMLS_CC); -+ return 0; -+ } -+ ctxt.copy = APC_COPY_IN_USER; -+ ctxt.force_update = 0; -+ -+ if(!ctxt.pool) { -+ ret = 0; -+ goto nocache; -+ } -+ -+ if (!apc_cache_make_user_key(&key, strkey, strkey_len, t)) { -+ goto freepool; -+ } -+ -+ if (apc_cache_is_last_key(apc_user_cache, &key, t TSRMLS_CC)) { -+ goto freepool; -+ } -+ -+ if (!(entry = apc_cache_make_user_entry(strkey, strkey_len, val, &ctxt, ttl TSRMLS_CC))) { -+ goto freepool; -+ } -+ -+ if (!apc_cache_user_insert(apc_user_cache, key, entry, &ctxt, t, exclusive TSRMLS_CC)) { -+freepool: -+ apc_pool_destroy(ctxt.pool TSRMLS_CC); -+ ret = 0; -+ } -+ -+nocache: -+ -+ APCG(current_cache) = NULL; -+ -+ HANDLE_UNBLOCK_INTERRUPTIONS(); -+ -+ return ret; -+} -+/* }}} */ -+ -+/* {{{ apc_store_helper(INTERNAL_FUNCTION_PARAMETERS, const int exclusive) -+ */ -+static void apc_store_helper(INTERNAL_FUNCTION_PARAMETERS, const int exclusive) -+{ -+ zval *key = NULL; -+ zval *val = NULL; -+ long ttl = 0L; -+ HashTable *hash; -+ HashPosition hpos; -+ zval **hentry; -+ char *hkey=NULL; -+ uint hkey_len; -+ ulong hkey_idx; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|zl", &key, &val, &ttl) == FAILURE) { -+ return; -+ } -+ -+ if (!key) RETURN_FALSE; -+ -+ if (Z_TYPE_P(key) == IS_ARRAY) { -+ hash = Z_ARRVAL_P(key); -+ array_init(return_value); -+ zend_hash_internal_pointer_reset_ex(hash, &hpos); -+ while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) { -+ zend_hash_get_current_key_ex(hash, &hkey, &hkey_len, &hkey_idx, 0, &hpos); -+ if (hkey) { -+ if(!_apc_store(hkey, hkey_len, *hentry, (unsigned int)ttl, exclusive TSRMLS_CC)) { -+ add_assoc_long_ex(return_value, hkey, hkey_len, -1); /* -1: insertion error */ -+ } -+ hkey = NULL; -+ } else { -+ add_index_long(return_value, hkey_idx, -1); /* -1: insertion error */ -+ } -+ zend_hash_move_forward_ex(hash, &hpos); -+ } -+ return; -+ } else if (Z_TYPE_P(key) == IS_STRING) { -+ if (!val) RETURN_FALSE; -+ if(_apc_store(Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, val, (unsigned int)ttl, exclusive TSRMLS_CC)) -+ RETURN_TRUE; -+ } else { -+ apc_warning("apc_store expects key parameter to be a string or an array of key/value pairs." TSRMLS_CC); -+ } -+ -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+/* {{{ proto int apc_store(mixed key, mixed var [, long ttl ]) -+ */ -+PHP_FUNCTION(apc_store) { -+ apc_store_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); -+} -+/* }}} */ -+ -+/* {{{ proto int apc_add(mixed key, mixed var [, long ttl ]) -+ */ -+PHP_FUNCTION(apc_add) { -+ apc_store_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -+} -+/* }}} */ -+ -+/* {{{ inc_updater */ -+ -+struct _inc_update_args { -+ long step; -+ long lval; -+}; -+ -+static int inc_updater(apc_cache_t* cache, apc_cache_entry_t* entry, void* data) { -+ -+ struct _inc_update_args *args = (struct _inc_update_args*) data; -+ -+ zval* val = entry->data.user.val; -+ -+ if(Z_TYPE_P(val) == IS_LONG) { -+ Z_LVAL_P(val) += args->step; -+ args->lval = Z_LVAL_P(val); -+ return 1; -+ } -+ -+ return 0; -+} -+/* }}} */ -+ -+/* {{{ proto long apc_inc(string key [, long step [, bool& success]]) -+ */ -+PHP_FUNCTION(apc_inc) { -+ char *strkey; -+ int strkey_len; -+ struct _inc_update_args args = {1L, -1}; -+ zval *success = NULL; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz", &strkey, &strkey_len, &(args.step), &success) == FAILURE) { -+ return; -+ } -+ -+ if (success) { -+ zval_dtor(success); -+ } -+ -+ if(_apc_update(strkey, strkey_len, inc_updater, &args TSRMLS_CC)) { -+ if(success) ZVAL_TRUE(success); -+ RETURN_LONG(args.lval); -+ } -+ -+ if(success) ZVAL_FALSE(success); -+ -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+/* {{{ proto long apc_dec(string key [, long step [, bool &success]]) -+ */ -+PHP_FUNCTION(apc_dec) { -+ char *strkey; -+ int strkey_len; -+ struct _inc_update_args args = {1L, -1}; -+ zval *success = NULL; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz", &strkey, &strkey_len, &(args.step), &success) == FAILURE) { -+ return; -+ } -+ -+ if (success) { -+ zval_dtor(success); -+ } -+ -+ args.step = args.step * -1; -+ -+ if(_apc_update(strkey, strkey_len, inc_updater, &args TSRMLS_CC)) { -+ if(success) ZVAL_TRUE(success); -+ RETURN_LONG(args.lval); -+ } -+ -+ if(success) ZVAL_FALSE(success); -+ -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+/* {{{ cas_updater */ -+static int cas_updater(apc_cache_t* cache, apc_cache_entry_t* entry, void* data) { -+ long* vals = ((long*)data); -+ long old = vals[0]; -+ long new = vals[1]; -+ zval* val = entry->data.user.val; -+ -+ if(Z_TYPE_P(val) == IS_LONG) { -+ if(Z_LVAL_P(val) == old) { -+ Z_LVAL_P(val) = new; -+ return 1; -+ } -+ } -+ -+ return 0; -+} -+/* }}} */ -+ -+/* {{{ proto int apc_cas(string key, int old, int new) -+ */ -+PHP_FUNCTION(apc_cas) { -+ char *strkey; -+ int strkey_len; -+ long vals[2]; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll", &strkey, &strkey_len, &vals[0], &vals[1]) == FAILURE) { -+ return; -+ } -+ -+ if(_apc_update(strkey, strkey_len, cas_updater, &vals TSRMLS_CC)) RETURN_TRUE; -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+void *apc_erealloc_wrapper(void *ptr, size_t size) { -+ return _erealloc(ptr, size, 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); -+} -+ -+/* {{{ proto mixed apc_fetch(mixed key[, bool &success]) -+ */ -+PHP_FUNCTION(apc_fetch) { -+ zval *key; -+ zval *success = NULL; -+ HashTable *hash; -+ HashPosition hpos; -+ zval **hentry; -+ zval *result; -+ zval *result_entry; -+ char *strkey; -+ int strkey_len; -+ apc_cache_entry_t* entry; -+ time_t t; -+ apc_context_t ctxt = {0,}; -+ -+ if(!APCG(enabled)) RETURN_FALSE; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &key, &success) == FAILURE) { -+ return; -+ } -+ -+ t = apc_time(); -+ -+ if (success) { -+ ZVAL_BOOL(success, 0); -+ } -+ -+ ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, NULL, NULL TSRMLS_CC); -+ if (!ctxt.pool) { -+ apc_warning("Unable to allocate memory for pool." TSRMLS_CC); -+ RETURN_FALSE; -+ } -+ ctxt.copy = APC_COPY_OUT_USER; -+ ctxt.force_update = 0; -+ -+ if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) { -+ convert_to_string(key); -+ } -+ -+ if(Z_TYPE_P(key) == IS_STRING) { -+ strkey = Z_STRVAL_P(key); -+ strkey_len = Z_STRLEN_P(key); -+ if(!strkey_len) RETURN_FALSE; -+ entry = apc_cache_user_find(apc_user_cache, strkey, (strkey_len + 1), t TSRMLS_CC); -+ if(entry) { -+ /* deep-copy returned shm zval to emalloc'ed return_value */ -+ apc_cache_fetch_zval(return_value, entry->data.user.val, &ctxt TSRMLS_CC); -+ apc_cache_release(apc_user_cache, entry TSRMLS_CC); -+ } else { -+ goto freepool; -+ } -+ } else if(Z_TYPE_P(key) == IS_ARRAY) { -+ hash = Z_ARRVAL_P(key); -+ MAKE_STD_ZVAL(result); -+ array_init(result); -+ zend_hash_internal_pointer_reset_ex(hash, &hpos); -+ while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) { -+ if(Z_TYPE_PP(hentry) != IS_STRING) { -+ apc_warning("apc_fetch() expects a string or array of strings." TSRMLS_CC); -+ goto freepool; -+ } -+ entry = apc_cache_user_find(apc_user_cache, Z_STRVAL_PP(hentry), (Z_STRLEN_PP(hentry) + 1), t TSRMLS_CC); -+ if(entry) { -+ /* deep-copy returned shm zval to emalloc'ed return_value */ -+ MAKE_STD_ZVAL(result_entry); -+ apc_cache_fetch_zval(result_entry, entry->data.user.val, &ctxt TSRMLS_CC); -+ apc_cache_release(apc_user_cache, entry TSRMLS_CC); -+ zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL); -+ } /* don't set values we didn't find */ -+ zend_hash_move_forward_ex(hash, &hpos); -+ } -+ RETVAL_ZVAL(result, 0, 1); -+ } else { -+ apc_warning("apc_fetch() expects a string or array of strings." TSRMLS_CC); -+freepool: -+ apc_pool_destroy(ctxt.pool TSRMLS_CC); -+ RETURN_FALSE; -+ } -+ -+ if (success) { -+ ZVAL_BOOL(success, 1); -+ } -+ -+ apc_pool_destroy(ctxt.pool TSRMLS_CC); -+ return; -+} -+/* }}} */ -+ -+/* {{{ proto mixed apc_exists(mixed key) -+ */ -+PHP_FUNCTION(apc_exists) { -+ zval *key; -+ HashTable *hash; -+ HashPosition hpos; -+ zval **hentry; -+ char *strkey; -+ int strkey_len; -+ apc_cache_entry_t* entry; -+ zval *result; -+ zval *result_entry; -+ time_t t; -+ -+ if(!APCG(enabled)) RETURN_FALSE; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) == FAILURE) { -+ return; -+ } -+ -+ t = apc_time(); -+ -+ if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) { -+ convert_to_string(key); -+ } -+ -+ if(Z_TYPE_P(key) == IS_STRING) { -+ strkey = Z_STRVAL_P(key); -+ strkey_len = Z_STRLEN_P(key); -+ if(!strkey_len) RETURN_FALSE; -+ entry = apc_cache_user_exists(apc_user_cache, strkey, strkey_len + 1, t TSRMLS_CC); -+ if(entry) { -+ RETURN_TRUE; -+ } -+ } else if(Z_TYPE_P(key) == IS_ARRAY) { -+ hash = Z_ARRVAL_P(key); -+ MAKE_STD_ZVAL(result); -+ array_init(result); -+ zend_hash_internal_pointer_reset_ex(hash, &hpos); -+ while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) { -+ if(Z_TYPE_PP(hentry) != IS_STRING) { -+ apc_warning("apc_exists() expects a string or array of strings." TSRMLS_CC); -+ RETURN_FALSE; -+ } -+ -+ entry = apc_cache_user_exists(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1, t TSRMLS_CC); -+ if(entry) { -+ MAKE_STD_ZVAL(result_entry); -+ ZVAL_BOOL(result_entry, 1); -+ zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL); -+ } /* don't set values we didn't find */ -+ zend_hash_move_forward_ex(hash, &hpos); -+ } -+ RETURN_ZVAL(result, 0, 1); -+ } else { -+ apc_warning("apc_exists() expects a string or array of strings." TSRMLS_CC); -+ } -+ -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+ -+/* {{{ proto mixed apc_delete(mixed keys) -+ */ -+PHP_FUNCTION(apc_delete) { -+ zval *keys; -+ -+ if(!APCG(enabled)) RETURN_FALSE; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &keys) == FAILURE) { -+ return; -+ } -+ -+ if (Z_TYPE_P(keys) == IS_STRING) { -+ if (!Z_STRLEN_P(keys)) RETURN_FALSE; -+ if(apc_cache_user_delete(apc_user_cache, Z_STRVAL_P(keys), (Z_STRLEN_P(keys) + 1) TSRMLS_CC)) { -+ RETURN_TRUE; -+ } else { -+ RETURN_FALSE; -+ } -+ } else if (Z_TYPE_P(keys) == IS_ARRAY) { -+ HashTable *hash = Z_ARRVAL_P(keys); -+ HashPosition hpos; -+ zval **hentry; -+ array_init(return_value); -+ zend_hash_internal_pointer_reset_ex(hash, &hpos); -+ while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) { -+ if(Z_TYPE_PP(hentry) != IS_STRING) { -+ apc_warning("apc_delete() expects a string, array of strings, or APCIterator instance." TSRMLS_CC); -+ add_next_index_zval(return_value, *hentry); -+ Z_ADDREF_PP(hentry); -+ } else if(apc_cache_user_delete(apc_user_cache, Z_STRVAL_PP(hentry), (Z_STRLEN_PP(hentry) + 1) TSRMLS_CC) != 1) { -+ add_next_index_zval(return_value, *hentry); -+ Z_ADDREF_PP(hentry); -+ } -+ zend_hash_move_forward_ex(hash, &hpos); -+ } -+ return; -+ } else if (Z_TYPE_P(keys) == IS_OBJECT) { -+ if (apc_iterator_delete(keys TSRMLS_CC)) { -+ RETURN_TRUE; -+ } else { -+ RETURN_FALSE; -+ } -+ } else { -+ apc_warning("apc_delete() expects a string, array of strings, or APCIterator instance." TSRMLS_CC); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto mixed apc_delete_file(mixed keys) -+ * Deletes the given files from the opcode cache. -+ * Accepts a string, array of strings, or APCIterator object. -+ * Returns True/False, or for an Array an Array of failed files. -+ */ -+PHP_FUNCTION(apc_delete_file) { -+ zval *keys; -+ -+ if(!APCG(enabled)) RETURN_FALSE; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &keys) == FAILURE) { -+ return; -+ } -+ -+ if (Z_TYPE_P(keys) == IS_STRING) { -+ if (!Z_STRLEN_P(keys)) RETURN_FALSE; -+ if(apc_cache_delete(apc_cache, Z_STRVAL_P(keys), Z_STRLEN_P(keys) + 1 TSRMLS_CC) != 1) { -+ RETURN_FALSE; -+ } else { -+ RETURN_TRUE; -+ } -+ } else if (Z_TYPE_P(keys) == IS_ARRAY) { -+ HashTable *hash = Z_ARRVAL_P(keys); -+ HashPosition hpos; -+ zval **hentry; -+ array_init(return_value); -+ zend_hash_internal_pointer_reset_ex(hash, &hpos); -+ while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) { -+ if(Z_TYPE_PP(hentry) != IS_STRING) { -+ apc_warning("apc_delete_file() expects a string, array of strings, or APCIterator instance." TSRMLS_CC); -+ add_next_index_zval(return_value, *hentry); -+ Z_ADDREF_PP(hentry); -+ } else if(apc_cache_delete(apc_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1 TSRMLS_CC) != 1) { -+ add_next_index_zval(return_value, *hentry); -+ Z_ADDREF_PP(hentry); -+ } -+ zend_hash_move_forward_ex(hash, &hpos); -+ } -+ return; -+ } else if (Z_TYPE_P(keys) == IS_OBJECT) { -+ if (apc_iterator_delete(keys TSRMLS_CC)) { -+ RETURN_TRUE; -+ } else { -+ RETURN_FALSE; -+ } -+ } else { -+ apc_warning("apc_delete_file() expects a string, array of strings, or APCIterator instance." TSRMLS_CC); -+ } -+} -+/* }}} */ -+ -+static void _apc_define_constants(zval *constants, zend_bool case_sensitive TSRMLS_DC) { -+ char *const_key; -+ unsigned int const_key_len; -+ zval **entry; -+ HashPosition pos; -+ -+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(constants), &pos); -+ while (zend_hash_get_current_data_ex(Z_ARRVAL_P(constants), (void**)&entry, &pos) == SUCCESS) { -+ zend_constant c; -+ int key_type; -+ ulong num_key; -+ -+ key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(constants), &const_key, &const_key_len, &num_key, 0, &pos); -+ if(key_type != HASH_KEY_IS_STRING) { -+ zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos); -+ continue; -+ } -+ switch(Z_TYPE_PP(entry)) { -+ case IS_LONG: -+ case IS_DOUBLE: -+ case IS_STRING: -+ case IS_BOOL: -+ case IS_RESOURCE: -+ case IS_NULL: -+ break; -+ default: -+ zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos); -+ continue; -+ } -+ c.value = **entry; -+ zval_copy_ctor(&c.value); -+ c.flags = case_sensitive; -+ c.name = zend_strndup(const_key, const_key_len); -+ c.name_len = const_key_len; -+ c.module_number = PHP_USER_CONSTANT; -+ zend_register_constant(&c TSRMLS_CC); -+ -+ zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos); -+ } -+} -+ -+/* {{{ proto mixed apc_define_constants(string key, array constants [, bool case_sensitive]) -+ */ -+PHP_FUNCTION(apc_define_constants) { -+ char *strkey; -+ int strkey_len; -+ zval *constants = NULL; -+ zend_bool case_sensitive = 1; -+ int argc = ZEND_NUM_ARGS(); -+ -+ if (zend_parse_parameters(argc TSRMLS_CC, "sa|b", &strkey, &strkey_len, &constants, &case_sensitive) == FAILURE) { -+ return; -+ } -+ -+ if(!strkey_len) RETURN_FALSE; -+ -+ _apc_define_constants(constants, case_sensitive TSRMLS_CC); -+ if(_apc_store(strkey, strkey_len + 1, constants, 0, 0 TSRMLS_CC)) RETURN_TRUE; -+ RETURN_FALSE; -+} /* }}} */ -+ -+/* {{{ proto mixed apc_load_constants(string key [, bool case_sensitive]) -+ */ -+PHP_FUNCTION(apc_load_constants) { -+ char *strkey; -+ int strkey_len; -+ apc_cache_entry_t* entry; -+ time_t t; -+ zend_bool case_sensitive = 1; -+ -+ if(!APCG(enabled)) RETURN_FALSE; -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &strkey, &strkey_len, &case_sensitive) == FAILURE) { -+ return; -+ } -+ -+ if(!strkey_len) RETURN_FALSE; -+ -+ t = apc_time(); -+ -+ entry = apc_cache_user_find(apc_user_cache, strkey, (strkey_len + 1), t TSRMLS_CC); -+ -+ if(entry) { -+ _apc_define_constants(entry->data.user.val, case_sensitive TSRMLS_CC); -+ apc_cache_release(apc_user_cache, entry TSRMLS_CC); -+ RETURN_TRUE; -+ } else { -+ RETURN_FALSE; -+ } -+} -+/* }}} */ -+ -+/* {{{ proto mixed apc_compile_file(mixed filenames [, bool atomic]) -+ */ -+PHP_FUNCTION(apc_compile_file) { -+ zval *file; -+ zend_file_handle file_handle; -+ zend_op_array *op_array; -+ char** filters = NULL; -+ zend_bool cache_by_default = 1; -+ HashTable cg_function_table, cg_class_table; -+ HashTable *cg_orig_function_table, *cg_orig_class_table, *eg_orig_function_table, *eg_orig_class_table; -+ apc_cache_entry_t** cache_entries; -+ apc_cache_key_t* keys; -+ zend_op_array **op_arrays; -+ time_t t; -+ zval **hentry; -+ HashPosition hpos; -+ int i=0, c=0; -+ int *rval=NULL; -+ int count=0; -+ zend_bool atomic=1; -+ apc_context_t ctxt = {0,}; -+ zend_execute_data *orig_current_execute_data; -+ int atomic_fail; -+ -+ if(!APCG(enabled)) RETURN_FALSE; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &file, &atomic) == FAILURE) { -+ return; -+ } -+ -+ if (Z_TYPE_P(file) != IS_ARRAY && Z_TYPE_P(file) != IS_STRING) { -+ apc_warning("apc_compile_file argument must be a string or an array of strings" TSRMLS_CC); -+ RETURN_FALSE; -+ } -+ -+ HANDLE_BLOCK_INTERRUPTIONS(); -+ APCG(current_cache) = apc_cache; -+ -+ /* reset filters and cache_by_default */ -+ filters = APCG(filters); -+ APCG(filters) = NULL; -+ -+ cache_by_default = APCG(cache_by_default); -+ APCG(cache_by_default) = 1; -+ -+ /* Replace function/class tables to avoid namespace conflicts */ -+ zend_hash_init_ex(&cg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0); -+ cg_orig_function_table = CG(function_table); -+ CG(function_table) = &cg_function_table; -+ zend_hash_init_ex(&cg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0); -+ cg_orig_class_table = CG(class_table); -+ CG(class_table) = &cg_class_table; -+ eg_orig_function_table = EG(function_table); -+ EG(function_table) = CG(function_table); -+ eg_orig_class_table = EG(class_table); -+ EG(class_table) = CG(class_table); -+ APCG(force_file_update) = 1; -+ -+ /* Compile the file(s), loading it into the cache */ -+ if (Z_TYPE_P(file) == IS_STRING) { -+ file_handle.type = ZEND_HANDLE_FILENAME; -+ file_handle.filename = Z_STRVAL_P(file); -+ file_handle.free_filename = 0; -+ file_handle.opened_path = NULL; -+ -+ orig_current_execute_data = EG(current_execute_data); -+ zend_try { -+ op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC); -+ } zend_catch { -+ EG(current_execute_data) = orig_current_execute_data; -+ EG(in_execution) = 1; -+ CG(unclean_shutdown) = 0; -+ apc_warning("Error compiling %s in apc_compile_file." TSRMLS_CC, file_handle.filename); -+ op_array = NULL; -+ } zend_end_try(); -+ if(op_array != NULL) { -+ /* Free up everything */ -+ destroy_op_array(op_array TSRMLS_CC); -+ efree(op_array); -+ RETVAL_TRUE; -+ } else { -+ RETVAL_FALSE; -+ } -+ zend_destroy_file_handle(&file_handle TSRMLS_CC); -+ -+ } else { /* IS_ARRAY */ -+ -+ array_init(return_value); -+ -+ t = apc_time(); -+ -+ op_arrays = ecalloc(Z_ARRVAL_P(file)->nNumOfElements, sizeof(zend_op_array*)); -+ cache_entries = ecalloc(Z_ARRVAL_P(file)->nNumOfElements, sizeof(apc_cache_entry_t*)); -+ keys = ecalloc(Z_ARRVAL_P(file)->nNumOfElements, sizeof(apc_cache_key_t)); -+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(file), &hpos); -+ while(zend_hash_get_current_data_ex(Z_ARRVAL_P(file), (void**)&hentry, &hpos) == SUCCESS) { -+ if (Z_TYPE_PP(hentry) != IS_STRING) { -+ apc_warning("apc_compile_file array values must be strings, aborting." TSRMLS_CC); -+ break; -+ } -+ file_handle.type = ZEND_HANDLE_FILENAME; -+ file_handle.filename = Z_STRVAL_PP(hentry); -+ file_handle.free_filename = 0; -+ file_handle.opened_path = NULL; -+ -+ if (!apc_cache_make_file_key(&(keys[i]), file_handle.filename, PG(include_path), t TSRMLS_CC)) { -+ add_assoc_long(return_value, Z_STRVAL_PP(hentry), -1); /* -1: compilation error */ -+ apc_warning("Error compiling %s in apc_compile_file." TSRMLS_CC, file_handle.filename); -+ break; -+ } -+ -+ if (keys[i].type == APC_CACHE_KEY_FPFILE) { -+ keys[i].data.fpfile.fullpath = estrndup(keys[i].data.fpfile.fullpath, keys[i].data.fpfile.fullpath_len); -+ } else if (keys[i].type == APC_CACHE_KEY_USER) { -+ keys[i].data.user.identifier = estrndup(keys[i].data.user.identifier, keys[i].data.user.identifier_len); -+ } -+ -+ orig_current_execute_data = EG(current_execute_data); -+ zend_try { -+ if (apc_compile_cache_entry(&keys[i], &file_handle, ZEND_INCLUDE, t, &op_arrays[i], &cache_entries[i] TSRMLS_CC) != SUCCESS) { -+ op_arrays[i] = NULL; -+ cache_entries[i] = NULL; -+ add_assoc_long(return_value, Z_STRVAL_PP(hentry), -2); /* -2: input or cache insertion error */ -+ apc_warning("Error compiling %s in apc_compile_file." TSRMLS_CC, file_handle.filename); -+ } -+ } zend_catch { -+ EG(current_execute_data) = orig_current_execute_data; -+ EG(in_execution) = 1; -+ CG(unclean_shutdown) = 0; -+ op_arrays[i] = NULL; -+ cache_entries[i] = NULL; -+ add_assoc_long(return_value, Z_STRVAL_PP(hentry), -1); /* -1: compilation error */ -+ apc_warning("Error compiling %s in apc_compile_file." TSRMLS_CC, file_handle.filename); -+ } zend_end_try(); -+ -+ zend_destroy_file_handle(&file_handle TSRMLS_CC); -+ if(op_arrays[i] != NULL) { -+ count++; -+ } -+ -+ /* clean out the function/class tables */ -+ zend_hash_clean(&cg_function_table); -+ zend_hash_clean(&cg_class_table); -+ -+ zend_hash_move_forward_ex(Z_ARRVAL_P(file), &hpos); -+ i++; -+ } -+ -+ /* atomically update the cache if no errors or not atomic */ -+ ctxt.copy = APC_COPY_IN_OPCODE; -+ ctxt.force_update = 1; -+ if (count == i || !atomic) { -+ rval = apc_cache_insert_mult(apc_cache, keys, cache_entries, &ctxt, t, i TSRMLS_CC); -+ atomic_fail = 0; -+ } else { -+ atomic_fail = 1; -+ } -+ -+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(file), &hpos); -+ for(c=0; c < i; c++) { -+ zend_hash_get_current_data_ex(Z_ARRVAL_P(file), (void**)&hentry, &hpos); -+ if (rval && rval[c] != 1) { -+ add_assoc_long(return_value, Z_STRVAL_PP(hentry), -2); /* -2: input or cache insertion error */ -+ if (cache_entries[c]) { -+ apc_pool_destroy(cache_entries[c]->pool TSRMLS_CC); -+ } -+ } -+ if (op_arrays[c]) { -+ destroy_op_array(op_arrays[c] TSRMLS_CC); -+ efree(op_arrays[c]); -+ } -+ if (atomic_fail && cache_entries[c]) { -+ apc_pool_destroy(cache_entries[c]->pool TSRMLS_CC); -+ } -+ if (keys[c].type == APC_CACHE_KEY_FPFILE) { -+ efree((void*)keys[c].data.fpfile.fullpath); -+ } else if (keys[c].type == APC_CACHE_KEY_USER) { -+ efree((void*)keys[c].data.user.identifier); -+ } -+ zend_hash_move_forward_ex(Z_ARRVAL_P(file), &hpos); -+ } -+ efree(op_arrays); -+ efree(keys); -+ efree(cache_entries); -+ if (rval) { -+ efree(rval); -+ } -+ -+ } -+ -+ /* Return class/function tables to previous states, destroy temp tables */ -+ APCG(force_file_update) = 0; -+ CG(function_table) = cg_orig_function_table; -+ zend_hash_destroy(&cg_function_table); -+ CG(class_table) = cg_orig_class_table; -+ zend_hash_destroy(&cg_class_table); -+ EG(function_table) = eg_orig_function_table; -+ EG(class_table) = eg_orig_class_table; -+ -+ /* Restore global settings */ -+ APCG(filters) = filters; -+ APCG(cache_by_default) = cache_by_default; -+ -+ APCG(current_cache) = NULL; -+ HANDLE_UNBLOCK_INTERRUPTIONS(); -+ -+} -+/* }}} */ -+ -+/* {{{ proto mixed apc_bin_dump([array files [, array user_vars]]) -+ Returns a binary dump of the given files and user variables from the APC cache. -+ A NULL for files or user_vars signals a dump of every entry, while array() will dump nothing. -+ */ -+PHP_FUNCTION(apc_bin_dump) { -+ -+ zval *z_files = NULL, *z_user_vars = NULL; -+ HashTable *h_files, *h_user_vars; -+ apc_bd_t *bd; -+ -+ if(!APCG(enabled)) { -+ apc_warning("APC is not enabled, apc_bin_dump not available." TSRMLS_CC); -+ RETURN_FALSE; -+ } -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!a!", &z_files, &z_user_vars) == FAILURE) { -+ return; -+ } -+ -+ h_files = z_files ? Z_ARRVAL_P(z_files) : NULL; -+ h_user_vars = z_user_vars ? Z_ARRVAL_P(z_user_vars) : NULL; -+ bd = apc_bin_dump(h_files, h_user_vars TSRMLS_CC); -+ if(bd) { -+ RETVAL_STRINGL((char*)bd, bd->size-1, 0); -+ } else { -+ apc_error("Unknown error encountered during apc_bin_dump." TSRMLS_CC); -+ RETVAL_NULL(); -+ } -+ -+ return; -+} -+ -+/* {{{ proto mixed apc_bin_dumpfile(array files, array user_vars, string filename, [int flags [, resource context]]) -+ Output a binary dump of the given files and user variables from the APC cache to the named file. -+ */ -+PHP_FUNCTION(apc_bin_dumpfile) { -+ -+ zval *z_files = NULL, *z_user_vars = NULL; -+ HashTable *h_files, *h_user_vars; -+ char *filename = NULL; -+ int filename_len; -+ long flags=0; -+ zval *zcontext = NULL; -+ php_stream_context *context = NULL; -+ php_stream *stream; -+ int numbytes = 0; -+ apc_bd_t *bd; -+ -+ if(!APCG(enabled)) { -+ apc_warning("APC is not enabled, apc_bin_dumpfile not available." TSRMLS_CC); -+ RETURN_FALSE; -+ } -+ -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!s|lr!", &z_files, &z_user_vars, &filename, &filename_len, &flags, &zcontext) == FAILURE) { -+ return; -+ } -+ -+ if(!filename_len) { -+ apc_error("apc_bin_dumpfile filename argument must be a valid filename." TSRMLS_CC); -+ RETURN_FALSE; -+ } -+ -+ h_files = z_files ? Z_ARRVAL_P(z_files) : NULL; -+ h_user_vars = z_user_vars ? Z_ARRVAL_P(z_user_vars) : NULL; -+ bd = apc_bin_dump(h_files, h_user_vars TSRMLS_CC); -+ if(!bd) { -+ apc_error("Unknown error encountered during apc_bin_dumpfile." TSRMLS_CC); -+ RETURN_FALSE; -+ } -+ -+ -+ /* Most of the following has been taken from the file_get/put_contents functions */ -+ -+ context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT); -+ stream = php_stream_open_wrapper_ex(filename, (flags & PHP_FILE_APPEND) ? "ab" : "wb", -+ ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context); -+ if (stream == NULL) { -+ efree(bd); -+ apc_error("Unable to write to file in apc_bin_dumpfile." TSRMLS_CC); -+ RETURN_FALSE; -+ } -+ -+ if (flags & LOCK_EX && php_stream_lock(stream, LOCK_EX)) { -+ php_stream_close(stream); -+ efree(bd); -+ apc_error("Unable to get a lock on file in apc_bin_dumpfile." TSRMLS_CC); -+ RETURN_FALSE; -+ } -+ -+ numbytes = php_stream_write(stream, (char*)bd, bd->size); -+ if(numbytes != bd->size) { -+ numbytes = -1; -+ } -+ -+ php_stream_close(stream); -+ efree(bd); -+ -+ if(numbytes < 0) { -+ apc_error("Only %d of %d bytes written, possibly out of free disk space" TSRMLS_CC, numbytes, bd->size); -+ RETURN_FALSE; -+ } -+ -+ RETURN_LONG(numbytes); -+} -+ -+/* {{{ proto mixed apc_bin_load(string data, [int flags]) -+ Load the given binary dump into the APC file/user cache. -+ */ -+PHP_FUNCTION(apc_bin_load) { -+ -+ int data_len; -+ char *data; -+ long flags = 0; -+ -+ if(!APCG(enabled)) { -+ apc_warning("APC is not enabled, apc_bin_load not available." TSRMLS_CC); -+ RETURN_FALSE; -+ } -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &flags) == FAILURE) { -+ return; -+ } -+ -+ if(!data_len || data_len != ((apc_bd_t*)data)->size -1) { -+ apc_error("apc_bin_load string argument does not appear to be a valid APC binary dump due to size (%d vs expected %d)." TSRMLS_CC, data_len, ((apc_bd_t*)data)->size -1); -+ RETURN_FALSE; -+ } -+ -+ apc_bin_load((apc_bd_t*)data, (int)flags TSRMLS_CC); -+ -+ RETURN_TRUE; -+} -+ -+/* {{{ proto mixed apc_bin_loadfile(string filename, [resource context, [int flags]]) -+ Load the given binary dump from the named file into the APC file/user cache. -+ */ -+PHP_FUNCTION(apc_bin_loadfile) { -+ -+ char *filename; -+ int filename_len; -+ zval *zcontext = NULL; -+ long flags; -+ php_stream_context *context = NULL; -+ php_stream *stream; -+ char *data; -+ int len; -+ -+ if(!APCG(enabled)) { -+ apc_warning("APC is not enabled, apc_bin_loadfile not available." TSRMLS_CC); -+ RETURN_FALSE; -+ } -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r!l", &filename, &filename_len, &zcontext, &flags) == FAILURE) { -+ return; -+ } -+ -+ if(!filename_len) { -+ apc_error("apc_bin_loadfile filename argument must be a valid filename." TSRMLS_CC); -+ RETURN_FALSE; -+ } -+ -+ context = php_stream_context_from_zval(zcontext, 0); -+ stream = php_stream_open_wrapper_ex(filename, "rb", -+ ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context); -+ if (!stream) { -+ apc_error("Unable to read from file in apc_bin_loadfile." TSRMLS_CC); -+ RETURN_FALSE; -+ } -+ -+ len = php_stream_copy_to_mem(stream, &data, PHP_STREAM_COPY_ALL, 0); -+ if(len == 0) { -+ apc_warning("File passed to apc_bin_loadfile was empty: %s." TSRMLS_CC, filename); -+ RETURN_FALSE; -+ } else if(len < 0) { -+ apc_warning("Error reading file passed to apc_bin_loadfile: %s." TSRMLS_CC, filename); -+ RETURN_FALSE; -+ } else if(len != ((apc_bd_t*)data)->size) { -+ apc_warning("file passed to apc_bin_loadfile does not appear to be valid due to size (%d vs expected %d)." TSRMLS_CC, len, ((apc_bd_t*)data)->size -1); -+ RETURN_FALSE; -+ } -+ php_stream_close(stream); -+ -+ apc_bin_load((apc_bd_t*)data, (int)flags TSRMLS_CC); -+ efree(data); -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ arginfo */ -+#if (PHP_MAJOR_VERSION >= 6 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3)) -+# define PHP_APC_ARGINFO -+#else -+# define PHP_APC_ARGINFO static -+#endif -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_store, 0, 0, 2) -+ ZEND_ARG_INFO(0, key) -+ ZEND_ARG_INFO(0, var) -+ ZEND_ARG_INFO(0, ttl) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_clear_cache, 0, 0, 0) -+ ZEND_ARG_INFO(0, info) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_sma_info, 0, 0, 0) -+ ZEND_ARG_INFO(0, limited) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_cache_info, 0, 0, 0) -+ ZEND_ARG_INFO(0, type) -+ ZEND_ARG_INFO(0, limited) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_define_constants, 0, 0, 2) -+ ZEND_ARG_INFO(0, key) -+ ZEND_ARG_INFO(0, constants) -+ ZEND_ARG_INFO(0, case_sensitive) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO(arginfo_apc_delete_file, 0) -+ ZEND_ARG_INFO(0, keys) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO(arginfo_apc_delete, 0) -+ ZEND_ARG_INFO(0, keys) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_fetch, 0, 0, 1) -+ ZEND_ARG_INFO(0, key) -+ ZEND_ARG_INFO(1, success) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_inc, 0, 0, 1) -+ ZEND_ARG_INFO(0, key) -+ ZEND_ARG_INFO(0, step) -+ ZEND_ARG_INFO(1, success) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO(arginfo_apc_cas, 0) -+ ZEND_ARG_INFO(0, key) -+ ZEND_ARG_INFO(0, old) -+ ZEND_ARG_INFO(0, new) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_load_constants, 0, 0, 1) -+ ZEND_ARG_INFO(0, key) -+ ZEND_ARG_INFO(0, case_sensitive) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_compile_file, 0, 0, 1) -+ ZEND_ARG_INFO(0, filenames) -+ ZEND_ARG_INFO(0, atomic) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_dump, 0, 0, 0) -+ ZEND_ARG_INFO(0, files) -+ ZEND_ARG_INFO(0, user_vars) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_dumpfile, 0, 0, 3) -+ ZEND_ARG_INFO(0, files) -+ ZEND_ARG_INFO(0, user_vars) -+ ZEND_ARG_INFO(0, filename) -+ ZEND_ARG_INFO(0, flags) -+ ZEND_ARG_INFO(0, context) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_load, 0, 0, 1) -+ ZEND_ARG_INFO(0, data) -+ ZEND_ARG_INFO(0, flags) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_loadfile, 0, 0, 1) -+ ZEND_ARG_INFO(0, filename) -+ ZEND_ARG_INFO(0, context) -+ ZEND_ARG_INFO(0, flags) -+ZEND_END_ARG_INFO() -+ -+PHP_APC_ARGINFO -+ZEND_BEGIN_ARG_INFO(arginfo_apc_exists, 0) -+ ZEND_ARG_INFO(0, keys) -+ZEND_END_ARG_INFO() -+/* }}} */ -+ -+/* {{{ apc_functions[] */ -+zend_function_entry apc_functions[] = { -+ PHP_FE(apc_cache_info, arginfo_apc_cache_info) -+ PHP_FE(apc_clear_cache, arginfo_apc_clear_cache) -+ PHP_FE(apc_sma_info, arginfo_apc_sma_info) -+ PHP_FE(apc_store, arginfo_apc_store) -+ PHP_FE(apc_fetch, arginfo_apc_fetch) -+ PHP_FE(apc_delete, arginfo_apc_delete) -+ PHP_FE(apc_delete_file, arginfo_apc_delete_file) -+ PHP_FE(apc_define_constants, arginfo_apc_define_constants) -+ PHP_FE(apc_load_constants, arginfo_apc_load_constants) -+ PHP_FE(apc_compile_file, arginfo_apc_compile_file) -+ PHP_FE(apc_add, arginfo_apc_store) -+ PHP_FE(apc_inc, arginfo_apc_inc) -+ PHP_FE(apc_dec, arginfo_apc_inc) -+ PHP_FE(apc_cas, arginfo_apc_cas) -+ PHP_FE(apc_bin_dump, arginfo_apc_bin_dump) -+ PHP_FE(apc_bin_load, arginfo_apc_bin_load) -+ PHP_FE(apc_bin_dumpfile, arginfo_apc_bin_dumpfile) -+ PHP_FE(apc_bin_loadfile, arginfo_apc_bin_loadfile) -+ PHP_FE(apc_exists, arginfo_apc_exists) -+ {NULL, NULL, NULL} -+}; -+/* }}} */ -+ -+/* {{{ module definition structure */ -+ -+zend_module_entry apc_module_entry = { -+ STANDARD_MODULE_HEADER, -+ "apc", -+ apc_functions, -+ PHP_MINIT(apc), -+ PHP_MSHUTDOWN(apc), -+ PHP_RINIT(apc), -+ PHP_RSHUTDOWN(apc), -+ PHP_MINFO(apc), -+ PHP_APC_VERSION, -+ STANDARD_MODULE_PROPERTIES -+}; -+ -+#ifdef COMPILE_DL_APC -+ZEND_GET_MODULE(apc) -+#endif -+/* }}} */ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/php_apc.h b/ext/apc/php_apc.h ---- a/ext/apc/php_apc.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/php_apc.h 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,54 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | APC | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2006-2011 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: Daniel Cowgill | -+ | George Schlossnagle | -+ | Rasmus Lerdorf | -+ +----------------------------------------------------------------------+ -+ -+ This software was contributed to PHP by Community Connect Inc. in 2002 -+ and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1. -+ Future revisions and derivatives of this source code must acknowledge -+ Community Connect Inc. as the original contributor of this module by -+ leaving this note intact in the source code. -+ -+ All other licensing and usage conditions are those of the PHP Group. -+ -+ */ -+ -+/* $Id: php_apc.h 326713 2012-07-19 22:07:31Z rasmus $ */ -+ -+#ifndef PHP_APC_H -+#define PHP_APC_H -+ -+#include "apc_php.h" -+#include "apc_globals.h" -+ -+#define PHP_APC_VERSION "3.1.11" -+ -+extern zend_module_entry apc_module_entry; -+#define apc_module_ptr &apc_module_entry -+ -+#define phpext_apc_ptr apc_module_ptr -+ -+#endif /* PHP_APC_H */ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker -+ * vim<600: expandtab sw=4 ts=4 sts=4 -+ */ -diff -Naur a/ext/apc/TECHNOTES.txt b/ext/apc/TECHNOTES.txt ---- a/ext/apc/TECHNOTES.txt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/TECHNOTES.txt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,361 @@ -+APC Quick-Start Braindump -+ -+This is a rapidly written braindump of how APC currently works in the -+form of a quick-start guide to start hacking on APC. -+ -+1. Install and use APC a bit so you know what it does from the end-user's -+ perspective. -+ user-space functions are all explained here: -+ -+2. Grab the current APC code from CVS: -+ -+ cvs -d:pserver:cvsread@cvs.php.net:/repository login -+ Password: phpfi -+ cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/apc -+ -+ apc/php_apc.c has most of the code for the user-visible stuff. It is -+ also a regular PHP extension in the sense that there are MINIT, MINFO, -+ MSHUTDOWN, RSHUTDOWN, etc. functions. -+ -+3. Build it. -+ -+ cd pecl/apc -+ phpize -+ ./configure --enable-apc --enable-mmap -+ make -+ cp modules/apc.so /usr/local/lib/php -+ apachectl restart -+ -+4. Debugging Hints -+ -+ apachectl stop -+ gdb /usr/bin/httpd -+ break ?? -+ run -X -+ -+ Grab the .gdbinit from the PHP source tree and have a look at the macros. -+ -+5. Look through apc/apc_sma.c -+ It is a pretty standard memory allocator. -+ -+ apc_sma_malloc, apc_sma_realloc, apc_sma_strdup and apc_sma_free behave to the -+ caller just like malloc, realloc, strdup and free -+ -+ On server startup the MINIT hook in php_apc.c calls apc_module_init() in -+ apc_main.c which in turn calls apc_sma_init(). apc_sma_init calls into -+ apc_mmap.c to mmap the specified sized segment (I tend to just use a single -+ segment). apc_mmap.c should be self-explanatory. It mmaps a temp file and -+ then unlinks that file right after the mmap to provide automatic shared memory -+ cleanup in case the process dies. -+ -+ Once the region has been initialized we stick a header_t at the beginning -+ of the region. It contains the total size in header->segsize and the number -+ of bytes available in header->avail. -+ -+ After the header comes a bit of a hack. A zero-sized block is inserted just -+ to make things easier later on. And then a huge block that is basically -+ the size of the entire segment minus the two (for the 0-sized block, and this one) -+ block headers. -+ -+ The code for this is: -+ -+ header = (header_t*) shmaddr; -+ header->segsize = sma_segsize; -+ header->avail = sma_segsize - sizeof(header_t) - sizeof(block_t) - alignword(sizeof(int)); -+ memset(&header->lock,0,sizeof(header->lock)); -+ sma_lock = &header->lock; -+ block = BLOCKAT(sizeof(header_t)); -+ block->size = 0; -+ block->next = sizeof(header_t) + sizeof(block_t); -+ block = BLOCKAT(block->next); -+ block->size = header->avail; -+ block->next = 0; -+ -+ So the shared memory looks like this: -+ -+ +--------+-------+---------------------------------+ -+ | header | block | block | -+ +--------+-------+---------------------------------+ -+ -+ sma_shmaddrs[0] gives you the address of header -+ -+ The blocks are just a simple offset-based linked list (so no pointers): -+ -+ typedef struct block_t block_t; -+ struct block_t { -+ size_t size; /* size of this block */ -+ size_t next; /* offset in segment of next free block */ -+ size_t canary; /* canary to check for memory overwrites */ -+#ifdef __APC_SMA_DEBUG__ -+ int id; /* identifier for the memory block */ -+#endif -+ }; -+ -+ The BLOCKAT macro turns an offset into an actual address for you: -+ -+ #define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset)) -+ -+ where shmaddr = sma_shaddrs[0] -+ -+ And the OFFSET macro goes the other way: -+ -+ #define OFFSET(block) ((int)(((char*)block) - (char*)shmaddr)) -+ -+ Allocating a block with a call to apc_sma_allocate() walks through the -+ linked list of blocks until it finds one that is >= to the requested size. -+ The first call to apc_sma_allocate() will hit the second block. We then -+ chop up that block so it looks like this: -+ -+ +--------+-------+-------+-------------------------+ -+ | header | block | block | block | -+ +--------+-------+-------+-------------------------+ -+ -+ Then we unlink that block from the linked list so it won't show up -+ as an available block on the next allocate. So we actually have: -+ -+ +--------+-------+ +-------------------------+ -+ | header | block |------>| block | -+ +--------+-------+ +-------------------------+ -+ -+ And header->avail along with block->size of the remaining large -+ block are updated accordingly. The arrow there representing the -+ link which now points to a block with an offset further along in -+ the segment. -+ -+ When the block is freed using apc_sma_deallocate() the steps are -+ basically just reversed. The block is put back and then the deallocate -+ code looks at the block before and after to see if the block immediately -+ before and after are free and if so the blocks are combined. So you never -+ have 2 free blocks next to each other, apart from at the front with that -+ 0-sized dummy block. This mostly prevents fragmentation. I have been -+ toying with the idea of always allocating block at 2^n boundaries to make -+ it more likely that they will be re-used to cut down on fragmentation further. -+ That's what the POWER_OF_TWO_BLOCKSIZE you see in apc_sma.c is all about. -+ -+ Of course, anytime we fiddle with our shared memory segment we lock using -+ the locking macros, LOCK() and UNLOCK(). -+ -+ That should mostly take care of the low-level shared memory handling. -+ -+6. Next up is apc_main.c and apc_cache.c which implement the meat of the -+ cache logic. -+ -+ The apc_main.c file mostly calls functions in apc_sma.c to allocate memory -+ and apc_cache.c for actual cache manipulation. -+ -+ After the shared memory segment is created and the caches are initialized, -+ apc_module_init() installs the my_compile_file() function overriding Zend's -+ version. I'll talk about my_compile_file() and the rest of apc_compile.c -+ in the next section. For now I will stick with apc_main.c and apc_cache.c -+ and talk about the actual caches. A cache consists of a block of shared -+ memory returned by apc_sma_allocate() via apc_sma_malloc(). You will -+ notice references to apc_emalloc(). apc_emalloc() is just a thin wrapper -+ around PHP's own emalloc() function which allocates per-process memory from -+ PHP's pool-based memory allocator. Don't confuse apc_emalloc() and -+ apc_sma_malloc() as the first is per-process and the second is shared memory. -+ -+ The cache is stored in/described by this struct allocated locally using -+ emalloc(): -+ -+ struct apc_cache_t { -+ void* shmaddr; /* process (local) address of shared cache */ -+ header_t* header; /* cache header (stored in SHM) */ -+ slot_t** slots; /* array of cache slots (stored in SHM) */ -+ int num_slots; /* number of slots in cache */ -+ int gc_ttl; /* maximum time on GC list for a slot */ -+ int ttl; /* if slot is needed and entry's access time is older than this ttl, remove it */ -+ }; -+ -+ Whenever you see functions that take a 'cache' argument, this is what they -+ take. And apc_cache_create() returns a pointer to this populated struct. -+ -+ At the beginning of the cache we have a header. Remember, we are down a level now -+ from the sma stuff. The sma stuff is the low-level shared-memory allocator which -+ has its own header which is completely separate and invisible to apc_cache.c. -+ As far as apc_cache.c is concerned the block of memory it is working with could -+ have come from a call to malloc(). -+ -+ The header looks like this: -+ -+ typedef struct header_t header_t; -+ struct header_t { -+ int num_hits; /* total successful hits in cache */ -+ int num_misses; /* total unsuccessful hits in cache */ -+ slot_t* deleted_list; /* linked list of to-be-deleted slots */ -+ }; -+ -+ Since this is at the start of the shared memory segment, these values are accessible -+ across all the apache processes and hence access to them has to be locked. -+ -+ After the header we have an array of slots. The number of slots is user-defined -+ through the apc.num_slots ini hint. Each slot is described by: -+ -+ typedef struct slot_t slot_t; -+ struct slot_t { -+ apc_cache_key_t key; /* slot key */ -+ apc_cache_entry_t* value; /* slot value */ -+ slot_t* next; /* next slot in linked list */ -+ int num_hits; /* number of hits to this bucket */ -+ time_t creation_time; /* time slot was initialized */ -+ time_t deletion_time; /* time slot was removed from cache */ -+ time_t access_time; /* time slot was last accessed */ -+ }; -+ -+ The slot_t *next there is a linked list to other slots that happened to hash to the -+ same array position. -+ -+ apc_cache_insert() shows what happens on a new cache insert. -+ -+ slot = &cache->slots[hash(key) % cache->num_slots]; -+ -+ cache->slots is our array of slots in the segment. hash() is simply: -+ -+ static unsigned int hash(apc_cache_key_t key) -+ { -+ return key.data.file.device + key.data.file.inode; -+ } -+ -+ That is, we use the file's device and inode to uniquely identify it. Initially -+ we had used the file's full path, but getting that requires a realpath() call which -+ is amazingly expensive since it has to stat each component of the path to resolve -+ symlinks and get rid of relative path components. By using the device+inode we -+ can uniquely identify a file with a single stat. -+ -+ So, on an insert we find the array position in the slots array by hashing the device+inode. -+ If there are currently no other slots there, we just create the slot and stick it into -+ the array: -+ -+ *slot = make_slot(key, value, *slot, t) -+ -+ If there are other slots already at this position we walk the link list to get to -+ the end. Here is the loop: -+ -+ while (*slot) { -+ if (key_equals((*slot)->key.data.file, key.data.file)) { -+ /* If existing slot for the same device+inode is different, remove it and insert the new version */ -+ if ((*slot)->key.mtime != key.mtime) { -+ remove_slot(cache, slot); -+ break; -+ } -+ UNLOCK(cache); -+ return 0; -+ } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) { -+ remove_slot(cache, slot); -+ continue; -+ } -+ slot = &(*slot)->next; -+ } -+ -+ That first key_equals() check sees if we have an exact match meaning the file -+ is already in the cache. Since we try to find the file in the cache before doing -+ an insert, this will generally only happen if another process managed to beat us -+ to inserting it. If we have a newer version of the file at this point we remove -+ it an insert the new version. If our version is not newer we just return without -+ doing anything. -+ -+ While walking the linked list we also check to see if the cache has a TTL defined. -+ If while walking the linked list we see a slot that has expired, we remove it -+ since we are right there looking at it. This is the only place we remove stale -+ entries unless the shared memory segment fills up and we force a full expunge via -+ apc_cache_expunge(). apc_cache_expunge() walks the entire slots array and walks -+ down every linked list removing stale slots to free up room. This is obviously -+ slow and thus only happens when we have run out of room. -+ -+ apc_cache_find() simply hashes and returns the entry if it is there. If it is there -+ but older than the mtime in the entry we are looking for, we delete the one that is -+ there and return indicating we didn't find it. -+ -+ Next we need to understand what an actual cache entry looks like. Have a look at -+ apc_cache.h for the structs. I sort of glossed over the key part earlier saying -+ that we just used the device+inode to find a hash slot. It is actually a bit more -+ complex than that because we have two kinds of caches. We have the standard file -+ cache containing opcode arrays, but we also have a user-controlled cache that the -+ user can insert whatever they want into via apc_store(). For the user cache we -+ obviously don't have a device+inode. The actual identifier is provided by the user -+ as a char *. So the key is actually a union that looks like this: -+ -+ typedef union _apc_cache_key_data_t { -+ struct { -+ int device; /* the filesystem device */ -+ int inode; /* the filesystem inode */ -+ } file; -+ struct { -+ char *identifier; -+ } user; -+ } apc_cache_key_data_t; -+ -+ struct apc_cache_key_t { -+ apc_cache_key_data_t data; -+ int mtime; /* the mtime of this cached entry */ -+ }; -+ -+ And we have two sets of functions to do inserts and finds. apc_cache_user_find() -+ and apc_cache_user_insert() operate on the user cache. -+ -+ Ok, on to the actual cache entry. Again, because we have two kinds of caches, we -+ also have the corresponding two kinds of cache entries described by this union: -+ -+ typedef union _apc_cache_entry_value_t { -+ struct { -+ char *filename; /* absolute path to source file */ -+ zend_op_array* op_array; /* op_array allocated in shared memory */ -+ apc_function_t* functions; /* array of apc_function_t's */ -+ apc_class_t* classes; /* array of apc_class_t's */ -+ } file; -+ struct { -+ char *info; -+ zval *val; -+ unsigned int ttl; -+ } user; -+ } apc_cache_entry_value_t; -+ -+ And then the actual cache entry: -+ -+ struct apc_cache_entry_t { -+ apc_cache_entry_value_t data; -+ unsigned char type; -+ int ref_count; -+ }; -+ -+ The user entry is pretty simple and not all that important for now. I will -+ concentrate on the file entries since that is what holds the actual compiled -+ opcode arrays along with the functions and classes required by the executor. -+ -+ apc_cache_make_file_entry() in apc_cache.c shows how an entry is constructed. -+ The main thing to understand here is that we need more than just the opcode -+ array, we also need the functions and classes created by the compiler when it -+ created the opcode array. As far as the executor is concerned, it doesn't know -+ that it isn't operating in normal mode being called right after the parse/compile -+ phase, so we need to recreate everything so it looks exactly like it would at -+ that point. -+ -+7. my_compile_file() and apc_compile.c -+ -+ my_compile_file() in apc_main.c controls where we get the opcodes from. If -+ the user-specified filters exclude the file from being cached, then we just -+ call the original compile function and return. Otherwise we fetch the request -+ time from Apache to avoid an extra syscall, create the key so we can look up -+ the file in the cache. If we find it we stick it on a local stack which we -+ use at cleanup time to make sure we return everything back to normal after a -+ request and call cached_compile() which installs the functions and classes -+ associated with the op_array in this entry and then copy the op_array down -+ into our memory space for execution. -+ -+ If we didn't find the file in the cache, we need to compile it and insert it. -+ To compile it we simply call the original compile function: -+ -+ op_array = old_compile_file(h, type TSRMLS_CC); -+ -+ To do the insert we need to copy the functions, classes and the opcode array -+ the compile phase created into shared memory. This all happens in apc_compile.c -+ in the apc_copy_op_array(), apc_copy_new_functions() and apc_copy_new_classes() -+ functions. Then we make the file entry and do the insert. Both of these -+ operations were described in the previous section. -+ -+8. The Optimizer -+ -+ The optimizer has been deprecated. -+ -+If you made it to the end of this, you should have a pretty good idea of where things are in -+the code. I skimmed over a lot of things, so plan on spending some time reading through the code. -+ -diff -Naur a/ext/apc/tests/apc_001.phpt b/ext/apc/tests/apc_001.phpt ---- a/ext/apc/tests/apc_001.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc_001.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,32 @@ -+--TEST-- -+APC: apc_store/fetch with strings -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+ -+===DONE=== -+ -+--EXPECTF-- -+string(11) "hello world" -+string(11) "hello world" -+string(4) "nice" -+string(11) "hello world" -+===DONE=== -diff -Naur a/ext/apc/tests/apc_002.phpt b/ext/apc/tests/apc_002.phpt ---- a/ext/apc/tests/apc_002.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc_002.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,34 @@ -+--TEST-- -+APC: apc_store/fetch with objects -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+a = true; -+var_dump($bar); -+ -+?> -+===DONE=== -+ -+--EXPECTF-- -+object(foo)#%d (0) { -+} -+object(foo)#%d (0) { -+} -+object(foo)#%d (1) { -+ ["a"]=> -+ bool(true) -+} -+===DONE=== -diff -Naur a/ext/apc/tests/apc_003b.phpt b/ext/apc/tests/apc_003b.phpt ---- a/ext/apc/tests/apc_003b.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc_003b.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,117 @@ -+--TEST-- -+APC: apc_store/fetch with objects (php 5.3) -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+a = true; -+var_dump($bar); -+ -+class bar extends foo -+{ -+ public $pub = 'bar'; -+ protected $pro = 'bar'; -+ private $pri = 'bar'; // we don't see this, we'd need php 5.1 new serialization -+ -+ function __construct() -+ { -+ $this->bar = true; -+ } -+ -+ function change() -+ { -+ $this->pri = 'mod'; -+ } -+} -+ -+class baz extends bar -+{ -+ private $pri = 'baz'; -+ -+ function __construct() -+ { -+ parent::__construct(); -+ $this->baz = true; -+ } -+} -+ -+$baz = new baz; -+var_dump($baz); -+$baz->change(); -+var_dump($baz); -+apc_store('baz', $baz); -+unset($baz); -+var_dump(apc_fetch('baz')); -+ -+?> -+===DONE=== -+ -+--EXPECTF-- -+object(foo)#%d (0) { -+} -+object(foo)#%d (0) { -+} -+object(foo)#%d (1) { -+ ["a"]=> -+ bool(true) -+} -+object(baz)#%d (6) { -+ ["pri":"baz":private]=> -+ string(3) "baz" -+ ["pub"]=> -+ string(3) "bar" -+ ["pro":protected]=> -+ string(3) "bar" -+ ["pri":"bar":private]=> -+ string(3) "bar" -+ ["bar"]=> -+ bool(true) -+ ["baz"]=> -+ bool(true) -+} -+object(baz)#%d (6) { -+ ["pri":"baz":private]=> -+ string(3) "baz" -+ ["pub"]=> -+ string(3) "bar" -+ ["pro":protected]=> -+ string(3) "bar" -+ ["pri":"bar":private]=> -+ string(3) "mod" -+ ["bar"]=> -+ bool(true) -+ ["baz"]=> -+ bool(true) -+} -+object(baz)#%d (6) { -+ ["pri":"baz":private]=> -+ string(3) "baz" -+ ["pub"]=> -+ string(3) "bar" -+ ["pro":protected]=> -+ string(3) "bar" -+ ["pri":"bar":private]=> -+ string(3) "mod" -+ ["bar"]=> -+ bool(true) -+ ["baz"]=> -+ bool(true) -+} -+===DONE=== -diff -Naur a/ext/apc/tests/apc_003.phpt b/ext/apc/tests/apc_003.phpt ---- a/ext/apc/tests/apc_003.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc_003.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,117 @@ -+--TEST-- -+APC: apc_store/fetch with objects (php pre-5.3) -+--SKIPIF-- -+= 0) { -+ echo "skip\n"; -+ } -+?> -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+a = true; -+var_dump($bar); -+ -+class bar extends foo -+{ -+ public $pub = 'bar'; -+ protected $pro = 'bar'; -+ private $pri = 'bar'; // we don't see this, we'd need php 5.1 new serialization -+ -+ function __construct() -+ { -+ $this->bar = true; -+ } -+ -+ function change() -+ { -+ $this->pri = 'mod'; -+ } -+} -+ -+class baz extends bar -+{ -+ private $pri = 'baz'; -+ -+ function __construct() -+ { -+ parent::__construct(); -+ $this->baz = true; -+ } -+} -+ -+$baz = new baz; -+var_dump($baz); -+$baz->change(); -+var_dump($baz); -+apc_store('baz', $baz); -+unset($baz); -+var_dump(apc_fetch('baz')); -+ -+?> -+===DONE=== -+ -+--EXPECTF-- -+object(foo)#%d (0) { -+} -+object(foo)#%d (0) { -+} -+object(foo)#%d (1) { -+ ["a"]=> -+ bool(true) -+} -+object(baz)#%d (6) { -+ ["pri:private"]=> -+ string(3) "baz" -+ ["pub"]=> -+ string(3) "bar" -+ ["pro:protected"]=> -+ string(3) "bar" -+ ["pri:private"]=> -+ string(3) "bar" -+ ["bar"]=> -+ bool(true) -+ ["baz"]=> -+ bool(true) -+} -+object(baz)#%d (6) { -+ ["pri:private"]=> -+ string(3) "baz" -+ ["pub"]=> -+ string(3) "bar" -+ ["pro:protected"]=> -+ string(3) "bar" -+ ["pri:private"]=> -+ string(3) "mod" -+ ["bar"]=> -+ bool(true) -+ ["baz"]=> -+ bool(true) -+} -+object(baz)#%d (6) { -+ ["pri:private"]=> -+ string(3) "baz" -+ ["pub"]=> -+ string(3) "bar" -+ ["pro:protected"]=> -+ string(3) "bar" -+ ["pri:private"]=> -+ string(3) "mod" -+ ["bar"]=> -+ bool(true) -+ ["baz"]=> -+ bool(true) -+} -+===DONE=== -diff -Naur a/ext/apc/tests/apc_004.phpt b/ext/apc/tests/apc_004.phpt ---- a/ext/apc/tests/apc_004.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc_004.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,38 @@ -+--TEST-- -+APC: apc_store/fetch with bools -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+ -+===DONE=== -+ -+--EXPECTF-- -+bool(false) -+bool(false) -+bool(false) -+bool(true) -+bool(false) -+bool(false) -+bool(false) -+===DONE=== -diff -Naur a/ext/apc/tests/apc_005.phpt b/ext/apc/tests/apc_005.phpt ---- a/ext/apc/tests/apc_005.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc_005.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,50 @@ -+--TEST-- -+APC: apc_store/fetch with arrays of objects -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+ -+===DONE=== -+ -+--EXPECTF-- -+array(2) { -+ [0]=> -+ object(stdClass)#1 (0) { -+ } -+ [1]=> -+ object(stdClass)#2 (0) { -+ } -+} -+array(2) { -+ [0]=> -+ object(stdClass)#1 (0) { -+ } -+ [1]=> -+ object(stdClass)#2 (0) { -+ } -+} -+array(2) { -+ [0]=> -+ object(stdClass)#3 (0) { -+ } -+ [1]=> -+ object(stdClass)#4 (0) { -+ } -+} -+===DONE=== -diff -Naur a/ext/apc/tests/apc_006.phpt b/ext/apc/tests/apc_006.phpt ---- a/ext/apc/tests/apc_006.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc_006.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,73 @@ -+--TEST-- -+APC: apc_store/fetch reference test -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+apc.serializer=default -+report_memleaks=0 -+--FILE-- -+ -+===DONE=== -+ -+--EXPECTF-- -+array(9) refcount(2){ -+ [0]=> -+ string(1) "a" refcount(1) -+ [1]=> -+ &array(1) refcount(2){ -+ [0]=> -+ string(1) "c" refcount(1) -+ } -+ [2]=> -+ &array(1) refcount(2){ -+ [0]=> -+ string(1) "c" refcount(1) -+ } -+ [3]=> -+ &string(1) "d" refcount(3) -+ [4]=> -+ &string(1) "d" refcount(3) -+ [5]=> -+ &string(1) "d" refcount(3) -+ [6]=> -+ string(1) "e" refcount(2) -+ [7]=> -+ string(1) "e" refcount(2) -+ [8]=> -+ &array(2) refcount(2){ -+ [0]=> -+ string(1) "f" refcount(1) -+ [1]=> -+ &array(2) refcount(2){ -+ [0]=> -+ string(1) "f" refcount(1) -+ [1]=> -+ *RECURSION* -+ } -+ } -+} -+===DONE=== -diff -Naur a/ext/apc/tests/apc_007.phpt b/ext/apc/tests/apc_007.phpt ---- a/ext/apc/tests/apc_007.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc_007.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,46 @@ -+--TEST-- -+APC: apc_inc/apc_dec test -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+ -+===DONE=== -+ -+--EXPECTF-- -+$foobar = 2 -+$foobar += 1 = 3 -+$foobar += 10 = 13 -+$foobar -= 1 = 12 -+$foobar -= 10 = 2 -+$f__bar += 1 = fail -+$perfection -= 1 = epic fail -+$foobar += 1 = 3 -+pass by ref success 1 -+$foobar -= 1 = 2 -+pass by ref success 1 -+===DONE=== -diff -Naur a/ext/apc/tests/apc_008.phpt b/ext/apc/tests/apc_008.phpt ---- a/ext/apc/tests/apc_008.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc_008.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,34 @@ -+--TEST-- -+APC: apc_cas test -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+ -+===DONE=== -+ -+--EXPECTF-- -+$foobar = 2 -+$foobar == 1 ? 2 : 1 = fail -+$foobar == 2 ? 1 : 2 = ok -+$foobar = 1 -+$f__bar == 1 ? 2 : 1 = fail -+$perfection == 2 ? 1 : 2 = epic fail -+$foobar = 1 -+===DONE=== -diff -Naur a/ext/apc/tests/apc_009.phpt b/ext/apc/tests/apc_009.phpt ---- a/ext/apc/tests/apc_009.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc_009.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,97 @@ -+--TEST-- -+APC: apc_delete_file test -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+apc.stat=On -+report_memleaks=0 -+--FILE-- -+ -+===DONE=== -+ -+--CLEAN-- -+ -+--EXPECTF-- -+apc_009.php Found File -+apc_009.php Not Found -+apc_009.php Not Found -+apc_009.php Not Found -+array(0) { -+} -+apc_009.php Found File -+apc_009-1.php Found File -+ -+Parse error: syntax error, unexpected '!' in %s/apc_009-2.php on line 1 -+ -+Warning: apc_compile_file(): Error compiling apc_009-2.php in apc_compile_file. in %s/apc_009.php on line 29 -+ -+Warning: apc_compile_file(): Error compiling nofile.php in apc_compile_file. in %s/apc_009.php on line 29 -+array(2) { -+ ["apc_009-2.php"]=> -+ int(-1) -+ ["nofile.php"]=> -+ int(-1) -+} -+apc_009.php Found File -+apc_009-1.php Found File -+apc_009-2.php Not Found -+nofile.php Not Found -+===DONE=== -diff -Naur a/ext/apc/tests/apc_010.phpt b/ext/apc/tests/apc_010.phpt ---- a/ext/apc/tests/apc_010.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc_010.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,83 @@ -+--TEST-- -+APC: apc_store/fetch/add with array of key/value pairs. -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+ -+===DONE=== -+ -+--EXPECTF-- -+array(0) { -+} -+array(4) { -+ ["key1"]=> -+ string(6) "value1" -+ ["key2"]=> -+ string(6) "value2" -+ ["key3"]=> -+ array(2) { -+ [0]=> -+ string(7) "value3a" -+ [1]=> -+ string(7) "value3b" -+ } -+ ["key4"]=> -+ int(4) -+} -+array(2) { -+ ["key1"]=> -+ string(6) "value1" -+ ["key3"]=> -+ array(2) { -+ [0]=> -+ string(7) "value3a" -+ [1]=> -+ string(7) "value3b" -+ } -+} -+array(2) { -+ ["key1"]=> -+ int(-1) -+ ["key3"]=> -+ int(-1) -+} -+array(4) { -+ ["key1"]=> -+ string(6) "value1" -+ ["key2"]=> -+ string(6) "value2" -+ ["key3"]=> -+ array(2) { -+ [0]=> -+ string(7) "value3a" -+ [1]=> -+ string(7) "value3b" -+ } -+ ["key4"]=> -+ int(4) -+} -+===DONE=== -diff -Naur a/ext/apc/tests/apc53_001.phpt b/ext/apc/tests/apc53_001.phpt ---- a/ext/apc/tests/apc53_001.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc53_001.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,33 @@ -+--TEST-- -+APC: classes with namespaces (php 5.3) -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+ -+===DONE=== -+ -+--EXPECTF-- -+object(Foo\Bar\Baz)#1 (3) { -+ ["i"]=> -+ int(1) -+ ["f":protected]=> -+ float(3.14) -+ ["s":"Foo\Bar\Baz":private]=> -+ string(11) "hello world" -+} -+===DONE=== -diff -Naur a/ext/apc/tests/apc53_002.phpt b/ext/apc/tests/apc53_002.phpt ---- a/ext/apc/tests/apc53_002.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc53_002.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,47 @@ -+--TEST-- -+APC: global spaces (php 5.3) -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+foo(); -+var_dump(Foo\Bar\sort()); -+?> -+===DONE=== -+ -+--EXPECTF-- -+array(4) { -+ [0]=> -+ int(1) -+ [1]=> -+ int(2) -+ [2]=> -+ int(3) -+ [3]=> -+ int(4) -+} -+array(4) { -+ [0]=> -+ int(1) -+ [1]=> -+ int(2) -+ [2]=> -+ int(3) -+ [3]=> -+ int(4) -+} -+string(8) "IT WORKS" -+===DONE=== -diff -Naur a/ext/apc/tests/apc53_003.phpt b/ext/apc/tests/apc53_003.phpt ---- a/ext/apc/tests/apc53_003.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc53_003.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,31 @@ -+--TEST-- -+APC: anonymous functions (php 5.3) -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+ -+===DONE=== -+ -+--EXPECTF-- -+Hello World -+Hello PHP -+===DONE=== -diff -Naur a/ext/apc/tests/apc53_004.phpt b/ext/apc/tests/apc53_004.phpt ---- a/ext/apc/tests/apc53_004.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc53_004.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,33 @@ -+--TEST-- -+APC: closures (php 5.3) -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+ -+===DONE=== -+ -+--EXPECTF-- -+double of 9 is 18 -+triple of 4 is 12 -+===DONE=== -diff -Naur a/ext/apc/tests/apc53_005.phpt b/ext/apc/tests/apc53_005.phpt ---- a/ext/apc/tests/apc53_005.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc53_005.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,35 @@ -+--TEST-- -+APC: goto (php 5.3) -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+ -+===DONE=== -+ -+--EXPECTF-- -+1 -+2 -+4 -+5 -+7 -+8 -+10 -+===DONE=== -diff -Naur a/ext/apc/tests/apc_bin_001.phpt b/ext/apc/tests/apc_bin_001.phpt ---- a/ext/apc/tests/apc_bin_001.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc_bin_001.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,24 @@ -+--TEST-- -+APC: bindump user cache -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+--FILE-- -+ -+===DONE=== -+ -+--EXPECTF-- -+bool(false) -+string(9) "testvalue" -+===DONE=== -diff -Naur a/ext/apc/tests/apc_bin_002-1.inc b/ext/apc/tests/apc_bin_002-1.inc ---- a/ext/apc/tests/apc_bin_002-1.inc 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc_bin_002-1.inc 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,42 @@ -+my_method()."\n"; -+echo "class static property: ".my_class::$my_static_property."\n"; -+echo "class dynamic property: ".$my_class->my_property."\n"; -+echo "class constant: ".my_class::my_constant."\n"; -+echo "\n"; -+echo "inherited class static method: ".my_i_class::my_static_method()."\n"; -+echo "inherited class dynamic method: ".$my_i_class->my_method()."\n"; -+echo "inherited class static property: ".my_i_class::$my_static_property."\n"; -+echo "inherited class dynamic property: ".$my_i_class->my_property."\n"; -+echo "inherited class constant: ".my_i_class::my_constant."\n"; -+echo "\n"; -+ -+ -+ -+function my_function() { return "Success"; } -+ -+ -+class my_class { -+ static $my_static_property = "Success"; -+ var $my_property = "Success"; -+ const my_constant = "Success"; -+ static function my_static_method() { return "Success"; } -+ function my_method() { return "Success"; } -+} -+ -+class my_i_class extends my_class { -+ function dummy() { return 1; } -+} -+ -diff -Naur a/ext/apc/tests/apc_bin_002-2.inc b/ext/apc/tests/apc_bin_002-2.inc ---- a/ext/apc/tests/apc_bin_002-2.inc 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc_bin_002-2.inc 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,5 @@ -+ -diff -Naur a/ext/apc/tests/apc_bin_002.phpt b/ext/apc/tests/apc_bin_002.phpt ---- a/ext/apc/tests/apc_bin_002.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/apc_bin_002.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,53 @@ -+--TEST-- -+APC: bindump file cache part 1 -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.stat=0 -+apc.cache_by_default=1 -+apc.filters= -+report_memleaks = Off -+--FILE-- -+ -+===DONE=== -+ -+--EXPECTF-- -+apc bindump 002 test -+ -+global scope execution: Success -+ -+function execution: Success -+ -+class static method: Success -+class dynamic method: Success -+class static property: Success -+class dynamic property: Success -+class constant: Success -+ -+inherited class static method: Success -+inherited class dynamic method: Success -+inherited class static property: Success -+inherited class dynamic property: Success -+inherited class constant: Success -+ -+===DONE=== -diff -Naur a/ext/apc/tests/iterator_001.phpt b/ext/apc/tests/iterator_001.phpt ---- a/ext/apc/tests/iterator_001.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/iterator_001.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,110 @@ -+--TEST-- -+APC: APCIterator general -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+$value) { -+ $vals[$key] = $value['key']; -+} -+ksort($vals); -+var_dump($vals); -+ -+?> -+===DONE=== -+ -+--EXPECT-- -+array(41) { -+ ["key0"]=> -+ string(4) "key0" -+ ["key1"]=> -+ string(4) "key1" -+ ["key10"]=> -+ string(5) "key10" -+ ["key11"]=> -+ string(5) "key11" -+ ["key12"]=> -+ string(5) "key12" -+ ["key13"]=> -+ string(5) "key13" -+ ["key14"]=> -+ string(5) "key14" -+ ["key15"]=> -+ string(5) "key15" -+ ["key16"]=> -+ string(5) "key16" -+ ["key17"]=> -+ string(5) "key17" -+ ["key18"]=> -+ string(5) "key18" -+ ["key19"]=> -+ string(5) "key19" -+ ["key2"]=> -+ string(4) "key2" -+ ["key20"]=> -+ string(5) "key20" -+ ["key21"]=> -+ string(5) "key21" -+ ["key22"]=> -+ string(5) "key22" -+ ["key23"]=> -+ string(5) "key23" -+ ["key24"]=> -+ string(5) "key24" -+ ["key25"]=> -+ string(5) "key25" -+ ["key26"]=> -+ string(5) "key26" -+ ["key27"]=> -+ string(5) "key27" -+ ["key28"]=> -+ string(5) "key28" -+ ["key29"]=> -+ string(5) "key29" -+ ["key3"]=> -+ string(4) "key3" -+ ["key30"]=> -+ string(5) "key30" -+ ["key31"]=> -+ string(5) "key31" -+ ["key32"]=> -+ string(5) "key32" -+ ["key33"]=> -+ string(5) "key33" -+ ["key34"]=> -+ string(5) "key34" -+ ["key35"]=> -+ string(5) "key35" -+ ["key36"]=> -+ string(5) "key36" -+ ["key37"]=> -+ string(5) "key37" -+ ["key38"]=> -+ string(5) "key38" -+ ["key39"]=> -+ string(5) "key39" -+ ["key4"]=> -+ string(4) "key4" -+ ["key40"]=> -+ string(5) "key40" -+ ["key5"]=> -+ string(4) "key5" -+ ["key6"]=> -+ string(4) "key6" -+ ["key7"]=> -+ string(4) "key7" -+ ["key8"]=> -+ string(4) "key8" -+ ["key9"]=> -+ string(4) "key9" -+} -+===DONE=== -diff -Naur a/ext/apc/tests/iterator_002.phpt b/ext/apc/tests/iterator_002.phpt ---- a/ext/apc/tests/iterator_002.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/iterator_002.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,36 @@ -+--TEST-- -+APC: APCIterator regex -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+$value) { -+ $vals[$key] = $value['key']; -+} -+ksort($vals); -+var_dump($vals); -+ -+?> -+===DONE=== -+ -+--EXPECT-- -+array(4) { -+ ["key10"]=> -+ string(5) "key10" -+ ["key20"]=> -+ string(5) "key20" -+ ["key30"]=> -+ string(5) "key30" -+ ["key40"]=> -+ string(5) "key40" -+} -+===DONE=== -diff -Naur a/ext/apc/tests/iterator_003.phpt b/ext/apc/tests/iterator_003.phpt ---- a/ext/apc/tests/iterator_003.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/iterator_003.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,110 @@ -+--TEST-- -+APC: APCIterator chunk size -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+$value) { -+ $vals[$key] = $value['key']; -+} -+ksort($vals); -+var_dump($vals); -+ -+?> -+===DONE=== -+ -+--EXPECT-- -+array(41) { -+ ["key0"]=> -+ string(4) "key0" -+ ["key1"]=> -+ string(4) "key1" -+ ["key10"]=> -+ string(5) "key10" -+ ["key11"]=> -+ string(5) "key11" -+ ["key12"]=> -+ string(5) "key12" -+ ["key13"]=> -+ string(5) "key13" -+ ["key14"]=> -+ string(5) "key14" -+ ["key15"]=> -+ string(5) "key15" -+ ["key16"]=> -+ string(5) "key16" -+ ["key17"]=> -+ string(5) "key17" -+ ["key18"]=> -+ string(5) "key18" -+ ["key19"]=> -+ string(5) "key19" -+ ["key2"]=> -+ string(4) "key2" -+ ["key20"]=> -+ string(5) "key20" -+ ["key21"]=> -+ string(5) "key21" -+ ["key22"]=> -+ string(5) "key22" -+ ["key23"]=> -+ string(5) "key23" -+ ["key24"]=> -+ string(5) "key24" -+ ["key25"]=> -+ string(5) "key25" -+ ["key26"]=> -+ string(5) "key26" -+ ["key27"]=> -+ string(5) "key27" -+ ["key28"]=> -+ string(5) "key28" -+ ["key29"]=> -+ string(5) "key29" -+ ["key3"]=> -+ string(4) "key3" -+ ["key30"]=> -+ string(5) "key30" -+ ["key31"]=> -+ string(5) "key31" -+ ["key32"]=> -+ string(5) "key32" -+ ["key33"]=> -+ string(5) "key33" -+ ["key34"]=> -+ string(5) "key34" -+ ["key35"]=> -+ string(5) "key35" -+ ["key36"]=> -+ string(5) "key36" -+ ["key37"]=> -+ string(5) "key37" -+ ["key38"]=> -+ string(5) "key38" -+ ["key39"]=> -+ string(5) "key39" -+ ["key4"]=> -+ string(4) "key4" -+ ["key40"]=> -+ string(5) "key40" -+ ["key5"]=> -+ string(4) "key5" -+ ["key6"]=> -+ string(4) "key6" -+ ["key7"]=> -+ string(4) "key7" -+ ["key8"]=> -+ string(4) "key8" -+ ["key9"]=> -+ string(4) "key9" -+} -+===DONE=== -diff -Naur a/ext/apc/tests/iterator_004.phpt b/ext/apc/tests/iterator_004.phpt ---- a/ext/apc/tests/iterator_004.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/iterator_004.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,36 @@ -+--TEST-- -+APC: APCIterator regex & chunk size & list -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+$value) { -+ $vals[$key] = $value['key']; -+} -+ksort($vals); -+var_dump($vals); -+ -+?> -+===DONE=== -+ -+--EXPECT-- -+array(4) { -+ ["key10"]=> -+ string(5) "key10" -+ ["key20"]=> -+ string(5) "key20" -+ ["key30"]=> -+ string(5) "key30" -+ ["key40"]=> -+ string(5) "key40" -+} -+===DONE=== -diff -Naur a/ext/apc/tests/iterator_005.phpt b/ext/apc/tests/iterator_005.phpt ---- a/ext/apc/tests/iterator_005.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/iterator_005.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,112 @@ -+--TEST-- -+APC: APCIterator delete -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+--FILE-- -+$value) { -+ $vals[$key] = $value['key']; -+} -+foreach($it2 as $key=>$value) { -+ $vals2[$key] = $value['key']; -+} -+ksort($vals2); -+var_dump($vals); -+var_dump($vals2); -+ -+?> -+===DONE=== -+ -+--EXPECT-- -+array(0) { -+} -+array(37) { -+ ["key0"]=> -+ string(4) "key0" -+ ["key1"]=> -+ string(4) "key1" -+ ["key11"]=> -+ string(5) "key11" -+ ["key12"]=> -+ string(5) "key12" -+ ["key13"]=> -+ string(5) "key13" -+ ["key14"]=> -+ string(5) "key14" -+ ["key15"]=> -+ string(5) "key15" -+ ["key16"]=> -+ string(5) "key16" -+ ["key17"]=> -+ string(5) "key17" -+ ["key18"]=> -+ string(5) "key18" -+ ["key19"]=> -+ string(5) "key19" -+ ["key2"]=> -+ string(4) "key2" -+ ["key21"]=> -+ string(5) "key21" -+ ["key22"]=> -+ string(5) "key22" -+ ["key23"]=> -+ string(5) "key23" -+ ["key24"]=> -+ string(5) "key24" -+ ["key25"]=> -+ string(5) "key25" -+ ["key26"]=> -+ string(5) "key26" -+ ["key27"]=> -+ string(5) "key27" -+ ["key28"]=> -+ string(5) "key28" -+ ["key29"]=> -+ string(5) "key29" -+ ["key3"]=> -+ string(4) "key3" -+ ["key31"]=> -+ string(5) "key31" -+ ["key32"]=> -+ string(5) "key32" -+ ["key33"]=> -+ string(5) "key33" -+ ["key34"]=> -+ string(5) "key34" -+ ["key35"]=> -+ string(5) "key35" -+ ["key36"]=> -+ string(5) "key36" -+ ["key37"]=> -+ string(5) "key37" -+ ["key38"]=> -+ string(5) "key38" -+ ["key39"]=> -+ string(5) "key39" -+ ["key4"]=> -+ string(4) "key4" -+ ["key5"]=> -+ string(4) "key5" -+ ["key6"]=> -+ string(4) "key6" -+ ["key7"]=> -+ string(4) "key7" -+ ["key8"]=> -+ string(4) "key8" -+ ["key9"]=> -+ string(4) "key9" -+} -+===DONE=== -diff -Naur a/ext/apc/tests/iterator_006.phpt b/ext/apc/tests/iterator_006.phpt ---- a/ext/apc/tests/iterator_006.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/iterator_006.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,1536 @@ -+--TEST-- -+APC: APCIterator formats -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+apc.file_update_protection=0 -+apc.user_entries_hint=4096 -+--FILE-- -+ $format) { -+ $it_array[$idx] = new APCIterator('user', NULL, $format); -+} -+ -+for($i = 0; $i < 11; $i++) { -+ apc_store("key$i", "value$i"); -+} -+ -+foreach ($it_array as $idx => $it) { -+ print_it($it, $idx); -+} -+ -+function print_it($it, $idx) { -+ echo "IT #$idx\n"; -+ echo "============================\n"; -+ foreach ($it as $key=>$value) { -+ var_dump($key); -+ var_dump($value); -+ } -+ echo "============================\n\n"; -+} -+ -+?> -+===DONE=== -+ -+--EXPECTF-- -+IT #0 -+============================ -+string(5) "key10" -+array(1) { -+ ["type"]=> -+ string(4) "user" -+} -+string(4) "key0" -+array(1) { -+ ["type"]=> -+ string(4) "user" -+} -+string(4) "key1" -+array(1) { -+ ["type"]=> -+ string(4) "user" -+} -+string(4) "key2" -+array(1) { -+ ["type"]=> -+ string(4) "user" -+} -+string(4) "key3" -+array(1) { -+ ["type"]=> -+ string(4) "user" -+} -+string(4) "key4" -+array(1) { -+ ["type"]=> -+ string(4) "user" -+} -+string(4) "key5" -+array(1) { -+ ["type"]=> -+ string(4) "user" -+} -+string(4) "key6" -+array(1) { -+ ["type"]=> -+ string(4) "user" -+} -+string(4) "key7" -+array(1) { -+ ["type"]=> -+ string(4) "user" -+} -+string(4) "key8" -+array(1) { -+ ["type"]=> -+ string(4) "user" -+} -+string(4) "key9" -+array(1) { -+ ["type"]=> -+ string(4) "user" -+} -+============================ -+ -+IT #1 -+============================ -+string(5) "key10" -+array(1) { -+ ["key"]=> -+ string(5) "key10" -+} -+string(4) "key0" -+array(1) { -+ ["key"]=> -+ string(4) "key0" -+} -+string(4) "key1" -+array(1) { -+ ["key"]=> -+ string(4) "key1" -+} -+string(4) "key2" -+array(1) { -+ ["key"]=> -+ string(4) "key2" -+} -+string(4) "key3" -+array(1) { -+ ["key"]=> -+ string(4) "key3" -+} -+string(4) "key4" -+array(1) { -+ ["key"]=> -+ string(4) "key4" -+} -+string(4) "key5" -+array(1) { -+ ["key"]=> -+ string(4) "key5" -+} -+string(4) "key6" -+array(1) { -+ ["key"]=> -+ string(4) "key6" -+} -+string(4) "key7" -+array(1) { -+ ["key"]=> -+ string(4) "key7" -+} -+string(4) "key8" -+array(1) { -+ ["key"]=> -+ string(4) "key8" -+} -+string(4) "key9" -+array(1) { -+ ["key"]=> -+ string(4) "key9" -+} -+============================ -+ -+IT #2 -+============================ -+string(5) "key10" -+array(0) { -+} -+string(4) "key0" -+array(0) { -+} -+string(4) "key1" -+array(0) { -+} -+string(4) "key2" -+array(0) { -+} -+string(4) "key3" -+array(0) { -+} -+string(4) "key4" -+array(0) { -+} -+string(4) "key5" -+array(0) { -+} -+string(4) "key6" -+array(0) { -+} -+string(4) "key7" -+array(0) { -+} -+string(4) "key8" -+array(0) { -+} -+string(4) "key9" -+array(0) { -+} -+============================ -+ -+IT #3 -+============================ -+string(5) "key10" -+array(0) { -+} -+string(4) "key0" -+array(0) { -+} -+string(4) "key1" -+array(0) { -+} -+string(4) "key2" -+array(0) { -+} -+string(4) "key3" -+array(0) { -+} -+string(4) "key4" -+array(0) { -+} -+string(4) "key5" -+array(0) { -+} -+string(4) "key6" -+array(0) { -+} -+string(4) "key7" -+array(0) { -+} -+string(4) "key8" -+array(0) { -+} -+string(4) "key9" -+array(0) { -+} -+============================ -+ -+IT #4 -+============================ -+string(5) "key10" -+array(0) { -+} -+string(4) "key0" -+array(0) { -+} -+string(4) "key1" -+array(0) { -+} -+string(4) "key2" -+array(0) { -+} -+string(4) "key3" -+array(0) { -+} -+string(4) "key4" -+array(0) { -+} -+string(4) "key5" -+array(0) { -+} -+string(4) "key6" -+array(0) { -+} -+string(4) "key7" -+array(0) { -+} -+string(4) "key8" -+array(0) { -+} -+string(4) "key9" -+array(0) { -+} -+============================ -+ -+IT #5 -+============================ -+string(5) "key10" -+array(1) { -+ ["value"]=> -+ string(7) "value10" -+} -+string(4) "key0" -+array(1) { -+ ["value"]=> -+ string(6) "value0" -+} -+string(4) "key1" -+array(1) { -+ ["value"]=> -+ string(6) "value1" -+} -+string(4) "key2" -+array(1) { -+ ["value"]=> -+ string(6) "value2" -+} -+string(4) "key3" -+array(1) { -+ ["value"]=> -+ string(6) "value3" -+} -+string(4) "key4" -+array(1) { -+ ["value"]=> -+ string(6) "value4" -+} -+string(4) "key5" -+array(1) { -+ ["value"]=> -+ string(6) "value5" -+} -+string(4) "key6" -+array(1) { -+ ["value"]=> -+ string(6) "value6" -+} -+string(4) "key7" -+array(1) { -+ ["value"]=> -+ string(6) "value7" -+} -+string(4) "key8" -+array(1) { -+ ["value"]=> -+ string(6) "value8" -+} -+string(4) "key9" -+array(1) { -+ ["value"]=> -+ string(6) "value9" -+} -+============================ -+ -+IT #6 -+============================ -+string(5) "key10" -+array(0) { -+} -+string(4) "key0" -+array(0) { -+} -+string(4) "key1" -+array(0) { -+} -+string(4) "key2" -+array(0) { -+} -+string(4) "key3" -+array(0) { -+} -+string(4) "key4" -+array(0) { -+} -+string(4) "key5" -+array(0) { -+} -+string(4) "key6" -+array(0) { -+} -+string(4) "key7" -+array(0) { -+} -+string(4) "key8" -+array(0) { -+} -+string(4) "key9" -+array(0) { -+} -+============================ -+ -+IT #7 -+============================ -+string(5) "key10" -+array(1) { -+ ["num_hits"]=> -+ int(0) -+} -+string(4) "key0" -+array(1) { -+ ["num_hits"]=> -+ int(0) -+} -+string(4) "key1" -+array(1) { -+ ["num_hits"]=> -+ int(0) -+} -+string(4) "key2" -+array(1) { -+ ["num_hits"]=> -+ int(0) -+} -+string(4) "key3" -+array(1) { -+ ["num_hits"]=> -+ int(0) -+} -+string(4) "key4" -+array(1) { -+ ["num_hits"]=> -+ int(0) -+} -+string(4) "key5" -+array(1) { -+ ["num_hits"]=> -+ int(0) -+} -+string(4) "key6" -+array(1) { -+ ["num_hits"]=> -+ int(0) -+} -+string(4) "key7" -+array(1) { -+ ["num_hits"]=> -+ int(0) -+} -+string(4) "key8" -+array(1) { -+ ["num_hits"]=> -+ int(0) -+} -+string(4) "key9" -+array(1) { -+ ["num_hits"]=> -+ int(0) -+} -+============================ -+ -+IT #8 -+============================ -+string(5) "key10" -+array(1) { -+ ["mtime"]=> -+ int(%d) -+} -+string(4) "key0" -+array(1) { -+ ["mtime"]=> -+ int(%d) -+} -+string(4) "key1" -+array(1) { -+ ["mtime"]=> -+ int(%d) -+} -+string(4) "key2" -+array(1) { -+ ["mtime"]=> -+ int(%d) -+} -+string(4) "key3" -+array(1) { -+ ["mtime"]=> -+ int(%d) -+} -+string(4) "key4" -+array(1) { -+ ["mtime"]=> -+ int(%d) -+} -+string(4) "key5" -+array(1) { -+ ["mtime"]=> -+ int(%d) -+} -+string(4) "key6" -+array(1) { -+ ["mtime"]=> -+ int(%d) -+} -+string(4) "key7" -+array(1) { -+ ["mtime"]=> -+ int(%d) -+} -+string(4) "key8" -+array(1) { -+ ["mtime"]=> -+ int(%d) -+} -+string(4) "key9" -+array(1) { -+ ["mtime"]=> -+ int(%d) -+} -+============================ -+ -+IT #9 -+============================ -+string(5) "key10" -+array(1) { -+ ["creation_time"]=> -+ int(%d) -+} -+string(4) "key0" -+array(1) { -+ ["creation_time"]=> -+ int(%d) -+} -+string(4) "key1" -+array(1) { -+ ["creation_time"]=> -+ int(%d) -+} -+string(4) "key2" -+array(1) { -+ ["creation_time"]=> -+ int(%d) -+} -+string(4) "key3" -+array(1) { -+ ["creation_time"]=> -+ int(%d) -+} -+string(4) "key4" -+array(1) { -+ ["creation_time"]=> -+ int(%d) -+} -+string(4) "key5" -+array(1) { -+ ["creation_time"]=> -+ int(%d) -+} -+string(4) "key6" -+array(1) { -+ ["creation_time"]=> -+ int(%d) -+} -+string(4) "key7" -+array(1) { -+ ["creation_time"]=> -+ int(%d) -+} -+string(4) "key8" -+array(1) { -+ ["creation_time"]=> -+ int(%d) -+} -+string(4) "key9" -+array(1) { -+ ["creation_time"]=> -+ int(%d) -+} -+============================ -+ -+IT #10 -+============================ -+string(5) "key10" -+array(1) { -+ ["deletion_time"]=> -+ int(0) -+} -+string(4) "key0" -+array(1) { -+ ["deletion_time"]=> -+ int(0) -+} -+string(4) "key1" -+array(1) { -+ ["deletion_time"]=> -+ int(0) -+} -+string(4) "key2" -+array(1) { -+ ["deletion_time"]=> -+ int(0) -+} -+string(4) "key3" -+array(1) { -+ ["deletion_time"]=> -+ int(0) -+} -+string(4) "key4" -+array(1) { -+ ["deletion_time"]=> -+ int(0) -+} -+string(4) "key5" -+array(1) { -+ ["deletion_time"]=> -+ int(0) -+} -+string(4) "key6" -+array(1) { -+ ["deletion_time"]=> -+ int(0) -+} -+string(4) "key7" -+array(1) { -+ ["deletion_time"]=> -+ int(0) -+} -+string(4) "key8" -+array(1) { -+ ["deletion_time"]=> -+ int(0) -+} -+string(4) "key9" -+array(1) { -+ ["deletion_time"]=> -+ int(0) -+} -+============================ -+ -+IT #11 -+============================ -+string(5) "key10" -+array(1) { -+ ["access_time"]=> -+ int(%d) -+} -+string(4) "key0" -+array(1) { -+ ["access_time"]=> -+ int(%d) -+} -+string(4) "key1" -+array(1) { -+ ["access_time"]=> -+ int(%d) -+} -+string(4) "key2" -+array(1) { -+ ["access_time"]=> -+ int(%d) -+} -+string(4) "key3" -+array(1) { -+ ["access_time"]=> -+ int(%d) -+} -+string(4) "key4" -+array(1) { -+ ["access_time"]=> -+ int(%d) -+} -+string(4) "key5" -+array(1) { -+ ["access_time"]=> -+ int(%d) -+} -+string(4) "key6" -+array(1) { -+ ["access_time"]=> -+ int(%d) -+} -+string(4) "key7" -+array(1) { -+ ["access_time"]=> -+ int(%d) -+} -+string(4) "key8" -+array(1) { -+ ["access_time"]=> -+ int(%d) -+} -+string(4) "key9" -+array(1) { -+ ["access_time"]=> -+ int(%d) -+} -+============================ -+ -+IT #12 -+============================ -+string(5) "key10" -+array(1) { -+ ["ref_count"]=> -+ int(0) -+} -+string(4) "key0" -+array(1) { -+ ["ref_count"]=> -+ int(0) -+} -+string(4) "key1" -+array(1) { -+ ["ref_count"]=> -+ int(0) -+} -+string(4) "key2" -+array(1) { -+ ["ref_count"]=> -+ int(0) -+} -+string(4) "key3" -+array(1) { -+ ["ref_count"]=> -+ int(0) -+} -+string(4) "key4" -+array(1) { -+ ["ref_count"]=> -+ int(0) -+} -+string(4) "key5" -+array(1) { -+ ["ref_count"]=> -+ int(0) -+} -+string(4) "key6" -+array(1) { -+ ["ref_count"]=> -+ int(0) -+} -+string(4) "key7" -+array(1) { -+ ["ref_count"]=> -+ int(0) -+} -+string(4) "key8" -+array(1) { -+ ["ref_count"]=> -+ int(0) -+} -+string(4) "key9" -+array(1) { -+ ["ref_count"]=> -+ int(0) -+} -+============================ -+ -+IT #13 -+============================ -+string(5) "key10" -+array(1) { -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key0" -+array(1) { -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key1" -+array(1) { -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key2" -+array(1) { -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key3" -+array(1) { -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key4" -+array(1) { -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key5" -+array(1) { -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key6" -+array(1) { -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key7" -+array(1) { -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key8" -+array(1) { -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key9" -+array(1) { -+ ["mem_size"]=> -+ int(%d) -+} -+============================ -+ -+IT #14 -+============================ -+string(5) "key10" -+array(1) { -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key0" -+array(1) { -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key1" -+array(1) { -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key2" -+array(1) { -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key3" -+array(1) { -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key4" -+array(1) { -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key5" -+array(1) { -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key6" -+array(1) { -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key7" -+array(1) { -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key8" -+array(1) { -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key9" -+array(1) { -+ ["ttl"]=> -+ int(0) -+} -+============================ -+ -+IT #15 -+============================ -+string(5) "key10" -+array(0) { -+} -+string(4) "key0" -+array(0) { -+} -+string(4) "key1" -+array(0) { -+} -+string(4) "key2" -+array(0) { -+} -+string(4) "key3" -+array(0) { -+} -+string(4) "key4" -+array(0) { -+} -+string(4) "key5" -+array(0) { -+} -+string(4) "key6" -+array(0) { -+} -+string(4) "key7" -+array(0) { -+} -+string(4) "key8" -+array(0) { -+} -+string(4) "key9" -+array(0) { -+} -+============================ -+ -+IT #16 -+============================ -+string(5) "key10" -+array(11) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(5) "key10" -+ ["value"]=> -+ string(7) "value10" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key0" -+array(11) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key0" -+ ["value"]=> -+ string(6) "value0" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key1" -+array(11) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key1" -+ ["value"]=> -+ string(6) "value1" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key2" -+array(11) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key2" -+ ["value"]=> -+ string(6) "value2" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key3" -+array(11) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key3" -+ ["value"]=> -+ string(6) "value3" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key4" -+array(11) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key4" -+ ["value"]=> -+ string(6) "value4" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key5" -+array(11) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key5" -+ ["value"]=> -+ string(6) "value5" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key6" -+array(11) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key6" -+ ["value"]=> -+ string(6) "value6" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key7" -+array(11) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key7" -+ ["value"]=> -+ string(6) "value7" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key8" -+array(11) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key8" -+ ["value"]=> -+ string(6) "value8" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+ ["ttl"]=> -+ int(0) -+} -+string(4) "key9" -+array(11) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key9" -+ ["value"]=> -+ string(6) "value9" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+ ["ttl"]=> -+ int(0) -+} -+============================ -+ -+IT #17 -+============================ -+string(5) "key10" -+array(10) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(5) "key10" -+ ["value"]=> -+ string(7) "value10" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key0" -+array(10) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key0" -+ ["value"]=> -+ string(6) "value0" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key1" -+array(10) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key1" -+ ["value"]=> -+ string(6) "value1" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key2" -+array(10) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key2" -+ ["value"]=> -+ string(6) "value2" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key3" -+array(10) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key3" -+ ["value"]=> -+ string(6) "value3" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key4" -+array(10) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key4" -+ ["value"]=> -+ string(6) "value4" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key5" -+array(10) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key5" -+ ["value"]=> -+ string(6) "value5" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key6" -+array(10) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key6" -+ ["value"]=> -+ string(6) "value6" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key7" -+array(10) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key7" -+ ["value"]=> -+ string(6) "value7" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key8" -+array(10) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key8" -+ ["value"]=> -+ string(6) "value8" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key9" -+array(10) { -+ ["type"]=> -+ string(4) "user" -+ ["key"]=> -+ string(4) "key9" -+ ["value"]=> -+ string(6) "value9" -+ ["num_hits"]=> -+ int(0) -+ ["mtime"]=> -+ int(%d) -+ ["creation_time"]=> -+ int(%d) -+ ["deletion_time"]=> -+ int(0) -+ ["access_time"]=> -+ int(%d) -+ ["ref_count"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+============================ -+ -+IT #18 -+============================ -+string(5) "key10" -+array(3) { -+ ["key"]=> -+ string(5) "key10" -+ ["num_hits"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key0" -+array(3) { -+ ["key"]=> -+ string(4) "key0" -+ ["num_hits"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key1" -+array(3) { -+ ["key"]=> -+ string(4) "key1" -+ ["num_hits"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key2" -+array(3) { -+ ["key"]=> -+ string(4) "key2" -+ ["num_hits"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key3" -+array(3) { -+ ["key"]=> -+ string(4) "key3" -+ ["num_hits"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key4" -+array(3) { -+ ["key"]=> -+ string(4) "key4" -+ ["num_hits"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key5" -+array(3) { -+ ["key"]=> -+ string(4) "key5" -+ ["num_hits"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key6" -+array(3) { -+ ["key"]=> -+ string(4) "key6" -+ ["num_hits"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key7" -+array(3) { -+ ["key"]=> -+ string(4) "key7" -+ ["num_hits"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key8" -+array(3) { -+ ["key"]=> -+ string(4) "key8" -+ ["num_hits"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+string(4) "key9" -+array(3) { -+ ["key"]=> -+ string(4) "key9" -+ ["num_hits"]=> -+ int(0) -+ ["mem_size"]=> -+ int(%d) -+} -+============================ -+ -+===DONE=== -diff -Naur a/ext/apc/tests/iterator_007.phpt b/ext/apc/tests/iterator_007.phpt ---- a/ext/apc/tests/iterator_007.phpt 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/iterator_007.phpt 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,36 @@ -+--TEST-- -+APC: APCIterator Overwriting the ctor -+--SKIPIF-- -+ -+--INI-- -+apc.enabled=1 -+apc.enable_cli=1 -+--FILE-- -+rewind(), -+ $obj->current(), -+ $obj->key(), -+ $obj->next(), -+ $obj->valid(), -+ $obj->getTotalHits(), -+ $obj->getTotalSize(), -+ $obj->getTotalCount(), -+ apc_delete($obj) -+); -+?> -+--EXPECTF-- -+bool(false) -+bool(false) -+bool(false) -+bool(false) -+bool(false) -+bool(false) -+bool(false) -+bool(false) -+bool(false) -+ -diff -Naur a/ext/apc/tests/php_5_3_ns.inc b/ext/apc/tests/php_5_3_ns.inc ---- a/ext/apc/tests/php_5_3_ns.inc 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/tests/php_5_3_ns.inc 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,18 @@ -+ -diff -Naur a/ext/apc/TODO b/ext/apc/TODO ---- a/ext/apc/TODO 1970-01-01 01:00:00.000000000 +0100 -+++ b/ext/apc/TODO 2012-07-20 00:10:35.000000000 +0200 -@@ -0,0 +1,35 @@ -+Known Bugs -+ -+1. Gallery2 doesn't work with PHP5+APC. There is something wrong -+ with the way methods are restored in some edge case I haven't -+ been able to figure out yet. -+ To reproduce install gallery2 and click down to an individual photo. -+ -+2. apc_store() probably needs some checks to skip trying to store -+ internal classes. Something along the lines of: -+ -+ if(Z_TYPE_P(val) == IS_OBJECT) { -+ zend_class_entry *ce = Z_OBJCE_P(val); -+ if(ce->type == ZEND_INTERNAL_CLASS) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot cache internal objects"); -+ RETURN_FALSE; -+ } -+ } -+ -+ in the apc_store() function in php_apc.c but I am wondering if it needs to do more -+ than that. -+ -+Windows -+ -+1. The following configurations (build arguments) have not been implemented yet -+ -+ (*) --enable-apc-mmap Memory mapping support -+ (*) --enable-apc-sem Semaphore locking support (FCNTL replacement) -+ (*) --enable-apc-phreadmutex Thread mutexes, while implemented we should probably rename the internals to thread -+ (*) --enable-apc-pthreadrwlocks Thread mutexes, read/write locking -+ -+2. Non-blocking locks is not supported either -+ -+3. Update fileinfo to support stat info in a more portable way (see PECL #17903) -+ -+4. Check whether the signal handling needs to be enabled, and if it makes sense on Windows -\ Kein Zeilenumbruch am Dateiende. diff --git a/lang/php5/patches/010-PECL-dio.patch b/lang/php5/patches/010-PECL-dio.patch deleted file mode 100644 index e3b22c4da..000000000 --- a/lang/php5/patches/010-PECL-dio.patch +++ /dev/null @@ -1,3546 +0,0 @@ ---- /dev/null -+++ b/ext/dio/config.m4 -@@ -0,0 +1,10 @@ -+dnl -+dnl $Id: config.m4 291957 2009-12-10 17:13:14Z cyberspice $ -+dnl -+ -+PHP_ARG_ENABLE(dio, whether to enable direct I/O support, -+[ --enable-dio Enable direct I/O support]) -+ -+if test "$PHP_DIO" != "no"; then -+ PHP_NEW_EXTENSION(dio, dio.c dio_common.c dio_posix.c dio_stream_wrappers.c, $ext_shared) -+fi ---- /dev/null -+++ b/ext/dio/dio.c -@@ -0,0 +1,871 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | PHP Version 5 | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 1997-2009 The PHP Group | -+ +----------------------------------------------------------------------+ -+ | This source file is subject to version 3.0 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_0.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. | -+ +----------------------------------------------------------------------+ -+ | Author: Sterling Hughes | -+ | Author: Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include "php.h" -+#include "php_ini.h" -+#include "ext/standard/info.h" -+ -+#include "php_dio.h" -+#include "php_dio_stream_wrappers.h" -+ -+#include -+#include -+ -+#ifdef HAVE_UNISTD_H -+#include -+#endif -+ -+#include -+#ifndef PHP_WIN32 -+#include -+#endif -+ -+/* e.g. IRIX does not have CRTSCTS */ -+#ifndef CRTSCTS -+# ifdef CNEW_RTSCTS -+# define CRTSCTS CNEW_RTSCTS -+# else -+# define CRTSCTS 0 -+# endif /* CNEW_RTSCTS */ -+#endif /* !CRTSCTS */ -+ -+/* -+ +----------------------------------------------------------------------+ -+ | DEPRECATED FUNCTIONALITY | -+ +----------------------------------------------------------------------+ -+ | The functions below are from the earlier DIO versions. They will | -+ | continue to be maintained but not extended. It is thoroughly | -+ | recommended that you should use either the stream wrappers or the | -+ | DIO classes in new code. - Melanie | -+ +----------------------------------------------------------------------+ -+ */ -+ -+#define le_fd_name "Direct I/O File Descriptor" -+static int le_fd; -+ -+static int new_php_fd(php_fd_t **f, int fd) -+{ -+ if (!(*f = malloc(sizeof(php_fd_t)))) { -+ return 0; -+ } -+ (*f)->fd = fd; -+ return 1; -+} -+ -+static void _dio_close_fd(zend_rsrc_list_entry *rsrc TSRMLS_DC) -+{ -+ php_fd_t *f = (php_fd_t *) rsrc->ptr; -+ if (f) { -+ close(f->fd); -+ free(f); -+ } -+} -+ -+/* {{{ proto resource dio_open(string filename, int flags[, int mode]) -+ Open a new filename with specified permissions of flags and creation permissions of mode */ -+PHP_FUNCTION(dio_open) -+{ -+ php_fd_t *f; -+ char *file_name; -+ int file_name_length; -+ long flags; -+ long mode = 0; -+ int fd; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|l", &file_name, &file_name_length, &flags, &mode) == FAILURE) { -+ return; -+ } -+ -+ if (php_check_open_basedir(file_name TSRMLS_CC) || DIO_SAFE_MODE_CHECK(file_name, "wb+")) { -+ RETURN_FALSE; -+ } -+ -+ if (ZEND_NUM_ARGS() == 3) { -+ fd = open(file_name, flags, mode); -+ } else { -+ fd = open(file_name, flags); -+ } -+ -+ if (fd == -1) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot open file %s with flags %ld and permissions %ld: %s", file_name, flags, mode, strerror(errno)); -+ RETURN_FALSE; -+ } -+ -+ if (!new_php_fd(&f, fd)) { -+ RETURN_FALSE; -+ } -+ -+ ZEND_REGISTER_RESOURCE(return_value, f, le_fd); -+} -+/* }}} */ -+ -+#ifndef PHP_WIN32 -+ -+/* {{{ proto resource dio_fdopen(int fd) -+ Returns a resource for the specified file descriptor. */ -+PHP_FUNCTION(dio_fdopen) -+{ -+ php_fd_t *f; -+ long lfd; -+ int fd; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &lfd) == FAILURE) { -+ return; -+ } -+ -+ fd = (int)lfd; -+ -+ if ((fcntl(fd, F_GETFL, 0) == -1) && (errno == EBADF)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad file descriptor %d", fd); -+ RETURN_FALSE; -+ } -+ -+ if (!new_php_fd(&f, fd)) { -+ RETURN_FALSE; -+ } -+ -+ ZEND_REGISTER_RESOURCE(return_value, f, le_fd); -+} -+/* }}} */ -+ -+ -+/* {{{ proto resource dio_dup(resource fd) -+ Opens a duplicate of the specified open resource. */ -+PHP_FUNCTION(dio_dup) -+{ -+ zval *r_fd; -+ php_fd_t *f, *df; -+ int dfd; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &r_fd) == FAILURE) { -+ return; -+ } -+ -+ ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); -+ -+ dfd = dup(f->fd); -+ if (dfd == -1) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot duplication file descriptor %d: %s", f->fd, strerror(errno)); -+ RETURN_FALSE; -+ } -+ -+ if (!new_php_fd(&df, dfd)) { -+ RETURN_FALSE; -+ } -+ -+ ZEND_REGISTER_RESOURCE(return_value, df, le_fd); -+} -+/* }}} */ -+#endif -+ -+/* {{{ proto string dio_read(resource fd[, int n]) -+ Read n bytes from fd and return them, if n is not specified, read 1k */ -+PHP_FUNCTION(dio_read) -+{ -+ zval *r_fd; -+ php_fd_t *f; -+ char *data; -+ long bytes = 1024; -+ ssize_t res; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &r_fd, &bytes) == FAILURE) { -+ return; -+ } -+ -+ ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); -+ -+ if (bytes <= 0) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0."); -+ RETURN_FALSE; -+ } -+ -+ data = emalloc(bytes + 1); -+ res = read(f->fd, data, bytes); -+ if (res <= 0) { -+ efree(data); -+ RETURN_NULL(); -+ } -+ -+ data = erealloc(data, res + 1); -+ data[res] = 0; -+ -+ RETURN_STRINGL(data, res, 0); -+} -+/* }}} */ -+ -+/* {{{ proto int dio_write(resource fd, string data[, int len]) -+ Write data to fd with optional truncation at length */ -+PHP_FUNCTION(dio_write) -+{ -+ zval *r_fd; -+ php_fd_t *f; -+ char *data; -+ int data_len; -+ long trunc_len = 0; -+ ssize_t res; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &r_fd, &data, &data_len, &trunc_len) == FAILURE) { -+ return; -+ } -+ -+ if (trunc_len < 0 || trunc_len > data_len) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "length must be greater or equal to zero and less then the length of the specified string."); -+ RETURN_FALSE; -+ } -+ -+ ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); -+ -+ res = write(f->fd, data, trunc_len ? trunc_len : data_len); -+ if (res == -1) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot write data to file descriptor %d: %s", f->fd, strerror(errno)); -+ } -+ -+ RETURN_LONG(res); -+} -+/* }}} */ -+ -+#ifndef PHP_WIN32 -+ -+/* {{{ proto bool dio_truncate(resource fd, int offset) -+ Truncate file descriptor fd to offset bytes */ -+PHP_FUNCTION(dio_truncate) -+{ -+ zval *r_fd; -+ php_fd_t *f; -+ long offset; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &r_fd, &offset) == FAILURE) { -+ return; -+ } -+ -+ ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); -+ -+ if (ftruncate(f->fd, offset) == -1) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "couldn't truncate %d to %ld bytes: %s", f->fd, offset, strerror(errno)); -+ RETURN_FALSE; -+ } -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+#endif -+ -+#define ADD_FIELD(f, v) add_assoc_long_ex(return_value, (f), sizeof(f), v); -+ -+/* {{{ proto array dio_stat(resource fd) -+ Get stat information about the file descriptor fd */ -+PHP_FUNCTION(dio_stat) -+{ -+ zval *r_fd; -+ php_fd_t *f; -+ struct stat s; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &r_fd) == FAILURE) { -+ return; -+ } -+ -+ ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); -+ -+ if (fstat(f->fd, &s) == -1) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot stat %d: %s", f->fd, strerror(errno)); -+ RETURN_FALSE; -+ } -+ -+ array_init(return_value); -+ ADD_FIELD("device", s.st_dev); -+ ADD_FIELD("inode", s.st_ino); -+ ADD_FIELD("mode", s.st_mode); -+ ADD_FIELD("nlink", s.st_nlink); -+ ADD_FIELD("uid", s.st_uid); -+ ADD_FIELD("gid", s.st_gid); -+ ADD_FIELD("device_type", s.st_rdev); -+ ADD_FIELD("size", s.st_size); -+#ifndef PHP_WIN32 -+ ADD_FIELD("block_size", s.st_blksize); -+ ADD_FIELD("blocks", s.st_blocks); -+#endif -+ ADD_FIELD("atime", s.st_atime); -+ ADD_FIELD("mtime", s.st_mtime); -+ ADD_FIELD("ctime", s.st_ctime); -+} -+/* }}} */ -+ -+/* {{{ proto int dio_seek(resource fd, int pos, int whence) -+ Seek to pos on fd from whence */ -+PHP_FUNCTION(dio_seek) -+{ -+ zval *r_fd; -+ php_fd_t *f; -+ long offset; -+ long whence = SEEK_SET; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|l", &r_fd, &offset, &whence) == FAILURE) { -+ return; -+ } -+ -+ ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); -+ -+ RETURN_LONG(lseek(f->fd, offset, whence)); -+} -+/* }}} */ -+ -+#ifndef PHP_WIN32 -+ -+/* {{{ proto mixed dio_fcntl(resource fd, int cmd[, mixed arg]) -+ Perform a c library fcntl on fd */ -+PHP_FUNCTION(dio_fcntl) -+{ -+ zval *r_fd; -+ zval *arg = NULL; -+ php_fd_t *f; -+ long cmd; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|z", &r_fd, &cmd, &arg) == FAILURE) { -+ return; -+ } -+ -+ ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); -+ -+ switch (cmd) { -+ case F_SETLK: -+ case F_SETLKW: { -+ zval **element; -+ struct flock lk = {0}; -+ HashTable *fh; -+ -+ if (!arg) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "expects argument 3 to be array or int, none given"); -+ RETURN_FALSE; -+ } -+ if (Z_TYPE_P(arg) == IS_ARRAY) { -+ fh = HASH_OF(arg); -+ if (zend_hash_find(fh, "start", sizeof("start"), (void **) &element) == FAILURE) { -+ lk.l_start = 0; -+ } else { -+ lk.l_start = Z_LVAL_PP(element); -+ } -+ -+ if (zend_hash_find(fh, "length", sizeof("length"), (void **) &element) == FAILURE) { -+ lk.l_len = 0; -+ } else { -+ lk.l_len = Z_LVAL_PP(element); -+ } -+ -+ if (zend_hash_find(fh, "whence", sizeof("whence"), (void **) &element) == FAILURE) { -+ lk.l_whence = 0; -+ } else { -+ lk.l_whence = Z_LVAL_PP(element); -+ } -+ -+ if (zend_hash_find(fh, "type", sizeof("type"), (void **) &element) == FAILURE) { -+ lk.l_type = 0; -+ } else { -+ lk.l_type = Z_LVAL_PP(element); -+ } -+ } else if (Z_TYPE_P(arg) == IS_LONG) { -+ lk.l_start = 0; -+ lk.l_len = 0; -+ lk.l_whence = SEEK_SET; -+ lk.l_type = Z_LVAL_P(arg); -+ } else { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "expects argument 3 to be array or int, %s given", zend_zval_type_name(arg)); -+ RETURN_FALSE; -+ } -+ -+ RETURN_LONG(fcntl(f->fd, cmd, &lk)); -+ break; -+ } -+ case F_GETLK: { -+ struct flock lk = {0}; -+ -+ fcntl(f->fd, cmd, &lk); -+ -+ array_init(return_value); -+ add_assoc_long(return_value, "type", lk.l_type); -+ add_assoc_long(return_value, "whence", lk.l_whence); -+ add_assoc_long(return_value, "start", lk.l_start); -+ add_assoc_long(return_value, "length", lk.l_len); -+ add_assoc_long(return_value, "pid", lk.l_pid); -+ -+ break; -+ } -+ case F_DUPFD: { -+ php_fd_t *new_f; -+ -+ if (!arg || Z_TYPE_P(arg) != IS_LONG) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "expects argument 3 to be int"); -+ RETURN_FALSE; -+ } -+ -+ if (!new_php_fd(&new_f, fcntl(f->fd, cmd, Z_LVAL_P(arg)))) { -+ RETURN_FALSE; -+ } -+ ZEND_REGISTER_RESOURCE(return_value, new_f, le_fd); -+ break; -+ } -+ default: -+ if (!arg || Z_TYPE_P(arg) != IS_LONG) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "expects argument 3 to be int"); -+ RETURN_FALSE; -+ } -+ -+ RETURN_LONG(fcntl(f->fd, cmd, Z_LVAL_P(arg))); -+ } -+} -+/* }}} */ -+#endif -+ -+#ifndef PHP_WIN32 -+ -+/* {{{ proto mixed dio_tcsetattr(resource fd, array args ) -+ Perform a c library tcsetattr on fd */ -+PHP_FUNCTION(dio_tcsetattr) -+{ -+ zval *r_fd; -+ zval *arg = NULL; -+ php_fd_t *f; -+ struct termios newtio; -+ int Baud_Rate, Data_Bits=8, Stop_Bits=1, Parity=0, Flow_Control=1, Is_Canonical=1; -+ long BAUD,DATABITS,STOPBITS,PARITYON,PARITY; -+ HashTable *fh; -+ zval **element; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &r_fd, &arg) == FAILURE) { -+ return; -+ } -+ -+ ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); -+ -+ if (Z_TYPE_P(arg) != IS_ARRAY) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING,"tcsetattr, third argument should be an associative array"); -+ return; -+ } -+ -+ fh = HASH_OF(arg); -+ -+ if (zend_hash_find(fh, "baud", sizeof("baud"), (void **) &element) == FAILURE) { -+ Baud_Rate = 9600; -+ } else { -+ Baud_Rate = Z_LVAL_PP(element); -+ } -+ -+ if (zend_hash_find(fh, "bits", sizeof("bits"), (void **) &element) == FAILURE) { -+ Data_Bits = 8; -+ } else { -+ Data_Bits = Z_LVAL_PP(element); -+ } -+ -+ if (zend_hash_find(fh, "stop", sizeof("stop"), (void **) &element) == FAILURE) { -+ Stop_Bits = 1; -+ } else { -+ Stop_Bits = Z_LVAL_PP(element); -+ } -+ -+ if (zend_hash_find(fh, "parity", sizeof("parity"), (void **) &element) == FAILURE) { -+ Parity = 0; -+ } else { -+ Parity = Z_LVAL_PP(element); -+ } -+ -+ if (zend_hash_find(fh, "flow_control", sizeof("flow_control"), (void **) &element) == FAILURE) { -+ Flow_Control = 1; -+ } else { -+ Flow_Control = Z_LVAL_PP(element); -+ } -+ -+ if (zend_hash_find(fh, "is_canonical", sizeof("is_canonical"), (void **) &element) == FAILURE) { -+ Is_Canonical = 0; -+ } else { -+ Is_Canonical = Z_LVAL_PP(element); -+ } -+ -+ /* assign to correct values... */ -+ switch (Baud_Rate) { -+ case 38400: -+ BAUD = B38400; -+ break; -+ case 19200: -+ BAUD = B19200; -+ break; -+ case 9600: -+ BAUD = B9600; -+ break; -+ case 4800: -+ BAUD = B4800; -+ break; -+ case 2400: -+ BAUD = B2400; -+ break; -+ case 1800: -+ BAUD = B1800; -+ break; -+ case 1200: -+ BAUD = B1200; -+ break; -+ case 600: -+ BAUD = B600; -+ break; -+ case 300: -+ BAUD = B300; -+ break; -+ case 200: -+ BAUD = B200; -+ break; -+ case 150: -+ BAUD = B150; -+ break; -+ case 134: -+ BAUD = B134; -+ break; -+ case 110: -+ BAUD = B110; -+ break; -+ case 75: -+ BAUD = B75; -+ break; -+ case 50: -+ BAUD = B50; -+ break; -+ default: -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid baud rate %d", Baud_Rate); -+ RETURN_FALSE; -+ } -+ switch (Data_Bits) { -+ case 8: -+ DATABITS = CS8; -+ break; -+ case 7: -+ DATABITS = CS7; -+ break; -+ case 6: -+ DATABITS = CS6; -+ break; -+ case 5: -+ DATABITS = CS5; -+ break; -+ default: -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data bits %d", Data_Bits); -+ RETURN_FALSE; -+ } -+ switch (Stop_Bits) { -+ case 1: -+ STOPBITS = 0; -+ break; -+ case 2: -+ STOPBITS = CSTOPB; -+ break; -+ default: -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid stop bits %d", Stop_Bits); -+ RETURN_FALSE; -+ } -+ -+ switch (Parity) { -+ case 0: -+ PARITYON = 0; -+ PARITY = 0; -+ break; -+ case 1: -+ PARITYON = PARENB; -+ PARITY = PARODD; -+ break; -+ case 2: -+ PARITYON = PARENB; -+ PARITY = 0; -+ break; -+ default: -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid parity %d", Parity); -+ RETURN_FALSE; -+ } -+ -+ memset(&newtio, 0, sizeof(newtio)); -+ tcgetattr(f->fd, &newtio); -+ -+ if (Is_Canonical) { -+ newtio.c_iflag = IGNPAR | ICRNL; -+ newtio.c_oflag = 0; -+ newtio.c_lflag = ICANON; -+ } else { -+ cfmakeraw(&newtio); -+ } -+ -+ newtio.c_cflag = BAUD | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD; -+ -+#ifdef CRTSCTS -+ if (Flow_Control) { -+ newtio.c_cflag |= CRTSCTS; -+ } -+#endif -+ -+ if (Is_Canonical) -+ -+ newtio.c_cc[VMIN] = 1; -+ newtio.c_cc[VTIME] = 0; -+ tcflush(f->fd, TCIFLUSH); -+ tcsetattr(f->fd,TCSANOW,&newtio); -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+#endif -+ -+/* {{{ proto void dio_close(resource fd) -+ Close the file descriptor given by fd */ -+PHP_FUNCTION(dio_close) -+{ -+ zval *r_fd; -+ php_fd_t *f; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &r_fd) == FAILURE) { -+ return; -+ } -+ -+ ZEND_FETCH_RESOURCE(f, php_fd_t *, &r_fd, -1, le_fd_name, le_fd); -+ -+ zend_list_delete(Z_LVAL_P(r_fd)); -+} -+/* }}} */ -+ -+#define RDIOC(c) REGISTER_LONG_CONSTANT(#c, c, CONST_CS | CONST_PERSISTENT) -+ -+/* {{{ dio_init_legacy_defines -+ * Initialises the legacy PHP defines -+ */ -+static void dio_init_legacy_defines(int module_number TSRMLS_DC) { -+ RDIOC(O_RDONLY); -+ RDIOC(O_WRONLY); -+ RDIOC(O_RDWR); -+ RDIOC(O_CREAT); -+ RDIOC(O_EXCL); -+ RDIOC(O_TRUNC); -+ RDIOC(O_APPEND); -+#ifdef O_NONBLOCK -+ RDIOC(O_NONBLOCK); -+#endif -+#ifdef O_NDELAY -+ RDIOC(O_NDELAY); -+#endif -+#ifdef O_SYNC -+ RDIOC(O_SYNC); -+#endif -+#ifdef O_ASYNC -+ RDIOC(O_ASYNC); -+#endif -+#ifdef O_NOCTTY -+ RDIOC(O_NOCTTY); -+#endif -+#ifndef PHP_WIN32 -+ RDIOC(S_IRWXU); -+ RDIOC(S_IRUSR); -+ RDIOC(S_IWUSR); -+ RDIOC(S_IXUSR); -+ RDIOC(S_IRWXG); -+ RDIOC(S_IRGRP); -+ RDIOC(S_IWGRP); -+ RDIOC(S_IXGRP); -+ RDIOC(S_IRWXO); -+ RDIOC(S_IROTH); -+ RDIOC(S_IWOTH); -+ RDIOC(S_IXOTH); -+ RDIOC(F_DUPFD); -+ RDIOC(F_GETFD); -+ RDIOC(F_GETFL); -+ RDIOC(F_SETFL); -+ RDIOC(F_GETLK); -+ RDIOC(F_SETLK); -+ RDIOC(F_SETLKW); -+ RDIOC(F_SETOWN); -+ RDIOC(F_GETOWN); -+ RDIOC(F_UNLCK); -+ RDIOC(F_RDLCK); -+ RDIOC(F_WRLCK); -+#endif -+} -+ -+ZEND_BEGIN_ARG_INFO_EX(dio_open_args, 0, 0, 2) -+ ZEND_ARG_INFO(0, filename) -+ ZEND_ARG_INFO(0, flags) -+ ZEND_ARG_INFO(0, mode) -+ZEND_END_ARG_INFO() -+ -+ZEND_BEGIN_ARG_INFO_EX(dio_fdopen_args, 0, 0, 1) -+ ZEND_ARG_INFO(0, fd) -+ZEND_END_ARG_INFO() -+ -+ZEND_BEGIN_ARG_INFO_EX(dio_dup_args, 0, 0, 1) -+ ZEND_ARG_INFO(0, fd) -+ZEND_END_ARG_INFO() -+ -+ -+ZEND_BEGIN_ARG_INFO_EX(dio_read_args, 0, 0, 1) -+ ZEND_ARG_INFO(0, fd) -+ ZEND_ARG_INFO(0, n) -+ZEND_END_ARG_INFO() -+ -+ZEND_BEGIN_ARG_INFO_EX(dio_write_args, 0, 0, 2) -+ ZEND_ARG_INFO(0, fd) -+ ZEND_ARG_INFO(0, data) -+ ZEND_ARG_INFO(0, len) -+ZEND_END_ARG_INFO() -+ -+ZEND_BEGIN_ARG_INFO_EX(dio_stat_args, 0, 0, 1) -+ ZEND_ARG_INFO(0, fd) -+ZEND_END_ARG_INFO() -+ -+ZEND_BEGIN_ARG_INFO_EX(dio_truncate_args, 0, 0, 2) -+ ZEND_ARG_INFO(0, fd) -+ ZEND_ARG_INFO(0, offset) -+ZEND_END_ARG_INFO() -+ -+ZEND_BEGIN_ARG_INFO_EX(dio_seek_args, 0, 0, 3) -+ ZEND_ARG_INFO(0, fd) -+ ZEND_ARG_INFO(0, pos) -+ ZEND_ARG_INFO(0, whence) -+ZEND_END_ARG_INFO() -+ -+ZEND_BEGIN_ARG_INFO_EX(dio_fcntl_args, 0, 0, 2) -+ ZEND_ARG_INFO(0, fd) -+ ZEND_ARG_INFO(0, cmd) -+ ZEND_ARG_INFO(0, arg) -+ZEND_END_ARG_INFO() -+ -+ZEND_BEGIN_ARG_INFO_EX(dio_tcsetattr_args, 0, 0, 2) -+ ZEND_ARG_INFO(0, fd) -+ ZEND_ARG_INFO(0, args) -+ZEND_END_ARG_INFO() -+ -+ZEND_BEGIN_ARG_INFO_EX(dio_close_args, 0, 0, 1) -+ ZEND_ARG_INFO(0, fd) -+ZEND_END_ARG_INFO() -+ -+/* -+ +----------------------------------------------------------------------+ -+ | END OF DEPRECATED FUNCTIONALITY | -+ +----------------------------------------------------------------------+ -+ */ -+ -+ZEND_BEGIN_ARG_INFO_EX(dio_raw_args, 0, 0, 2) -+ ZEND_ARG_INFO(0, filename) -+ ZEND_ARG_INFO(0, mode) -+ ZEND_ARG_INFO(0, options) -+ZEND_END_ARG_INFO() -+ -+ZEND_BEGIN_ARG_INFO_EX(dio_serial_args, 0, 0, 2) -+ ZEND_ARG_INFO(0, filename) -+ ZEND_ARG_INFO(0, mode) -+ ZEND_ARG_INFO(0, options) -+ZEND_END_ARG_INFO() -+ -+static zend_object_handlers dio_raw_object_handlers; -+ -+static zend_function_entry dio_functions[] = { -+ /* Class functions. */ -+ -+ /* Legacy functions (Deprecated - See dio_legacy.c) */ -+ PHP_FE(dio_open, dio_open_args) -+#ifndef PHP_WIN32 -+ PHP_FE(dio_fdopen, dio_fdopen_args) -+ PHP_FE(dio_dup, dio_dup_args) -+ PHP_FE(dio_truncate, dio_truncate_args) -+#endif -+ PHP_FE(dio_stat, dio_stat_args) -+ PHP_FE(dio_seek, dio_seek_args) -+#ifndef PHP_WIN32 -+ PHP_FE(dio_fcntl, dio_fcntl_args) -+#endif -+ PHP_FE(dio_read, dio_read_args) -+ PHP_FE(dio_write, dio_write_args) -+ PHP_FE(dio_close, dio_close_args) -+#ifndef PHP_WIN32 -+ PHP_FE(dio_tcsetattr, dio_tcsetattr_args) -+#endif -+ -+ /* Stream functions */ -+ PHP_FE(dio_raw, dio_raw_args) -+ PHP_FE(dio_serial, dio_serial_args) -+ -+ /* End of functions */ -+ {NULL, NULL, NULL} -+}; -+ -+zend_module_entry dio_module_entry = { -+ STANDARD_MODULE_HEADER, -+ "dio", -+ dio_functions, -+ PHP_MINIT(dio), -+ NULL, -+ NULL, -+ NULL, -+ PHP_MINFO(dio), -+ PHP_DIO_VERSION, -+ STANDARD_MODULE_PROPERTIES -+}; -+ -+#ifdef COMPILE_DL_DIO -+ZEND_GET_MODULE(dio) -+#endif -+ -+#define DIO_UNDEF_CONST -1 -+ -+/* {{{ PHP_MINIT_FUNCTION -+ */ -+PHP_MINIT_FUNCTION(dio) -+{ -+ /* Legacy resource destructor. */ -+ le_fd = zend_register_list_destructors_ex(_dio_close_fd, NULL, le_fd_name, module_number); -+ -+ dio_init_legacy_defines(module_number TSRMLS_CC); -+ -+ /* Register the stream wrappers */ -+ return (php_register_url_stream_wrapper(DIO_RAW_STREAM_NAME, &php_dio_raw_stream_wrapper TSRMLS_CC) == SUCCESS && -+ php_register_url_stream_wrapper(DIO_SERIAL_STREAM_NAME, &php_dio_serial_stream_wrapper TSRMLS_CC) == SUCCESS) ? SUCCESS : FAILURE; -+} -+/* }}} */ -+ -+/* {{{ PHP_MSHUTDOWN_FUNCTION -+ */ -+PHP_MSHUTDOWN_FUNCTION(dio) -+{ -+ return (php_unregister_url_stream_wrapper(DIO_RAW_STREAM_NAME TSRMLS_CC) == SUCCESS && -+ php_unregister_url_stream_wrapper(DIO_SERIAL_STREAM_NAME TSRMLS_CC) == SUCCESS) ? SUCCESS : FAILURE; -+} -+/* }}} */ -+ -+/* {{{ PHP_MINFO_FUNCTION -+ */ -+PHP_MINFO_FUNCTION(dio) -+{ -+ php_info_print_table_start(); -+ php_info_print_table_header(2, "dio support", "enabled"); -+ php_info_print_table_row(2, "version", PHP_DIO_VERSION); -+ php_info_print_table_end(); -+} -+/* }}} */ -+ -+/* -+ * Local variables: -+ * c-basic-offset: 4 -+ * tab-width: 4 -+ * End: -+ * vim600: fdm=marker -+ * vim: sw=4 ts=4 noet -+ */ ---- /dev/null -+++ b/ext/dio/dio_common.c -@@ -0,0 +1,230 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | PHP Version 5 | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2009 Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ | This source file is subject to version 3.0 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_0.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. | -+ +----------------------------------------------------------------------+ -+ | Author: Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include "php.h" -+ -+#include "php_dio.h" -+#include "php_dio_common.h" -+ -+/* {{{ dio_init_stream_data -+ * Initialises the command parts of the stream data. -+ */ -+void dio_init_stream_data(php_dio_stream_data *data) { -+ data->stream_type = DIO_STREAM_TYPE_NONE; -+ data->end_of_file = 0; -+#ifdef DIO_HAS_FILEPERMS -+ data->has_perms = 0; -+ data->perms = 0; -+#endif -+#ifdef DIO_NONBLOCK -+ data->is_blocking = 1; -+ data->has_timeout = 0; -+ data->timeout_sec = 0; -+ data->timeout_usec = 0; -+ data->timed_out = 0; -+#endif -+ /* Serial options */ -+ data->data_rate = 9600; -+ data->data_bits = 8; -+ data->stop_bits = 1; -+ data->parity = 0; -+ data->flow_control = 1; -+ data->canonical = 1; -+} -+/* }}} */ -+ -+/* {{{ dio_convert_to_long -+ * Returns as a long, the value of the zval regardless of its type. -+ */ -+long dio_convert_to_long(zval *val) { -+ zval *copyval; -+ long longval; -+ -+ ALLOC_INIT_ZVAL(copyval); -+ *copyval = *val; -+ convert_to_long(copyval); -+ longval = Z_LVAL_P(copyval); -+ zval_ptr_dtor(©val); -+ -+ return longval; -+} -+/* }}} */ -+ -+/* {{{ dio_assoc_array_get_basic_options -+ * Retrieves the basic open option values from an associative array -+ */ -+void dio_assoc_array_get_basic_options(zval *options, php_dio_stream_data *data TSRMLS_DC) { -+#if defined(DIO_HAS_FILEPERMS) || defined(DIO_NONBLOCK) -+ zval **tmpzval; -+ HashTable *opthash; -+ -+ opthash = HASH_OF(options); -+#endif -+ -+#ifdef DIO_HAS_FILEPERMS -+ /* This is the file mode flags used by open(). */ -+ if (zend_hash_find(opthash, "perms", sizeof("perms"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->perms = (int)dio_convert_to_long(*tmpzval); -+ data->has_perms = 1; -+ } -+#endif -+ -+#ifdef DIO_NONBLOCK -+ /* This sets the underlying stream to be blocking/non -+ block (i.e. O_NONBLOCK) */ -+ if (zend_hash_find(opthash, "is_blocking", sizeof("is_blocking"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->is_blocking = dio_convert_to_long(*tmpzval) ? 1 : 0; -+ } -+ -+ /* This is the timeout value for reads in seconds. Only one of -+ timeout_secs or timeout_usecs need be defined to define a timeout. */ -+ if (zend_hash_find(opthash, "timeout_secs", sizeof("timeout_secs"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->timeout_sec = dio_convert_to_long(*tmpzval); -+ } -+ -+ /* This is the timeout value for reads in microseconds. Only one of -+ timeout_secs or timeout_usecs need be defined to define a timeout. */ -+ if (zend_hash_find(opthash, "timeout_usecs", sizeof("timeout_usecs"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->timeout_usec = dio_convert_to_long(*tmpzval); -+ } -+ -+ data->has_timeout = (data->timeout_sec | data->timeout_usec) ? 1 : 0; -+#endif -+} -+/* }}} */ -+ -+/* {{{ dio_assoc_array_get_serial_options -+ * Retrieves the serial open option values from an associative array -+ */ -+void dio_assoc_array_get_serial_options(zval *options, php_dio_stream_data *data TSRMLS_DC) { -+ zval **tmpzval; -+ HashTable *opthash; -+ -+ opthash = HASH_OF(options); -+ -+ if (zend_hash_find(opthash, "data_rate", sizeof("data_rate"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->data_rate = dio_convert_to_long(*tmpzval); -+ } -+ -+ if (zend_hash_find(opthash, "data_bits", sizeof("data_bits"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->data_bits = (int)dio_convert_to_long(*tmpzval); -+ } -+ -+ if (zend_hash_find(opthash, "stop_bits", sizeof("stop_bits"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->stop_bits = (int)dio_convert_to_long(*tmpzval); -+ } -+ -+ if (zend_hash_find(opthash, "parity", sizeof("parity"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->parity = (int)dio_convert_to_long(*tmpzval); -+ } -+ -+ if (zend_hash_find(opthash, "flow_control", sizeof("flow_control"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->flow_control = (int)(dio_convert_to_long(*tmpzval) ? 1 : 0); -+ } -+ -+ if (zend_hash_find(opthash, "is_canonical", sizeof("is_canonical"), (void **)&tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->canonical = (int)(dio_convert_to_long(*tmpzval) ? 1 : 0); -+ } -+} -+/* }}} */ -+ -+/* {{{ dio_stream_context_get_raw_options -+ * Extracts the option values for dio.raw mode from a context -+ */ -+void dio_stream_context_get_basic_options(php_stream_context *context, php_dio_stream_data *data TSRMLS_DC) { -+#if defined(DIO_HAS_FILEPERMS) || defined(DIO_NONBLOCK) -+ zval **tmpzval; -+#endif -+ -+#ifdef DIO_HAS_FILEPERMS -+ /* This is the file mode flags used by open(). */ -+ if (php_stream_context_get_option(context, "dio", "perms", &tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->perms = (int)dio_convert_to_long(*tmpzval); -+ data->has_perms = 1; -+ } -+#endif -+ -+#ifdef DIO_NONBLOCK -+ /* This sets the underlying stream to be blocking/non -+ block (i.e. O_NONBLOCK) */ -+ if (php_stream_context_get_option(context, "dio", "is_blocking", &tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->is_blocking = dio_convert_to_long(*tmpzval) ? 1 : 0; -+ } -+ -+ /* This is the timeout value for reads in seconds. Only one of -+ timeout_secs or timeout_usecs need be defined to define a timeout. */ -+ if (php_stream_context_get_option(context, "dio", "timeout_secs", &tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->timeout_sec = dio_convert_to_long(*tmpzval); -+ } -+ -+ /* This is the timeout value for reads in microseconds. Only one of -+ timeout_secs or timeout_usecs need be defined to define a timeout. */ -+ if (php_stream_context_get_option(context, "dio", "timeout_usecs", &tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->timeout_usec = dio_convert_to_long(*tmpzval); -+ } -+ -+ data->has_timeout = (data->timeout_sec | data->timeout_usec) ? 1 : 0; -+#endif -+} -+/* }}} */ -+ -+/* {{{ dio_stream_context_get_serial_options -+ * Extracts the option values for dio.serial mode from a context -+ */ -+void dio_stream_context_get_serial_options(php_stream_context *context, php_dio_stream_data *data TSRMLS_DC) { -+ zval **tmpzval; -+ -+ if (php_stream_context_get_option(context, "dio", "data_rate", &tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->data_rate = dio_convert_to_long(*tmpzval); -+ } -+ -+ if (php_stream_context_get_option(context, "dio", "data_bits", &tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->data_bits = (int)dio_convert_to_long(*tmpzval); -+ } -+ -+ if (php_stream_context_get_option(context, "dio", "stop_bits", &tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->stop_bits = (int)dio_convert_to_long(*tmpzval); -+ } -+ -+ if (php_stream_context_get_option(context, "dio", "parity", &tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->parity = (int)dio_convert_to_long(*tmpzval); -+ } -+ -+ if (php_stream_context_get_option(context, "dio", "flow_control", &tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->flow_control = (int)(dio_convert_to_long(*tmpzval) ? 1 : 0); -+ } -+ -+ if (php_stream_context_get_option(context, "dio", "is_canonical", &tmpzval) == SUCCESS && tmpzval && *tmpzval) { -+ data->canonical = (int)(dio_convert_to_long(*tmpzval) ? 1 : 0); -+ } -+} -+/* }}} */ -+ -+/* -+ * Local variables: -+ * c-basic-offset: 4 -+ * tab-width: 4 -+ * End: -+ * vim600: fdm=marker -+ * vim: sw=4 ts=4 noet -+ */ -+ ---- /dev/null -+++ b/ext/dio/dio_posix.c -@@ -0,0 +1,659 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | PHP Version 5 | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2009 Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ | This source file is subject to version 3.0 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_0.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. | -+ +----------------------------------------------------------------------+ -+ | Author: Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include "php.h" -+ -+#include "php_dio_common.h" -+ -+/* {{{ dio_stream_mode_to_flags -+ * Convert an fopen() mode string to open() flags -+ */ -+static int dio_stream_mode_to_flags(const char *mode) { -+ int flags = 0, ch = 0, bin = 1; -+ -+ switch(mode[ch++]) { -+ case 'r': -+ flags = 0; -+ break; -+ case 'w': -+ flags = O_TRUNC | O_CREAT; -+ break; -+ case 'a': -+ flags = O_APPEND | O_CREAT; -+ break; -+ case 'x': -+ flags = O_EXCL | O_CREAT; -+ break; -+ } -+ -+ if (mode[ch] != '+') { -+ bin = (mode[ch++] == 'b'); -+ } -+ -+ if (mode[ch] == '+') { -+ flags |= O_RDWR; -+ } else if (flags) { -+ flags |= O_WRONLY; -+ } else { -+ flags |= O_RDONLY; -+ } -+ -+#if defined(_O_TEXT) && defined(O_BINARY) -+ if (bin) { -+ flags |= O_BINARY; -+ } else { -+ flags |= _O_TEXT; -+ } -+#endif -+ -+ return flags; -+} -+/* }}} */ -+ -+/* {{{ dio_data_rate_to_define -+ * Converts a numeric data rate to a termios define -+ */ -+static int dio_data_rate_to_define(long rate, speed_t *def) { -+ speed_t val; -+ -+ switch (rate) { -+ case 0: -+ val = 0; -+ break; -+ case 50: -+ val = B50; -+ break; -+ case 75: -+ val = B75; -+ break; -+ case 110: -+ val = B110; -+ break; -+ case 134: -+ val = B134; -+ break; -+ case 150: -+ val = B150; -+ break; -+ case 200: -+ val = B200; -+ break; -+ case 300: -+ val = B300; -+ break; -+ case 600: -+ val = B600; -+ break; -+ case 1200: -+ val = B1200; -+ break; -+ case 1800: -+ val = B1800; -+ break; -+ case 2400: -+ val = B2400; -+ break; -+ case 4800: -+ val = B4800; -+ break; -+ case 9600: -+ val = B9600; -+ break; -+ case 19200: -+ val = B19200; -+ break; -+ case 38400: -+ val = B38400; -+ break; -+#ifdef B57600 -+ case 57600: -+ val = B57600; -+ break; -+#endif -+#ifdef B115200 -+ case 115200: -+ val = B115200; -+ break; -+#endif -+#ifdef B230400 -+ case 230400: -+ val = B230400; -+ break; -+#endif -+#ifdef B460800 -+ case 460800: -+ val = B460800; -+ break; -+#endif -+ default: -+ return 0; -+ } -+ -+ *def = val; -+ return 1; -+} -+ -+/* {{{ dio_data_bits_to_define -+ * Converts a number of data bits to a termios define -+ */ -+static int dio_data_bits_to_define(int data_bits, int *def) { -+ int val; -+ -+ switch (data_bits) { -+ case 8: -+ val = CS8; -+ break; -+ case 7: -+ val = CS7; -+ break; -+ case 6: -+ val = CS6; -+ break; -+ case 5: -+ val = CS5; -+ break; -+ default: -+ return 0; -+ } -+ -+ *def = val; -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_stop_bits_to_define -+ * Converts a number of stop bits to a termios define -+ */ -+static int dio_stop_bits_to_define(int stop_bits, int *def) { -+ int val; -+ -+ switch (stop_bits) { -+ case 1: -+ val = 0; -+ break; -+ case 2: -+ val = CSTOPB; -+ break; -+ default: -+ return 0; -+ } -+ -+ *def = val; -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_parity_to_define -+ * Converts a parity type to a termios define -+ */ -+static int dio_parity_to_define(int parity, int *def) { -+ int val; -+ -+ switch (parity) { -+ case 0: -+ val = 0; -+ break; -+ case 1: -+ val = PARENB | PARODD; -+ break; -+ case 2: -+ val = PARENB; -+ break; -+ default: -+ return 0; -+ } -+ -+ *def = val; -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_create_stream_data -+ * Creates an initialised stream data structure. Free with efree(). -+ */ -+php_dio_stream_data * dio_create_stream_data(void) { -+ php_dio_posix_stream_data * data = emalloc(sizeof(php_dio_posix_stream_data)); -+ dio_init_stream_data(&(data->common)); -+ data->fd = -1; -+ data->flags = 0; -+ -+ return (php_dio_stream_data *)data; -+} -+/* }}} */ -+ -+/* {{{ dio_common_write -+ * Writes count chars from the buffer to the stream described by the stream data. -+ */ -+size_t dio_common_write(php_dio_stream_data *data, const char *buf, size_t count) { -+ size_t ret; -+ -+ /* Blocking writes can be interrupted by signals etc. If -+ * interrupted try again. Not sure about non-blocking -+ * writes but it doesn't hurt to check. */ -+ do { -+ ret = write(((php_dio_posix_stream_data*)data)->fd, buf, count); -+ if (ret > 0) { -+ return ret; -+ } -+ } while (errno == EINTR); -+ return 0; -+} -+/* }}} */ -+ -+#ifdef DIO_NONBLOCK -+/* {{{ dio_timeval_subtract -+ * Calculates the difference between two timevals returning the result in the -+ * structure pointed to by diffptr. Returns -1 as error if late time is -+ * earlier than early time. -+ */ -+static int dio_timeval_subtract(struct timeval *late, struct timeval *early, struct timeval *diff) { -+ struct timeval *tmp; -+ -+ /* Handle negatives */ -+ if (late->tv_sec < early->tv_sec) { -+ return 0; -+ } -+ -+ if ((late->tv_sec == early->tv_sec) && (late->tv_usec < early->tv_usec)) { -+ return 0; -+ } -+ -+ /* Handle any carry. If later usec is smaller than earlier usec simple -+ * subtraction will result in negative value. Since usec has a maximum -+ * of one second by adding another second before the subtraction the -+ * result will always be positive. */ -+ if (late->tv_usec < early->tv_usec) { -+ late->tv_usec += 1000000; -+ late->tv_sec--; -+ } -+ -+ /* Once adjusted can just subtract values. */ -+ diff->tv_sec = late->tv_sec - early->tv_sec; -+ diff->tv_usec = late->tv_usec - early->tv_usec; -+ -+ return 1; -+} -+#endif -+ -+/* {{{ dio_common_read -+ * Reads count chars to the buffer to the stream described by the stream data. -+ */ -+size_t dio_common_read(php_dio_stream_data *data, const char *buf, size_t count) { -+ int fd = ((php_dio_posix_stream_data*)data)->fd; -+ size_t ret, total = 0; -+ char *ptr = (char*)buf; -+ -+ struct timeval timeout, timeouttmp, before, after, diff; -+ fd_set rfds; -+ -+ if (!data->has_timeout) { -+ /* Blocking reads can be interrupted by signals etc. If -+ * interrupted try again. Not sure about non-blocking -+ * reads but it doesn't hurt to check. */ -+ do { -+ ret = read(fd, (char*)ptr, count); -+ if (ret > 0) { -+ return ret; -+ } else if (!ret) { -+ data->end_of_file = 1; -+ } -+ } while ((errno == EINTR) && !data->end_of_file); -+ return 0; -+ } -+#ifdef DIO_NONBLOCK -+ else { -+ /* Clear timed out flag */ -+ data->timed_out = 0; -+ -+ /* The initial timeout value */ -+ timeout.tv_sec = data->timeout_sec; -+ timeout.tv_usec = data->timeout_usec; -+ -+ do { -+ /* The semantics of select() are that you cannot guarantee -+ * that the timeval structure passed in has not been changed by -+ * the select call. So you keep a copy. */ -+ timeouttmp = timeout; -+ -+ /* The time before we wait for data. */ -+ (void) gettimeofday(&before, NULL); -+ -+ /* Wait for an event on our file descriptor. */ -+ FD_ZERO(&rfds); -+ FD_SET(fd, &rfds); -+ -+ ret = select(fd + 1, &rfds, NULL, NULL, &timeouttmp); -+ /* An error. */ -+ if ((ret < 0) && (errno != EINTR) && (errno != EAGAIN)) { -+ return 0; -+ } -+ -+ /* We have data to read. */ -+ if ((ret > 0) && FD_ISSET(fd, &rfds)) { -+ ret = read(fd, ptr, count); -+ /* Another error */ -+ if ((ret < 0) && (errno != EINTR) && (errno != EAGAIN)) { -+ return 0; -+ } -+ -+ if (ret > 0) { -+ /* Got data, add it to the buffer. */ -+ ptr += ret; -+ total += ret; -+ count -= ret; -+ } else if (!ret) { -+ /* This should never happen since how can we have -+ * data to read at an end of file, but still -+ * just in case! */ -+ data->end_of_file = 1; -+ break; -+ } -+ } -+ -+ /* If not timed out and not end of file and not all data read -+ * calculate how long it took us and loop if we still have time -+ * out time left. */ -+ if (count) { -+ (void) gettimeofday(&after, NULL); -+ -+ /* Diff the timevals */ -+ (void) dio_timeval_subtract(&after, &before, &diff); -+ -+ /* Now adjust the timeout. */ -+ if (!dio_timeval_subtract(&timeout, &diff, &timeout)) { -+ /* If it errors we've run out of time. */ -+ data->timed_out = 1; -+ break; -+ } else if (!timeout.tv_sec && !(timeout.tv_usec / 1000)) { -+ /* Check for rounding issues (millisecond accuracy) */ -+ data->timed_out = 1; -+ break; -+ } -+ } -+ } while (count); /* Until time out or end of file or all data read. */ -+ -+ return total; -+ } -+#endif -+} -+/* }}} */ -+ -+/* {{{ php_dio_stream_data -+ * Closes the php_stream. -+ */ -+int dio_common_close(php_dio_stream_data *data) { -+ if (close(((php_dio_posix_stream_data*)data)->fd) < 0) { -+ return 0; -+ } -+ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_common_set_option -+ * Sets/gets stream options -+ */ -+int dio_common_set_option(php_dio_stream_data *data, int option, int value, void *ptrparam) { -+ int fd = ((php_dio_posix_stream_data*)data)->fd; -+ int old_is_blocking; -+ int flags; -+ -+ switch (option) { -+#ifdef DIO_NONBLOCK -+ case PHP_STREAM_OPTION_READ_TIMEOUT: -+ if (ptrparam) { -+ struct timeval *tv = (struct timeval*)ptrparam; -+ -+ flags = fcntl(fd, F_GETFL, 0); -+ -+ /* A timeout of zero seconds and zero microseconds disables -+ any existing timeout. */ -+ if (tv->tv_sec || tv->tv_usec) { -+ data->timeout_sec = tv->tv_sec; -+ data->timeout_usec = tv->tv_usec; -+ data->has_timeout = -1; -+ (void) fcntl(fd, F_SETFL, flags & ~DIO_NONBLOCK); -+ } else { -+ data->timeout_sec = 0; -+ data->timeout_usec = 0; -+ data->has_timeout = 0; -+ data->timed_out = 0; -+ (void) fcntl(fd, F_SETFL, flags | DIO_NONBLOCK); -+ } -+ -+ return PHP_STREAM_OPTION_RETURN_OK; -+ } else { -+ return PHP_STREAM_OPTION_RETURN_ERR; -+ } -+ -+ case PHP_STREAM_OPTION_BLOCKING: -+ flags = fcntl(fd, F_GETFL, 0); -+ if (value) { -+ flags &= ~DIO_NONBLOCK; -+ } else { -+ flags |= DIO_NONBLOCK; -+ } -+ (void) fcntl(fd, F_SETFL, flags); -+ -+ old_is_blocking = data->is_blocking; -+ data->is_blocking = value; -+ return old_is_blocking ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR; -+#endif /* O_NONBLOCK */ -+ -+ default: -+ break; -+ } -+ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_raw_open_stream -+ * Opens the underlying stream. -+ */ -+int dio_raw_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) { -+ php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data; -+ pdata->flags = dio_stream_mode_to_flags(mode); -+ -+#ifdef DIO_NONBLOCK -+ if (!data->is_blocking || data->has_timeout) { -+ pdata->flags |= DIO_NONBLOCK; -+ } -+#endif -+ -+ /* Open the file and handle any errors. */ -+#ifdef DIO_HAS_FILEPERMS -+ if (data->has_perms) { -+ pdata->fd = open(filename, pdata->flags, (mode_t)data->perms); -+ } else { -+ pdata->fd = open(filename, pdata->flags); -+ } -+#else -+ pdata->fd = open(filename, pdata->flags); -+#endif -+ -+ if (pdata->fd < 0) { -+ switch (errno) { -+ case EEXIST: -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "File exists!"); -+ return 0; -+ default: -+ return 0; -+ } -+ } -+ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_serial_init -+ * Initialises the serial settings storing the original settings before hand. -+ */ -+static int dio_serial_init(php_dio_stream_data *data TSRMLS_DC) { -+ php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data; -+ int ret = 0, data_bits_def, stop_bits_def, parity_def; -+ struct termios tio; -+ speed_t rate_def; -+ -+ if (!dio_data_rate_to_define(data->data_rate, &rate_def)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_rate value (%ld)", data->data_rate); -+ return 0; -+ } -+ -+ if (!dio_data_bits_to_define(data->data_bits, &data_bits_def)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_bits value (%d)", data->data_bits); -+ return 0; -+ } -+ -+ if (!dio_stop_bits_to_define(data->stop_bits, &stop_bits_def)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid stop_bits value (%d)", data->stop_bits); -+ return 0; -+ } -+ -+ if (!dio_parity_to_define(data->parity, &parity_def)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid parity value (%d)", data->parity); -+ return 0; -+ } -+ -+ ret = tcgetattr(pdata->fd, &(pdata->oldtio)); -+ if (ret < 0) { -+ if ((errno == ENOTTY) || (errno == ENODEV)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a serial port or terminal!"); -+ } -+ return 0; -+ } -+ -+ ret = tcgetattr(pdata->fd, &tio); -+ if (ret < 0) { -+ return 0; -+ } -+ -+ if (data->canonical) { -+ tio.c_iflag = IGNPAR | ICRNL; -+ tio.c_oflag = 0; -+ tio.c_lflag = ICANON; -+ } else { -+ cfmakeraw(&tio); -+ } -+ -+ cfsetispeed(&tio, rate_def); -+ cfsetospeed(&tio, rate_def); -+ -+ tio.c_cflag &= ~CSIZE; -+ tio.c_cflag |= data_bits_def; -+ tio.c_cflag &= ~CSTOPB; -+ tio.c_cflag |= stop_bits_def; -+ tio.c_cflag &= ~(PARENB|PARODD); -+ tio.c_cflag |= parity_def; -+ -+#ifdef CRTSCTS -+ tio.c_cflag &= ~(CLOCAL | CRTSCTS); -+#else -+ tio.c_cflag &= ~CLOCAL; -+#endif -+ if (!data->flow_control) { -+ tio.c_cflag |= CLOCAL; -+#ifdef CRTSCTS -+ } else { -+ tio.c_cflag |= CRTSCTS; -+#endif -+ } -+ -+ ret = tcsetattr(pdata->fd, TCSANOW, &tio); -+ if (ret < 0) { -+ return 0; -+ } -+ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_serial_uninit -+ * Restores the serial settings back to their original state. -+ */ -+int dio_serial_uninit(php_dio_stream_data *data) { -+ php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data; -+ int ret; -+ -+ do { -+ ret = tcsetattr(pdata->fd, TCSANOW, &(pdata->oldtio)); -+ } while ((ret < 0) && (errno == EINTR)); -+ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_serial_flush -+ * Purges the serial buffers of data. -+ */ -+int dio_serial_purge(php_dio_stream_data *data) { -+ php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data; -+ int ret; -+ -+ if ((pdata->flags & O_RDWR) == O_RDWR) { -+ ret = tcflush(pdata->fd, TCIOFLUSH); -+ } else if ((pdata->flags & O_WRONLY) == O_WRONLY) { -+ ret = tcflush(pdata->fd, TCOFLUSH); -+ } else if ((pdata->flags & O_RDONLY) == O_RDONLY) { -+ ret = tcflush(pdata->fd, TCIFLUSH); -+ } -+ -+ if (ret < 0) { -+ return 0; -+ } -+ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_serial_open_stream -+ * Opens the underlying stream. -+ */ -+int dio_serial_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) { -+ php_dio_posix_stream_data *pdata = (php_dio_posix_stream_data*)data; -+ -+#ifdef O_NOCTTY -+ /* We don't want a controlling TTY */ -+ pdata->flags |= O_NOCTTY; -+#endif -+ -+ if (!dio_raw_open_stream(filename, mode, data TSRMLS_CC)) { -+ return 0; -+ } -+ -+ if (!dio_serial_init(data TSRMLS_CC)) { -+ close(pdata->fd); -+ return 0; -+ } -+ -+ return 1; -+} -+/* }}} */ -+ -+/* -+ * Local variables: -+ * c-basic-offset: 4 -+ * tab-width: 4 -+ * End: -+ * vim600: fdm=marker -+ * vim: sw=4 ts=4 noet -+ */ ---- /dev/null -+++ b/ext/dio/dio_stream_wrappers.c -@@ -0,0 +1,406 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | PHP Version 5 | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2009 Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ | This source file is subject to version 3.0 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_0.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. | -+ +----------------------------------------------------------------------+ -+ | Author: Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include "php.h" -+#include "ext/standard/url.h" -+ -+#include "php_dio.h" -+#include "php_dio_common.h" -+#include "php_dio_stream_wrappers.h" -+ -+/* -+ +----------------------------------------------------------------------+ -+ | Raw stream handling | -+ +----------------------------------------------------------------------+ -+*/ -+ -+/* {{{ dio_stream_write -+ * Write to the stream -+ */ -+static size_t dio_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) -+{ -+ return dio_common_write((php_dio_stream_data*)stream->abstract, buf, count); -+} -+/* }}} */ -+ -+/* {{{ dio_stream_read -+ * Read from the stream -+ */ -+static size_t dio_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) -+{ -+ php_dio_stream_data* data = (php_dio_stream_data*)stream->abstract; -+ size_t bytes = dio_common_read(data, buf, count); -+ stream->eof = data->end_of_file; -+ -+ return bytes; -+} -+/* }}} */ -+ -+/* {{{ dio_stream_flush -+ * Flush the stream. For raw streams this does nothing. -+ */ -+static int dio_stream_flush(php_stream *stream TSRMLS_DC) -+{ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_stream_close -+ * Close the stream -+ */ -+static int dio_stream_close(php_stream *stream, int close_handle TSRMLS_DC) -+{ -+ php_dio_stream_data *abstract = (php_dio_stream_data*)stream->abstract; -+ -+ if (!dio_common_close(abstract)) { -+ return 0; -+ } -+ -+ efree(abstract); -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_stream_set_option -+ * Set the stream options. -+ */ -+static int dio_stream_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC) -+{ -+ php_dio_stream_data *abstract = (php_dio_stream_data*)stream->abstract; -+ -+ switch (option) { -+ case PHP_STREAM_OPTION_META_DATA_API: -+#ifdef DIO_NONBLOCK -+ add_assoc_bool((zval *)ptrparam, "timed_out", abstract->timed_out); -+ add_assoc_bool((zval *)ptrparam, "blocked", abstract->is_blocking); -+#endif -+ add_assoc_bool((zval *)ptrparam, "eof", stream->eof); -+ return PHP_STREAM_OPTION_RETURN_OK; -+ -+#if PHP_MAJOR_VERSION >= 5 -+ case PHP_STREAM_OPTION_CHECK_LIVENESS: -+ stream->eof = abstract->end_of_file; -+ return PHP_STREAM_OPTION_RETURN_OK; -+#endif /* PHP_MAJOR_VERSION >= 5 */ -+ -+ default: -+ break; -+ } -+ -+ return dio_common_set_option(abstract, option, value, ptrparam); -+} -+/* }}} */ -+ -+php_stream_ops dio_raw_stream_ops = { -+ dio_stream_write, -+ dio_stream_read, -+ dio_stream_close, -+ dio_stream_flush, -+ "dio", -+ NULL, /* seek */ -+ NULL, /* cast */ -+ NULL, /* stat */ -+ dio_stream_set_option, -+}; -+ -+/* {{{ dio_raw_fopen_wrapper -+ * fopen for the dio.raw stream. -+ */ -+static php_stream *dio_raw_fopen_wrapper(php_stream_wrapper *wrapper, -+ char *path, char *mode, -+ int options, char **opened_path, -+ php_stream_context *context STREAMS_DC TSRMLS_DC) { -+ php_dio_stream_data *data; -+ php_stream *stream; -+ char *filename; -+ -+ /* Check it was actually for us (not a corrupted function pointer -+ somewhere!). */ -+ if (strncmp(path, DIO_RAW_STREAM_PROTOCOL, sizeof(DIO_RAW_STREAM_PROTOCOL) - 1)) { -+ return NULL; -+ } -+ -+ /* Get the actually file system name/path. */ -+ filename = path + sizeof(DIO_RAW_STREAM_PROTOCOL) - 1; -+ -+ /* Check we can actually access it. */ -+ if (php_check_open_basedir(filename TSRMLS_CC) || DIO_SAFE_MODE_CHECK(filename, mode)) { -+ return NULL; -+ } -+ -+ data = dio_create_stream_data(); -+ data->stream_type = DIO_STREAM_TYPE_RAW; -+ -+ /* Parse the context. */ -+ if (context) { -+ dio_stream_context_get_basic_options(context, data TSRMLS_CC); -+ } -+ -+ /* Try and open a raw stream. */ -+ if (!dio_raw_open_stream(filename, mode, data TSRMLS_CC)) { -+ return NULL; -+ } -+ -+ /* Create a PHP stream based on raw stream */ -+ stream = php_stream_alloc(&dio_raw_stream_ops, data, 0, mode); -+ if (!stream) { -+ (void) dio_common_close(data); -+ efree(data); -+ } -+ -+ return stream; -+} -+/* }}} */ -+ -+static php_stream_wrapper_ops dio_raw_stream_wops = { -+ dio_raw_fopen_wrapper, -+ NULL, /* stream_close */ -+ NULL, /* stat */ -+ NULL, /* stat_url */ -+ NULL, /* opendir */ -+ DIO_RAW_STREAM_NAME -+}; -+ -+php_stream_wrapper php_dio_raw_stream_wrapper = { -+ &dio_raw_stream_wops, -+ NULL, -+ 0 -+}; -+ -+/* {{{ proto dio_raw(string filename, string mode[, array options]) -+ * Opens a raw direct IO stream. -+ */ -+PHP_FUNCTION(dio_raw) { -+ zval *options = NULL; -+ php_dio_stream_data *data; -+ php_stream *stream; -+ -+ char *filename; -+ int filename_len; -+ char *mode; -+ int mode_len; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|z", &filename, &filename_len, &mode, &mode_len, &options) == FAILURE) { -+ RETURN_FALSE; -+ } -+ -+ /* Check the third argument is an array. */ -+ if (options && (Z_TYPE_P(options) != IS_ARRAY)) { -+ RETURN_FALSE; -+ } -+ -+ /* Check we can actually access the file. */ -+ if (php_check_open_basedir(filename TSRMLS_CC) || DIO_SAFE_MODE_CHECK(filename, mode)) { -+ RETURN_FALSE; -+ } -+ -+ data = dio_create_stream_data(); -+ data->stream_type = DIO_STREAM_TYPE_RAW; -+ -+ if (options) { -+ dio_assoc_array_get_basic_options(options, data TSRMLS_CC); -+ } -+ -+ /* Try and open a raw stream. */ -+ if (dio_raw_open_stream(filename, mode, data TSRMLS_CC)) { -+ stream = php_stream_alloc(&dio_raw_stream_ops, data, 0, mode); -+ if (!stream) { -+ (void) dio_common_close(data); -+ efree(data); -+ RETURN_FALSE; -+ } -+ } -+ -+ php_stream_to_zval(stream, return_value); -+} -+/* }}} */ -+ -+/* -+ +----------------------------------------------------------------------+ -+ | Serial stream handling | -+ +----------------------------------------------------------------------+ -+*/ -+ -+/* {{{ dio_stream_flush -+ * Flush the stream. If the stream is read only, it flushes the read -+ * stream, if it is write only it flushes the write, otherwise it flushes -+ * both. -+ */ -+static int dio_serial_stream_flush(php_stream *stream TSRMLS_DC) -+{ -+ return dio_serial_purge((php_dio_stream_data*)stream->abstract); -+} -+/* }}} */ -+ -+/* {{{ dio_stream_close -+ * Close the stream. Restores the serial settings to their value before -+ * the stream was open. -+ */ -+static int dio_serial_stream_close(php_stream *stream, int close_handle TSRMLS_DC) -+{ -+ php_dio_stream_data *abstract = (php_dio_stream_data*)stream->abstract; -+ -+ if (!dio_serial_uninit(abstract)) { -+ return 0; -+ } -+ -+ if (!dio_common_close(abstract)) { -+ return 0; -+ } -+ -+ efree(abstract); -+ return 1; -+} -+/* }}} */ -+ -+php_stream_ops dio_serial_stream_ops = { -+ dio_stream_write, -+ dio_stream_read, -+ dio_serial_stream_close, -+ dio_serial_stream_flush, -+ "dio", -+ NULL, /* seek */ -+ NULL, /* cast */ -+ NULL, /* stat */ -+ dio_stream_set_option, -+}; -+ -+/* {{{ dio_raw_fopen_wrapper -+ * fopen for the dio.raw stream. -+ */ -+static php_stream *dio_serial_fopen_wrapper(php_stream_wrapper *wrapper, -+ char *path, char *mode, -+ int options, char **opened_path, -+ php_stream_context *context STREAMS_DC TSRMLS_DC) { -+ php_dio_stream_data *data; -+ php_stream *stream; -+ char *filename; -+ -+ /* Check it was actually for us (not a corrupted function pointer -+ somewhere!). */ -+ if (strncmp(path, DIO_SERIAL_STREAM_PROTOCOL, sizeof(DIO_SERIAL_STREAM_PROTOCOL) - 1)) { -+ return NULL; -+ } -+ -+ /* Get the actually file system name/path. */ -+ filename = path + sizeof(DIO_SERIAL_STREAM_PROTOCOL) - 1; -+ -+ /* Check we can actually access it. */ -+ if (php_check_open_basedir(filename TSRMLS_CC) || DIO_SAFE_MODE_CHECK(filename, mode)) { -+ return NULL; -+ } -+ -+ data = dio_create_stream_data(); -+ data->stream_type = DIO_STREAM_TYPE_SERIAL; -+ -+ /* Parse the context. */ -+ if (context) { -+ dio_stream_context_get_basic_options(context, data TSRMLS_CC); -+ dio_stream_context_get_serial_options(context, data TSRMLS_CC); -+ } -+ -+ /* Try and open a serial stream. */ -+ if (!dio_serial_open_stream(filename, mode, data TSRMLS_CC)) { -+ return NULL; -+ } -+ -+ stream = php_stream_alloc(&dio_serial_stream_ops, data, 0, mode); -+ if (!stream) { -+ efree(data); -+ } -+ -+ return stream; -+} -+/* }}} */ -+ -+static php_stream_wrapper_ops dio_serial_stream_wops = { -+ dio_serial_fopen_wrapper, -+ NULL, /* stream_close */ -+ NULL, /* stat */ -+ NULL, /* stat_url */ -+ NULL, /* opendir */ -+ DIO_SERIAL_STREAM_NAME -+}; -+ -+php_stream_wrapper php_dio_serial_stream_wrapper = { -+ &dio_serial_stream_wops, -+ NULL, -+ 0 -+}; -+ -+/* {{{ proto dio_serial(string filename, string mode[, array options]) -+ * Opens a serial direct IO stream. -+ */ -+PHP_FUNCTION(dio_serial) { -+ zval *options = NULL; -+ php_dio_stream_data *data; -+ php_stream *stream; -+ -+ char *filename; -+ int filename_len; -+ char *mode; -+ int mode_len; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|z", &filename, &filename_len, &mode, &mode_len, &options) == FAILURE) { -+ RETURN_FALSE; -+ } -+ -+ /* Check the third argument is an array. */ -+ if (options && (Z_TYPE_P(options) != IS_ARRAY)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING,"dio_serial, the third argument should be an array of options"); -+ RETURN_FALSE; -+ } -+ -+ /* Check we can actually access the file. */ -+ if (php_check_open_basedir(filename TSRMLS_CC) || DIO_SAFE_MODE_CHECK(filename, mode)) { -+ RETURN_FALSE; -+ } -+ -+ data = dio_create_stream_data(); -+ data->stream_type = DIO_STREAM_TYPE_SERIAL; -+ -+ if (options) { -+ dio_assoc_array_get_basic_options(options, data TSRMLS_CC); -+ dio_assoc_array_get_serial_options(options, data TSRMLS_CC); -+ } -+ -+ /* Try and open a serial stream. */ -+ if (dio_serial_open_stream(filename, mode, data TSRMLS_CC)) { -+ stream = php_stream_alloc(&dio_serial_stream_ops, data, 0, mode); -+ if (!stream) { -+ efree(data); -+ RETURN_FALSE; -+ } -+ } -+ -+ php_stream_to_zval(stream, return_value); -+} -+/* }}} */ -+ -+/* -+ * Local variables: -+ * c-basic-offset: 4 -+ * tab-width: 4 -+ * End: -+ * vim600: fdm=marker -+ * vim: sw=4 ts=4 noet -+ */ ---- /dev/null -+++ b/ext/dio/dio_win32.c -@@ -0,0 +1,669 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | PHP Version 5 | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2009 Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ | This source file is subject to version 3.0 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_0.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. | -+ +----------------------------------------------------------------------+ -+ | Author: Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include "php.h" -+ -+#include "php_dio_common.h" -+ -+/* {{{ dio_data_rate_to_define -+ * Converts a numeric data rate to a termios define -+ */ -+static int dio_data_rate_to_define(long rate, DWORD *def) { -+ switch (rate) { -+ case 75: -+ case 110: -+ case 134: -+ case 150: -+ case 300: -+ case 600: -+ case 1200: -+ case 1800: -+ case 2400: -+ case 4800: -+ case 7200: -+ case 9600: -+ case 14400: -+ case 19200: -+ case 38400: -+ case 57600: -+ case 115200: -+ case 56000: -+ case 128000: -+ break; -+ default: -+ return 0; -+ } -+ -+ *def = (DWORD)rate; -+ return 1; -+} -+/* }}} */ -+ -+ -+/* {{{ dio_data_bits_to_define -+ * Converts a number of data bits to a termios define -+ */ -+static int dio_data_bits_to_define(int data_bits, DWORD *def) { -+ switch (data_bits) { -+ case 8: -+ case 7: -+ case 6: -+ case 5: -+ case 4: -+ break; -+ default: -+ return 0; -+ } -+ -+ *def = (DWORD)data_bits; -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_stop_bits_to_define -+ * Converts a number of stop bits to a termios define -+ */ -+static int dio_stop_bits_to_define(int stop_bits, DWORD *def) { -+ DWORD val; -+ -+ switch (stop_bits) { -+ case 1: -+ val = 0; -+ break; -+ case 2: -+ val = 2; -+ break; -+ case 3: -+ val = 1; -+ break; -+ default: -+ return 0; -+ } -+ -+ *def = val; -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_parity_to_define -+ * Converts a parity type to a termios define -+ */ -+static int dio_parity_to_define(int parity, DWORD *def) { -+ switch (parity) { -+ case 0: -+ case 1: -+ case 2: -+ break; -+ default: -+ return 0; -+ } -+ -+ *def = (DWORD)parity; -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_create_stream_data -+ * Creates an initialised stream data structure. Free with efree(). -+ */ -+php_dio_stream_data * dio_create_stream_data(void) { -+ php_dio_win32_stream_data * data = emalloc(sizeof(php_dio_win32_stream_data)); -+ memset(data, 0, sizeof(php_dio_win32_stream_data)); -+ dio_init_stream_data(&(data->common)); -+ data->handle = INVALID_HANDLE_VALUE; -+ data->desired_access = 0; -+ data->creation_disposition = 0; -+ data->olddcb.DCBlength = sizeof(DCB); -+ -+ return (php_dio_stream_data *)data; -+} -+/* }}} */ -+ -+/* {{{ dio_common_write -+ * Writes count chars from the buffer to the stream described by the stream data. -+ */ -+size_t dio_common_write(php_dio_stream_data *data, const char *buf, size_t count) { -+ php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data; -+ DWORD total = 0; -+ -+ if (WriteFile(wdata->handle, buf, (DWORD)count, &total, NULL)) { -+ return (size_t)total; -+ } -+ -+ return 0; -+} -+/* }}} */ -+ -+/* {{{ dio_buffer_read -+ * Reads any available chars from the canonical buffer. -+ */ -+static size_t dio_buffer_read(php_dio_win32_stream_data *wdata, const char *buf, size_t count) { -+ php_dio_win32_canon_data *canon_data = wdata->canon_data; -+ size_t total = 0; -+ -+ /* Read always follows write. I.e. if read ptr > write ptr buffer has -+ wrapped and so we need to copy two blocks of data. */ -+ if (canon_data->read_pos > canon_data->write_pos) { -+ -+ /* Check we actually need to copy both blocks */ -+ if ((canon_data->size - canon_data->read_pos) > count) { -+ -+ /* No we don't. Just copy as much as we were asked for. */ -+ memcpy((char*)buf, -+ &(canon_data->buf[canon_data->read_pos]), -+ count); -+ /* Update the read pointer. */ -+ canon_data->read_pos += count; -+ -+ /* Return the amount read. */ -+ return count; -+ } else { -+ -+ /* We need to copy both blocks so copy data up to the end of -+ the buffer. */ -+ total = canon_data->size - canon_data->read_pos; -+ memcpy((char*)buf, -+ &(canon_data->buf[canon_data->read_pos]), -+ total); -+ canon_data->read_pos = 0; -+ count -= total; -+ -+ /* Now copy the data from the start of the buffer either up -+ count or the number of bytes in the buffer. */ -+ -+ if (canon_data->write_pos > count) { -+ memcpy((char*)buf, canon_data->buf, count); -+ canon_data->read_pos = count; -+ total += count; -+ -+ return total; -+ } else { -+ memcpy((char*)buf, canon_data->buf, canon_data->write_pos); -+ canon_data->read_pos = canon_data->write_pos; -+ total += canon_data->write_pos; -+ -+ return total; -+ } -+ } -+ -+ /* Else if write follows read. This is a simpler case. We just copy -+ either all the data buffered or count, which ever is smaller. */ -+ } else if (canon_data->write_pos > canon_data->read_pos) { -+ if ((canon_data->write_pos - canon_data->read_pos) > count) { -+ memcpy((char*)buf, -+ &(canon_data->buf[canon_data->read_pos]), -+ count); -+ canon_data->read_pos += count; -+ -+ return count; -+ } else { -+ total = canon_data->write_pos - canon_data->read_pos; -+ memcpy((char*)buf, -+ &(canon_data->buf[canon_data->read_pos]), -+ total); -+ canon_data->read_pos += total; -+ -+ return total; -+ } -+ } -+ -+ /* Else we need to read more data from the data port. */ -+ return 0; -+} -+ -+/* {{{ dio_com_read -+ * Read chars from the data port. -+ */ -+static size_t dio_com_read(php_dio_stream_data *data, const char *buf, size_t count) { -+ php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data; -+ DWORD err, total = 0; -+ -+ if (ReadFile(wdata->handle, (void*)buf, (DWORD)count, &total, NULL)) { -+ -+ if (total) { -+ return (size_t)total; -+ } -+ -+ data->end_of_file = 1; -+ } -+ -+ if (!data->end_of_file) { -+ err = GetLastError(); -+ -+ if (ERROR_HANDLE_EOF == err) { -+ data->end_of_file = 1; -+ } -+ } -+ -+ return 0; -+} -+ -+/* {{{ dio_canonical_read -+ * Reads chars from the input stream until the internal buffer is full or a new -+ * line is reached. -+ */ -+static size_t dio_canonical_read(php_dio_win32_stream_data *wdata, const char *buf, size_t count) { -+ php_dio_win32_canon_data *canon_data = wdata->canon_data; -+ size_t total = 0; -+ char ch; -+ -+ /* See if there's any buffered data and copy it. */ -+ total = dio_buffer_read(wdata, buf, count); -+ if (total) { -+ return total; -+ } -+ -+ /* Need to read more data from the data port. Buffer should be empty(er) -+ by now. */ -+ do { -+ /* Is the buffer full? */ -+ if (((canon_data->write_pos + 1) % canon_data->size) == -+ canon_data->read_pos) { -+ break; -+ } -+ -+ /* Read a byte from the input checking for EOF. */ -+ if (!dio_com_read((php_dio_stream_data*)wdata, &ch, 1)) { -+ break; -+ } -+ -+ /* Translate CR to newlines (same as ICRNL in POSIX) */ -+ ch = (ch != '\r') ? ch : '\n'; -+ -+ /* We read a character! So buffer it. */ -+ canon_data->buf[canon_data->write_pos++] = ch; -+ if (canon_data->write_pos >= canon_data->size) { -+ canon_data->write_pos = 0; -+ } -+ -+ /* End of line/input (^D)? */ -+ } while ((ch != '\n') && (ch != 0x04)); -+ -+ return dio_buffer_read(wdata, buf, count); -+} -+/* }}} */ -+ -+/* {{{ dio_common_read -+ * Reads count chars to the buffer to the stream described by the stream data. -+ */ -+size_t dio_common_read(php_dio_stream_data *data, const char *buf, size_t count) { -+ -+ /* You ask for no bytes you'll get none :-) */ -+ if (!count) { -+ return 0; -+ } -+ -+ if (data->canonical) { -+ return dio_canonical_read((php_dio_win32_stream_data*)data, buf, count); -+ } else { -+ return dio_com_read(data, buf, count); -+ } -+} -+/* }}} */ -+ -+/* {{{ php_dio_stream_data -+ * Closes the php_stream. -+ */ -+int dio_common_close(php_dio_stream_data *data) { -+ php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data; -+ -+ if (data->canonical) { -+ efree(wdata->canon_data); -+ } -+ -+ if (!CloseHandle(wdata->handle)) { -+ return 0; -+ } -+ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_common_set_option -+ * Sets/gets stream options -+ */ -+int dio_common_set_option(php_dio_stream_data *data, int option, int value, void *ptrparam) { -+ COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 }; -+ int old_is_blocking = 0; -+ -+ /* Can't do timeouts or non blocking with raw windows streams :-( */ -+ if (DIO_STREAM_TYPE_SERIAL == data->stream_type) { -+ switch (option) { -+ case PHP_STREAM_OPTION_BLOCKING: -+ old_is_blocking = data->is_blocking; -+ data->is_blocking = value ? 1 : 0; -+ -+ /* Only change values if we need to change them. */ -+ if (data->is_blocking != old_is_blocking) { -+ /* If we're not blocking but don't have a timeout -+ set to return immediately */ -+ if (!data->is_blocking && !data->has_timeout) { -+ cto.ReadIntervalTimeout = MAXDWORD; -+ } -+ -+ /* If we have a timeout ignore the blocking and set -+ the total time in which to read the data */ -+ if (data->has_timeout) { -+ cto.ReadIntervalTimeout = MAXDWORD; -+ cto.ReadTotalTimeoutMultiplier = MAXDWORD; -+ cto.ReadTotalTimeoutConstant = (data->timeout_usec / 1000) + -+ (data->timeout_sec * 1000); -+ } -+ -+ if (!SetCommTimeouts(((php_dio_win32_stream_data*)data)->handle, &cto)) { -+ return PHP_STREAM_OPTION_RETURN_ERR; -+ } -+ } -+ return old_is_blocking ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR; -+ -+ case PHP_STREAM_OPTION_READ_TIMEOUT: -+ if (ptrparam) { -+ /* struct timeval is supported with PHP_WIN32 defined. */ -+ struct timeval *tv = (struct timeval*)ptrparam; -+ -+ /* A timeout of zero seconds and zero microseconds disables -+ any existing timeout. */ -+ if (tv->tv_sec || tv->tv_usec) { -+ data->timeout_sec = tv->tv_sec; -+ data->timeout_usec = tv->tv_usec; -+ data->has_timeout = -1; -+ -+ cto.ReadIntervalTimeout = MAXDWORD; -+ cto.ReadTotalTimeoutMultiplier = MAXDWORD; -+ cto.ReadTotalTimeoutConstant = (data->timeout_usec / 1000) + -+ (data->timeout_sec * 1000); -+ } else { -+ data->timeout_sec = 0; -+ data->timeout_usec = 0; -+ data->has_timeout = 0; -+ data->timed_out = 0; -+ -+ /* If we're not blocking but don't have a timeout -+ set to return immediately */ -+ if (!data->is_blocking) { -+ cto.ReadIntervalTimeout = MAXDWORD; -+ } -+ } -+ -+ if (!SetCommTimeouts(((php_dio_win32_stream_data*)data)->handle, &cto)) { -+ return PHP_STREAM_OPTION_RETURN_ERR; -+ } else { -+ return PHP_STREAM_OPTION_RETURN_OK; -+ } -+ } else { -+ return PHP_STREAM_OPTION_RETURN_ERR; -+ } -+ -+ default: -+ break; -+ } -+ } -+ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_raw_open_stream -+ * Opens the underlying stream. -+ */ -+int dio_raw_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) { -+ php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data; -+ DWORD err; -+ -+ switch(*mode) { -+ case 'r': -+ wdata->creation_disposition = OPEN_EXISTING; -+ break; -+ case 'w': -+ wdata->creation_disposition = TRUNCATE_EXISTING; -+ break; -+ case 'a': -+ wdata->creation_disposition = OPEN_ALWAYS; -+ break; -+ case 'x': -+ wdata->creation_disposition = CREATE_NEW; -+ break; -+ } -+ mode ++; -+ -+ if (*mode && (*mode != '+')) { -+ mode++; -+ } -+ -+ if (*mode && (*mode == '+')) { -+ wdata->desired_access = GENERIC_READ | GENERIC_WRITE; -+ } else if (OPEN_EXISTING == wdata->creation_disposition) { -+ wdata->desired_access = GENERIC_READ; -+ } else { -+ wdata->desired_access = GENERIC_WRITE; -+ } -+ -+ wdata->handle = CreateFile(filename, wdata->desired_access, 0, -+ NULL, wdata->creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL); -+ if (INVALID_HANDLE_VALUE == wdata->handle) { -+ err = GetLastError(); -+ switch (err) { -+ case ERROR_FILE_EXISTS: -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "File exists!"); -+ return 0; -+ -+ case ERROR_FILE_NOT_FOUND: -+ /* ERROR_FILE_NOT_FOUND with TRUNCATE_EXISTING means that -+ * the file doesn't exist so now try to create it. */ -+ if (TRUNCATE_EXISTING == wdata->creation_disposition) { -+ wdata->handle = CreateFile(filename, wdata->desired_access, 0, -+ NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); -+ if (INVALID_HANDLE_VALUE == wdata->handle) { -+ err = GetLastError(); -+ return 0; -+ } -+ } else { -+ return 0; -+ } -+ break; -+ -+ default: -+ return 0; -+ } -+ } -+ -+ /* If canonical allocate the canonical buffer. */ -+ if (data->canonical) { -+ wdata->canon_data = emalloc(sizeof(php_dio_win32_canon_data)); -+ memset(wdata->canon_data, 0, sizeof(php_dio_win32_canon_data)); -+ wdata->canon_data->size = DIO_WIN32_CANON_BUF_SIZE; -+ } -+ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_serial_init -+ * Initialises the serial port -+ */ -+static int dio_serial_init(php_dio_stream_data *data TSRMLS_DC) { -+ php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data; -+ DWORD err, rate_def, data_bits_def, stop_bits_def, parity_def; -+ DCB dcb; -+ -+ if (!dio_data_rate_to_define(data->data_rate, &rate_def)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_rate value (%d) (%d)", data->data_rate, __LINE__); -+ return 0; -+ } -+ -+ if (!dio_data_bits_to_define(data->data_bits, &data_bits_def)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid data_bits value (%d)", data->data_bits); -+ return 0; -+ } -+ -+ if (!dio_stop_bits_to_define(data->stop_bits, &stop_bits_def)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid stop_bits value (%d)", data->stop_bits); -+ return 0; -+ } -+ -+ if (!dio_parity_to_define(data->parity, &parity_def)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid parity value (%d)", data->parity); -+ return 0; -+ } -+ -+ if (!GetCommState(wdata->handle, &(wdata->olddcb))) { -+ err = GetLastError(); -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "GetCommState() failed! (%d)", err); -+ return 0; -+ } -+ -+ /* Init the DCB structure */ -+ memset(&dcb, 0, sizeof(DCB)); -+ dcb.DCBlength = sizeof(DCB); -+ -+ /* Set the communication parameters */ -+ dcb.fBinary = 1; -+ dcb.BaudRate = rate_def; -+ dcb.ByteSize = (BYTE)data_bits_def; -+ dcb.StopBits = (BYTE)stop_bits_def; -+ dcb.Parity = (BYTE)parity_def; -+ -+ /* Set the control line parameters */ -+ dcb.fDtrControl = DTR_CONTROL_DISABLE; -+ dcb.fDsrSensitivity = FALSE; -+ dcb.fOutxDsrFlow = FALSE; -+ dcb.fTXContinueOnXoff = FALSE; -+ dcb.fOutX = FALSE; -+ dcb.fInX = FALSE; -+ dcb.fErrorChar = FALSE; -+ dcb.fNull = FALSE; -+ dcb.fAbortOnError = FALSE; -+ -+ /* Hardware flow control */ -+ if (data->flow_control) { -+ dcb.fOutxCtsFlow = TRUE; -+ dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; -+ } else { -+ dcb.fOutxCtsFlow = FALSE; -+ dcb.fRtsControl = RTS_CONTROL_DISABLE; -+ } -+ -+ if (!SetCommState(wdata->handle, &dcb)) { -+ return 0; -+ } -+ -+ return 1; -+} -+/* }}} */ -+ -+ -+/* {{{ dio_serial_uninit -+ * Restores the serial settings back to their original state. -+ */ -+int dio_serial_uninit(php_dio_stream_data *data) { -+ php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data; -+ -+ if (!SetCommState(wdata->handle, &(wdata->olddcb))) { -+ return 0; -+ } -+ -+ return 1; -+} -+/* }}} */ -+ -+/* {{{ dio_serial_flush -+ * Purges the serial buffers of data. -+ */ -+int dio_serial_purge(php_dio_stream_data *data) { -+ php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data; -+ BOOL ret; -+ -+ /* Purge the canonical buffer if required */ -+ if (data->canonical && ((wdata->desired_access & GENERIC_READ) == GENERIC_READ)) { -+ wdata->canon_data->read_pos = 0; -+ wdata->canon_data->write_pos = 0; -+ } -+ -+ /* Purge the com port */ -+ if ((wdata->desired_access & (GENERIC_READ|GENERIC_WRITE)) == (GENERIC_READ|GENERIC_WRITE)) { -+ ret = PurgeComm(wdata->handle, PURGE_RXCLEAR|PURGE_TXCLEAR); -+ } else if ((wdata->desired_access & GENERIC_WRITE) == GENERIC_WRITE) { -+ ret = PurgeComm(wdata->handle, PURGE_TXCLEAR); -+ } else if ((wdata->desired_access & GENERIC_READ) == GENERIC_READ) { -+ ret = PurgeComm(wdata->handle, PURGE_RXCLEAR); -+ } -+ -+ return ret; -+} -+/* }}} */ -+ -+/* {{{ dio_serial_open_stream -+ * Opens the underlying stream. -+ */ -+int dio_serial_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC) { -+ php_dio_win32_stream_data *wdata = (php_dio_win32_stream_data*)data; -+ COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 }; -+ DWORD err; -+ -+ if (!dio_raw_open_stream(filename, mode, data TSRMLS_CC)) { -+ return 0; -+ } -+ -+ if (!GetCommTimeouts(wdata->handle, &(wdata->oldcto))) { -+ err = GetLastError(); -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "SetCommTimeouts() failed! (%d) Not a comm port?", err); -+ CloseHandle(wdata->handle); -+ return 0; -+ } -+ -+ /* If we're not blocking but don't have a timeout -+ set to return immediately */ -+ if (!data->is_blocking && !data->has_timeout) { -+ cto.ReadIntervalTimeout = MAXDWORD; -+ } -+ -+ /* If we have a timeout ignore the blocking and set -+ the total time in which to read the data */ -+ if (data->has_timeout) { -+ cto.ReadIntervalTimeout = MAXDWORD; -+ cto.ReadTotalTimeoutMultiplier = MAXDWORD; -+ cto.ReadTotalTimeoutConstant = (data->timeout_usec / 1000) + -+ (data->timeout_sec * 1000); -+ } -+ -+ if (!SetCommTimeouts(wdata->handle, &cto)) { -+ CloseHandle(wdata->handle); -+ return 0; -+ } -+ -+ if (!dio_serial_init(data TSRMLS_CC)) { -+ CloseHandle(wdata->handle); -+ return 0; -+ } -+ -+ return 1; -+} -+/* }}} */ -+ -+/* -+ * Local variables: -+ * c-basic-offset: 4 -+ * tab-width: 4 -+ * End: -+ * vim600: fdm=marker -+ * vim: sw=4 ts=4 noet -+ */ ---- /dev/null -+++ b/ext/dio/php_dio.h -@@ -0,0 +1,60 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | PHP Version 5 | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 1997-2004 The PHP Group | -+ +----------------------------------------------------------------------+ -+ | This source file is subject to version 3.0 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_0.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. | -+ +----------------------------------------------------------------------+ -+ */ -+ -+#ifndef PHP_DIO_H -+#define PHP_DIO_H -+ -+#include "php.h" -+#include "php_dio_common.h" -+#include "php_dio_stream_wrappers.h" -+ -+extern zend_module_entry dio_module_entry; -+#define phpext_dio_ptr &dio_module_entry -+ -+#define PHP_DIO_VERSION "0.0.4RC4" -+ -+/* Standard module functions. */ -+PHP_MINIT_FUNCTION(dio); -+PHP_MSHUTDOWN_FUNCTION(dio); -+PHP_RINIT_FUNCTION(dio); -+PHP_RSHUTDOWN_FUNCTION(dio); -+PHP_MINFO_FUNCTION(dio); -+ -+/* Legacy functions. */ -+PHP_FUNCTION(dio_open); -+PHP_FUNCTION(dio_truncate); -+PHP_FUNCTION(dio_stat); -+PHP_FUNCTION(dio_seek); -+PHP_FUNCTION(dio_read); -+PHP_FUNCTION(dio_write); -+PHP_FUNCTION(dio_fcntl); -+PHP_FUNCTION(dio_close); -+PHP_FUNCTION(dio_tcsetattr); -+ -+typedef struct { -+ int fd; -+} php_fd_t; -+ -+#endif -+ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * indent-tabs-mode: t -+ * End: -+ */ ---- /dev/null -+++ b/ext/dio/php_dio_common.h -@@ -0,0 +1,77 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | PHP Version 5 | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2009 Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ | This source file is subject to version 3.0 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_0.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. | -+ +----------------------------------------------------------------------+ -+ | Author: Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ */ -+ -+#ifndef PHP_DIO_COMMON_H_ -+#define PHP_DIO_COMMON_H_ -+ -+#ifdef PHP_WIN32 -+#define PHP_DIO_API __declspec(dllexport) -+#else -+#define PHP_DIO_API -+#endif -+ -+#ifdef PHP_WIN32 -+#include "php_dio_win32.h" -+#else -+#include "php_dio_posix.h" -+#endif -+ -+#define DIO_STREAM_TYPE_NONE 0 -+#define DIO_STREAM_TYPE_RAW 1 -+#define DIO_STREAM_TYPE_SERIAL 2 -+ -+long dio_convert_to_long(zval *val); -+ -+php_dio_stream_data * dio_create_stream_data(void); -+ -+void dio_init_stream_data(php_dio_stream_data *data); -+ -+void dio_assoc_array_get_basic_options(zval *options, php_dio_stream_data *data TSRMLS_DC); -+ -+void dio_assoc_array_get_serial_options(zval *options, php_dio_stream_data *data TSRMLS_DC); -+ -+void dio_stream_context_get_basic_options(php_stream_context *context, php_dio_stream_data *data TSRMLS_DC); -+ -+void dio_stream_context_get_serial_options(php_stream_context *context, php_dio_stream_data *data TSRMLS_DC); -+ -+size_t dio_common_write(php_dio_stream_data *data, const char *buf, size_t count); -+ -+size_t dio_common_read(php_dio_stream_data *data, const char *buf, size_t count); -+ -+int dio_common_close(php_dio_stream_data *data); -+ -+int dio_common_set_option(php_dio_stream_data *data, int option, int value, void *ptrparam); -+ -+int dio_raw_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC); -+ -+int dio_serial_uninit(php_dio_stream_data *data); -+ -+int dio_serial_purge(php_dio_stream_data *data); -+ -+int dio_serial_open_stream(char *filename, char *mode, php_dio_stream_data *data TSRMLS_DC); -+ -+#endif /* PHP_DIO_COMMON_H_ */ -+ -+/* -+ * Local variables: -+ * c-basic-offset: 4 -+ * tab-width: 4 -+ * End: -+ * vim600: fdm=marker -+ * vim: sw=4 ts=4 noet -+ */ ---- /dev/null -+++ b/ext/dio/php_dio_common_data.h -@@ -0,0 +1,59 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | PHP Version 5 | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2009 Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ | This source file is subject to version 3.0 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_0.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. | -+ +----------------------------------------------------------------------+ -+ | Author: Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ */ -+ -+#ifndef PHP_DIO_COMMON_DATA_H_ -+#define PHP_DIO_COMMON_DATA_H_ -+ -+/* This is the data structure 'base class'. It is common data fields used -+ * by all versions of DIO. -+ */ -+typedef struct _php_dio_stream_data { -+ /* Stream type */ -+ int stream_type; -+ /* Stream options */ -+ int end_of_file; -+#ifdef DIO_HAS_FILEPERMS -+ int has_perms; -+ int perms; -+#endif -+#ifdef DIO_NONBLOCK -+ int is_blocking; -+ int has_timeout; -+ long timeout_sec; -+ long timeout_usec; -+ int timed_out; -+#endif -+ /* Serial options */ -+ long data_rate; -+ int data_bits; -+ int stop_bits; -+ int parity; -+ int flow_control; -+ int canonical; -+} php_dio_stream_data ; -+ -+#endif /* PHP_DIO_COMMON_DATA_H_ */ -+ -+/* -+ * Local variables: -+ * c-basic-offset: 4 -+ * tab-width: 4 -+ * End: -+ * vim600: fdm=marker -+ * vim: sw=4 ts=4 noet -+ */ ---- /dev/null -+++ b/ext/dio/php_dio_posix.h -@@ -0,0 +1,70 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | PHP Version 5 | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2009 Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ | This source file is subject to version 3.0 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_0.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. | -+ +----------------------------------------------------------------------+ -+ | Author: Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ */ -+ -+#ifndef PHP_DIO_POSIX_H_ -+#define PHP_DIO_POSIX_H_ -+ -+#include -+#include -+#include -+#include -+ -+#ifdef HAVE_UNISTD_H -+#include -+#endif -+ -+#include -+#include -+ -+ -+/** -+ * Detect if we can support non blocking IO. -+ */ -+#ifdef O_NONBLOCK -+#define DIO_NONBLOCK O_NONBLOCK -+#else -+#ifdef O_NDELAY -+#define DIO_NONBLOCK O_NDELAY -+#endif -+#endif -+ -+/** -+ * POSIXy platforms have file permissions -+ */ -+#define DIO_HAS_FILEPERMS -+ -+#include "php_dio_common_data.h" -+ -+typedef struct _php_dio_posix_stream_data { -+ php_dio_stream_data common; -+ int fd; -+ int flags; -+ /* Serial options */ -+ struct termios oldtio; -+} php_dio_posix_stream_data ; -+ -+#endif /* PHP_DIO_POSIX_H_ */ -+ -+/* -+ * Local variables: -+ * c-basic-offset: 4 -+ * tab-width: 4 -+ * End: -+ * vim600: fdm=marker -+ * vim: sw=4 ts=4 noet -+ */ ---- /dev/null -+++ b/ext/dio/php_dio_stream_wrappers.h -@@ -0,0 +1,51 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | PHP Version 5 | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2009 Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ | This source file is subject to version 3.0 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_0.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. | -+ +----------------------------------------------------------------------+ -+ | Author: Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ */ -+ -+#ifndef PHP_DIO_STREAM_WRAPPERS_H_ -+#define PHP_DIO_STREAM_WRAPPERS_H_ -+ -+#define DIO_RAW_STREAM_NAME "dio.raw" -+#define DIO_RAW_STREAM_PROTOCOL "dio.raw://" -+#define DIO_SERIAL_STREAM_NAME "dio.serial" -+#define DIO_SERIAL_STREAM_PROTOCOL "dio.serial://" -+ -+/* To support PHP 5.4 and later */ -+#if PHP_VERSION_ID < 50399 -+#define DIO_SAFE_MODE_CHECK(f, m) (PG(safe_mode) && !php_checkuid(f, m, CHECKUID_CHECK_MODE_PARAM)) -+#else -+#define DIO_SAFE_MODE_CHECK(f, m) (0) -+#endif -+ -+extern php_stream_wrapper php_dio_raw_stream_wrapper; -+ -+PHP_FUNCTION(dio_raw); -+ -+extern php_stream_wrapper php_dio_serial_stream_wrapper; -+ -+PHP_FUNCTION(dio_serial); -+ -+#endif /* PHP_DIO_STREAM_WRAPPERS_H_ */ -+ -+/* -+ * Local variables: -+ * c-basic-offset: 4 -+ * tab-width: 4 -+ * End: -+ * vim600: fdm=marker -+ * vim: sw=4 ts=4 noet -+ */ ---- /dev/null -+++ b/ext/dio/php_dio_win32.h -@@ -0,0 +1,62 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | PHP Version 5 | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 2009 Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ | This source file is subject to version 3.0 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_0.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. | -+ +----------------------------------------------------------------------+ -+ | Author: Melanie Rhianna Lewis | -+ +----------------------------------------------------------------------+ -+ */ -+ -+#ifndef PHP_DIO_WIN32_H_ -+#define PHP_DIO_WIN32_H_ -+ -+#include -+ -+/* Windows platform can do non blocking. */ -+#define DIO_NONBLOCK -+ -+#include "php_dio_common_data.h" -+ -+#define DIO_WIN32_CANON_BUF_SIZE 8192 -+ -+/* This is the buffer information when reading in canonical mode. Data is -+ read right up to either buffer being full or a newline being read. Excess -+ data will be retained in the buffer until the next read. */ -+typedef struct _php_dio_win32_canon_data { -+ size_t size; -+ size_t read_pos; -+ size_t write_pos; -+ char buf[DIO_WIN32_CANON_BUF_SIZE]; -+ -+} php_dio_win32_canon_data; -+ -+typedef struct _php_dio_win32_stream_data { -+ php_dio_stream_data common; -+ HANDLE handle; -+ DWORD desired_access; -+ DWORD creation_disposition; -+ DCB olddcb; -+ COMMTIMEOUTS oldcto; -+ php_dio_win32_canon_data *canon_data; -+ -+} php_dio_win32_stream_data ; -+ -+#endif /* PHP_DIO_WIN32_H_ */ -+ -+/* -+ * Local variables: -+ * c-basic-offset: 4 -+ * tab-width: 4 -+ * End: -+ * vim600: fdm=marker -+ * vim: sw=4 ts=4 noet -+ */ ---- /dev/null -+++ b/ext/dio/tests/001.phpt -@@ -0,0 +1,23 @@ -+--TEST-- -+Test dio legacy open -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECT-- -+Legacy open passed ---- /dev/null -+++ b/ext/dio/tests/dio_raw_stream_001.phpt -@@ -0,0 +1,24 @@ -+--TEST-- -+Test dio raw stream open -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECT-- -+Raw open passed ---- /dev/null -+++ b/ext/dio/tests/dio_raw_stream_002.phpt -@@ -0,0 +1,27 @@ -+--TEST-- -+Test dio raw stream close -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECT-- -+Raw close passed ---- /dev/null -+++ b/ext/dio/tests/dio_raw_stream_003.phpt -@@ -0,0 +1,29 @@ -+--TEST-- -+Test dio raw stream write -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECT-- -+Raw write passed ---- /dev/null -+++ b/ext/dio/tests/dio_raw_stream_004.phpt -@@ -0,0 +1,46 @@ -+--TEST-- -+Test dio raw read -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECT-- -+Raw read passed ---- /dev/null -+++ b/ext/dio/tests/dio_raw_stream_005.phpt -@@ -0,0 +1,45 @@ -+--TEST-- -+Test dio eof read -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECT-- -+Raw feof passed ---- /dev/null -+++ b/ext/dio/tests/dio_raw_stream_006.phpt -@@ -0,0 +1,46 @@ -+--TEST-- -+Test dio raw read -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECT-- -+Raw set blocking passed ---- /dev/null -+++ b/ext/dio/tests/dio_raw_stream_007.phpt -@@ -0,0 +1,22 @@ -+--TEST-- -+Test dio_raw() call -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECT-- -+dio_raw passed diff --git a/lang/php5/patches/011-PECL-dio-additional-baudrates.patch b/lang/php5/patches/011-PECL-dio-additional-baudrates.patch deleted file mode 100644 index fc534d022..000000000 --- a/lang/php5/patches/011-PECL-dio-additional-baudrates.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- a/ext/dio/dio.c -+++ b/ext/dio/dio.c -@@ -501,6 +501,26 @@ PHP_FUNCTION(dio_tcsetattr) - - /* assign to correct values... */ - switch (Baud_Rate) { -+#ifdef B460800 -+ case 460800: -+ BAUD = B460800; -+ break; -+#endif -+#ifdef B230400 -+ case 230400: -+ BAUD = B230400; -+ break; -+#endif -+#ifdef B115200 -+ case 115200: -+ BAUD = B115200; -+ break; -+#endif -+#ifdef B57600 -+ case 57600: -+ BAUD = B57600; -+ break; -+#endif - case 38400: - BAUD = B38400; - break; diff --git a/lang/php5/patches/020-PECL-add-libevent.patch b/lang/php5/patches/020-PECL-add-libevent.patch deleted file mode 100644 index 7e8ede653..000000000 --- a/lang/php5/patches/020-PECL-add-libevent.patch +++ /dev/null @@ -1,1857 +0,0 @@ ---- /dev/null -+++ b/ext/libevent/CREDITS -@@ -0,0 +1 @@ -+Antony Dovgal, Arnaud Le Blanc ---- /dev/null -+++ b/ext/libevent/config.m4 -@@ -0,0 +1,52 @@ -+dnl $Id: config.m4 287913 2009-08-31 08:45:42Z tony2001 $ -+ -+PHP_ARG_WITH(libevent, for libevent support, -+[ --with-libevent Include libevent support]) -+ -+if test "$PHP_LIBEVENT" != "no"; then -+ SEARCH_PATH="/usr /usr/local" -+ SEARCH_FOR="/include/event.h" -+ -+ if test "$PHP_LIBEVENT" = "yes"; then -+ AC_MSG_CHECKING([for libevent headers in default path]) -+ for i in $SEARCH_PATH ; do -+ if test -r $i/$SEARCH_FOR; then -+ LIBEVENT_DIR=$i -+ AC_MSG_RESULT(found in $i) -+ fi -+ done -+ else -+ AC_MSG_CHECKING([for libevent headers in $PHP_LIBEVENT]) -+ if test -r $PHP_LIBEVENT/$SEARCH_FOR; then -+ LIBEVENT_DIR=$PHP_LIBEVENT -+ AC_MSG_RESULT([found]) -+ fi -+ fi -+ -+ if test -z "$LIBEVENT_DIR"; then -+ AC_MSG_RESULT([not found]) -+ AC_MSG_ERROR([Cannot find libevent headers]) -+ fi -+ -+ PHP_ADD_INCLUDE($LIBEVENT_DIR/include) -+ -+ LIBNAME=event -+ LIBSYMBOL=event_base_new -+ -+ if test "x$PHP_LIBDIR" = "x"; then -+ PHP_LIBDIR=lib -+ fi -+ -+ PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, -+ [ -+ PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $LIBEVENT_DIR/$PHP_LIBDIR, LIBEVENT_SHARED_LIBADD) -+ ],[ -+ AC_MSG_ERROR([wrong libevent version {1.4.+ is required} or lib not found]) -+ ],[ -+ -L$LIBEVENT_DIR/$PHP_LIBDIR -+ ]) -+ -+ PHP_ADD_EXTENSION_DEP(libevent, sockets, true) -+ PHP_SUBST(LIBEVENT_SHARED_LIBADD) -+ PHP_NEW_EXTENSION(libevent, libevent.c, $ext_shared) -+fi ---- /dev/null -+++ b/ext/libevent/libevent.c -@@ -0,0 +1,1663 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | PHP Version 5 | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 1997-2008 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. | -+ +----------------------------------------------------------------------+ -+ | Author: Antony Dovgal | -+ | Arnaud Le Blanc | -+ +----------------------------------------------------------------------+ -+*/ -+ -+/* $Id: libevent.c 318910 2011-11-08 12:34:37Z tony2001 $ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include "php.h" -+#include "php_ini.h" -+#include "ext/standard/info.h" -+#include "php_streams.h" -+#include "php_network.h" -+#include "php_libevent.h" -+ -+#include -+ -+#if PHP_VERSION_ID >= 50301 && (HAVE_SOCKETS || defined(COMPILE_DL_SOCKETS)) -+# include "ext/sockets/php_sockets.h" -+# define LIBEVENT_SOCKETS_SUPPORT -+#endif -+ -+#ifndef ZEND_FETCH_RESOURCE_NO_RETURN -+# define ZEND_FETCH_RESOURCE_NO_RETURN(rsrc, rsrc_type, passed_id, default_id, resource_type_name, resource_type) \ -+ (rsrc = (rsrc_type) zend_fetch_resource(passed_id TSRMLS_CC, default_id, resource_type_name, NULL, 1, resource_type)) -+#endif -+ -+#include -+ -+#if PHP_MAJOR_VERSION < 5 -+# ifdef PHP_WIN32 -+typedef SOCKET php_socket_t; -+# else -+typedef int php_socket_t; -+# endif -+ -+# ifdef ZTS -+# define TSRMLS_FETCH_FROM_CTX(ctx) void ***tsrm_ls = (void ***) ctx -+# define TSRMLS_SET_CTX(ctx) ctx = (void ***) tsrm_ls -+# else -+# define TSRMLS_FETCH_FROM_CTX(ctx) -+# define TSRMLS_SET_CTX(ctx) -+# endif -+ -+# ifndef Z_ADDREF_P -+# define Z_ADDREF_P(x) (x)->refcount++ -+# endif -+#endif -+ -+static int le_event_base; -+static int le_event; -+static int le_bufferevent; -+ -+#ifdef COMPILE_DL_LIBEVENT -+ZEND_GET_MODULE(libevent) -+#endif -+ -+typedef struct _php_event_base_t { /* {{{ */ -+ struct event_base *base; -+ int rsrc_id; -+ zend_uint events; -+} php_event_base_t; -+/* }}} */ -+ -+typedef struct _php_event_callback_t { /* {{{ */ -+ zval *func; -+ zval *arg; -+} php_event_callback_t; -+/* }}} */ -+ -+typedef struct _php_event_t { /* {{{ */ -+ struct event *event; -+ int rsrc_id; -+ int stream_id; -+ php_event_base_t *base; -+ php_event_callback_t *callback; -+#ifdef ZTS -+ void ***thread_ctx; -+#endif -+ int in_free; -+} php_event_t; -+/* }}} */ -+ -+typedef struct _php_bufferevent_t { /* {{{ */ -+ struct bufferevent *bevent; -+ int rsrc_id; -+ php_event_base_t *base; -+ zval *readcb; -+ zval *writecb; -+ zval *errorcb; -+ zval *arg; -+#ifdef ZTS -+ void ***thread_ctx; -+#endif -+} php_bufferevent_t; -+/* }}} */ -+ -+#define ZVAL_TO_BASE(zval, base) \ -+ ZEND_FETCH_RESOURCE(base, php_event_base_t *, &zval, -1, "event base", le_event_base) -+ -+#define ZVAL_TO_EVENT(zval, event) \ -+ ZEND_FETCH_RESOURCE(event, php_event_t *, &zval, -1, "event", le_event) -+ -+#define ZVAL_TO_BEVENT(zval, bevent) \ -+ ZEND_FETCH_RESOURCE(bevent, php_bufferevent_t *, &zval, -1, "buffer event", le_bufferevent) -+ -+/* {{{ internal funcs */ -+ -+static inline void _php_event_callback_free(php_event_callback_t *callback) /* {{{ */ -+{ -+ if (!callback) { -+ return; -+ } -+ -+ zval_ptr_dtor(&callback->func); -+ if (callback->arg) { -+ zval_ptr_dtor(&callback->arg); -+ } -+ efree(callback); -+} -+/* }}} */ -+ -+static void _php_event_base_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ -+{ -+ php_event_base_t *base = (php_event_base_t*)rsrc->ptr; -+ -+ event_base_free(base->base); -+ efree(base); -+} -+/* }}} */ -+ -+static void _php_event_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ -+{ -+ php_event_t *event = (php_event_t*)rsrc->ptr; -+ int base_id = -1; -+ -+ if (event->in_free) { -+ return; -+ } -+ -+ event->in_free = 1; -+ -+ if (event->base) { -+ base_id = event->base->rsrc_id; -+ --event->base->events; -+ } -+ if (event->stream_id >= 0) { -+ zend_list_delete(event->stream_id); -+ } -+ event_del(event->event); -+ -+ _php_event_callback_free(event->callback); -+ efree(event->event); -+ efree(event); -+ -+ if (base_id >= 0) { -+ zend_list_delete(base_id); -+ } -+} -+/* }}} */ -+ -+static void _php_bufferevent_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ -+{ -+ php_bufferevent_t *bevent = (php_bufferevent_t*)rsrc->ptr; -+ int base_id = -1; -+ -+ if (bevent->base) { -+ base_id = bevent->base->rsrc_id; -+ --bevent->base->events; -+ } -+ if (bevent->readcb) { -+ zval_ptr_dtor(&(bevent->readcb)); -+ } -+ if (bevent->writecb) { -+ zval_ptr_dtor(&(bevent->writecb)); -+ } -+ if (bevent->errorcb) { -+ zval_ptr_dtor(&(bevent->errorcb)); -+ } -+ if (bevent->arg) { -+ zval_ptr_dtor(&(bevent->arg)); -+ } -+ -+ bufferevent_free(bevent->bevent); -+ efree(bevent); -+ -+ if (base_id >= 0) { -+ zend_list_delete(base_id); -+ } -+} -+/* }}} */ -+ -+static void _php_event_callback(int fd, short events, void *arg) /* {{{ */ -+{ -+ zval *args[3]; -+ php_event_t *event = (php_event_t *)arg; -+ php_event_callback_t *callback; -+ zval retval; -+ TSRMLS_FETCH_FROM_CTX(event ? event->thread_ctx : NULL); -+ -+ if (!event || !event->callback || !event->base) { -+ return; -+ } -+ -+ callback = event->callback; -+ -+ MAKE_STD_ZVAL(args[0]); -+ if (event->stream_id >= 0) { -+ ZVAL_RESOURCE(args[0], event->stream_id); -+ zend_list_addref(event->stream_id); -+ } else { -+ ZVAL_NULL(args[0]); -+ } -+ -+ MAKE_STD_ZVAL(args[1]); -+ ZVAL_LONG(args[1], events); -+ -+ args[2] = callback->arg; -+ Z_ADDREF_P(callback->arg); -+ -+ if (call_user_function(EG(function_table), NULL, callback->func, &retval, 3, args TSRMLS_CC) == SUCCESS) { -+ zval_dtor(&retval); -+ } -+ -+ zval_ptr_dtor(&(args[0])); -+ zval_ptr_dtor(&(args[1])); -+ zval_ptr_dtor(&(args[2])); -+ -+} -+/* }}} */ -+ -+static void _php_bufferevent_readcb(struct bufferevent *be, void *arg) /* {{{ */ -+{ -+ zval *args[2]; -+ zval retval; -+ php_bufferevent_t *bevent = (php_bufferevent_t *)arg; -+ TSRMLS_FETCH_FROM_CTX(bevent ? bevent->thread_ctx : NULL); -+ -+ if (!bevent || !bevent->base || !bevent->readcb) { -+ return; -+ } -+ -+ MAKE_STD_ZVAL(args[0]); -+ ZVAL_RESOURCE(args[0], bevent->rsrc_id); -+ zend_list_addref(bevent->rsrc_id); /* we do refcount-- later in zval_ptr_dtor */ -+ -+ args[1] = bevent->arg; -+ Z_ADDREF_P(args[1]); -+ -+ if (call_user_function(EG(function_table), NULL, bevent->readcb, &retval, 2, args TSRMLS_CC) == SUCCESS) { -+ zval_dtor(&retval); -+ } -+ -+ zval_ptr_dtor(&(args[0])); -+ zval_ptr_dtor(&(args[1])); -+ -+} -+/* }}} */ -+ -+static void _php_bufferevent_writecb(struct bufferevent *be, void *arg) /* {{{ */ -+{ -+ zval *args[2]; -+ zval retval; -+ php_bufferevent_t *bevent = (php_bufferevent_t *)arg; -+ TSRMLS_FETCH_FROM_CTX(bevent ? bevent->thread_ctx : NULL); -+ -+ if (!bevent || !bevent->base || !bevent->writecb) { -+ return; -+ } -+ -+ MAKE_STD_ZVAL(args[0]); -+ ZVAL_RESOURCE(args[0], bevent->rsrc_id); -+ zend_list_addref(bevent->rsrc_id); /* we do refcount-- later in zval_ptr_dtor */ -+ -+ args[1] = bevent->arg; -+ Z_ADDREF_P(args[1]); -+ -+ if (call_user_function(EG(function_table), NULL, bevent->writecb, &retval, 2, args TSRMLS_CC) == SUCCESS) { -+ zval_dtor(&retval); -+ } -+ -+ zval_ptr_dtor(&(args[0])); -+ zval_ptr_dtor(&(args[1])); -+ -+} -+/* }}} */ -+ -+static void _php_bufferevent_errorcb(struct bufferevent *be, short what, void *arg) /* {{{ */ -+{ -+ zval *args[3]; -+ zval retval; -+ php_bufferevent_t *bevent = (php_bufferevent_t *)arg; -+ TSRMLS_FETCH_FROM_CTX(bevent ? bevent->thread_ctx : NULL); -+ -+ if (!bevent || !bevent->base || !bevent->errorcb) { -+ return; -+ } -+ -+ MAKE_STD_ZVAL(args[0]); -+ ZVAL_RESOURCE(args[0], bevent->rsrc_id); -+ zend_list_addref(bevent->rsrc_id); /* we do refcount-- later in zval_ptr_dtor */ -+ -+ MAKE_STD_ZVAL(args[1]); -+ ZVAL_LONG(args[1], what); -+ -+ args[2] = bevent->arg; -+ Z_ADDREF_P(args[2]); -+ -+ if (call_user_function(EG(function_table), NULL, bevent->errorcb, &retval, 3, args TSRMLS_CC) == SUCCESS) { -+ zval_dtor(&retval); -+ } -+ -+ zval_ptr_dtor(&(args[0])); -+ zval_ptr_dtor(&(args[1])); -+ zval_ptr_dtor(&(args[2])); -+ -+} -+/* }}} */ -+ -+/* }}} */ -+ -+ -+/* {{{ proto resource event_base_new() -+ */ -+static PHP_FUNCTION(event_base_new) -+{ -+ php_event_base_t *base; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") != SUCCESS) { -+ return; -+ } -+ -+ base = emalloc(sizeof(php_event_base_t)); -+ base->base = event_base_new(); -+ if (!base->base) { -+ efree(base); -+ RETURN_FALSE; -+ } -+ -+ base->events = 0; -+ -+#if PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 4 -+ base->rsrc_id = zend_list_insert(base, le_event_base TSRMLS_CC); -+#else -+ base->rsrc_id = zend_list_insert(base, le_event_base); -+#endif -+ RETURN_RESOURCE(base->rsrc_id); -+} -+/* }}} */ -+ -+/* {{{ proto void event_base_free(resource base) -+ */ -+static PHP_FUNCTION(event_base_free) -+{ -+ zval *zbase; -+ php_event_base_t *base; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zbase) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BASE(zbase, base); -+ -+ if (base->events > 0) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "base has events attached to it and cannot be freed"); -+ RETURN_FALSE; -+ } -+ -+ zend_list_delete(base->rsrc_id); -+} -+/* }}} */ -+ -+/* {{{ proto int event_base_loop(resource base[, int flags]) -+ */ -+static PHP_FUNCTION(event_base_loop) -+{ -+ zval *zbase; -+ php_event_base_t *base; -+ long flags = 0; -+ int ret; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zbase, &flags) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BASE(zbase, base); -+ zend_list_addref(base->rsrc_id); /* make sure the base cannot be destroyed during the loop */ -+ ret = event_base_loop(base->base, flags); -+ zend_list_delete(base->rsrc_id); -+ -+ RETURN_LONG(ret); -+} -+/* }}} */ -+ -+/* {{{ proto bool event_base_loopbreak(resource base) -+ */ -+static PHP_FUNCTION(event_base_loopbreak) -+{ -+ zval *zbase; -+ php_event_base_t *base; -+ int ret; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zbase) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BASE(zbase, base); -+ ret = event_base_loopbreak(base->base); -+ if (ret == 0) { -+ RETURN_TRUE; -+ } -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+/* {{{ proto bool event_base_loopexit(resource base[, int timeout]) -+ */ -+static PHP_FUNCTION(event_base_loopexit) -+{ -+ zval *zbase; -+ php_event_base_t *base; -+ int ret; -+ long timeout = -1; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zbase, &timeout) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BASE(zbase, base); -+ -+ if (timeout < 0) { -+ ret = event_base_loopexit(base->base, NULL); -+ } else { -+ struct timeval time; -+ -+ time.tv_usec = timeout % 1000000; -+ time.tv_sec = timeout / 1000000; -+ ret = event_base_loopexit(base->base, &time); -+ } -+ -+ if (ret == 0) { -+ RETURN_TRUE; -+ } -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+/* {{{ proto bool event_base_set(resource event, resource base) -+ */ -+static PHP_FUNCTION(event_base_set) -+{ -+ zval *zbase, *zevent; -+ php_event_base_t *base, *old_base; -+ php_event_t *event; -+ int ret; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &zevent, &zbase) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BASE(zbase, base); -+ ZVAL_TO_EVENT(zevent, event); -+ -+ old_base = event->base; -+ ret = event_base_set(base->base, event->event); -+ -+ if (ret == 0) { -+ if (base != old_base) { -+ /* make sure the base is destroyed after the event */ -+ zend_list_addref(base->rsrc_id); -+ ++base->events; -+ } -+ -+ if (old_base) { -+ --old_base->events; -+ zend_list_delete(old_base->rsrc_id); -+ } -+ -+ event->base = base; -+ RETURN_TRUE; -+ } -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+/* {{{ proto bool event_base_priority_init(resource base, int npriorities) -+ */ -+static PHP_FUNCTION(event_base_priority_init) -+{ -+ zval *zbase; -+ php_event_base_t *base; -+ long npriorities; -+ int ret; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zbase, &npriorities) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BASE(zbase, base); -+ -+ if (npriorities < 0) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "npriorities cannot be less than zero"); -+ RETURN_FALSE; -+ } -+ -+ ret = event_base_priority_init(base->base, npriorities); -+ if (ret == 0) { -+ RETURN_TRUE; -+ } -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+ -+/* {{{ proto resource event_new() -+ */ -+static PHP_FUNCTION(event_new) -+{ -+ php_event_t *event; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") != SUCCESS) { -+ return; -+ } -+ -+ event = emalloc(sizeof(php_event_t)); -+ event->event = ecalloc(1, sizeof(struct event)); -+ -+ event->stream_id = -1; -+ event->callback = NULL; -+ event->base = NULL; -+ event->in_free = 0; -+ TSRMLS_SET_CTX(event->thread_ctx); -+ -+#if PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 4 -+ event->rsrc_id = zend_list_insert(event, le_event TSRMLS_CC); -+#else -+ event->rsrc_id = zend_list_insert(event, le_event); -+#endif -+ RETURN_RESOURCE(event->rsrc_id); -+} -+/* }}} */ -+ -+/* {{{ proto void event_free(resource event) -+ */ -+static PHP_FUNCTION(event_free) -+{ -+ zval *zevent; -+ php_event_t *event; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zevent) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_EVENT(zevent, event); -+ zend_list_delete(event->rsrc_id); -+} -+/* }}} */ -+ -+/* {{{ proto bool event_add(resource event[, int timeout]) -+ */ -+static PHP_FUNCTION(event_add) -+{ -+ zval *zevent; -+ php_event_t *event; -+ int ret; -+ long timeout = -1; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zevent, &timeout) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_EVENT(zevent, event); -+ -+ if (!event->base) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add event without an event base"); -+ RETURN_FALSE; -+ } -+ -+ if (timeout < 0) { -+ ret = event_add(event->event, NULL); -+ } else { -+ struct timeval time; -+ -+ time.tv_usec = timeout % 1000000; -+ time.tv_sec = timeout / 1000000; -+ ret = event_add(event->event, &time); -+ } -+ -+ if (ret != 0) { -+ RETURN_FALSE; -+ } -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto bool event_set(resource event, mixed fd, int events, mixed callback[, mixed arg]) -+ */ -+static PHP_FUNCTION(event_set) -+{ -+ zval *zevent, **fd, *zcallback, *zarg = NULL; -+ php_event_t *event; -+ long events; -+ php_event_callback_t *callback, *old_callback; -+ char *func_name; -+ php_stream *stream; -+ php_socket_t file_desc; -+#ifdef LIBEVENT_SOCKETS_SUPPORT -+ php_socket *php_sock; -+#endif -+ int ret; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZlz|z", &zevent, &fd, &events, &zcallback, &zarg) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_EVENT(zevent, event); -+ -+ if (events & EV_SIGNAL) { -+ /* signal support */ -+ convert_to_long_ex(fd); -+ file_desc = Z_LVAL_PP(fd); -+ if (file_desc < 0 || file_desc >= NSIG) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid signal passed"); -+ RETURN_FALSE; -+ } -+ } else { -+ if (Z_TYPE_PP(fd) == IS_RESOURCE) { -+ if (ZEND_FETCH_RESOURCE_NO_RETURN(stream, php_stream *, fd, -1, NULL, php_file_le_stream())) { -+ if (php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&file_desc, 1) != SUCCESS || file_desc < 0) { -+ RETURN_FALSE; -+ } -+ } else { -+#ifdef LIBEVENT_SOCKETS_SUPPORT -+ if (ZEND_FETCH_RESOURCE_NO_RETURN(php_sock, php_socket *, fd, -1, NULL, php_sockets_le_socket())) { -+ file_desc = php_sock->bsd_socket; -+ } else { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "fd argument must be either valid PHP stream or valid PHP socket resource"); -+ RETURN_FALSE; -+ } -+#else -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "fd argument must be valid PHP stream resource"); -+ RETURN_FALSE; -+#endif -+ } -+ } else if (Z_TYPE_PP(fd) == IS_LONG) { -+ file_desc = Z_LVAL_PP(fd); -+ if (file_desc < 0) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid file descriptor passed"); -+ RETURN_FALSE; -+ } -+ } else { -+#ifdef LIBEVENT_SOCKETS_SUPPORT -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "fd argument must be valid PHP stream or socket resource or a file descriptor of type long"); -+#else -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "fd argument must be valid PHP stream resource or a file descriptor of type long"); -+#endif -+ RETURN_FALSE; -+ } -+ } -+ -+ if (!zend_is_callable(zcallback, 0, &func_name TSRMLS_CC)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s' is not a valid callback", func_name); -+ efree(func_name); -+ RETURN_FALSE; -+ } -+ efree(func_name); -+ -+ zval_add_ref(&zcallback); -+ if (zarg) { -+ zval_add_ref(&zarg); -+ } else { -+ ALLOC_INIT_ZVAL(zarg); -+ } -+ -+ callback = emalloc(sizeof(php_event_callback_t)); -+ callback->func = zcallback; -+ callback->arg = zarg; -+ -+ old_callback = event->callback; -+ event->callback = callback; -+ if (events & EV_SIGNAL) { -+ event->stream_id = -1; -+ } else { -+ zend_list_addref(Z_LVAL_PP(fd)); -+ event->stream_id = Z_LVAL_PP(fd); -+ } -+ -+ event_set(event->event, (int)file_desc, (short)events, _php_event_callback, event); -+ -+ if (old_callback) { -+ _php_event_callback_free(old_callback); -+ } -+ -+ if (event->base) { -+ ret = event_base_set(event->base->base, event->event); -+ if (ret != 0) { -+ RETURN_FALSE; -+ } -+ } -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto bool event_del(resource event) -+ */ -+static PHP_FUNCTION(event_del) -+{ -+ zval *zevent; -+ php_event_t *event; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zevent) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_EVENT(zevent, event); -+ -+ if (!event->base) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to delete event without an event base"); -+ RETURN_FALSE; -+ } -+ -+ if (event_del(event->event) == 0) { -+ RETURN_TRUE; -+ } -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+/* {{{ proto bool event_priority_set(resource event, int priority) -+ */ -+static PHP_FUNCTION(event_priority_set) -+{ -+ zval *zevent; -+ php_event_t *event; -+ long priority; -+ int ret; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zevent, &priority) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_EVENT(zevent, event); -+ -+ if (!event->base) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set event priority without an event base"); -+ RETURN_FALSE; -+ } -+ -+ ret = event_priority_set(event->event, priority); -+ -+ if (ret == 0) { -+ RETURN_TRUE; -+ } -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+/* {{{ proto bool event_timer_set(resource event, mixed callback[, mixed arg]) -+ */ -+static PHP_FUNCTION(event_timer_set) -+{ -+ zval *zevent, *zcallback, *zarg = NULL; -+ php_event_t *event; -+ php_event_callback_t *callback, *old_callback; -+ char *func_name; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|z", &zevent, &zcallback, &zarg) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_EVENT(zevent, event); -+ -+ if (!zend_is_callable(zcallback, 0, &func_name TSRMLS_CC)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s' is not a valid callback", func_name); -+ efree(func_name); -+ RETURN_FALSE; -+ } -+ efree(func_name); -+ -+ zval_add_ref(&zcallback); -+ if (zarg) { -+ zval_add_ref(&zarg); -+ } else { -+ ALLOC_INIT_ZVAL(zarg); -+ } -+ -+ callback = emalloc(sizeof(php_event_callback_t)); -+ callback->func = zcallback; -+ callback->arg = zarg; -+ -+ old_callback = event->callback; -+ event->callback = callback; -+ if (event->stream_id >= 0) { -+ zend_list_delete(event->stream_id); -+ } -+ event->stream_id = -1; -+ -+ event_set(event->event, -1, 0, _php_event_callback, event); -+ -+ if (old_callback) { -+ _php_event_callback_free(old_callback); -+ } -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto bool event_timer_pending(resource event[, int timeout]) -+ */ -+static PHP_FUNCTION(event_timer_pending) -+{ -+ zval *zevent; -+ php_event_t *event; -+ int ret; -+ long timeout = -1; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zevent, &timeout) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_EVENT(zevent, event); -+ -+ if (timeout < 0) { -+ ret = event_pending(event->event, EV_TIMEOUT, NULL); -+ } else { -+ struct timeval time; -+ -+ time.tv_usec = timeout % 1000000; -+ time.tv_sec = timeout / 1000000; -+ ret = event_pending(event->event, EV_TIMEOUT, &time); -+ } -+ -+ if (ret != 0) { -+ RETURN_FALSE; -+ } -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+ -+ -+/* {{{ proto resource event_buffer_new(mixed fd, mixed readcb, mixed writecb, mixed errorcb[, mixed arg]) -+ */ -+static PHP_FUNCTION(event_buffer_new) -+{ -+ php_bufferevent_t *bevent; -+ php_stream *stream; -+ zval *zfd, *zreadcb, *zwritecb, *zerrorcb, *zarg = NULL; -+ php_socket_t fd; -+ char *func_name; -+#ifdef LIBEVENT_SOCKETS_SUPPORT -+ php_socket *php_sock; -+#endif -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzzz|z", &zfd, &zreadcb, &zwritecb, &zerrorcb, &zarg) != SUCCESS) { -+ return; -+ } -+ -+ if (Z_TYPE_P(zfd) == IS_RESOURCE) { -+ if (ZEND_FETCH_RESOURCE_NO_RETURN(stream, php_stream *, &zfd, -1, NULL, php_file_le_stream())) { -+ if (php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&fd, 1) != SUCCESS || fd < 0) { -+ RETURN_FALSE; -+ } -+ } else { -+#ifdef LIBEVENT_SOCKETS_SUPPORT -+ if (ZEND_FETCH_RESOURCE_NO_RETURN(php_sock, php_socket *, &zfd, -1, NULL, php_sockets_le_socket())) { -+ fd = php_sock->bsd_socket; -+ } else { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "fd argument must be valid PHP stream or socket resource or a file descriptor of type long"); -+ RETURN_FALSE; -+ } -+#else -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "fd argument must be valid PHP stream resource or a file descriptor of type long"); -+ RETURN_FALSE; -+#endif -+ } -+ } else if (Z_TYPE_P(zfd) == IS_LONG) { -+ fd = Z_LVAL_P(zfd); -+ } else { -+#ifdef LIBEVENT_SOCKETS_SUPPORT -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "fd argument must be valid PHP stream or socket resource or a file descriptor of type long"); -+#else -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "fd argument must be valid PHP stream resource or a file descriptor of type long"); -+#endif -+ RETURN_FALSE; -+ } -+ -+ if (Z_TYPE_P(zreadcb) != IS_NULL) { -+ if (!zend_is_callable(zreadcb, 0, &func_name TSRMLS_CC)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s' is not a valid read callback", func_name); -+ efree(func_name); -+ RETURN_FALSE; -+ } -+ efree(func_name); -+ } else { -+ zreadcb = NULL; -+ } -+ -+ if (Z_TYPE_P(zwritecb) != IS_NULL) { -+ if (!zend_is_callable(zwritecb, 0, &func_name TSRMLS_CC)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s' is not a valid write callback", func_name); -+ efree(func_name); -+ RETURN_FALSE; -+ } -+ efree(func_name); -+ } else { -+ zwritecb = NULL; -+ } -+ -+ if (!zend_is_callable(zerrorcb, 0, &func_name TSRMLS_CC)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s' is not a valid error callback", func_name); -+ efree(func_name); -+ RETURN_FALSE; -+ } -+ efree(func_name); -+ -+ bevent = emalloc(sizeof(php_bufferevent_t)); -+ bevent->bevent = bufferevent_new(fd, _php_bufferevent_readcb, _php_bufferevent_writecb, _php_bufferevent_errorcb, bevent); -+ -+ bevent->base = NULL; -+ -+ if (zreadcb) { -+ zval_add_ref(&zreadcb); -+ } -+ bevent->readcb = zreadcb; -+ -+ if (zwritecb) { -+ zval_add_ref(&zwritecb); -+ } -+ bevent->writecb = zwritecb; -+ -+ zval_add_ref(&zerrorcb); -+ bevent->errorcb = zerrorcb; -+ -+ if (zarg) { -+ zval_add_ref(&zarg); -+ bevent->arg = zarg; -+ } else { -+ ALLOC_INIT_ZVAL(bevent->arg); -+ } -+ -+ TSRMLS_SET_CTX(bevent->thread_ctx); -+ -+#if PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 4 -+ bevent->rsrc_id = zend_list_insert(bevent, le_bufferevent TSRMLS_CC); -+#else -+ bevent->rsrc_id = zend_list_insert(bevent, le_bufferevent); -+#endif -+ RETURN_RESOURCE(bevent->rsrc_id); -+} -+/* }}} */ -+ -+/* {{{ proto void event_buffer_free(resource bevent) -+ */ -+static PHP_FUNCTION(event_buffer_free) -+{ -+ zval *zbevent; -+ php_bufferevent_t *bevent; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zbevent) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BEVENT(zbevent, bevent); -+ zend_list_delete(bevent->rsrc_id); -+} -+/* }}} */ -+ -+/* {{{ proto bool event_buffer_base_set(resource bevent, resource base) -+ */ -+static PHP_FUNCTION(event_buffer_base_set) -+{ -+ zval *zbase, *zbevent; -+ php_event_base_t *base, *old_base; -+ php_bufferevent_t *bevent; -+ int ret; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &zbevent, &zbase) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BASE(zbase, base); -+ ZVAL_TO_BEVENT(zbevent, bevent); -+ -+ old_base = bevent->base; -+ ret = bufferevent_base_set(base->base, bevent->bevent); -+ -+ if (ret == 0) { -+ if (base != old_base) { -+ /* make sure the base is destroyed after the event */ -+ zend_list_addref(base->rsrc_id); -+ ++base->events; -+ } -+ -+ if (old_base) { -+ --old_base->events; -+ zend_list_delete(old_base->rsrc_id); -+ } -+ -+ bevent->base = base; -+ RETURN_TRUE; -+ } -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+/* {{{ proto bool event_buffer_priority_set(resource bevent, int priority) -+ */ -+static PHP_FUNCTION(event_buffer_priority_set) -+{ -+ zval *zbevent; -+ php_bufferevent_t *bevent; -+ long priority; -+ int ret; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zbevent, &priority) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BEVENT(zbevent, bevent); -+ -+ if (!bevent->base) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set event priority without an event base"); -+ RETURN_FALSE; -+ } -+ -+ ret = bufferevent_priority_set(bevent->bevent, priority); -+ -+ if (ret == 0) { -+ RETURN_TRUE; -+ } -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+/* {{{ proto bool event_buffer_write(resource bevent, string data[, int data_size]) -+ */ -+static PHP_FUNCTION(event_buffer_write) -+{ -+ zval *zbevent; -+ php_bufferevent_t *bevent; -+ char *data; -+ int data_len; -+ long data_size = -1; -+ int ret; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &zbevent, &data, &data_len, &data_size) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BEVENT(zbevent, bevent); -+ -+ if (ZEND_NUM_ARGS() < 3 || data_size < 0) { -+ data_size = data_len; -+ } else if (data_size > data_len) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_size out of range"); -+ RETURN_FALSE; -+ } -+ -+ ret = bufferevent_write(bevent->bevent, (const void *)data, data_size); -+ -+ if (ret == 0) { -+ RETURN_TRUE; -+ } -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+/* {{{ proto string event_buffer_read(resource bevent, int data_size) -+ */ -+static PHP_FUNCTION(event_buffer_read) -+{ -+ zval *zbevent; -+ php_bufferevent_t *bevent; -+ char *data; -+ long data_size; -+ int ret; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zbevent, &data_size) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BEVENT(zbevent, bevent); -+ -+ if (data_size == 0) { -+ RETURN_EMPTY_STRING(); -+ } else if (data_size < 0) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_size cannot be less than zero"); -+ RETURN_FALSE; -+ } -+ -+ data = safe_emalloc((int)data_size, sizeof(char), 1); -+ -+ ret = bufferevent_read(bevent->bevent, data, data_size); -+ if (ret > 0) { -+ if (ret > data_size) { /* paranoia */ -+ ret = data_size; -+ } -+ data[ret] = '\0'; -+ RETURN_STRINGL(data, ret, 0); -+ } -+ efree(data); -+ RETURN_EMPTY_STRING(); -+} -+/* }}} */ -+ -+/* {{{ proto bool event_buffer_enable(resource bevent, int events) -+ */ -+static PHP_FUNCTION(event_buffer_enable) -+{ -+ zval *zbevent; -+ php_bufferevent_t *bevent; -+ long events; -+ int ret; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zbevent, &events) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BEVENT(zbevent, bevent); -+ -+ ret = bufferevent_enable(bevent->bevent, events); -+ -+ if (ret == 0) { -+ RETURN_TRUE; -+ } -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+/* {{{ proto bool event_buffer_disable(resource bevent, int events) -+ */ -+static PHP_FUNCTION(event_buffer_disable) -+{ -+ zval *zbevent; -+ php_bufferevent_t *bevent; -+ long events; -+ int ret; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zbevent, &events) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BEVENT(zbevent, bevent); -+ -+ ret = bufferevent_disable(bevent->bevent, events); -+ -+ if (ret == 0) { -+ RETURN_TRUE; -+ } -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+/* {{{ proto void event_buffer_timeout_set(resource bevent, int read_timeout, int write_timeout) -+ */ -+static PHP_FUNCTION(event_buffer_timeout_set) -+{ -+ zval *zbevent; -+ php_bufferevent_t *bevent; -+ long read_timeout, write_timeout; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rll", &zbevent, &read_timeout, &write_timeout) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BEVENT(zbevent, bevent); -+ bufferevent_settimeout(bevent->bevent, read_timeout, write_timeout); -+} -+/* }}} */ -+ -+/* {{{ proto void event_buffer_watermark_set(resource bevent, int events, int lowmark, int highmark) -+ */ -+static PHP_FUNCTION(event_buffer_watermark_set) -+{ -+ zval *zbevent; -+ php_bufferevent_t *bevent; -+ long events, lowmark, highmark; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlll", &zbevent, &events, &lowmark, &highmark) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BEVENT(zbevent, bevent); -+ bufferevent_setwatermark(bevent->bevent, events, lowmark, highmark); -+} -+/* }}} */ -+ -+/* {{{ proto void event_buffer_fd_set(resource bevent, resource fd) -+ */ -+static PHP_FUNCTION(event_buffer_fd_set) -+{ -+ zval *zbevent, *zfd; -+ php_stream *stream; -+ php_bufferevent_t *bevent; -+ php_socket_t fd; -+#ifdef LIBEVENT_SOCKETS_SUPPORT -+ php_socket *php_sock; -+#endif -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &zbevent, &zfd) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BEVENT(zbevent, bevent); -+ -+ if (Z_TYPE_P(zfd) == IS_RESOURCE) { -+ if (ZEND_FETCH_RESOURCE_NO_RETURN(stream, php_stream *, &zfd, -1, NULL, php_file_le_stream())) { -+ if (php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&fd, 1) != SUCCESS || fd < 0) { -+ RETURN_FALSE; -+ } -+ } else { -+#ifdef LIBEVENT_SOCKETS_SUPPORT -+ if (ZEND_FETCH_RESOURCE_NO_RETURN(php_sock, php_socket *, &zfd, -1, NULL, php_sockets_le_socket())) { -+ fd = php_sock->bsd_socket; -+ } else { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "fd argument must be valid PHP stream or socket resource or a file descriptor of type long"); -+ RETURN_FALSE; -+ } -+#else -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "fd argument must be valid PHP stream resource or a file descriptor of type long"); -+ RETURN_FALSE; -+#endif -+ } -+ } else if (Z_TYPE_P(zfd) == IS_LONG) { -+ fd = Z_LVAL_P(zfd); -+ } else { -+#ifdef LIBEVENT_SOCKETS_SUPPORT -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "fd argument must be valid PHP stream or socket resource or a file descriptor of type long"); -+#else -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "fd argument must be valid PHP stream resource or a file descriptor of type long"); -+#endif -+ RETURN_FALSE; -+ } -+ -+ bufferevent_setfd(bevent->bevent, fd); -+} -+/* }}} */ -+ -+/* {{{ proto resource event_buffer_set_callback(resource bevent, mixed readcb, mixed writecb, mixed errorcb[, mixed arg]) -+ */ -+static PHP_FUNCTION(event_buffer_set_callback) -+{ -+ php_bufferevent_t *bevent; -+ zval *zbevent, *zreadcb, *zwritecb, *zerrorcb, *zarg = NULL; -+ char *func_name; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzzz|z", &zbevent, &zreadcb, &zwritecb, &zerrorcb, &zarg) != SUCCESS) { -+ return; -+ } -+ -+ ZVAL_TO_BEVENT(zbevent, bevent); -+ -+ if (Z_TYPE_P(zreadcb) != IS_NULL) { -+ if (!zend_is_callable(zreadcb, 0, &func_name TSRMLS_CC)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s' is not a valid read callback", func_name); -+ efree(func_name); -+ RETURN_FALSE; -+ } -+ efree(func_name); -+ } else { -+ zreadcb = NULL; -+ } -+ -+ if (Z_TYPE_P(zwritecb) != IS_NULL) { -+ if (!zend_is_callable(zwritecb, 0, &func_name TSRMLS_CC)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s' is not a valid write callback", func_name); -+ efree(func_name); -+ RETURN_FALSE; -+ } -+ efree(func_name); -+ } else { -+ zwritecb = NULL; -+ } -+ -+ if (Z_TYPE_P(zerrorcb) != IS_NULL) { -+ if (!zend_is_callable(zerrorcb, 0, &func_name TSRMLS_CC)) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "'%s' is not a valid error callback", func_name); -+ efree(func_name); -+ RETURN_FALSE; -+ } -+ efree(func_name); -+ } else { -+ zerrorcb = NULL; -+ } -+ -+ if (zreadcb) { -+ zval_add_ref(&zreadcb); -+ -+ if (bevent->readcb) { -+ zval_ptr_dtor(&bevent->readcb); -+ } -+ bevent->readcb = zreadcb; -+ } else { -+ if (bevent->readcb) { -+ zval_ptr_dtor(&bevent->readcb); -+ } -+ bevent->readcb = NULL; -+ } -+ -+ if (zwritecb) { -+ zval_add_ref(&zwritecb); -+ -+ if (bevent->writecb) { -+ zval_ptr_dtor(&bevent->writecb); -+ } -+ bevent->writecb = zwritecb; -+ } else { -+ if (bevent->writecb) { -+ zval_ptr_dtor(&bevent->writecb); -+ } -+ bevent->writecb = NULL; -+ } -+ -+ if (zerrorcb) { -+ zval_add_ref(&zerrorcb); -+ -+ if (bevent->errorcb) { -+ zval_ptr_dtor(&bevent->errorcb); -+ } -+ bevent->errorcb = zerrorcb; -+ } -+ -+ if (zarg) { -+ zval_add_ref(&zarg); -+ if (bevent->arg) { -+ zval_ptr_dtor(&bevent->arg); -+ } -+ bevent->arg = zarg; -+ } -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+ -+/* {{{ PHP_MINIT_FUNCTION -+ */ -+static PHP_MINIT_FUNCTION(libevent) -+{ -+ le_event_base = zend_register_list_destructors_ex(_php_event_base_dtor, NULL, "event base", module_number); -+ le_event = zend_register_list_destructors_ex(_php_event_dtor, NULL, "event", module_number); -+ le_bufferevent = zend_register_list_destructors_ex(_php_bufferevent_dtor, NULL, "buffer event", module_number); -+ -+ REGISTER_LONG_CONSTANT("EV_TIMEOUT", EV_TIMEOUT, CONST_CS | CONST_PERSISTENT); -+ REGISTER_LONG_CONSTANT("EV_READ", EV_READ, CONST_CS | CONST_PERSISTENT); -+ REGISTER_LONG_CONSTANT("EV_WRITE", EV_WRITE, CONST_CS | CONST_PERSISTENT); -+ REGISTER_LONG_CONSTANT("EV_SIGNAL", EV_SIGNAL, CONST_CS | CONST_PERSISTENT); -+ REGISTER_LONG_CONSTANT("EV_PERSIST", EV_PERSIST, CONST_CS | CONST_PERSISTENT); -+ REGISTER_LONG_CONSTANT("EVLOOP_NONBLOCK", EVLOOP_NONBLOCK, CONST_CS | CONST_PERSISTENT); -+ REGISTER_LONG_CONSTANT("EVLOOP_ONCE", EVLOOP_ONCE, CONST_CS | CONST_PERSISTENT); -+ -+ REGISTER_LONG_CONSTANT("EVBUFFER_READ", EVBUFFER_READ, CONST_CS | CONST_PERSISTENT); -+ REGISTER_LONG_CONSTANT("EVBUFFER_WRITE", EVBUFFER_WRITE, CONST_CS | CONST_PERSISTENT); -+ REGISTER_LONG_CONSTANT("EVBUFFER_EOF", EVBUFFER_EOF, CONST_CS | CONST_PERSISTENT); -+ REGISTER_LONG_CONSTANT("EVBUFFER_ERROR", EVBUFFER_ERROR, CONST_CS | CONST_PERSISTENT); -+ REGISTER_LONG_CONSTANT("EVBUFFER_TIMEOUT", EVBUFFER_TIMEOUT, CONST_CS | CONST_PERSISTENT); -+ -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ PHP_MINFO_FUNCTION -+ */ -+static PHP_MINFO_FUNCTION(libevent) -+{ -+ char buf[64]; -+ -+ -+ php_info_print_table_start(); -+ php_info_print_table_header(2, "libevent support", "enabled"); -+ php_info_print_table_row(2, "extension version", PHP_LIBEVENT_VERSION); -+ php_info_print_table_row(2, "Revision", "$Revision: 318910 $"); -+ -+ snprintf(buf, sizeof(buf) - 1, "%s", event_get_version()); -+ php_info_print_table_row(2, "libevent version", buf); -+ -+ php_info_print_table_end(); -+} -+/* }}} */ -+ -+#if PHP_MAJOR_VERSION >= 5 -+/* {{{ arginfo */ -+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3) || PHP_MAJOR_VERSION > 5 -+# define EVENT_ARGINFO -+#else -+# define EVENT_ARGINFO static -+#endif -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_base_loop, 0, 0, 1) -+ ZEND_ARG_INFO(0, base) -+ ZEND_ARG_INFO(0, flags) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_base_loopbreak, 0, 0, 1) -+ ZEND_ARG_INFO(0, base) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_base_loopexit, 0, 0, 1) -+ ZEND_ARG_INFO(0, base) -+ ZEND_ARG_INFO(0, timeout) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_base_set, 0, 0, 2) -+ ZEND_ARG_INFO(0, event) -+ ZEND_ARG_INFO(0, base) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_base_priority_init, 0, 0, 2) -+ ZEND_ARG_INFO(0, base) -+ ZEND_ARG_INFO(0, npriorities) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO(arginfo_event_new, 0) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_add, 0, 0, 1) -+ ZEND_ARG_INFO(0, event) -+ ZEND_ARG_INFO(0, timeout) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_set, 0, 0, 4) -+ ZEND_ARG_INFO(0, event) -+ ZEND_ARG_INFO(0, fd) -+ ZEND_ARG_INFO(0, events) -+ ZEND_ARG_INFO(0, callback) -+ ZEND_ARG_INFO(0, arg) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_del, 0, 0, 1) -+ ZEND_ARG_INFO(0, event) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_priority_set, 0, 0, 2) -+ ZEND_ARG_INFO(0, event) -+ ZEND_ARG_INFO(0, priority) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_buffer_new, 0, 0, 4) -+ ZEND_ARG_INFO(0, stream) -+ ZEND_ARG_INFO(0, readcb) -+ ZEND_ARG_INFO(0, writecb) -+ ZEND_ARG_INFO(0, errorcb) -+ ZEND_ARG_INFO(0, arg) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_buffer_free, 0, 0, 1) -+ ZEND_ARG_INFO(0, bevent) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_buffer_base_set, 0, 0, 2) -+ ZEND_ARG_INFO(0, bevent) -+ ZEND_ARG_INFO(0, base) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_buffer_priority_set, 0, 0, 2) -+ ZEND_ARG_INFO(0, bevent) -+ ZEND_ARG_INFO(0, priority) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_buffer_write, 0, 0, 2) -+ ZEND_ARG_INFO(0, bevent) -+ ZEND_ARG_INFO(0, data) -+ ZEND_ARG_INFO(0, data_size) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_buffer_read, 0, 0, 2) -+ ZEND_ARG_INFO(0, bevent) -+ ZEND_ARG_INFO(0, data_size) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_buffer_disable, 0, 0, 2) -+ ZEND_ARG_INFO(0, bevent) -+ ZEND_ARG_INFO(0, events) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_buffer_timeout_set, 0, 0, 3) -+ ZEND_ARG_INFO(0, bevent) -+ ZEND_ARG_INFO(0, read_timeout) -+ ZEND_ARG_INFO(0, write_timeout) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_buffer_watermark_set, 0, 0, 4) -+ ZEND_ARG_INFO(0, bevent) -+ ZEND_ARG_INFO(0, events) -+ ZEND_ARG_INFO(0, lowmark) -+ ZEND_ARG_INFO(0, highmark) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_buffer_fd_set, 0, 0, 2) -+ ZEND_ARG_INFO(0, bevent) -+ ZEND_ARG_INFO(0, fd) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_buffer_set_callback, 0, 0, 4) -+ ZEND_ARG_INFO(0, bevent) -+ ZEND_ARG_INFO(0, readcb) -+ ZEND_ARG_INFO(0, writecb) -+ ZEND_ARG_INFO(0, errorcb) -+ ZEND_ARG_INFO(0, arg) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_timer_set, 0, 0, 2) -+ ZEND_ARG_INFO(0, event) -+ ZEND_ARG_INFO(0, callback) -+ ZEND_ARG_INFO(0, arg) -+ZEND_END_ARG_INFO() -+ -+EVENT_ARGINFO -+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_timer_pending, 0, 0, 1) -+ ZEND_ARG_INFO(0, event) -+ ZEND_ARG_INFO(0, timeout) -+ZEND_END_ARG_INFO() -+/* }}} */ -+ -+/* {{{ libevent_functions[] -+ */ -+#if ZEND_MODULE_API_NO >= 20071006 -+const -+#endif -+zend_function_entry libevent_functions[] = { -+ PHP_FE(event_base_new, arginfo_event_new) -+ PHP_FE(event_base_free, arginfo_event_base_loopbreak) -+ PHP_FE(event_base_loop, arginfo_event_base_loop) -+ PHP_FE(event_base_loopbreak, arginfo_event_base_loopbreak) -+ PHP_FE(event_base_loopexit, arginfo_event_base_loopexit) -+ PHP_FE(event_base_set, arginfo_event_base_set) -+ PHP_FE(event_base_priority_init, arginfo_event_base_priority_init) -+ PHP_FE(event_new, arginfo_event_new) -+ PHP_FE(event_free, arginfo_event_del) -+ PHP_FE(event_add, arginfo_event_add) -+ PHP_FE(event_set, arginfo_event_set) -+ PHP_FE(event_del, arginfo_event_del) -+ PHP_FE(event_priority_set, arginfo_event_priority_set) -+ PHP_FE(event_buffer_new, arginfo_event_buffer_new) -+ PHP_FE(event_buffer_free, arginfo_event_buffer_free) -+ PHP_FE(event_buffer_base_set, arginfo_event_buffer_base_set) -+ PHP_FE(event_buffer_priority_set, arginfo_event_buffer_priority_set) -+ PHP_FE(event_buffer_write, arginfo_event_buffer_write) -+ PHP_FE(event_buffer_read, arginfo_event_buffer_read) -+ PHP_FE(event_buffer_enable, arginfo_event_buffer_disable) -+ PHP_FE(event_buffer_disable, arginfo_event_buffer_disable) -+ PHP_FE(event_buffer_timeout_set, arginfo_event_buffer_timeout_set) -+ PHP_FE(event_buffer_watermark_set, arginfo_event_buffer_watermark_set) -+ PHP_FE(event_buffer_fd_set, arginfo_event_buffer_fd_set) -+ PHP_FE(event_buffer_set_callback, arginfo_event_buffer_set_callback) -+ PHP_FALIAS(event_timer_new, event_new, arginfo_event_new) -+ PHP_FE(event_timer_set, arginfo_event_timer_set) -+ PHP_FE(event_timer_pending, arginfo_event_timer_pending) -+ PHP_FALIAS(event_timer_add, event_add, arginfo_event_add) -+ PHP_FALIAS(event_timer_del, event_del, arginfo_event_del) -+ {NULL, NULL, NULL} -+}; -+/* }}} */ -+#else -+/* {{{ libevent_functions[] -+ */ -+zend_function_entry libevent_functions[] = { -+ PHP_FE(event_base_new, NULL) -+ PHP_FE(event_base_free, NULL) -+ PHP_FE(event_base_loop, NULL) -+ PHP_FE(event_base_loopbreak, NULL) -+ PHP_FE(event_base_loopexit, NULL) -+ PHP_FE(event_base_set, NULL) -+ PHP_FE(event_base_priority_init, NULL) -+ PHP_FE(event_new, NULL) -+ PHP_FE(event_free, NULL) -+ PHP_FE(event_add, NULL) -+ PHP_FE(event_set, NULL) -+ PHP_FE(event_del, NULL) -+ PHP_FE(event_priority_set, NULL) -+ PHP_FE(event_buffer_new, NULL) -+ PHP_FE(event_buffer_free, NULL) -+ PHP_FE(event_buffer_base_set, NULL) -+ PHP_FE(event_buffer_priority_set, NULL) -+ PHP_FE(event_buffer_write, NULL) -+ PHP_FE(event_buffer_read, NULL) -+ PHP_FE(event_buffer_enable, NULL) -+ PHP_FE(event_buffer_disable, NULL) -+ PHP_FE(event_buffer_timeout_set, NULL) -+ PHP_FE(event_buffer_watermark_set, NULL) -+ PHP_FE(event_buffer_fd_set, NULL) -+ PHP_FALIAS(event_timer_new, event_new, NULL) -+ PHP_FE(event_timer_set, NULL) -+ PHP_FE(event_timer_pending, NULL) -+ PHP_FALIAS(event_timer_add, event_add, NULL) -+ PHP_FALIAS(event_timer_del, event_del, NULL) -+ {NULL, NULL, NULL} -+}; -+/* }}} */ -+#endif -+ -+static const zend_module_dep libevent_deps[] = { /* {{{ */ -+ ZEND_MOD_OPTIONAL("sockets") -+ {NULL, NULL, NULL} -+}; -+/* }}} */ -+ -+/* {{{ libevent_module_entry -+ */ -+zend_module_entry libevent_module_entry = { -+ STANDARD_MODULE_HEADER_EX, -+ NULL, -+ libevent_deps, -+ "libevent", -+ libevent_functions, -+ PHP_MINIT(libevent), -+ NULL, -+ NULL, -+ NULL, -+ PHP_MINFO(libevent), -+ PHP_LIBEVENT_VERSION, -+ STANDARD_MODULE_PROPERTIES -+}; -+/* }}} */ -+ -+/* -+ * 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 -+ */ ---- /dev/null -+++ b/ext/libevent/libevent.php -@@ -0,0 +1,58 @@ -+ ---- /dev/null -+++ b/ext/libevent/php_libevent.h -@@ -0,0 +1,68 @@ -+/* -+ +----------------------------------------------------------------------+ -+ | PHP Version 5 | -+ +----------------------------------------------------------------------+ -+ | Copyright (c) 1997-2008 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. | -+ +----------------------------------------------------------------------+ -+ | Author: Antony Dovgal | -+ | Arnaud Le Blanc | -+ +----------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_libevent.h 300687 2010-06-23 08:13:24Z tony2001 $ */ -+ -+#ifndef PHP_LIBEVENT_H -+#define PHP_LIBEVENT_H -+ -+#define PHP_LIBEVENT_VERSION "0.0.4" -+ -+extern zend_module_entry libevent_module_entry; -+#define phpext_libevent_ptr &libevent_module_entry -+ -+#ifdef ZTS -+#include "TSRM.h" -+#endif -+ -+#ifndef zend_always_inline -+# if defined(__GNUC__) -+# define zend_always_inline inline __attribute__((always_inline)) -+# elif defined(_MSC_VER) -+# define zend_always_inline __forceinline -+# else -+# define zend_always_inline inline -+# endif -+#endif -+ -+#ifndef Z_ADDREF_P -+#define Z_ADDREF_P(pz) zval_addref_p(pz) -+static zend_always_inline zend_uint zval_addref_p(zval* pz) { -+ return ++pz->refcount; -+} -+#endif -+ -+#ifndef Z_DELREF_P -+#define Z_DELREF_P(pz) zval_delref_p(pz) -+static zend_always_inline zend_uint zval_delref_p(zval* pz) { -+ return --pz->refcount; -+} -+#endif -+ -+#endif /* PHP_LIBEVENT_H */ -+ -+ -+/* -+ * 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 -+ */ diff --git a/lang/php5/patches/030-PECL-add-http.patch b/lang/php5/patches/030-PECL-add-http.patch deleted file mode 100644 index 96444b8a1..000000000 --- a/lang/php5/patches/030-PECL-add-http.patch +++ /dev/null @@ -1,29944 +0,0 @@ ---- /dev/null -+++ b/ext/http/CREDITS -@@ -0,0 +1,2 @@ -+HTTP extension for PHP -+Michael Wallner ---- /dev/null -+++ b/ext/http/KnownIssues.txt -@@ -0,0 +1,33 @@ -+Known Issues -+============ -+$Id: KnownIssues.txt 292753 2009-12-29 12:30:43Z mike $ -+ -+PHP < 5.1.3: -+ HttpResponse::getHeader() does not work with Apache2 SAPIs. -+ Using an encoding stream filter on a stream you read from doesn't work. -+ -+Windows: -+ If you keep getting "SSL connect error" when trying to issue -+ requests, try another (newer) libeay32.dll/ssleay32.dll pair. -+ -+Internals: -+ Our http_urlencode_hash() does not differentiate between prefixes -+ for numeric or string keys. -+ Inflating raw deflated data causes a re-initialization of the inflate -+ stream where the corresponding window bits are modified to tell libz -+ to not check for zlib header bytes. This is not preventable AFAICS. -+ LFS dependant parts of libcurl are left out because of off_t, -+ respectively off64_t confusion. -+ Persistent handles and "cookiestore" request option do interfere, -+ as libcurl saves the cookies to the file on curl_easy_destroy(), -+ cookies are not saved until the CURL handle will be recycled. -+ Thus one would either need to -+ * run PHP with http.persistent.handles.limit = 0 -+ * call http_persistent_handles_clean() every request -+ * call $HttpRequest->flushCookies(), which is available -+ since libcurl v7.17.1 and does not work with the -+ procedural API -+ Anyway, none of these options is really perfect. -+ HTTP and Proxy authentication information (username/password) can not be -+ unset with NULL prior libcurl v7.19.6 and separate options for setting -+ username and password--which work--are only available since v7.19.6. ---- /dev/null -+++ b/ext/http/LICENSE -@@ -0,0 +1,47 @@ -+Copyright (c) 2004-2010, Michael Wallner . -+All rights reserved. -+ -+Redistribution and use in source and binary forms, with or without -+modification, are permitted provided that the following conditions are met: -+ -+ * Redistributions of source code must retain the above copyright notice, -+ this list of conditions and the following disclaimer. -+ * Redistributions in binary form must reproduce the above copyright -+ notice, this list of conditions and the following disclaimer in the -+ documentation and/or other materials provided with the distribution. -+ -+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ -+=============================================================================== -+ -+The date parser in file http_date_api.c is derived from the implementation -+found in the original libcurl source, licensed under the following conditions: -+ -+Copyright (c) 1996 - 2006, Daniel Stenberg, . -+All rights reserved. -+ -+Permission to use, copy, modify, and distribute this software for any purpose -+with or without fee is hereby granted, provided that the above copyright -+notice and this permission notice appear in all copies. -+ -+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN -+NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -+OR OTHER DEALINGS IN THE SOFTWARE. -+ -+Except as contained in this notice, the name of a copyright holder shall not -+be used in advertising or otherwise to promote the sale, use or other dealings -+in this Software without prior written authorization of the copyright holder. -+ ---- /dev/null -+++ b/ext/http/Makefile.frag -@@ -0,0 +1,23 @@ -+# vim: noet ts=1 sw=1 -+ -+phpincludedir=$(prefix)/include/php -+ -+install-http: install install-http-headers -+ -+install-http-headers: -+ @echo "Installing HTTP headers: $(INSTALL_ROOT)$(phpincludedir)/ext/http/" -+ @$(mkinstalldirs) $(INSTALL_ROOT)$(phpincludedir)/ext/http -+ @for f in $(PHP_HTTP_HEADERS); do \ -+ if test -f "$(top_srcdir)/$$f"; then \ -+ $(INSTALL_DATA) $(top_srcdir)/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/http; \ -+ elif test -f "$(top_builddir)/$$f"; then \ -+ $(INSTALL_DATA) $(top_builddir)/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/http; \ -+ elif test -f "$(top_srcdir)/ext/http/$$f"; then \ -+ $(INSTALL_DATA) $(top_srcdir)/ext/http/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/http; \ -+ elif test -f "$(top_builddir)/ext/http/$$f"; then \ -+ $(INSTALL_DATA) $(top_builddir)/ext/http/$$f $(INSTALL_ROOT)$(phpincludedir)/ext/http; \ -+ else \ -+ echo "WTF? $$f"; \ -+ fi \ -+ done; -+ ---- /dev/null -+++ b/ext/http/ThanksTo.txt -@@ -0,0 +1,20 @@ -+Thanks To -+========= -+$Id: ThanksTo.txt 275653 2009-02-12 13:11:05Z mike $ -+ -+People who repeatedly reported issues with this extension in a manner -+so they could be fixed in a reasonable way, or suggested useful features -+to implement, in alphabetical order: -+ -+ Ilia Alshanetsky (ilia at php dot net) -+ Petr Czaderna (petr at hroch dot info) -+ David James (james82 at gmail dot com) -+ Thomas Landro Johnsen (thomas dot l dot johnsen at gmail dot com) -+ Clay Loveless (clay at killersoft dot com) -+ Felipe Pena (felipe at php dot net) -+ David Sklar (sklar at sklar dot com) -+ Travis Swicegood (travis at mashery dot com) -+ Alexey Zakhlestin (indeyets at gmail dot com) -+ Alexander Zhuravlev (zaa at zaa dot pp dot ru) -+ -+Thanks a lot! ---- /dev/null -+++ b/ext/http/config.m4 -@@ -0,0 +1,5 @@ -+dnl phpize stub of config9.m4 for pecl/http -+dnl $Id: config.m4 214417 2006-06-07 21:05:34Z mike $ -+dnl vim: noet ts=1 sw=1 -+ -+sinclude(config9.m4) ---- /dev/null -+++ b/ext/http/config.w32 -@@ -0,0 +1,129 @@ -+// config.w32 for pecl/http -+// $Id: config.w32 287971 2009-09-02 14:36:08Z pajoye $ -+ -+ARG_ENABLE("http", "whether to enable extended HTTP support", "no"); -+ -+function check_for_main_ext(ext, header) -+{ -+ if (!header) { -+ header = "php_"+ ext +".h"; -+ } -+ -+ /* When in configure, we're always in the root of PHP source */ -+ var ext_path = "ext\\" + ext; -+ -+ STDOUT.Write("Checking for ext/"+ ext +" ... "); -+ -+ if (FSO.FileExists(ext_path + "\\" + header)) { -+ STDOUT.WriteLine(ext_path); -+ return ext_path; -+ } -+ -+ STDOUT.WriteLine(""); -+ return false; -+} -+ -+function check_for_pecl_ext(ext, header) -+{ -+ if (!header) { -+ header = "php_"+ ext +".h"; -+ } -+ -+ var g; -+ var s = ext +"\\"+ header; -+ -+ STDOUT.Write("Checking for pecl/"+ ext +" ... "); -+ if ( (g = glob(configure_module_dirname +"\\..\\"+ s)) || -+ (g = glob(configure_module_dirname +"\\..\\..\\..\\pecl\\"+ s))) { -+ var f = g[0].substr(0, g[0].length - header.length - 1); -+ STDOUT.WriteLine(f); -+ return f; -+ } -+ STDOUT.WriteLine(""); -+ return false; -+} -+ -+if (PHP_HTTP != "no") { -+ -+ EXTENSION("http", -+ "missing.c http.c http_functions.c http_exception_object.c "+ -+ "http_util_object.c http_message_object.c http_requestpool_object.c "+ -+ "http_request_object.c http_response_object.c "+ -+ "http_api.c http_cache_api.c http_request_pool_api.c "+ -+ "http_request_api.c http_date_api.c http_headers_api.c "+ -+ "http_message_api.c http_send_api.c http_url_api.c "+ -+ "http_info_api.c http_request_method_api.c http_encoding_api.c "+ -+ "http_filter_api.c http_request_body_api.c http_querystring_object.c "+ -+ "http_deflatestream_object.c http_inflatestream_object.c "+ -+ "http_cookie_api.c http_querystring_api.c http_request_datashare_api.c "+ -+ "http_requestdatashare_object.c http_request_info.c http_persistent_handle_api.c", -+ null, -+ "/I\"" + configure_module_dirname + "/phpstr\""); -+ ADD_SOURCES(configure_module_dirname + "/phpstr", "phpstr.c", "http"); -+ AC_DEFINE("HAVE_HTTP", 1, "Have extended HTTP support"); -+ AC_DEFINE("HTTP_SHARED_DEPS", 1, "Depend on shared extensions"); -+ -+ AC_DEFINE("HAVE_GETHOSTNAME", 1); -+ AC_DEFINE("HAVE_GETSERVBYPORT", 1); -+ AC_DEFINE("HAVE_GETSERVBYNAME", 1); -+ -+ if (PHP_DEBUG != "no") { -+ ADD_FLAG("CFLAGS_HTTP", "/W3"); -+ } -+ -+ if (CHECK_HEADER_ADD_INCLUDE('zlib.h', 'CFLAGS_HTTP', '..\\zlib;' + php_usual_include_suspects)) { -+ AC_DEFINE('HTTP_HAVE_ZLIB', 1, "Have zlib library"); -+ ADD_FLAG("LDFLAGS_HTTP", "/FORCE:MULTIPLE"); -+ } else { -+ WARNING("zlib encoding functions not enabled; libraries and headers not found"); -+ } -+ -+ if (typeof(PHP_HASH) != "undefined" && PHP_HASH != "no") { -+ var f; -+ -+ if ((f = check_for_pecl_ext("hash")) || (f = check_for_main_ext("hash"))) { -+ ADD_FLAG("CFLAGS_HTTP", '/I "' + f + '" /DHTTP_HAVE_PHP_HASH_H=1'); -+ ADD_EXTENSION_DEP("http", "hash", true); -+ } -+ } -+ -+ if (PHP_SESSION != "no") { -+ ADD_EXTENSION_DEP("http", "session", true); -+ } -+ -+ if (PHP_ICONV != "no") { -+ ADD_EXTENSION_DEP("http", "iconv", true); -+ } -+ -+ CURL_LIB="libcurl_a.lib;libcurl.lib;" + (PHP_DEBUG != "no" ? "libcurld.lib":"libcurl.lib"); -+ if (CHECK_HEADER_ADD_INCLUDE("curl/curl.h", "CFLAGS_HTTP") && -+ CHECK_HEADER_ADD_INCLUDE("openssl/crypto.h", "CFLAGS_HTTP") && -+ CHECK_LIB(CURL_LIB, "http", PHP_HTTP) && -+ CHECK_LIB("ssleay32.lib", "http", PHP_HTTP) && -+ CHECK_LIB("libeay32.lib", "http", PHP_HTTP) && -+ CHECK_LIB("zlib.lib;zlib_a.lib", "http", PHP_HTTP) && -+ CHECK_LIB("winmm.lib", "http", PHP_HTTP)) { -+ AC_DEFINE("HTTP_HAVE_CURL", 1, "Have CURL library"); -+ AC_DEFINE("HTTP_HAVE_SSL", 1, "Have SSL"); -+ AC_DEFINE("HAVE_CURL_MULTI_STRERROR", 1, ""); -+ AC_DEFINE("HAVE_CURL_SHARE_STRERROR", 1, ""); -+ AC_DEFINE("HAVE_CURL_EASY_STRERROR", 1, ""); -+ AC_DEFINE("HAVE_CURL_EASY_RESET", 1, ""); -+ AC_DEFINE("HAVE_CURL_GETFORMDATA", 1, ""); -+ AC_DEFINE("HAVE_CURL_FORMGET", 1, ""); -+ AC_DEFINE("HAVE_CURL_MULTI_SETOPT", 1, ""); -+ AC_DEFINE("HAVE_CURL_MULTI_TIMEOUT", 1, ""); -+ } else { -+ WARNING("curl convenience functions not enabled; libraries and headers not found"); -+ } -+/* -+// MAGIC_LIB = PHP_DEBUG != "no" ? "libmagic-staticd.lib":"libmagic-static.lib"; -+// if (CHECK_HEADER_ADD_INCLUDE("magic.h", "CFLAGS_HTTP") && -+// CHECK_LIB(MAGIC_LIB, "http", PHP_HTTP)) { -+// AC_DEFINE("HTTP_HAVE_MAGIC", 1, "Have magic library"); -+// AC_DEFINE("USE_MAGIC_STATIC", "", ""); -+// } else { -+// WARNING("content type guessing not enabled; libraries and headers not found"); -+// } -+*/ -+} ---- /dev/null -+++ b/ext/http/config9.m4 -@@ -0,0 +1,468 @@ -+dnl config.m4 for pecl/http -+dnl $Id: config9.m4 242664 2007-09-18 19:13:37Z mike $ -+dnl vim: noet ts=1 sw=1 -+ -+PHP_ARG_ENABLE([http], [whether to enable extended HTTP support], -+[ --enable-http Enable extended HTTP support]) -+PHP_ARG_WITH([http-shared-deps], [whether to depend on extensions which have been built shared], -+[ --with-http-shared-deps -+ HTTP: disable to not depend on extensions like hash, -+ iconv and session (when built shared)], $PHP_HTTP, $PHP_HTTP) -+PHP_ARG_WITH([http-curl-requests], [whether to enable cURL HTTP request support], -+[ --with-http-curl-requests[=LIBCURLDIR] -+ HTTP: with cURL request support], $PHP_HTTP, $PHP_HTTP) -+PHP_ARG_WITH([http-curl-libevent], [whether to enable libevent support fur cURL], -+[ --with-http-curl-libevent[=LIBEVENTDIR] -+ HTTP: libevent install directory], $PHP_HTTP_CURL_REQUESTS, "") -+PHP_ARG_WITH([http-zlib-compression], [whether to enable zlib encodings support], -+[ --with-http-zlib-compression[=LIBZDIR] -+ HTTP: with zlib encodings support], $PHP_HTTP, $PHP_HTTP) -+PHP_ARG_WITH([http-magic-mime], [whether to enable response content type guessing], -+[ --with-http-magic-mime[=LIBMAGICDIR] -+ HTTP: with magic mime response content type guessing], "no", "no") -+ -+if test "$PHP_HTTP" != "no"; then -+ -+ ifdef([AC_PROG_EGREP], [ -+ AC_PROG_EGREP -+ ], [ -+ AC_CHECK_PROG(EGREP, egrep, egrep) -+ ]) -+ ifdef([AC_PROG_SED], [ -+ AC_PROG_SED -+ ], [ -+ ifdef([LT_AC_PROG_SED], [ -+ LT_AC_PROG_SED -+ ], [ -+ AC_CHECK_PROG(SED, sed, sed) -+ ]) -+ ]) -+ -+ AC_PROG_CPP -+ -+ if test "$PHP_HTTP_SHARED_DEPS" != "no"; then -+ AC_DEFINE([HTTP_SHARED_DEPS], [1], [ ]) -+ else -+ AC_DEFINE([HTTP_SHARED_DEPS], [0], [ ]) -+ fi -+ -+ dnl -+ dnl HTTP_SHARED_DEP(name[, code-if-yes[, code-if-not]]) -+ dnl -+ AC_DEFUN([HTTP_SHARED_DEP], [ -+ extname=$1 -+ haveext=$[HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__) -+ -+ AC_MSG_CHECKING([whether to add a dependency on ext/$extname]) -+ if test "$PHP_HTTP_SHARED_DEPS" = "no"; then -+ AC_MSG_RESULT([no]) -+ $3 -+ elif test "$haveext"; then -+ AC_MSG_RESULT([yes]) -+ ifdef([PHP_ADD_EXTENSION_DEP], [ -+ PHP_ADD_EXTENSION_DEP([http], $1, true) -+ ]) -+ $2 -+ else -+ AC_MSG_RESULT([no]) -+ $3 -+ fi -+ ]) -+ -+ dnl -+ dnl HTTP_HAVE_PHP_EXT(name[, code-if-yes[, code-if-not]]) -+ dnl -+ AC_DEFUN([HTTP_HAVE_PHP_EXT], [ -+ extname=$1 -+ haveext=$[PHP_]translit($1,a-z_-,A-Z__) -+ -+ AC_MSG_CHECKING([for ext/$extname support]) -+ if test -x "$PHP_EXECUTABLE"; then -+ grepext=`$PHP_EXECUTABLE -m | $EGREP ^$extname\$` -+ if test "$grepext" = "$extname"; then -+ [HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)=1 -+ AC_MSG_RESULT([yes]) -+ $2 -+ else -+ [HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)= -+ AC_MSG_RESULT([no]) -+ $3 -+ fi -+ elif test "$haveext" != "no" && test "x$haveext" != "x"; then -+ [HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)=1 -+ AC_MSG_RESULT([yes]) -+ $2 -+ else -+ [HTTP_HAVE_EXT_]translit($1,a-z_-,A-Z__)= -+ AC_MSG_RESULT([no]) -+ $3 -+ fi -+ ]) -+ -+ dnl -+ dnl odd PHP4 fix -+ dnl -+ if test "x$PHP_LIBDIR" = "x"; then -+ PHP_LIBDIR=lib -+ fi -+ -+dnl ---- -+dnl STDC -+dnl ---- -+ AC_CHECK_HEADERS([netdb.h unistd.h]) -+ PHP_CHECK_FUNC(gethostname, nsl) -+ PHP_CHECK_FUNC(getdomainname, nsl) -+ PHP_CHECK_FUNC(getservbyport, nsl) -+ PHP_CHECK_FUNC(getservbyname, nsl) -+ -+dnl ---- -+dnl ZLIB -+dnl ---- -+ if test "$PHP_HTTP_ZLIB_COMPRESSION" != "no"; then -+ AC_MSG_CHECKING([for zlib.h]) -+ ZLIB_DIR= -+ for i in "$PHP_HTTP_ZLIB_COMPRESSION" "$PHP_ZLIB_DIR" "$PHP_ZLIB" /usr/local /usr /opt; do -+ if test -f "$i/include/zlib.h"; then -+ ZLIB_DIR=$i -+ break; -+ fi -+ done -+ if test "x$ZLIB_DIR" = "x"; then -+ AC_MSG_RESULT([not found]) -+ AC_MSG_ERROR([could not find zlib.h]) -+ else -+ AC_MSG_RESULT([found in $ZLIB_DIR]) -+ AC_MSG_CHECKING([for zlib version >= 1.2.0.4]) -+ ZLIB_VERSION=`$EGREP "define ZLIB_VERSION" $ZLIB_DIR/include/zlib.h | $SED -e 's/[[^0-9\.]]//g'` -+ AC_MSG_RESULT([$ZLIB_VERSION]) -+ if test `echo $ZLIB_VERSION | $SED -e 's/[[^0-9]]/ /g' | $AWK '{print $1*1000000 + $2*10000 + $3*100 + $4}'` -lt 1020004; then -+ AC_MSG_ERROR([libz version greater or equal to 1.2.0.4 required]) -+ else -+ PHP_ADD_INCLUDE($ZLIB_DIR/include) -+ PHP_ADD_LIBRARY_WITH_PATH(z, $ZLIB_DIR/$PHP_LIBDIR, HTTP_SHARED_LIBADD) -+ AC_DEFINE([HTTP_HAVE_ZLIB], [1], [Have zlib support]) -+ fi -+ fi -+ fi -+ -+dnl ---- -+dnl CURL -+dnl ---- -+ if test "$PHP_HTTP_CURL_REQUESTS" != "no"; then -+ AC_MSG_CHECKING([for curl/curl.h]) -+ CURL_DIR= -+ for i in "$PHP_HTTP_CURL_REQUESTS" /usr/local /usr /opt; do -+ if test -f "$i/include/curl/curl.h"; then -+ CURL_DIR=$i -+ break -+ fi -+ done -+ if test "x$CURL_DIR" = "x"; then -+ AC_MSG_RESULT([not found]) -+ AC_MSG_ERROR([could not find curl/curl.h]) -+ else -+ AC_MSG_RESULT([found in $CURL_DIR]) -+ fi -+ -+ AC_MSG_CHECKING([for curl-config]) -+ CURL_CONFIG= -+ for i in "$CURL_DIR/bin/curl-config" "$CURL_DIR/curl-config" `which curl-config`; do -+ if test -x "$i"; then -+ CURL_CONFIG=$i -+ break -+ fi -+ done -+ if test "x$CURL_CONFIG" = "x"; then -+ AC_MSG_RESULT([not found]) -+ AC_MSG_ERROR([could not find curl-config]) -+ else -+ AC_MSG_RESULT([found: $CURL_CONFIG]) -+ fi -+ -+ dnl Debian stable has currently 7.13.2 (this is not a typo) -+ AC_MSG_CHECKING([for curl version >= 7.12.3]) -+ CURL_VERSION=`$CURL_CONFIG --version | $SED -e 's/[[^0-9\.]]//g'` -+ AC_MSG_RESULT([$CURL_VERSION]) -+ if test `echo $CURL_VERSION | $SED -e 's/[[^0-9]]/ /g' | $AWK '{print $1*10000 + $2*100 + $3}'` -lt 71203; then -+ AC_MSG_ERROR([libcurl version greater or equal to 7.12.3 required]) -+ fi -+ -+ dnl -+ dnl compile tests -+ dnl -+ -+ save_INCLUDES="$INCLUDES" -+ INCLUDES= -+ save_LIBS="$LIBS" -+ LIBS= -+ save_CFLAGS="$CFLAGS" -+ CFLAGS=`$CURL_CONFIG --cflags` -+ save_LDFLAGS="$LDFLAGS" -+ LDFLAGS=`$CURL_CONFIG --libs` -+ LDFLAGS="$LDFLAGS $ld_runpath_switch$CURL_DIR/$PHP_LIBDIR" -+ -+ AC_MSG_CHECKING([for SSL support in libcurl]) -+ CURL_SSL=`$CURL_CONFIG --feature | $EGREP SSL` -+ if test "$CURL_SSL" = "SSL"; then -+ AC_MSG_RESULT([yes]) -+ AC_DEFINE([HTTP_HAVE_SSL], [1], [ ]) -+ -+ AC_MSG_CHECKING([for openssl support in libcurl]) -+ AC_TRY_RUN([ -+ #include -+ int main(int argc, char *argv[]) { -+ curl_version_info_data *data = curl_version_info(CURLVERSION_NOW); -+ if (data && data->ssl_version && *data->ssl_version) { -+ const char *ptr = data->ssl_version; -+ while(*ptr == ' ') ++ptr; -+ return strncasecmp(ptr, "OpenSSL", sizeof("OpenSSL")-1); -+ } -+ return 1; -+ } -+ ], [ -+ AC_MSG_RESULT([yes]) -+ AC_CHECK_HEADER([openssl/crypto.h], [ -+ AC_DEFINE([HTTP_HAVE_OPENSSL], [1], [ ]) -+ ]) -+ ], [ -+ AC_MSG_RESULT([no]) -+ ], [ -+ AC_MSG_RESULT([no]) -+ ]) -+ -+ AC_MSG_CHECKING([for gnutls support in libcurl]) -+ AC_TRY_RUN([ -+ #include -+ int main(int argc, char *argv[]) { -+ curl_version_info_data *data = curl_version_info(CURLVERSION_NOW); -+ if (data && data->ssl_version && *data->ssl_version) { -+ const char *ptr = data->ssl_version; -+ while(*ptr == ' ') ++ptr; -+ return strncasecmp(ptr, "GnuTLS", sizeof("GnuTLS")-1); -+ } -+ return 1; -+ } -+ ], [ -+ AC_MSG_RESULT([yes]) -+ AC_CHECK_HEADER([gcrypt.h], [ -+ AC_DEFINE([HTTP_HAVE_GNUTLS], [1], [ ]) -+ ]) -+ ], [ -+ AC_MSG_RESULT([no]) -+ ], [ -+ AC_MSG_RESULT([no]) -+ ]) -+ else -+ AC_MSG_RESULT([no]) -+ fi -+ -+ INCLUDES="$save_INCLUDES" -+ LIBS="$save_LIBS" -+ CFLAGS="$save_CFLAGS" -+ LDFLAGS="$save_LDFLAGS" -+ -+ dnl end compile tests -+ -+ AC_MSG_CHECKING([for bundled SSL CA info]) -+ CURL_CAINFO= -+ for i in `$CURL_CONFIG --ca` "/etc/ssl/certs/ca-certificates.crt"; do -+ if test -f "$i"; then -+ CURL_CAINFO="$i" -+ break -+ fi -+ done -+ if test "x$CURL_CAINFO" = "x"; then -+ AC_MSG_RESULT([not found]) -+ else -+ AC_MSG_RESULT([$CURL_CAINFO]) -+ AC_DEFINE_UNQUOTED([HTTP_CURL_CAINFO], ["$CURL_CAINFO"], [path to bundled SSL CA info]) -+ fi -+ -+ PHP_ADD_INCLUDE($CURL_DIR/include) -+ PHP_ADD_LIBRARY_WITH_PATH(curl, $CURL_DIR/$PHP_LIBDIR, HTTP_SHARED_LIBADD) -+ PHP_EVAL_LIBLINE(`$CURL_CONFIG --libs`, HTTP_SHARED_LIBADD) -+ AC_DEFINE([HTTP_HAVE_CURL], [1], [Have cURL support]) -+ -+ PHP_CHECK_LIBRARY(curl, curl_share_strerror, -+ [AC_DEFINE([HAVE_CURL_SHARE_STRERROR], [1], [ ])], [ ], -+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR] -+ ) -+ PHP_CHECK_LIBRARY(curl, curl_multi_strerror, -+ [AC_DEFINE([HAVE_CURL_MULTI_STRERROR], [1], [ ])], [ ], -+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR] -+ ) -+ PHP_CHECK_LIBRARY(curl, curl_easy_strerror, -+ [AC_DEFINE([HAVE_CURL_EASY_STRERROR], [1], [ ])], [ ], -+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR] -+ ) -+ PHP_CHECK_LIBRARY(curl, curl_easy_reset, -+ [AC_DEFINE([HAVE_CURL_EASY_RESET], [1], [ ])], [ ], -+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR] -+ ) -+ PHP_CHECK_LIBRARY(curl, curl_formget, -+ [AC_DEFINE([HAVE_CURL_FORMGET], [1], [ ])], [ ], -+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR] -+ ) -+ PHP_CHECK_LIBRARY(curl, curl_multi_setopt, -+ [AC_DEFINE([HAVE_CURL_MULTI_SETOPT], [1], [ ])], [ ], -+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR] -+ ) -+ PHP_CHECK_LIBRARY(curl, curl_multi_timeout, -+ [AC_DEFINE([HAVE_CURL_MULTI_TIMEOUT], [1], [ ])], [ ], -+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR] -+ ) -+ -+ dnl ---- -+ dnl EVENT -+ dnl ---- -+ -+ if test "$PHP_HTTP_CURL_LIBEVENT" != "no"; then -+ HTTP_HAVE_PHP_EXT([event], [ -+ AC_MSG_WARN([event support is incompatible with pecl/event; continuing without libevent support]) -+ ], [ -+ AC_MSG_CHECKING([for event.h]) -+ EVENT_DIR= -+ for i in "$PHP_HTTP_CURL_LIBEVENT" /usr/local /usr /opt; do -+ if test -f "$i/include/event.h"; then -+ EVENT_DIR=$i -+ break -+ fi -+ done -+ if test "x$EVENT_DIR" = "x"; then -+ AC_MSG_RESULT([not found]) -+ AC_MSG_WARN([continuing without libevent support]) -+ else -+ AC_MSG_RESULT([found in $EVENT_DIR]) -+ -+ AC_MSG_CHECKING([for libevent version, roughly]) -+ EVENT_VER="1.1b or lower" -+ if test -f "$EVENT_DIR/include/evhttp.h" && test -f "$EVENT_DIR/include/evdns.h"; then -+ if test -f "$EVENT_DIR/include/evrpc.h"; then -+ EVENT_VER="1.4 or greater" -+ else -+ EVENT_VER="1.2 or greater" -+ fi -+ fi -+ AC_DEFINE_UNQUOTED([HTTP_EVENT_VERSION], ["$EVENT_VER"], [ ]) -+ AC_MSG_RESULT([$EVENT_VER]) -+ -+ AC_MSG_CHECKING([for libcurl version >= 7.16.0]) -+ AC_MSG_RESULT([$CURL_VERSION]) -+ if test `echo $CURL_VERSION | $SED -e 's/[[^0-9]]/ /g' | $AWK '{print $1*10000 + $2*100 + $3}'` -lt 71600; then -+ AC_MSG_WARN([libcurl version greater or equal to 7.16.0 required; continuing without libevent support]) -+ else -+ PHP_ADD_INCLUDE($EVENT_DIR/include) -+ PHP_ADD_LIBRARY_WITH_PATH(event, $EVENT_DIR/$PHP_LIBDIR, HTTP_SHARED_LIBADD) -+ AC_DEFINE([HTTP_HAVE_EVENT], [1], [Have libevent support for cURL]) -+ PHP_CHECK_LIBRARY(curl, curl_multi_socket_action, -+ [AC_DEFINE([HAVE_CURL_MULTI_SOCKET_ACTION], [1], [ ])], [ ], -+ [$CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR] -+ ) -+ fi -+ fi -+ ]) -+ fi -+ fi -+ -+dnl ---- -+dnl MAGIC -+dnl ---- -+ if test "$PHP_HTTP_MAGIC_MIME" != "no"; then -+ AC_MSG_CHECKING([for magic.h]) -+ MAGIC_DIR= -+ for i in "$PHP_HTTP_MAGIC_MIME" /usr/local /usr /opt; do -+ if test -f "$i/include/magic.h"; then -+ MAGIC_DIR=$i -+ break -+ fi -+ done -+ if test "x$MAGIC_DIR" = "x"; then -+ AC_MSG_RESULT([not found]) -+ AC_MSG_ERROR([could not find magic.h]) -+ else -+ AC_MSG_RESULT([found in $MAGIC_DIR]) -+ fi -+ -+ PHP_ADD_INCLUDE($MAGIC_DIR/include) -+ PHP_ADD_LIBRARY_WITH_PATH(magic, $MAGIC_DIR/$PHP_LIBDIR, HTTP_SHARED_LIBADD) -+ AC_DEFINE([HTTP_HAVE_MAGIC], [1], [Have magic mime support]) -+ fi -+ -+dnl ---- -+dnl HASH -+dnl ---- -+ HTTP_HAVE_PHP_EXT([hash], [ -+ AC_MSG_CHECKING([for php_hash.h]) -+ HTTP_EXT_HASH_INCDIR= -+ for i in `echo $INCLUDES | $SED -e's/-I//g'` $abs_srcdir ../hash; do -+ if test -d $i; then -+ if test -f $i/php_hash.h; then -+ HTTP_EXT_HASH_INCDIR=$i -+ break -+ elif test -f $i/ext/hash/php_hash.h; then -+ HTTP_EXT_HASH_INCDIR=$i/ext/hash -+ break -+ fi -+ fi -+ done -+ if test "x$HTTP_EXT_HASH_INCDIR" = "x"; then -+ AC_MSG_RESULT([not found]) -+ else -+ AC_MSG_RESULT([$HTTP_EXT_HASH_INCDIR]) -+ AC_DEFINE([HTTP_HAVE_PHP_HASH_H], [1], [Have ext/hash support]) -+ PHP_ADD_INCLUDE([$HTTP_EXT_HASH_INCDIR]) -+ fi -+ ]) -+ -+dnl ---- -+dnl ICONV -+dnl ---- -+ HTTP_HAVE_PHP_EXT([iconv]) -+ -+dnl ---- -+dnl SESSION -+dnl ---- -+ HTTP_HAVE_PHP_EXT([session]) -+ -+dnl ---- -+dnl DONE -+dnl ---- -+ PHP_HTTP_SOURCES="missing.c http.c http_functions.c phpstr/phpstr.c \ -+ http_util_object.c http_message_object.c http_request_object.c http_request_pool_api.c \ -+ http_response_object.c http_exception_object.c http_requestpool_object.c \ -+ http_api.c http_cache_api.c http_request_api.c http_request_info.c http_date_api.c \ -+ http_headers_api.c http_message_api.c http_send_api.c http_url_api.c \ -+ http_info_api.c http_request_method_api.c http_encoding_api.c \ -+ http_filter_api.c http_request_body_api.c http_querystring_object.c \ -+ http_deflatestream_object.c http_inflatestream_object.c http_cookie_api.c \ -+ http_querystring_api.c http_request_datashare_api.c http_requestdatashare_object.c \ -+ http_persistent_handle_api.c" -+ -+ PHP_NEW_EXTENSION([http], $PHP_HTTP_SOURCES, $ext_shared) -+ -+ dnl shared extension deps -+ HTTP_SHARED_DEP([hash]) -+ HTTP_SHARED_DEP([iconv]) -+ HTTP_SHARED_DEP([session]) -+ -+ PHP_ADD_BUILD_DIR($ext_builddir/phpstr, 1) -+ PHP_SUBST([HTTP_SHARED_LIBADD]) -+ -+ PHP_HTTP_HEADERS="php_http_std_defs.h php_http.h php_http_api.h php_http_cache_api.h \ -+ php_http_date_api.h php_http_headers_api.h php_http_info_api.h php_http_message_api.h \ -+ php_http_request_api.h php_http_request_method_api.h php_http_send_api.h php_http_url_api.h \ -+ php_http_encoding_api.h phpstr/phpstr.h missing.h php_http_request_body_api.h \ -+ php_http_exception_object.h php_http_message_object.h php_http_request_object.h \ -+ php_http_requestpool_object.h php_http_response_object.h php_http_util_object.h \ -+ php_http_querystring_object.h php_http_deflatestream_object.h php_http_inflatestream_object.h \ -+ php_http_cookie_api.h php_http_querystring_api.h php_http_request_datashare_api.h php_http_requestdatashare_object.h \ -+ php_http_persistent_handle_api.h" -+ ifdef([PHP_INSTALL_HEADERS], [ -+ PHP_INSTALL_HEADERS(ext/http, $PHP_HTTP_HEADERS) -+ ], [ -+ PHP_SUBST([PHP_HTTP_HEADERS]) -+ PHP_ADD_MAKEFILE_FRAGMENT -+ ]) -+ -+ AC_DEFINE([HAVE_HTTP], [1], [Have extended HTTP support]) -+fi ---- /dev/null -+++ b/ext/http/docs/examples/tutorial.txt -@@ -0,0 +1,175 @@ -+ -+A Beginners Tutorial -+-------------------- -+$Revision: 208773 $ -+ -+ -+- GET Queries -+ -+ The HttpRequest class can be used to execute any HTTP request method. -+ The following example shows a simple GET request where a few query -+ parameters are supplied. Additionally potential cookies will be -+ read from and written to a file. -+ -+setOptions( -+ array( 'cookiestore' => 'google.txt', -+ ) -+); -+ -+$r->setQueryData( -+ array( 'q' => '+"pecl_http" -msg -cvs -list', -+ 'hl' => 'de' -+ ) -+); -+ -+// HttpRequest::send() returns an HttpMessage object -+// of type HttpMessage::TYPE_RESPONSE or throws an exception -+try { -+ print $r->send()->getBody(); -+} catch (HttpException $e) { -+ print $e; -+} -+?> -+ -+- Multipart Posts -+ -+ The following example shows an multipart POST request, with two form -+ fields and an image that's supposed to be uploaded to the server. -+ It's a bad habit as well as common practice to issue a redirect after -+ an received POST request, so we'll allow a redirect by enabling the -+ redirect option. -+ -+setOptions( -+ array( 'cookies' => array('MyCookie' => 'has a value'), -+ 'redirect' => true, -+ ) -+); -+ -+// common form data -+$r->setPostFields( -+ array( 'name' => 'Mike', -+ 'mail' => 'mike@php.net', -+ ) -+); -+// add the file to post (form name, file name, file type) -+touch('profile.jpg'); -+$r->addPostFile('image', 'profile.jpg', 'image/jpeg'); -+ -+try { -+ print $r->send()->getBody(); -+} catch (HttpException $e) { -+ print $e; -+} -+?> -+ -+- Parallel Requests -+ -+ It's possible to execute several HttpRequests in parallel with the -+ HttpRequestPool class. HttpRequests to send, do not need to perform -+ the same request method, but can only be attached to one HttpRequestPool -+ at the same time. -+ -+attach(new HttpRequest('http://pear.php.net', HTTP_METH_HEAD)); -+ $p->attach(new HttpRequest('http://pecl.php.net', HTTP_METH_HEAD)); -+} catch (HttpException $e) { -+ print $e; -+ exit; -+} -+ -+try { -+ $p->send(); -+ // HttpRequestPool implements an iterator over attached HttpRequest objects -+ foreach ($p as $r) { -+ echo "Checking ", $r->getUrl(), " reported ", $r->getResponseCode(), "\n"; -+ } -+} catch (HttpException $e) { -+ print $e; -+} -+?> -+ -+- Parallel Requests? -+ -+ You can use a more advanced approach by using the protected interface of -+ the HttpRequestPool class. This allows you to perform some other tasks -+ while the requests are executed. -+ -+socketPerform(); $i++) { -+ $i % 10 or print "."; -+ if (!$this->socketSelect()) { -+ throw new HttpException("Socket error!"); -+ } -+ } -+ print "\nDone!\n"; -+ } -+} -+ -+try { -+ foreach (new Pool as $r) { -+ echo "Checking ", $r->getUrl(), " reported ", $r->getResponseCode(), "\n"; -+ } -+} catch (HttpException $ex) { -+ print $e; -+} -+?> -+ -+- Cached Responses -+ -+ One of the main key features of HttpResponse is HTTP caching. HttpResponse -+ will calculate an ETag based on the http.etag_mode INI setting as well as -+ it will determine the last modification time of the sent entity. It uses -+ those two indicators to decide if the cache entry on the client side is -+ still valid and will emit an "304 Not Modified" response if applicable. -+ -+ -+ -+- Bandwidth Throttling -+ -+ HttpResponse supports a basic throttling mechanism, which is enabled by -+ setting a throttle delay and a buffer size. PHP will sleep the specified -+ amount of seconds after each sent chunk of specified bytes. -+ -+ ---- /dev/null -+++ b/ext/http/docs/http.ini -@@ -0,0 +1,61 @@ -+; example INI file for pecl/http -+; $Id: http.ini 229420 2007-02-09 14:19:40Z mike $ -+ -+[http] -+; enable if you want to transform all errors to exceptions (PHP >= 5 only) -+;http.only_exceptions = 1 -+ -+; disable if you don't want php to exit in case of redirects and cache hits; -+; a "NULL" output handler will be started instead, which discards all output -+;http.force_exit = 0 -+ -+; disable if you don't want 404 Not found status messages being sent, -+; if a file attempted to be sent with http_send_file() etc. cannot be found -+;http.send.not_found_404 = 0 -+ -+; the hashing algorithm with wich ETags are generated (MD5, SHA1, CRC32B); -+; if ext/hash is available, this can be set to any hash algorithm ext/hash supports -+; MD5 is the default and fallback algorithm -+;http.etag.mode = "MD5" -+ -+; allowed request methods -+; by default PHP ignores unkown request methods -+; PHP will exit with a response status of 405 and an Allow header -+; if it encounters a request method not contained in the specified list -+;http.request.methods.allowed = "HEAD, GET, POST" -+ -+; custom request methods -+;http.request.methods.custom = "KICK, BANN" -+ -+; log file for positive cache hits -+;http.log.cache = -+ -+; log file for redirects -+;http.log.redirect = -+ -+; log file for responses with http_send_file() etc. where the file's not been found -+;http.log.not_found = -+ -+; log file for requests with an unallowed request method -+;http.log.allowed_methods = -+ -+; composite log file (i.e. log all messages to this file) -+;http.log.composite = -+ -+; automatically deflate content if requested/supported by client -+;http.send.deflate.start_auto = 1 -+;http.send.deflate.start_flags = HTTP_DEFLATE_LEVEL_DEF -+ -+; automatically inflate sent content -+;http.send.inflate.start_auto = 0 -+;http.send.inflate.start_flags = -+ -+; global HttpRequestDataShare settings -+;http.request.datashare.cookie = 0 -+;http.request.datashare.dns = 1 -+ -+; limit of idle persistent handles per provider -+;http.persistent.handles.limit = -1 -+ -+; default ident of persistent handles -+;http.persistent.handles.ident = "GLOBAL" ---- /dev/null -+++ b/ext/http/http.c -@@ -0,0 +1,546 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http.c 300300 2010-06-09 07:29:35Z mike $ */ -+ -+#define HTTP_WANT_SAPI -+#define HTTP_WANT_CURL -+#define HTTP_WANT_EVENT -+#define HTTP_WANT_ZLIB -+#define HTTP_WANT_MAGIC -+#include "php_http.h" -+ -+#include "php_ini.h" -+#include "ext/standard/info.h" -+#include "zend_extensions.h" -+ -+#include "php_http_api.h" -+#include "php_http_cache_api.h" -+#include "php_http_cookie_api.h" -+#include "php_http_encoding_api.h" -+#include "php_http_filter_api.h" -+#include "php_http_message_api.h" -+#include "php_http_persistent_handle_api.h" -+#include "php_http_request_api.h" -+#include "php_http_request_datashare_api.h" -+#include "php_http_request_method_api.h" -+#include "php_http_request_pool_api.h" -+#include "php_http_send_api.h" -+#include "php_http_url_api.h" -+ -+#include "php_http_deflatestream_object.h" -+#include "php_http_exception_object.h" -+#include "php_http_inflatestream_object.h" -+#include "php_http_message_object.h" -+#include "php_http_querystring_object.h" -+#include "php_http_request_object.h" -+#include "php_http_requestdatashare_object.h" -+#include "php_http_requestpool_object.h" -+#include "php_http_response_object.h" -+#include "php_http_util_object.h" -+ -+ZEND_DECLARE_MODULE_GLOBALS(http); -+HTTP_DECLARE_ARG_PASS_INFO(); -+ -+#ifdef COMPILE_DL_HTTP -+ZEND_GET_MODULE(http) -+#endif -+ -+/* {{{ http_functions[] */ -+zend_function_entry http_functions[] = { -+ PHP_FE(http_date, NULL) -+ PHP_FE(http_build_url, http_arg_pass_ref_4) -+ PHP_FE(http_build_str, NULL) -+#ifndef ZEND_ENGINE_2 -+ PHP_FALIAS(http_build_query, http_build_str, NULL) -+#endif -+ PHP_FE(http_negotiate_language, http_arg_pass_ref_2) -+ PHP_FE(http_negotiate_charset, http_arg_pass_ref_2) -+ PHP_FE(http_negotiate_content_type, http_arg_pass_ref_2) -+ PHP_FE(http_negotiate, http_arg_pass_ref_3) -+ PHP_FE(http_redirect, NULL) -+ PHP_FE(http_throttle, NULL) -+ PHP_FE(http_send_status, NULL) -+ PHP_FE(http_send_last_modified, NULL) -+ PHP_FE(http_send_content_type, NULL) -+ PHP_FE(http_send_content_disposition, NULL) -+ PHP_FE(http_match_modified, NULL) -+ PHP_FE(http_match_etag, NULL) -+ PHP_FE(http_cache_last_modified, NULL) -+ PHP_FE(http_cache_etag, NULL) -+ PHP_FE(http_send_data, NULL) -+ PHP_FE(http_send_file, NULL) -+ PHP_FE(http_send_stream, NULL) -+ PHP_FE(http_chunked_decode, NULL) -+ PHP_FE(http_parse_message, NULL) -+ PHP_FE(http_parse_headers, NULL) -+ PHP_FE(http_parse_cookie, NULL) -+ PHP_FE(http_build_cookie, NULL) -+ PHP_FE(http_parse_params, NULL) -+ PHP_FE(http_get_request_headers, NULL) -+ PHP_FE(http_get_request_body, NULL) -+ PHP_FE(http_get_request_body_stream, NULL) -+ PHP_FE(http_match_request_header, NULL) -+ PHP_FE(http_persistent_handles_count, NULL) -+ PHP_FE(http_persistent_handles_clean, NULL) -+ PHP_FE(http_persistent_handles_ident, NULL) -+#ifdef HTTP_HAVE_CURL -+ PHP_FE(http_get, http_arg_pass_ref_3) -+ PHP_FE(http_head, http_arg_pass_ref_3) -+ PHP_FE(http_post_data, http_arg_pass_ref_4) -+ PHP_FE(http_post_fields, http_arg_pass_ref_5) -+ PHP_FE(http_put_data, http_arg_pass_ref_4) -+ PHP_FE(http_put_file, http_arg_pass_ref_4) -+ PHP_FE(http_put_stream, http_arg_pass_ref_4) -+ PHP_FE(http_request, http_arg_pass_ref_5) -+ PHP_FE(http_request_body_encode, NULL) -+#endif -+ PHP_FE(http_request_method_register, NULL) -+ PHP_FE(http_request_method_unregister, NULL) -+ PHP_FE(http_request_method_exists, NULL) -+ PHP_FE(http_request_method_name, NULL) -+ PHP_FE(ob_etaghandler, NULL) -+#ifdef HTTP_HAVE_ZLIB -+ PHP_FE(http_deflate, NULL) -+ PHP_FE(http_inflate, NULL) -+ PHP_FE(ob_deflatehandler, NULL) -+ PHP_FE(ob_inflatehandler, NULL) -+#endif -+ PHP_FE(http_support, NULL) -+ -+ EMPTY_FUNCTION_ENTRY -+}; -+/* }}} */ -+ -+PHP_MINIT_FUNCTION(http); -+PHP_MSHUTDOWN_FUNCTION(http); -+PHP_RINIT_FUNCTION(http); -+PHP_RSHUTDOWN_FUNCTION(http); -+PHP_MINFO_FUNCTION(http); -+ -+/* {{{ http_module_dep */ -+#if ZEND_EXTENSION_API_NO >= 220050617 -+static zend_module_dep http_module_deps[] = { -+# ifdef HTTP_HAVE_SPL -+ ZEND_MOD_REQUIRED("spl") -+# endif -+# ifdef HTTP_HAVE_HASH -+ ZEND_MOD_REQUIRED("hash") -+# endif -+# ifdef HTTP_HAVE_SESSION -+ ZEND_MOD_REQUIRED("session") -+# endif -+# ifdef HTTP_HAVE_ICONV -+ ZEND_MOD_REQUIRED("iconv") -+# endif -+# ifdef HTTP_HAVE_EVENT -+ ZEND_MOD_CONFLICTS("event") -+#endif -+ {NULL, NULL, NULL, 0} -+}; -+#endif -+/* }}} */ -+ -+/* {{{ http_module_entry */ -+zend_module_entry http_module_entry = { -+#if ZEND_EXTENSION_API_NO >= 220050617 -+ STANDARD_MODULE_HEADER_EX, NULL, -+ http_module_deps, -+#else -+ STANDARD_MODULE_HEADER, -+#endif -+ "http", -+ http_functions, -+ PHP_MINIT(http), -+ PHP_MSHUTDOWN(http), -+ PHP_RINIT(http), -+ PHP_RSHUTDOWN(http), -+ PHP_MINFO(http), -+ PHP_HTTP_VERSION, -+ STANDARD_MODULE_PROPERTIES -+}; -+/* }}} */ -+ -+int http_module_number; -+ -+/* {{{ http_globals */ -+static void http_globals_init_once(zend_http_globals *G) -+{ -+ memset(G, 0, sizeof(zend_http_globals)); -+} -+ -+#define http_globals_init(g) _http_globals_init((g) TSRMLS_CC) -+static inline void _http_globals_init(zend_http_globals *G TSRMLS_DC) -+{ -+#ifdef HTTP_HAVE_SAPI_RTIME -+ G->request.time = sapi_get_request_time(TSRMLS_C); -+#else -+ G->request.time = time(NULL); -+#endif -+ G->send.buffer_size = 0; -+ G->read_post_data = 0; -+} -+ -+#define http_globals_free(g) _http_globals_free((g) TSRMLS_CC) -+static inline void _http_globals_free(zend_http_globals *G TSRMLS_DC) -+{ -+ if (G->request.headers) { -+ zend_hash_destroy(G->request.headers); -+ FREE_HASHTABLE(G->request.headers); -+ G->request.headers = NULL; -+ } -+ STR_SET(G->send.content_type, NULL); -+ STR_SET(G->send.unquoted_etag, NULL); -+ if (G->server_var) { -+ zval_ptr_dtor(&G->server_var); -+ G->server_var = NULL; -+ } -+} -+ -+#if defined(ZTS) && defined(PHP_DEBUG) -+#if ZTS && PHP_DEBUG -+zend_http_globals *http_globals(void) -+{ -+ TSRMLS_FETCH(); -+ return HTTP_G; -+} -+#endif -+#endif -+/* }}} */ -+ -+/* {{{ static inline void http_check_allowed_methods(char *) */ -+#define http_check_allowed_methods(m) _http_check_allowed_methods((m) TSRMLS_CC) -+static inline void _http_check_allowed_methods(const char *methods TSRMLS_DC) -+{ -+ if (*methods && SG(request_info).request_method) { -+ if (SUCCESS != http_check_method_ex(SG(request_info).request_method, methods)) { -+ char *header; -+ spprintf(&header, 0, "Allow: %s", methods); -+ http_exit(405, header); -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ PHP_INI */ -+PHP_INI_MH(http_update_allowed_methods) -+{ -+ if (*new_value) { -+ http_check_allowed_methods(new_value); -+ } -+ return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); -+} -+PHP_INI_MH(http_update_persistent_handle_ident) -+{ -+ HTTP_G->persistent.handles.ident.h = zend_hash_func(new_value, HTTP_G->persistent.handles.ident.l = new_value_length+1); -+ return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); -+} -+ -+#ifndef ZEND_ENGINE_2 -+# define OnUpdateLong OnUpdateInt -+#endif -+ -+PHP_INI_BEGIN() -+ HTTP_PHP_INI_ENTRY("http.etag.mode", "MD5", PHP_INI_ALL, OnUpdateString, etag.mode) -+ HTTP_PHP_INI_ENTRY("http.log.cache", "", PHP_INI_ALL, OnUpdateString, log.cache) -+ HTTP_PHP_INI_ENTRY("http.log.redirect", "", PHP_INI_ALL, OnUpdateString, log.redirect) -+ HTTP_PHP_INI_ENTRY("http.log.not_found", "", PHP_INI_ALL, OnUpdateString, log.not_found) -+ HTTP_PHP_INI_ENTRY("http.log.allowed_methods", "", PHP_INI_ALL, OnUpdateString, log.allowed_methods) -+ HTTP_PHP_INI_ENTRY("http.log.composite", "", PHP_INI_ALL, OnUpdateString, log.composite) -+ HTTP_PHP_INI_ENTRY("http.request.methods.allowed", "", PHP_INI_ALL, http_update_allowed_methods, request.methods.allowed) -+ HTTP_PHP_INI_ENTRY("http.request.methods.custom", "", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateString, request.methods.custom) -+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) -+ HTTP_PHP_INI_ENTRY("http.request.datashare.cookie", "0", PHP_INI_SYSTEM, OnUpdateBool, request.datashare.cookie) -+ HTTP_PHP_INI_ENTRY("http.request.datashare.dns", "1", PHP_INI_SYSTEM, OnUpdateBool, request.datashare.dns) -+ HTTP_PHP_INI_ENTRY("http.request.datashare.ssl", "0", PHP_INI_SYSTEM, OnUpdateBool, request.datashare.ssl) -+ HTTP_PHP_INI_ENTRY("http.request.datashare.connect", "0", PHP_INI_SYSTEM, OnUpdateBool, request.datashare.connect) -+#endif -+#ifdef HTTP_HAVE_ZLIB -+ HTTP_PHP_INI_ENTRY("http.send.inflate.start_auto", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, send.inflate.start_auto) -+ HTTP_PHP_INI_ENTRY("http.send.inflate.start_flags", "0", PHP_INI_ALL, OnUpdateLong, send.inflate.start_flags) -+ HTTP_PHP_INI_ENTRY("http.send.deflate.start_auto", "0", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, send.deflate.start_auto) -+ HTTP_PHP_INI_ENTRY("http.send.deflate.start_flags", "0", PHP_INI_ALL, OnUpdateLong, send.deflate.start_flags) -+#endif -+ HTTP_PHP_INI_ENTRY("http.persistent.handles.limit", "-1", PHP_INI_SYSTEM, OnUpdateLong, persistent.handles.limit) -+ HTTP_PHP_INI_ENTRY("http.persistent.handles.ident", "GLOBAL", PHP_INI_ALL, http_update_persistent_handle_ident, persistent.handles.ident.s) -+ HTTP_PHP_INI_ENTRY("http.send.not_found_404", "1", PHP_INI_ALL, OnUpdateBool, send.not_found_404) -+#ifdef ZEND_ENGINE_2 -+ HTTP_PHP_INI_ENTRY("http.only_exceptions", "0", PHP_INI_ALL, OnUpdateBool, only_exceptions) -+#endif -+ HTTP_PHP_INI_ENTRY("http.force_exit", "1", PHP_INI_ALL, OnUpdateBool, force_exit) -+PHP_INI_END() -+/* }}} */ -+ -+/* {{{ PHP_MINIT_FUNCTION */ -+PHP_MINIT_FUNCTION(http) -+{ -+ http_module_number = module_number; -+ ZEND_INIT_MODULE_GLOBALS(http, http_globals_init_once, NULL); -+ REGISTER_INI_ENTRIES(); -+ -+ if (0 -+ || SUCCESS != PHP_MINIT_CALL(http_persistent_handle) /* first */ -+ || SUCCESS != PHP_MINIT_CALL(http_cookie) -+#ifdef HTTP_HAVE_ZLIB -+ || SUCCESS != PHP_MINIT_CALL(http_encoding) -+#endif -+#ifdef HTTP_HAVE_CURL -+ || SUCCESS != PHP_MINIT_CALL(http_request) -+# ifdef ZEND_ENGINE_2 -+# endif -+#endif -+ || SUCCESS != PHP_MINIT_CALL(http_request_method) -+ || SUCCESS != PHP_MINIT_CALL(http_send) -+ || SUCCESS != PHP_MINIT_CALL(http_support) -+ || SUCCESS != PHP_MINIT_CALL(http_url) -+ -+#ifdef ZEND_ENGINE_2 -+ || SUCCESS != PHP_MINIT_CALL(http_filter) -+ || SUCCESS != PHP_MINIT_CALL(http_exception_object) -+# ifdef HTTP_HAVE_ZLIB -+ || SUCCESS != PHP_MINIT_CALL(http_deflatestream_object) -+ || SUCCESS != PHP_MINIT_CALL(http_inflatestream_object) -+# endif -+ || SUCCESS != PHP_MINIT_CALL(http_message_object) -+ || SUCCESS != PHP_MINIT_CALL(http_querystring_object) -+# ifdef HTTP_HAVE_CURL -+ || SUCCESS != PHP_MINIT_CALL(http_request_datashare) -+ || SUCCESS != PHP_MINIT_CALL(http_request_pool) -+ || SUCCESS != PHP_MINIT_CALL(http_request_object) -+ || SUCCESS != PHP_MINIT_CALL(http_requestdatashare_object) -+ || SUCCESS != PHP_MINIT_CALL(http_requestpool_object) -+# endif -+# ifndef WONKY -+ || SUCCESS != PHP_MINIT_CALL(http_response_object) -+# endif -+ || SUCCESS != PHP_MINIT_CALL(http_util_object) -+#endif -+ ) { -+ return FAILURE; -+ } -+ -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ PHP_MSHUTDOWN_FUNCTION */ -+PHP_MSHUTDOWN_FUNCTION(http) -+{ -+ UNREGISTER_INI_ENTRIES(); -+ -+ if (0 -+#ifdef HTTP_HAVE_CURL -+ || SUCCESS != PHP_MSHUTDOWN_CALL(http_request) -+# ifdef ZEND_ENGINE_2 -+ || SUCCESS != PHP_MSHUTDOWN_CALL(http_request_datashare) -+# endif -+#endif -+ || SUCCESS != PHP_MSHUTDOWN_CALL(http_message_object) -+ || SUCCESS != PHP_MSHUTDOWN_CALL(http_persistent_handle) /* last */ -+ ) { -+ return FAILURE; -+ } -+ -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ PHP_RINIT_FUNCTION */ -+PHP_RINIT_FUNCTION(http) -+{ -+ http_globals_init(HTTP_G); -+ -+ if (HTTP_G->request.methods.allowed && *HTTP_G->request.methods.allowed) { -+ http_check_allowed_methods(HTTP_G->request.methods.allowed); -+ } -+ -+ if (0 -+#ifdef HTTP_HAVE_ZLIB -+ || SUCCESS != PHP_RINIT_CALL(http_encoding) -+#endif -+#ifdef HTTP_HAVE_CURL -+# ifdef ZEND_ENGINE_2 -+# ifdef HTTP_HAVE_EVENT -+ || SUCCESS != PHP_RINIT_CALL(http_request_pool) -+# endif -+ || SUCCESS != PHP_RINIT_CALL(http_request_datashare) -+# endif -+#endif -+ || SUCCESS != PHP_RINIT_CALL(http_request_method) -+ ) { -+ return FAILURE; -+ } -+ -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ PHP_RSHUTDOWN_FUNCTION */ -+PHP_RSHUTDOWN_FUNCTION(http) -+{ -+ STATUS status = SUCCESS; -+ -+ if (0 -+#ifdef HTTP_HAVE_ZLIB -+ || SUCCESS != PHP_RSHUTDOWN_CALL(http_encoding) -+#endif -+#ifdef HTTP_HAVE_CURL -+# ifdef ZEND_ENGINE_2 -+ || SUCCESS != PHP_RSHUTDOWN_CALL(http_request_datashare) -+# endif -+#endif -+ || SUCCESS != PHP_RSHUTDOWN_CALL(http_request_method) -+ ) { -+ status = FAILURE; -+ } -+ -+ http_globals_free(HTTP_G); -+ return status; -+} -+/* }}} */ -+ -+/* {{{ PHP_MINFO_FUNCTION */ -+PHP_MINFO_FUNCTION(http) -+{ -+ php_info_print_table_start(); -+ { -+ php_info_print_table_header(2, "HTTP Support", "enabled"); -+ php_info_print_table_row(2, "Extension Version", PHP_HTTP_VERSION); -+ php_info_print_table_row(2, "Registered Classes", -+#ifndef ZEND_ENGINE_2 -+ "none" -+#else -+ "HttpUtil, " -+ "HttpMessage, " -+# ifdef HTTP_HAVE_CURL -+ "HttpRequest, " -+ "HttpRequestPool, " -+ "HttpRequestDataShare, " -+# endif -+# ifdef HTTP_HAVE_ZLIB -+ "HttpDeflateStream, " -+ "HttpInflateStream, " -+# endif -+# ifndef WONKY -+ "HttpResponse, " -+# endif -+ "HttpQueryString" -+#endif -+ ); -+ php_info_print_table_row(2, "Output Handlers", "ob_deflatehandler, ob_inflatehandler, ob_etaghandler"); -+ php_info_print_table_row(2, "Stream Filters", -+#ifndef ZEND_ENGINE_2 -+ "none" -+#else -+ "http.chunked_decode, http.chunked_encode, http.deflate, http.inflate" -+#endif -+ ); -+ } -+ php_info_print_table_end(); -+ -+ php_info_print_table_start(); -+ php_info_print_table_header(3, "Used Library", "Compiled", "Linked"); -+ { -+#ifdef HTTP_HAVE_CURL -+ curl_version_info_data *cv = curl_version_info(CURLVERSION_NOW); -+ php_info_print_table_row(3, "libcurl", LIBCURL_VERSION, cv->version); -+#else -+ php_info_print_table_row(2, "libcurl", "disabled", "disabled"); -+#endif -+#ifdef HTTP_HAVE_EVENT -+ php_info_print_table_row(3, "libevent", HTTP_EVENT_VERSION, event_get_version()); -+#else -+ php_info_print_table_row(3, "libevent", "disabled", "disabled"); -+#endif -+#ifdef HTTP_HAVE_ZLIB -+ php_info_print_table_row(3, "libz", ZLIB_VERSION, zlibVersion()); -+#else -+ php_info_print_table_row(3, "libz", "disabled", "disabled"); -+#endif -+#if defined(HTTP_HAVE_MAGIC) -+ php_info_print_table_row(3, "libmagic", "unknown", "unknown"); -+#else -+ php_info_print_table_row(3, "libmagic", "disabled", "disabled"); -+#endif -+ } -+ php_info_print_table_end(); -+ -+ php_info_print_table_start(); -+ php_info_print_table_colspan_header(4, "Persistent Handles"); -+ php_info_print_table_header(4, "Provider", "Ident", "Used", "Free"); -+ { -+ HashTable *ht; -+ HashPosition pos1, pos2; -+ HashKey provider = initHashKey(0), ident = initHashKey(0); -+ zval **val, **sub, **zused, **zfree; -+ -+ if ((ht = http_persistent_handle_statall()) && zend_hash_num_elements(ht)) { -+ FOREACH_HASH_KEYVAL(pos1, ht, provider, val) { -+ if (zend_hash_num_elements(Z_ARRVAL_PP(val))) { -+ FOREACH_KEYVAL(pos2, *val, ident, sub) { -+ if ( SUCCESS == zend_hash_find(Z_ARRVAL_PP(sub), ZEND_STRS("used"), (void *) &zused) && -+ SUCCESS == zend_hash_find(Z_ARRVAL_PP(sub), ZEND_STRS("free"), (void *) &zfree)) { -+ zval *used = http_zsep(IS_STRING, *zused); -+ zval *free = http_zsep(IS_STRING, *zfree); -+ php_info_print_table_row(4, provider.str, ident.str, Z_STRVAL_P(used), Z_STRVAL_P(free)); -+ zval_ptr_dtor(&used); -+ zval_ptr_dtor(&free); -+ } else { -+ php_info_print_table_row(4, provider.str, ident.str, "0", "0"); -+ } -+ } -+ } else { -+ php_info_print_table_row(4, provider.str, "N/A", "0", "0"); -+ } -+ } -+ } else { -+ php_info_print_table_row(4, "N/A", "N/A", "0", "0"); -+ } -+ if (ht) { -+ zend_hash_destroy(ht); -+ FREE_HASHTABLE(ht); -+ } -+ } -+ php_info_print_table_end(); -+ -+ php_info_print_table_start(); -+ php_info_print_table_colspan_header(2, "Request Methods"); -+ { -+ HashPosition pos; -+ phpstr *methods = phpstr_new(); -+ char **name; -+ -+ FOREACH_HASH_VAL(pos, &HTTP_G->request.methods.registered, name) { -+ if (pos->h) { -+ phpstr_appendf(methods, "%s, ", *name); -+ } -+ } -+ phpstr_fix(methods); -+ php_info_print_table_row(2, "Registered", PHPSTR_VAL(methods)); -+ php_info_print_table_row(2, "Allowed", *HTTP_G->request.methods.allowed ? HTTP_G->request.methods.allowed : "(ANY)"); -+ phpstr_free(&methods); -+ } -+ php_info_print_table_end(); -+ -+ DISPLAY_INI_ENTRIES(); -+} -+/* }}} */ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http.dsp -@@ -0,0 +1,257 @@ -+# Microsoft Developer Studio Project File - Name="http" - Package Owner=<4> -+# Microsoft Developer Studio Generated Build File, Format Version 6.00 -+# ** DO NOT EDIT ** -+ -+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 -+ -+CFG=http - Win32 Release_TS -+!MESSAGE This is not a valid makefile. To build this project using NMAKE, -+!MESSAGE use the Export Makefile command and run -+!MESSAGE -+!MESSAGE NMAKE /f "http.mak". -+!MESSAGE -+!MESSAGE You can specify a configuration when running NMAKE -+!MESSAGE by defining the macro CFG on the command line. For example: -+!MESSAGE -+!MESSAGE NMAKE /f "http.mak" CFG="http - Win32 Release_TS" -+!MESSAGE -+!MESSAGE Possible choices for configuration are: -+!MESSAGE -+!MESSAGE "http - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library") -+!MESSAGE "http - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library") -+!MESSAGE -+ -+# Begin Project -+# PROP AllowPerConfigDependencies 0 -+# PROP Scc_ProjName "" -+# PROP Scc_LocalPath "" -+CPP=cl.exe -+MTL=midl.exe -+RSC=rc.exe -+ -+!IF "$(CFG)" == "http - Win32 Release_TS" -+ -+# PROP BASE Use_MFC 0 -+# PROP BASE Use_Debug_Libraries 0 -+# PROP BASE Output_Dir "Release_TS" -+# PROP BASE Intermediate_Dir "Release_TS" -+# PROP BASE Ignore_Export_Lib 0 -+# PROP BASE Target_Dir "" -+# PROP Use_MFC 0 -+# PROP Use_Debug_Libraries 0 -+# PROP Output_Dir "Release_TS" -+# PROP Intermediate_Dir "Release_TS" -+# PROP Ignore_Export_Lib 0 -+# PROP Target_Dir "" -+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMPILE_DL_HTTP" /D ZTS=1 /YX /FD /c -+# ADD CPP /nologo /Gd /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D ZEND_DEBUG=0 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "HTTP_EXPORTS" /D "COMPILE_DL_HTTP" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_HTTP=1 /D HTTP_HAVE_CURL=1 /D HAVE_CURL_EASY_STRERROR=1 /D HAVE_CURL_SHARE_STRERROR=1 /D HAVE_CURL_MULTI_STRERROR=1 /D HAVE_CURL_EASY_RESET=1 /D HAVE_CURL_FORMGET=1 /D HAVE_GETHOSTNAME=1 /D HAVE_GETSERVBYPORT=1 /D HAVE_GETSERVBYNAME=1 /D "_WINSOCKAPI_=" /FR /YX /FD /c -+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -+# ADD BASE RSC /l 0x406 /d "NDEBUG" -+# ADD RSC /l 0x406 /d "NDEBUG" -+BSC32=bscmake.exe -+# ADD BASE BSC32 /nologo -+# ADD BSC32 /nologo -+LINK32=link.exe -+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /machine:I386 -+# ADD LINK32 libcurl.lib ssleay32.lib libeay32.lib zlib.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib wsock32.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS/php_http.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline" /libpath:"..\..\..\php_build\curl\lib" /libpath:"..\..\..\php4\Release_TS" /libpath:"..\..\..\php4\Release_TS_Inline" -+ -+!ELSEIF "$(CFG)" == "http - Win32 Debug_TS" -+ -+# PROP BASE Use_MFC 0 -+# PROP BASE Use_Debug_Libraries 0 -+# PROP BASE Output_Dir "Debug_TS" -+# PROP BASE Intermediate_Dir "Debug_TS" -+# PROP BASE Ignore_Export_Lib 0 -+# PROP BASE Target_Dir "" -+# PROP Use_MFC 0 -+# PROP Use_Debug_Libraries 0 -+# PROP Output_Dir "Debug_TS" -+# PROP Intermediate_Dir "Debug_TS" -+# PROP Ignore_Export_Lib 0 -+# PROP Target_Dir "" -+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMPILE_DL_HTTP" /D ZTS=1 /YX /FD /c -+# ADD CPP /nologo /MDd /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "HTTP_EXPORTS" /D "COMPILE_DL_HTTP" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_HTTP=1 /D HTTP_HAVE_CURL=1 /D HAVE_CURL_EASY_STRERROR=1 /D HAVE_CURL_SHARE_STRERROR=1 /D HAVE_CURL_MULTI_STRERROR=1 /D HAVE_CURL_EASY_RESET=1 /D HAVE_CURL_FORMGET=1 /D HAVE_GETHOSTNAME=1 /D HAVE_GETSERVBYPORT=1 /D HAVE_GETSERVBYNAME=1 /D "_WINSOCKAPI_=" /YX /FD /c -+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -+# ADD BASE RSC /l 0x406 /d "NDEBUG" -+# ADD RSC /l 0x406 /d "NDEBUG" -+BSC32=bscmake.exe -+# ADD BASE BSC32 /nologo -+# ADD BSC32 /nologo -+LINK32=link.exe -+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /machine:I386 -+# ADD LINK32 libcurl.lib ssleay32.lib libeay32.lib zlib.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts_debug.lib wsock32.lib /nologo /dll /machine:I386 /out:"..\..\Debug_TS/http.dll" /libpath:"..\..\Debug_TS" /libpath:"..\..\..\php_build\curl\lib" /libpath:"..\..\..\php4\Release_TS" /libpath:"..\..\..\php4\Release_TS_Inline" -+ -+!ENDIF -+ -+# Begin Target -+ -+# Name "http - Win32 Release_TS" -+# Name "http - Win32 Debug_TS" -+# Begin Group "Source Files" -+ -+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -+# Begin Source File -+ -+SOURCE=.\http.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_api.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_encoding_api.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_request_api.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_request_info.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_request_body_api.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_request_method_api.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_functions.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_persistent_handle_api.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_cache_api.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_cookie_api.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_date_api.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_headers_api.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_message_api.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_send_api.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_url_api.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_querystring_api.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\http_info_api.c -+# End Source File -+# Begin Source File -+ -+SOURCE=.\phpstr\phpstr.c -+# End Source File -+# End Group -+# Begin Group "Header Files" -+ -+# PROP Default_Filter "h;hpp;hxx;hm;inl" -+# Begin Source File -+ -+SOURCE=.\php_http.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_api.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_encoding_api.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_request_api.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_request_int.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_request_body_api.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_request_method_api.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_persistent_handle_api.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_cache_api.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_cookie_api.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_date_api.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_message_api.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_send_api.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_headers_api.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_url_api.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_querystring_api.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_info_api.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\php_http_std_defs.h -+# End Source File -+# Begin Source File -+ -+SOURCE=.\phpstr\phpstr.h -+# End Source File -+# End Group -+# Begin Group "Resource Files" -+ -+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -+# End Group -+# End Target -+# End Project ---- /dev/null -+++ b/ext/http/http_api.c -@@ -0,0 +1,754 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_api.c 323405 2012-02-21 10:05:05Z mike $ */ -+ -+#define HTTP_WANT_SAPI -+#include "php_http.h" -+ -+#include "php_output.h" -+#include "ext/standard/url.h" -+#include "ext/standard/php_lcg.h" -+ -+#include "php_http_api.h" -+#include "php_http_send_api.h" -+ -+#ifdef ZEND_ENGINE_2 -+# include "php_http_exception_object.h" -+#endif -+ -+PHP_MINIT_FUNCTION(http_support) -+{ -+ HTTP_LONG_CONSTANT("HTTP_SUPPORT", HTTP_SUPPORT); -+ HTTP_LONG_CONSTANT("HTTP_SUPPORT_REQUESTS", HTTP_SUPPORT_REQUESTS); -+ HTTP_LONG_CONSTANT("HTTP_SUPPORT_MAGICMIME", HTTP_SUPPORT_MAGICMIME); -+ HTTP_LONG_CONSTANT("HTTP_SUPPORT_ENCODINGS", HTTP_SUPPORT_ENCODINGS); -+ HTTP_LONG_CONSTANT("HTTP_SUPPORT_SSLREQUESTS", HTTP_SUPPORT_SSLREQUESTS); -+ HTTP_LONG_CONSTANT("HTTP_SUPPORT_EVENTS", HTTP_SUPPORT_EVENTS); -+ -+ HTTP_LONG_CONSTANT("HTTP_PARAMS_ALLOW_COMMA", HTTP_PARAMS_ALLOW_COMMA); -+ HTTP_LONG_CONSTANT("HTTP_PARAMS_ALLOW_FAILURE", HTTP_PARAMS_ALLOW_FAILURE); -+ HTTP_LONG_CONSTANT("HTTP_PARAMS_RAISE_ERROR", HTTP_PARAMS_RAISE_ERROR); -+ HTTP_LONG_CONSTANT("HTTP_PARAMS_DEFAULT", HTTP_PARAMS_DEFAULT); -+ -+ return SUCCESS; -+} -+ -+PHP_HTTP_API long _http_support(long feature) -+{ -+ long support = HTTP_SUPPORT; -+ -+#ifdef HTTP_HAVE_CURL -+ support |= HTTP_SUPPORT_REQUESTS; -+# ifdef HTTP_HAVE_SSL -+ support |= HTTP_SUPPORT_SSLREQUESTS; -+# endif -+# ifdef HTTP_HAVE_EVENT -+ support |= HTTP_SUPPORT_EVENTS; -+# endif -+#endif -+#ifdef HTTP_HAVE_MAGIC -+ support |= HTTP_SUPPORT_MAGICMIME; -+#endif -+#ifdef HTTP_HAVE_ZLIB -+ support |= HTTP_SUPPORT_ENCODINGS; -+#endif -+ -+ if (feature) { -+ return (feature == (support & feature)); -+ } -+ return support; -+} -+ -+/* char *pretty_key(char *, size_t, zend_bool, zend_bool) */ -+char *_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen) -+{ -+ size_t i; -+ int wasalpha; -+ -+ if (key && key_len) { -+ if ((wasalpha = HTTP_IS_CTYPE(alpha, key[0]))) { -+ key[0] = (char) (uctitle ? HTTP_TO_CTYPE(upper, key[0]) : HTTP_TO_CTYPE(lower, key[0])); -+ } -+ for (i = 1; i < key_len; i++) { -+ if (HTTP_IS_CTYPE(alpha, key[i])) { -+ key[i] = (char) (((!wasalpha) && uctitle) ? HTTP_TO_CTYPE(upper, key[i]) : HTTP_TO_CTYPE(lower, key[i])); -+ wasalpha = 1; -+ } else { -+ if (xhyphen && (key[i] == '_')) { -+ key[i] = '-'; -+ } -+ wasalpha = 0; -+ } -+ } -+ } -+ return key; -+} -+/* }}} */ -+ -+/* {{{ http_boundary(char *, size_t) */ -+size_t _http_boundary(char *buf, size_t buf_len TSRMLS_DC) -+{ -+ return snprintf(buf, buf_len, "%lu%0.9f", (ulong) HTTP_G->request.time, (float) php_combined_lcg(TSRMLS_C)); -+} -+/* }}} */ -+ -+/* {{{ void http_error(long, long, char*) */ -+void _http_error_ex(long type TSRMLS_DC, long code, const char *format, ...) -+{ -+ va_list args; -+ -+ va_start(args, format); -+#ifdef ZEND_ENGINE_2 -+ if ((type == E_THROW) || (GLOBAL_ERROR_HANDLING == EH_THROW)) { -+ char *message; -+ zend_class_entry *ce = http_exception_get_for_code(code); -+ -+ http_try { -+ vspprintf(&message, 0, format, args); -+ zend_throw_exception(ce, message, code TSRMLS_CC); -+ efree(message); -+ } http_catch(GLOBAL_EXCEPTION_CLASS ? GLOBAL_EXCEPTION_CLASS : HTTP_EX_DEF_CE); -+ } else -+#endif -+ php_verror(NULL, "", type, format, args TSRMLS_CC); -+ va_end(args); -+} -+/* }}} */ -+ -+#ifdef ZEND_ENGINE_2 -+static inline void copy_bt_args(zval *from, zval *to TSRMLS_DC) -+{ -+ zval **args, **trace_0, *old_trace_0, *trace = NULL; -+ -+ if ((trace = zend_read_property(ZEND_EXCEPTION_GET_DEFAULT(), from, "trace", lenof("trace"), 0 TSRMLS_CC))) { -+ if (Z_TYPE_P(trace) == IS_ARRAY && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(trace), 0, (void *) &trace_0)) { -+ old_trace_0 = *trace_0; -+ if (Z_TYPE_PP(trace_0) == IS_ARRAY && SUCCESS == zend_hash_find(Z_ARRVAL_PP(trace_0), "args", sizeof("args"), (void *) &args)) { -+ if ((trace = zend_read_property(ZEND_EXCEPTION_GET_DEFAULT(), to, "trace", lenof("trace"), 0 TSRMLS_CC))) { -+ if (Z_TYPE_P(trace) == IS_ARRAY && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(trace), 0, (void *) &trace_0)) { -+ ZVAL_ADDREF(*args); -+ add_assoc_zval(*trace_0, "args", *args); -+ } -+ } -+ } -+ } -+ } -+} -+ -+/* {{{ zval *http_exception_wrap(zval *, zval *, zend_class_entry *) */ -+zval *_http_exception_wrap(zval *old_exception, zval *new_exception, zend_class_entry *ce TSRMLS_DC) -+{ -+ int inner = 1; -+ char *message; -+ zval *sub_exception, *tmp_exception; -+ -+ if (!new_exception) { -+ MAKE_STD_ZVAL(new_exception); -+ object_init_ex(new_exception, ce); -+ -+ zend_update_property(ce, new_exception, "innerException", lenof("innerException"), old_exception TSRMLS_CC); -+ copy_bt_args(old_exception, new_exception TSRMLS_CC); -+ -+ sub_exception = old_exception; -+ -+ while ((sub_exception = zend_read_property(Z_OBJCE_P(sub_exception), sub_exception, "innerException", lenof("innerException"), 0 TSRMLS_CC)) && Z_TYPE_P(sub_exception) == IS_OBJECT) { -+ ++inner; -+ } -+ -+ spprintf(&message, 0, "Exception caused by %d inner exception(s)", inner); -+ zend_update_property_string(ZEND_EXCEPTION_GET_DEFAULT(), new_exception, "message", lenof("message"), message TSRMLS_CC); -+ efree(message); -+ } else { -+ sub_exception = new_exception; -+ tmp_exception = new_exception; -+ -+ while ((tmp_exception = zend_read_property(Z_OBJCE_P(tmp_exception), tmp_exception, "innerException", lenof("innerException"), 0 TSRMLS_CC)) && Z_TYPE_P(tmp_exception) == IS_OBJECT) { -+ sub_exception = tmp_exception; -+ } -+ -+ zend_update_property(Z_OBJCE_P(sub_exception), sub_exception, "innerException", lenof("innerException"), old_exception TSRMLS_CC); -+ copy_bt_args(old_exception, new_exception TSRMLS_CC); -+ copy_bt_args(old_exception, sub_exception TSRMLS_CC); -+ } -+#if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3 -+ Z_ADDREF_P(old_exception); -+ zend_exception_set_previous(new_exception, old_exception TSRMLS_CC); -+#endif -+ zval_ptr_dtor(&old_exception); -+ return new_exception; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_object_new(zend_object_value *, const char *, uint, http_object_new_t, zend_class_entry *, void *, void **) */ -+STATUS _http_object_new(zend_object_value *ov, const char *cname_str, uint cname_len, http_object_new_t create, zend_class_entry *parent_ce, void *intern_ptr, void **obj_ptr TSRMLS_DC) -+{ -+ zend_class_entry *ce = parent_ce; -+ -+ if (cname_str && cname_len) { -+ if (!(ce = zend_fetch_class(HTTP_ZAPI_CONST_CAST(char *) cname_str, cname_len, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC))) { -+ return FAILURE; -+ } -+ if (!instanceof_function(ce, parent_ce TSRMLS_CC)) { -+ http_error_ex(HE_WARNING, HTTP_E_RUNTIME, "Class %s does not extend %s", cname_str, parent_ce->name); -+ return FAILURE; -+ } -+ } -+ -+ *ov = create(ce, intern_ptr, obj_ptr TSRMLS_CC); -+ return SUCCESS; -+} -+/* }}} */ -+#endif /* ZEND_ENGINE_2 */ -+ -+/* {{{ void http_log(char *, char *, char *) */ -+void _http_log_ex(char *file, const char *ident, const char *message TSRMLS_DC) -+{ -+ time_t now; -+ struct tm nowtm; -+ char datetime[20] = {0}; -+ -+ now = HTTP_G->request.time; -+ strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", php_localtime_r(&now, &nowtm)); -+ -+#define HTTP_LOG_WRITE(file, type, msg) \ -+ if (file && *file) { \ -+ php_stream *log = php_stream_open_wrapper_ex(file, "ab", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT); \ -+ \ -+ if (log) { \ -+ php_stream_printf(log TSRMLS_CC, "%s\t[%s]\t%s\t<%s>%s", datetime, type, msg, SG(request_info).request_uri, PHP_EOL); \ -+ php_stream_close(log); \ -+ } \ -+ \ -+ } -+ -+ HTTP_LOG_WRITE(file, ident, message); -+ HTTP_LOG_WRITE(HTTP_G->log.composite, ident, message); -+} -+/* }}} */ -+ -+static void http_ob_blackhole(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC) -+{ -+ *handled_output = ecalloc(1,1); -+ *handled_output_len = 0; -+} -+ -+/* {{{ STATUS http_exit(int, char*, char*) */ -+STATUS _http_exit_ex(int status, char *header, char *body, zend_bool send_header TSRMLS_DC) -+{ -+ if ( (send_header && (SUCCESS != http_send_status_header(status, header))) || -+ (status && (SUCCESS != http_send_status(status)))) { -+ http_error_ex(HE_WARNING, HTTP_E_HEADER, "Failed to exit with status/header: %d - %s", status, STR_PTR(header)); -+ STR_FREE(header); -+ STR_FREE(body); -+ return FAILURE; -+ } -+ -+#ifndef PHP_OUTPUT_NEWAPI -+ if (!OG(ob_lock) && -+ !php_ob_handler_used("zlib output compression" TSRMLS_CC) && !php_ob_handler_used("ob_gzhandler" TSRMLS_CC)) { -+ php_end_ob_buffers(0 TSRMLS_CC); -+ } -+#endif -+ -+ if ((SUCCESS == sapi_send_headers(TSRMLS_C)) && body) { -+ PHPWRITE(body, strlen(body)); -+ } -+ -+ switch (status) { -+ case 301: http_log(HTTP_G->log.redirect, "301-REDIRECT", header); break; -+ case 302: http_log(HTTP_G->log.redirect, "302-REDIRECT", header); break; -+ case 303: http_log(HTTP_G->log.redirect, "303-REDIRECT", header); break; -+ case 305: http_log(HTTP_G->log.redirect, "305-REDIRECT", header); break; -+ case 307: http_log(HTTP_G->log.redirect, "307-REDIRECT", header); break; -+ case 304: http_log(HTTP_G->log.cache, "304-CACHE", header); break; -+ case 404: http_log(HTTP_G->log.not_found, "404-NOTFOUND", NULL); break; -+ case 405: http_log(HTTP_G->log.allowed_methods, "405-ALLOWED", header); break; -+ default: http_log(NULL, header, body); break; -+ } -+ -+ STR_FREE(header); -+ STR_FREE(body); -+ -+ if (HTTP_G->force_exit) { -+ zend_bailout(); -+ } else { -+#ifdef PHP_OUTPUT_NEWAPI -+ php_output_start_devnull(TSRMLS_C); -+#else -+ php_ob_set_internal_handler(http_ob_blackhole, 4096, "blackhole", 0 TSRMLS_CC); -+#endif -+ } -+ -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_check_method(char *) */ -+STATUS _http_check_method_ex(const char *method, const char *methods) -+{ -+ const char *found; -+ -+ if ( (found = strstr(methods, method)) && -+ (found == method || !HTTP_IS_CTYPE(alpha, found[-1])) && -+ (strlen(found) >= strlen(method) && !HTTP_IS_CTYPE(alpha, found[strlen(method)]))) { -+ return SUCCESS; -+ } -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ zval *http_get_server_var_ex(char *, size_t) */ -+PHP_HTTP_API zval *_http_get_server_var_ex(const char *key, size_t key_len, zend_bool check TSRMLS_DC) -+{ -+ zval **hsv, **var; -+ char *env; -+ -+ /* if available, this is a lot faster than accessing $_SERVER */ -+ if (sapi_module.getenv) { -+ if ((!(env = sapi_module.getenv((char *) key, key_len TSRMLS_CC))) || (check && !*env)) { -+ return NULL; -+ } -+ if (HTTP_G->server_var) { -+ zval_ptr_dtor(&HTTP_G->server_var); -+ } -+ MAKE_STD_ZVAL(HTTP_G->server_var); -+ ZVAL_STRING(HTTP_G->server_var, env, 1); -+ return HTTP_G->server_var; -+ } -+ -+#ifdef ZEND_ENGINE_2 -+ zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC); -+#endif -+ -+ if ((SUCCESS != zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &hsv)) || (Z_TYPE_PP(hsv) != IS_ARRAY)) { -+ return NULL; -+ } -+ if ((SUCCESS != zend_hash_find(Z_ARRVAL_PP(hsv), HTTP_ZAPI_CONST_CAST(char *) key, key_len + 1, (void *) &var))) { -+ return NULL; -+ } -+ if (check && !((Z_TYPE_PP(var) == IS_STRING) && Z_STRVAL_PP(var) && Z_STRLEN_PP(var))) { -+ return NULL; -+ } -+ return *var; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_get_request_body(char **, size_t *) */ -+PHP_HTTP_API STATUS _http_get_request_body_ex(char **body, size_t *length, zend_bool dup TSRMLS_DC) -+{ -+ *length = 0; -+ *body = NULL; -+ -+ if (SG(request_info).raw_post_data) { -+ *length = SG(request_info).raw_post_data_length; -+ *body = SG(request_info).raw_post_data; -+ -+ if (dup) { -+ *body = estrndup(*body, *length); -+ } -+ return SUCCESS; -+ } else if (sapi_module.read_post && !HTTP_G->read_post_data) { -+ char *buf = emalloc(4096); -+ int len; -+ -+ HTTP_G->read_post_data = 1; -+ -+ while (0 < (len = sapi_module.read_post(buf, 4096 TSRMLS_CC))) { -+ SG(read_post_bytes) += len; -+ *body = erealloc(*body, *length + len + 1); -+ memcpy(*body + *length, buf, len); -+ *length += len; -+ (*body)[*length] = '\0'; -+ if (len < 4096) { -+ break; -+ } -+ } -+ efree(buf); -+ -+ /* check for error */ -+ if (len < 0) { -+ STR_FREE(*body); -+ *length = 0; -+ return FAILURE; -+ } -+ -+ SG(request_info).raw_post_data = *body; -+ SG(request_info).raw_post_data_length = *length; -+ -+ if (dup) { -+ *body = estrndup(*body, *length); -+ } -+ return SUCCESS; -+ } -+ -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ php_stream *http_get_request_body_stream(void) */ -+PHP_HTTP_API php_stream *_http_get_request_body_stream(TSRMLS_D) -+{ -+ php_stream *s = NULL; -+ -+ if (SG(request_info).raw_post_data) { -+ s = php_stream_open_wrapper("php://input", "rb", 0, NULL); -+ } else if (sapi_module.read_post && !HTTP_G->read_post_data) { -+ HTTP_G->read_post_data = 1; -+ -+ if ((s = php_stream_temp_new())) { -+ char *buf = emalloc(4096); -+ int len; -+ -+ while (0 < (len = sapi_module.read_post(buf, 4096 TSRMLS_CC))) { -+ SG(read_post_bytes) += len; -+ php_stream_write(s, buf, len); -+ if (len < 4096) { -+ break; -+ } -+ } -+ efree(buf); -+ -+ if (len < 0) { -+ php_stream_close(s); -+ s = NULL; -+ } else { -+ php_stream_rewind(s); -+ } -+ } -+ } -+ -+ return s; -+} -+/* }}} */ -+ -+/* {{{ void http_parse_params_default_callback(...) */ -+PHP_HTTP_API void _http_parse_params_default_callback(void *arg, const char *key, int keylen, const char *val, int vallen TSRMLS_DC) -+{ -+ char *kdup; -+ zval tmp, *entry; -+ HashTable *ht = (HashTable *) arg; -+ -+ if (ht) { -+ INIT_ZARR(tmp, ht); -+ -+ if (vallen) { -+ MAKE_STD_ZVAL(entry); -+ array_init(entry); -+ if (keylen) { -+ kdup = estrndup(key, keylen); -+ add_assoc_stringl_ex(entry, kdup, keylen + 1, (char *) val, vallen, 1); -+ efree(kdup); -+ } else { -+ add_next_index_stringl(entry, (char *) val, vallen, 1); -+ } -+ add_next_index_zval(&tmp, entry); -+ } else { -+ add_next_index_stringl(&tmp, (char *) key, keylen, 1); -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ STATUS http_parse_params(const char *, HashTable *) */ -+PHP_HTTP_API STATUS _http_parse_params_ex(const char *param, int flags, http_parse_params_callback cb, void *cb_arg TSRMLS_DC) -+{ -+#define ST_QUOTE 1 -+#define ST_VALUE 2 -+#define ST_KEY 3 -+#define ST_ASSIGN 4 -+#define ST_ADD 5 -+ -+ int st = ST_KEY, keylen = 0, vallen = 0; -+ char *s, *c, *key = NULL, *val = NULL; -+ -+ for(c = s = estrdup(param);;) { -+ continued: -+#if 0 -+ { -+ char *tk = NULL, *tv = NULL; -+ -+ if (key) { -+ if (keylen) { -+ tk= estrndup(key, keylen); -+ } else { -+ tk = ecalloc(1, 7); -+ memcpy(tk, key, 3); -+ tk[3]='.'; tk[4]='.'; tk[5]='.'; -+ } -+ } -+ if (val) { -+ if (vallen) { -+ tv = estrndup(val, vallen); -+ } else { -+ tv = ecalloc(1, 7); -+ memcpy(tv, val, 3); -+ tv[3]='.'; tv[4]='.'; tv[5]='.'; -+ } -+ } -+ fprintf(stderr, "[%6s] %c \"%s=%s\"\n", -+ ( -+ st == ST_QUOTE ? "QUOTE" : -+ st == ST_VALUE ? "VALUE" : -+ st == ST_KEY ? "KEY" : -+ st == ST_ASSIGN ? "ASSIGN" : -+ st == ST_ADD ? "ADD": -+ "HUH?" -+ ), *c?*c:'0', tk, tv -+ ); -+ STR_FREE(tk); STR_FREE(tv); -+ } -+#endif -+ switch (st) { -+ case ST_QUOTE: -+ quote: -+ if (*c == '"') { -+ if (*(c-1) == '\\') { -+ memmove(c-1, c, strlen(c)+1); -+ goto quote; -+ } else { -+ goto add; -+ } -+ } else { -+ if (!val) { -+ val = c; -+ } -+ if (!*c) { -+ --val; -+ st = ST_ADD; -+ } -+ } -+ break; -+ -+ case ST_VALUE: -+ switch (*c) { -+ case '"': -+ if (!val) { -+ st = ST_QUOTE; -+ } -+ break; -+ -+ case ' ': -+ break; -+ -+ case ';': -+ case '\0': -+ goto add; -+ break; -+ case ',': -+ if (flags & HTTP_PARAMS_ALLOW_COMMA) { -+ goto add; -+ } -+ default: -+ if (!val) { -+ val = c; -+ } -+ break; -+ } -+ break; -+ -+ case ST_KEY: -+ switch (*c) { -+ case ',': -+ if (flags & HTTP_PARAMS_ALLOW_COMMA) { -+ goto allow_comma; -+ } -+ case '\r': -+ case '\n': -+ case '\t': -+ case '\013': -+ case '\014': -+ goto failure; -+ break; -+ -+ case ' ': -+ if (key) { -+ keylen = c - key; -+ st = ST_ASSIGN; -+ } -+ break; -+ -+ case ';': -+ case '\0': -+ allow_comma: -+ if (key) { -+ keylen = c-- - key; -+ st = ST_ADD; -+ } -+ break; -+ -+ case ':': -+ if (!(flags & HTTP_PARAMS_COLON_SEPARATOR)) { -+ goto not_separator; -+ } -+ if (key) { -+ keylen = c - key; -+ st = ST_VALUE; -+ } else { -+ goto failure; -+ } -+ break; -+ -+ case '=': -+ if (flags & HTTP_PARAMS_COLON_SEPARATOR) { -+ goto not_separator; -+ } -+ if (key) { -+ keylen = c - key; -+ st = ST_VALUE; -+ } else { -+ goto failure; -+ } -+ break; -+ -+ default: -+ not_separator: -+ if (!key) { -+ key = c; -+ } -+ break; -+ } -+ break; -+ -+ case ST_ASSIGN: -+ if (*c == '=') { -+ st = ST_VALUE; -+ } else if (!*c || *c == ';' || ((flags & HTTP_PARAMS_ALLOW_COMMA) && *c == ',')) { -+ st = ST_ADD; -+ } else if (*c != ' ') { -+ goto failure; -+ } -+ break; -+ -+ case ST_ADD: -+ add: -+ if (val) { -+ vallen = c - val; -+ if (st != ST_QUOTE) { -+ while (val[vallen-1] == ' ') --vallen; -+ } -+ } else { -+ val = ""; -+ vallen = 0; -+ } -+ -+ cb(cb_arg, key, keylen, val, vallen TSRMLS_CC); -+ -+ st = ST_KEY; -+ key = val = NULL; -+ keylen = vallen = 0; -+ break; -+ } -+ if (*c) { -+ ++c; -+ } else if (st == ST_ADD) { -+ goto add; -+ } else { -+ break; -+ } -+ } -+ -+ efree(s); -+ return SUCCESS; -+ -+failure: -+ if (flags & HTTP_PARAMS_RAISE_ERROR) { -+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Unexpected character (%c) at pos %tu of %zu", *c, c-s, strlen(s)); -+ } -+ if (flags & HTTP_PARAMS_ALLOW_FAILURE) { -+ if (st == ST_KEY) { -+ if (key) { -+ keylen = c - key; -+ } else { -+ key = c; -+ } -+ } else { -+ --c; -+ } -+ st = ST_ADD; -+ goto continued; -+ } -+ efree(s); -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ array_join */ -+int apply_array_append_func(void *pDest HTTP_ZAPI_HASH_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) -+{ -+ int flags; -+ char *key = NULL; -+ HashTable *dst; -+ zval **data = NULL, **value = (zval **) pDest; -+ -+ dst = va_arg(args, HashTable *); -+ flags = va_arg(args, int); -+ -+ if ((!(flags & ARRAY_JOIN_STRONLY)) || hash_key->nKeyLength) { -+ if ((flags & ARRAY_JOIN_PRETTIFY) && hash_key->nKeyLength) { -+ key = pretty_key(estrndup(hash_key->arKey, hash_key->nKeyLength - 1), hash_key->nKeyLength - 1, 1, 1); -+ zend_hash_find(dst, key, hash_key->nKeyLength, (void *) &data); -+ } else { -+ zend_hash_quick_find(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) &data); -+ } -+ -+ ZVAL_ADDREF(*value); -+ if (data) { -+ add_next_index_zval(http_zset(IS_ARRAY, *data), *value); -+ } else if (key) { -+ zend_hash_add(dst, key, hash_key->nKeyLength, value, sizeof(zval *), NULL); -+ } else { -+ zend_hash_quick_add(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, value, sizeof(zval *), NULL); -+ } -+ -+ if (key) { -+ efree(key); -+ } -+ } -+ -+ return ZEND_HASH_APPLY_KEEP; -+} -+ -+int apply_array_merge_func(void *pDest HTTP_ZAPI_HASH_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) -+{ -+ int flags; -+ char *key = NULL; -+ HashTable *dst; -+ zval **value = (zval **) pDest; -+ -+ dst = va_arg(args, HashTable *); -+ flags = va_arg(args, int); -+ -+ if ((!(flags & ARRAY_JOIN_STRONLY)) || hash_key->nKeyLength) { -+ ZVAL_ADDREF(*value); -+ if ((flags & ARRAY_JOIN_PRETTIFY) && hash_key->nKeyLength) { -+ key = pretty_key(estrndup(hash_key->arKey, hash_key->nKeyLength - 1), hash_key->nKeyLength - 1, 1, 1); -+ zend_hash_update(dst, key, hash_key->nKeyLength, (void *) value, sizeof(zval *), NULL); -+ efree(key); -+ } else { -+ zend_hash_quick_update(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) value, sizeof(zval *), NULL); -+ } -+ } -+ -+ return ZEND_HASH_APPLY_KEEP; -+} -+/* }}} */ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_cache_api.c -@@ -0,0 +1,267 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_cache_api.c 323304 2012-02-17 21:13:24Z mike $ */ -+ -+#define HTTP_WANT_SAPI -+#include "php_http.h" -+ -+#include "php_output.h" -+#include "php_streams.h" -+ -+#include "php_http_api.h" -+#include "php_http_cache_api.h" -+#include "php_http_date_api.h" -+#include "php_http_send_api.h" -+ -+/* {{{ char *http_etag(void *, size_t, http_send_mode) */ -+PHP_HTTP_API char *_http_etag(const void *data_ptr, size_t data_len, http_send_mode data_mode TSRMLS_DC) -+{ -+ void *ctx = http_etag_init(); -+ -+ if (data_mode == SEND_DATA) { -+ http_etag_update(ctx, data_ptr, data_len); -+ } else { -+ STATUS ss = FAILURE; -+ php_stream_statbuf ssb; -+ -+ if (data_mode == SEND_RSRC) { -+ ss = php_stream_stat((php_stream *) data_ptr, &ssb); -+ } else { -+ ss = php_stream_stat_path((char *) data_ptr, &ssb); -+ } -+ -+ if (SUCCESS != ss) { -+ efree(ctx); -+ return NULL; -+ } else { -+ size_t ssb_len; -+ char ssb_buf[128]; -+ -+ ssb_len = snprintf(ssb_buf, sizeof(ssb_buf), "%ld=%ld=%ld", (long) ssb.sb.st_mtime, -+ (long) ssb.sb.st_ino, -+ (long) ssb.sb.st_size); -+ http_etag_update(ctx, ssb_buf, ssb_len); -+ } -+ } -+ -+ return http_etag_finish(ctx); -+} -+/* }}} */ -+ -+/* {{{ time_t http_last_modified(void *, http_send_mode) */ -+PHP_HTTP_API time_t _http_last_modified(const void *data_ptr, http_send_mode data_mode TSRMLS_DC) -+{ -+ php_stream_statbuf ssb; -+ -+ switch (data_mode) { -+ case SEND_DATA: return HTTP_G->request.time; -+ case SEND_RSRC: return php_stream_stat((php_stream *) data_ptr, &ssb) ? 0 : ssb.sb.st_mtime; -+ default: return php_stream_stat_path((char *) data_ptr, &ssb) ? 0 : ssb.sb.st_mtime; -+ } -+} -+/* }}} */ -+ -+/* {{{ zend_bool http_match_last_modified(char *, time_t) */ -+PHP_HTTP_API zend_bool _http_match_last_modified_ex(const char *entry, time_t t, zend_bool enforce_presence TSRMLS_DC) -+{ -+ zend_bool retval; -+ zval *zmodified; -+ char *modified, *chr_ptr; -+ -+ if (!(zmodified = http_get_server_var(entry, 1))) { -+ return !enforce_presence; -+ } -+ -+ modified = estrndup(Z_STRVAL_P(zmodified), Z_STRLEN_P(zmodified)); -+ if ((chr_ptr = strrchr(modified, ';'))) { -+ chr_ptr = 0; -+ } -+ -+ retval = (t <= http_parse_date_ex(modified, 1)); -+ efree(modified); -+ return retval; -+} -+/* }}} */ -+ -+/* {{{ zend_bool http_match_etag(char *, char *) */ -+PHP_HTTP_API zend_bool _http_match_etag_ex(const char *entry, const char *etag, zend_bool enforce_presence TSRMLS_DC) -+{ -+ zval *zetag; -+ char *quoted_etag; -+ zend_bool result; -+ -+ if (!(zetag = http_get_server_var_ex(entry, strlen(entry)+1, 1))) { -+ return !enforce_presence; -+ } -+ -+ if (NULL != strchr(Z_STRVAL_P(zetag), '*')) { -+ return 1; -+ } -+ -+ spprintf("ed_etag, 0, "\"%s\"", etag); -+ if (!strchr(Z_STRVAL_P(zetag), ',')) { -+ result = !strcmp(Z_STRVAL_P(zetag), quoted_etag); -+ } else { -+ result = (NULL != strstr(Z_STRVAL_P(zetag), quoted_etag)); -+ } -+ efree(quoted_etag); -+ -+ return result; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_cache_last_modified(time_t, time_t, char *, size_t) */ -+PHP_HTTP_API STATUS _http_cache_last_modified(time_t last_modified, -+ time_t send_modified, const char *cache_control, size_t cc_len TSRMLS_DC) -+{ -+ char *sent_header = NULL; -+ -+ if (SG(headers_sent)) { -+ return FAILURE; -+ } -+ -+ if (cc_len && (SUCCESS != http_send_cache_control(cache_control, cc_len))) { -+ return FAILURE; -+ } -+ -+ if (SUCCESS != http_send_last_modified_ex(send_modified, &sent_header)) { -+ return FAILURE; -+ } -+ -+ if (http_match_last_modified("HTTP_IF_MODIFIED_SINCE", last_modified)) { -+ http_exit_ex(304, sent_header, NULL, 0); -+ } else { -+ STR_FREE(sent_header); -+ } -+ -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_cache_etag(char *, size_t, char *, size_t) */ -+PHP_HTTP_API STATUS _http_cache_etag(const char *etag, size_t etag_len, -+ const char *cache_control, size_t cc_len TSRMLS_DC) -+{ -+ char *sent_header = NULL; -+ -+ if (SG(headers_sent)) { -+ return FAILURE; -+ } -+ -+ if (cc_len && (SUCCESS != http_send_cache_control(cache_control, cc_len))) { -+ return FAILURE; -+ } -+ -+ if (etag_len) { -+ if (SUCCESS != http_send_etag_ex(etag, etag_len, &sent_header)) { -+ return FAILURE; -+ } -+ if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) { -+ http_exit_ex(304, sent_header, NULL, 0); -+ } else { -+ STR_FREE(sent_header); -+ } -+ return SUCCESS; -+ } -+ -+ /* start ob_etaghandler */ -+ return http_start_ob_etaghandler(); -+} -+/* }}} */ -+ -+PHP_HTTP_API STATUS _http_start_ob_etaghandler(TSRMLS_D) -+{ -+ /* already running? */ -+#ifdef PHP_OUTPUT_NEWAPI -+ STATUS rv; -+ -+ if (php_output_handler_conflict(ZEND_STRL("ob_etaghandler"), ZEND_STRL("ob_etaghandler") TSRMLS_CC)) { -+ return FAILURE; -+ } -+#else -+ if (php_ob_handler_used("ob_etaghandler" TSRMLS_CC)) { -+ http_error(HE_WARNING, HTTP_E_RUNTIME, "ob_etaghandler can only be used once"); -+ return FAILURE; -+ } -+#endif -+ HTTP_G->etag.started = 1; -+#ifdef PHP_OUTPUT_NEWAPI -+ return php_output_start_internal(ZEND_STRL("ob_etaghandler"), _http_ob_etaghandler, HTTP_G->send.buffer_size, 0 TSRMLS_CC); -+#else -+ return php_start_ob_buffer_named("ob_etaghandler", HTTP_G->send.buffer_size, 0 TSRMLS_CC); -+#endif -+} -+ -+PHP_HTTP_API zend_bool _http_interrupt_ob_etaghandler(TSRMLS_D) -+{ -+ if (HTTP_G->etag.started) { -+ HTTP_G->etag.started = 0; -+ if (HTTP_G->etag.ctx) { -+ efree(HTTP_G->etag.ctx); -+ HTTP_G->etag.ctx = NULL; -+ } -+ return 1; -+ } -+ return 0; -+} -+ -+/* {{{ void http_ob_etaghandler(char *, uint, char **, uint *, int) */ -+void _http_ob_etaghandler(char *output, uint output_len, -+ char **handled_output, uint *handled_output_len, int mode TSRMLS_DC) -+{ -+ /* passthru */ -+ *handled_output_len = output_len; -+ *handled_output = estrndup(output, output_len); -+ -+ /* are we supposed to run? */ -+ if (HTTP_G->etag.started) { -+ /* initialize the etag context */ -+ if (mode & PHP_OUTPUT_HANDLER_START) { -+ HTTP_G->etag.ctx = http_etag_init(); -+ } -+ -+ /* update */ -+ http_etag_update(HTTP_G->etag.ctx, output, output_len); -+ -+ /* finish */ -+ if (mode & PHP_OUTPUT_HANDLER_END) { -+ char *sent_header = NULL; -+ char *etag = http_etag_finish(HTTP_G->etag.ctx); -+ -+ HTTP_G->etag.ctx = NULL; -+ -+ http_send_cache_control(HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL)); -+ http_send_etag_ex(etag, strlen(etag), &sent_header); -+ -+ if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) { -+ /* force exit; ob within ob does not work */ -+ HTTP_G->force_exit = 1; -+ http_exit_ex(304, sent_header, etag, 0); -+ } -+ -+ STR_FREE(sent_header); -+ STR_FREE(etag); -+ } -+ } -+} -+/* }}} */ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim600: sw=4 ts=4 fdm=marker -+ * vim<600: sw=4 ts=4 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_cookie_api.c -@@ -0,0 +1,371 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_cookie_api.c 298662 2010-04-27 13:42:32Z mike $ */ -+ -+#include "php_http.h" -+#include "php_http_api.h" -+#include "php_http_date_api.h" -+#include "php_http_cookie_api.h" -+ -+#include "ext/standard/url.h" -+ -+/* {{{ PHP_MINIT_FUNCTION(http_cookie) */ -+PHP_MINIT_FUNCTION(http_cookie) -+{ -+ HTTP_LONG_CONSTANT("HTTP_COOKIE_PARSE_RAW", HTTP_COOKIE_PARSE_RAW); -+ HTTP_LONG_CONSTANT("HTTP_COOKIE_SECURE", HTTP_COOKIE_SECURE); -+ HTTP_LONG_CONSTANT("HTTP_COOKIE_HTTPONLY", HTTP_COOKIE_HTTPONLY); -+ -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ http_cookie_list *http_cookie_list_init(http_cookie_list *) */ -+PHP_HTTP_API http_cookie_list *_http_cookie_list_init(http_cookie_list *list ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC) -+{ -+ if (!list) { -+ list = emalloc_rel(sizeof(http_cookie_list)); -+ } -+ -+ zend_hash_init(&list->cookies, 0, NULL, ZVAL_PTR_DTOR, 0); -+ zend_hash_init(&list->extras, 0, NULL, ZVAL_PTR_DTOR, 0); -+ -+ list->path = NULL; -+ list->domain = NULL; -+ list->expires = 0; -+ list->flags = 0; -+ -+ return list; -+} -+/* }}} */ -+ -+/* {{{ void http_cookie_list_dtor(http_cookie_list *) */ -+PHP_HTTP_API void _http_cookie_list_dtor(http_cookie_list *list TSRMLS_DC) -+{ -+ if (list) { -+ zend_hash_destroy(&list->cookies); -+ zend_hash_destroy(&list->extras); -+ -+ STR_SET(list->path, NULL); -+ STR_SET(list->domain, NULL); -+ } -+} -+/* }}} */ -+ -+/* {{{ void http_cookie_list_free(http_cookie_list **) */ -+PHP_HTTP_API void _http_cookie_list_free(http_cookie_list **list TSRMLS_DC) -+{ -+ if (list) { -+ http_cookie_list_dtor(*list); -+ efree(*list); -+ *list = NULL; -+ } -+} -+/* }}} */ -+ -+/* {{{ const char *http_cookie_list_get_cookie(http_cookie_list *, const char*, size_t) */ -+PHP_HTTP_API const char *_http_cookie_list_get_cookie(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC) -+{ -+ zval **cookie = NULL; -+ if ((SUCCESS != zend_hash_find(&list->cookies, HTTP_ZAPI_CONST_CAST(char *) name, name_len + 1, (void *) &cookie)) || (Z_TYPE_PP(cookie) != IS_STRING)) { -+ return NULL; -+ } -+ return Z_STRVAL_PP(cookie); -+} -+/* }}} */ -+ -+/* {{{ const char *http_cookie_list_get_extra(http_cookie_list *, const char *, size_t) */ -+PHP_HTTP_API const char *_http_cookie_list_get_extra(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC) -+{ -+ zval **extra = NULL; -+ if ((SUCCESS != zend_hash_find(&list->extras, HTTP_ZAPI_CONST_CAST(char *) name, name_len + 1, (void *) &extra)) || (Z_TYPE_PP(extra) != IS_STRING)) { -+ return NULL; -+ } -+ return Z_STRVAL_PP(extra); -+} -+/* }}} */ -+ -+/* {{{ void http_cookie_list_add_cookie(http_cookie_list *, const char *, size_t, const char *, size_t) */ -+PHP_HTTP_API void _http_cookie_list_add_cookie(http_cookie_list *list, const char *name, size_t name_len, const char *value, size_t value_len TSRMLS_DC) -+{ -+ zval *cookie_value; -+ char *key = estrndup(name, name_len); -+ MAKE_STD_ZVAL(cookie_value); -+ ZVAL_STRINGL(cookie_value, estrndup(value, value_len), value_len, 0); -+ zend_hash_update(&list->cookies, key, name_len + 1, (void *) &cookie_value, sizeof(zval *), NULL); -+ efree(key); -+} -+/* }}} */ -+ -+/* {{{ void http_cookie_list_add_extr(http_cookie_list *, const char *, size_t, const char *, size_t) */ -+PHP_HTTP_API void _http_cookie_list_add_extra(http_cookie_list *list, const char *name, size_t name_len, const char *value, size_t value_len TSRMLS_DC) -+{ -+ zval *cookie_value; -+ char *key = estrndup(name, name_len); -+ MAKE_STD_ZVAL(cookie_value); -+ ZVAL_STRINGL(cookie_value, estrndup(value, value_len), value_len, 0); -+ zend_hash_update(&list->extras, key, name_len + 1, (void *) &cookie_value, sizeof(zval *), NULL); -+ efree(key); -+} -+/* }}} */ -+ -+typedef struct _http_parse_param_cb_arg_t { -+ http_cookie_list *list; -+ long flags; -+ char **allowed_extras; -+} http_parse_param_cb_arg; -+ -+/* {{{ static void http_parse_cookie_callback */ -+static void http_parse_cookie_callback(void *ptr, const char *key, int keylen, const char *val, int vallen TSRMLS_DC) -+{ -+ http_parse_param_cb_arg *arg = (http_parse_param_cb_arg *) ptr; -+ -+#define _KEY_IS(s) (keylen == lenof(s) && !strncasecmp(key, (s), keylen)) -+ if _KEY_IS("path") { -+ STR_SET(arg->list->path, estrndup(val, vallen)); -+ } else if _KEY_IS("domain") { -+ STR_SET(arg->list->domain, estrndup(val, vallen)); -+ } else if _KEY_IS("expires") { -+ char *date = estrndup(val, vallen); -+ arg->list->expires = http_parse_date(date); -+ efree(date); -+ } else if _KEY_IS("secure") { -+ arg->list->flags |= HTTP_COOKIE_SECURE; -+ } else if _KEY_IS("httpOnly") { -+ arg->list->flags |= HTTP_COOKIE_HTTPONLY; -+ } else { -+ /* check for extra */ -+ if (arg->allowed_extras) { -+ char **ae = arg->allowed_extras; -+ -+ for (; *ae; ++ae) { -+ if ((size_t) keylen == strlen(*ae) && !strncasecmp(key, *ae, keylen)) { -+ if (arg->flags & HTTP_COOKIE_PARSE_RAW) { -+ http_cookie_list_add_extra(arg->list, key, keylen, val, vallen); -+ } else { -+ char *dec = estrndup(val, vallen); -+ int declen = php_url_decode(dec, vallen); -+ -+ http_cookie_list_add_extra(arg->list, key, keylen, dec, declen); -+ efree(dec); -+ } -+ return; -+ } -+ } -+ } -+ /* new cookie */ -+ if (arg->flags & HTTP_COOKIE_PARSE_RAW) { -+ http_cookie_list_add_cookie(arg->list, key, keylen, val, vallen); -+ } else { -+ char *dec = estrndup(val, vallen); -+ int declen = php_url_decode(dec, vallen); -+ -+ http_cookie_list_add_cookie(arg->list, key, keylen, dec, declen); -+ efree(dec); -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ http_cookie_list *http_parse_cookie(char *, long) */ -+PHP_HTTP_API http_cookie_list *_http_parse_cookie_ex(http_cookie_list *list, const char *string, long flags, char **allowed_extras TSRMLS_DC) -+{ -+ int free_list = !list; -+ http_parse_param_cb_arg arg; -+ -+ list = http_cookie_list_init(list); -+ -+ arg.list = list; -+ arg.flags = flags; -+ arg.allowed_extras = allowed_extras; -+ -+ if (SUCCESS != http_parse_params_ex(string, HTTP_PARAMS_RAISE_ERROR, http_parse_cookie_callback, &arg)) { -+ if (free_list) { -+ http_cookie_list_free(&list); -+ } else { -+ http_cookie_list_dtor(list); -+ } -+ list = NULL; -+ } -+ -+ return list; -+} -+/* }}} */ -+ -+/* {{{ void http_cookie_list_tostruct(http_cookie_list *, zval *) */ -+PHP_HTTP_API void _http_cookie_list_tostruct(http_cookie_list *list, zval *strct TSRMLS_DC) -+{ -+ zval array, *cookies, *extras; -+ -+ INIT_ZARR(array, HASH_OF(strct)); -+ -+ MAKE_STD_ZVAL(cookies); -+ array_init(cookies); -+ zend_hash_copy(Z_ARRVAL_P(cookies), &list->cookies, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+ add_assoc_zval(&array, "cookies", cookies); -+ -+ MAKE_STD_ZVAL(extras); -+ array_init(extras); -+ zend_hash_copy(Z_ARRVAL_P(extras), &list->extras, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+ add_assoc_zval(&array, "extras", extras); -+ -+ add_assoc_long(&array, "flags", list->flags); -+ add_assoc_long(&array, "expires", (long) list->expires); -+ add_assoc_string(&array, "path", STR_PTR(list->path), 1); -+ add_assoc_string(&array, "domain", STR_PTR(list->domain), 1); -+} -+/* }}} */ -+ -+/* {{{ http_cookie_list *http_cookie_list_fromstruct(http_cookie_list *, zval *strct) */ -+PHP_HTTP_API http_cookie_list *_http_cookie_list_fromstruct(http_cookie_list *list, zval *strct TSRMLS_DC) -+{ -+ zval **tmp, *cpy; -+ HashTable *ht = HASH_OF(strct); -+ -+ list = http_cookie_list_init(list); -+ -+ if (SUCCESS == zend_hash_find(ht, "cookies", sizeof("cookies"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_ARRAY) { -+ zend_hash_copy(&list->cookies, Z_ARRVAL_PP(tmp), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+ } -+ if (SUCCESS == zend_hash_find(ht, "extras", sizeof("extras"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_ARRAY) { -+ zend_hash_copy(&list->extras, Z_ARRVAL_PP(tmp), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+ } -+ if (SUCCESS == zend_hash_find(ht, "flags", sizeof("flags"), (void *) &tmp)) { -+ switch (Z_TYPE_PP(tmp)) { -+ case IS_LONG: -+ list->flags = Z_LVAL_PP(tmp); -+ break; -+ case IS_DOUBLE: -+ list->flags = (long) Z_DVAL_PP(tmp); -+ break; -+ case IS_STRING: -+ cpy = http_zsep(IS_LONG, *tmp); -+ list->flags = Z_LVAL_P(cpy); -+ zval_ptr_dtor(&cpy); -+ break; -+ default: -+ break; -+ } -+ } -+ if (SUCCESS == zend_hash_find(ht, "expires", sizeof("expires"), (void *) &tmp)) { -+ switch (Z_TYPE_PP(tmp)) { -+ case IS_LONG: -+ list->expires = Z_LVAL_PP(tmp); -+ break; -+ case IS_DOUBLE: -+ list->expires = (long) Z_DVAL_PP(tmp); -+ break; -+ case IS_STRING: -+ cpy = http_zsep(IS_LONG, *tmp); -+ if (Z_LVAL_P(cpy)) { -+ list->expires = Z_LVAL_P(cpy); -+ } else { -+ time_t expires = http_parse_date(Z_STRVAL_PP(tmp)); -+ if (expires > 0) { -+ list->expires = expires; -+ } -+ } -+ zval_ptr_dtor(&cpy); -+ break; -+ default: -+ break; -+ } -+ } -+ if (SUCCESS == zend_hash_find(ht, "path", sizeof("path"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_STRING) { -+ list->path = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); -+ } -+ if (SUCCESS == zend_hash_find(ht, "domain", sizeof("domain"), (void *) &tmp) && Z_TYPE_PP(tmp) == IS_STRING) { -+ list->domain = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); -+ } -+ -+ return list; -+} -+/* }}} */ -+ -+/* {{{ inline append_encoded */ -+static inline void append_encoded(phpstr *buf, const char *key, size_t key_len, const char *val, size_t val_len) -+{ -+ char *enc_str[2]; -+ int enc_len[2]; -+ -+ enc_str[0] = php_url_encode(key, key_len, &enc_len[0]); -+ enc_str[1] = php_url_encode(val, val_len, &enc_len[1]); -+ -+ phpstr_append(buf, enc_str[0], enc_len[0]); -+ phpstr_appends(buf, "="); -+ phpstr_append(buf, enc_str[1], enc_len[1]); -+ phpstr_appends(buf, "; "); -+ -+ efree(enc_str[0]); -+ efree(enc_str[1]); -+} -+/* }}} */ -+ -+/* {{{ void http_cookie_list_tostring(http_cookie_list *, char **, size_t *) */ -+PHP_HTTP_API void _http_cookie_list_tostring(http_cookie_list *list, char **str, size_t *len TSRMLS_DC) -+{ -+ phpstr buf; -+ zval **val; -+ HashKey key = initHashKey(0); -+ HashPosition pos; -+ -+ phpstr_init(&buf); -+ -+ FOREACH_HASH_KEYVAL(pos, &list->cookies, key, val) { -+ if (key.type == HASH_KEY_IS_STRING && key.len) { -+ zval *tmp = http_zsep(IS_STRING, *val); -+ append_encoded(&buf, key.str, key.len-1, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)); -+ zval_ptr_dtor(&tmp); -+ } -+ } -+ -+ if (list->domain && *list->domain) { -+ phpstr_appendf(&buf, "domain=%s; ", list->domain); -+ } -+ if (list->path && *list->path) { -+ phpstr_appendf(&buf, "path=%s; ", list->path); -+ } -+ if (list->expires) { -+ char *date = http_date(list->expires); -+ phpstr_appendf(&buf, "expires=%s; ", date); -+ efree(date); -+ } -+ -+ FOREACH_HASH_KEYVAL(pos, &list->extras, key, val) { -+ if (key.type == HASH_KEY_IS_STRING && key.len) { -+ zval *tmp = http_zsep(IS_STRING, *val); -+ append_encoded(&buf, key.str, key.len-1, Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)); -+ } -+ } -+ -+ if (list->flags & HTTP_COOKIE_SECURE) { -+ phpstr_appends(&buf, "secure; "); -+ } -+ if (list->flags & HTTP_COOKIE_HTTPONLY) { -+ phpstr_appends(&buf, "httpOnly; "); -+ } -+ -+ phpstr_fix(&buf); -+ *str = PHPSTR_VAL(&buf); -+ *len = PHPSTR_LEN(&buf); -+} -+/* }}} */ -+ -+/* -+ * 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 -+ */ ---- /dev/null -+++ b/ext/http/http_date_api.c -@@ -0,0 +1,357 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_date_api.c 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#include "php_http.h" -+ -+#include "php_http_api.h" -+#include "php_http_date_api.h" -+ -+static inline int check_day(const char *day, size_t len); -+static inline int check_month(const char *month); -+static inline int check_tzone(const char *tzone); -+static inline time_t parse_date(const char *month); -+ -+/* {{{ day/month names */ -+static const char *days[] = { -+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -+}; -+static const char *wkdays[] = { -+ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" -+}; -+static const char *weekdays[] = { -+ "Monday", "Tuesday", "Wednesday", -+ "Thursday", "Friday", "Saturday", "Sunday" -+}; -+static const char *months[] = { -+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", -+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -+}; -+enum assume_next { -+ DATE_MDAY, -+ DATE_YEAR, -+ DATE_TIME -+}; -+#define DS -60 -+static const struct time_zone { -+ const char *name; -+ const int offset; -+} time_zones[] = { -+ {"GMT", 0}, /* Greenwich Mean */ -+ {"UTC", 0}, /* Universal (Coordinated) */ -+ {"WET", 0}, /* Western European */ -+ {"BST", 0 DS}, /* British Summer */ -+ {"WAT", 60}, /* West Africa */ -+ {"AST", 240}, /* Atlantic Standard */ -+ {"ADT", 240 DS},/* Atlantic Daylight */ -+ {"EST", 300}, /* Eastern Standard */ -+ {"EDT", 300 DS},/* Eastern Daylight */ -+ {"CST", 360}, /* Central Standard */ -+ {"CDT", 360 DS},/* Central Daylight */ -+ {"MST", 420}, /* Mountain Standard */ -+ {"MDT", 420 DS},/* Mountain Daylight */ -+ {"PST", 480}, /* Pacific Standard */ -+ {"PDT", 480 DS},/* Pacific Daylight */ -+ {"YST", 540}, /* Yukon Standard */ -+ {"YDT", 540 DS},/* Yukon Daylight */ -+ {"HST", 600}, /* Hawaii Standard */ -+ {"HDT", 600 DS},/* Hawaii Daylight */ -+ {"CAT", 600}, /* Central Alaska */ -+ {"AHST", 600}, /* Alaska-Hawaii Standard */ -+ {"NT", 660}, /* Nome */ -+ {"IDLW", 720}, /* International Date Line West */ -+ {"CET", -60}, /* Central European */ -+ {"MET", -60}, /* Middle European */ -+ {"MEWT", -60}, /* Middle European Winter */ -+ {"MEST", -60 DS},/* Middle European Summer */ -+ {"CEST", -60 DS},/* Central European Summer */ -+ {"MESZ", -60 DS},/* Middle European Summer */ -+ {"FWT", -60}, /* French Winter */ -+ {"FST", -60 DS},/* French Summer */ -+ {"EET", -120}, /* Eastern Europe, USSR Zone 1 */ -+ {"WAST", -420}, /* West Australian Standard */ -+ {"WADT", -420 DS},/* West Australian Daylight */ -+ {"CCT", -480}, /* China Coast, USSR Zone 7 */ -+ {"JST", -540}, /* Japan Standard, USSR Zone 8 */ -+ {"EAST", -600}, /* Eastern Australian Standard */ -+ {"EADT", -600 DS},/* Eastern Australian Daylight */ -+ {"GST", -600}, /* Guam Standard, USSR Zone 9 */ -+ {"NZT", -720}, /* New Zealand */ -+ {"NZST", -720}, /* New Zealand Standard */ -+ {"NZDT", -720 DS},/* New Zealand Daylight */ -+ {"IDLE", -720}, /* International Date Line East */ -+}; -+/* }}} */ -+ -+/* {{{ Day/Month/TZ checks for http_parse_date() -+ Originally by libcurl, Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. */ -+static inline int check_day(const char *day, size_t len) -+{ -+ int i; -+ const char * const *check = (len > 3) ? &weekdays[0] : &wkdays[0]; -+ for (i = 0; i < 7; i++) { -+ if (!strcmp(day, check[0])) { -+ return i; -+ } -+ check++; -+ } -+ return -1; -+} -+ -+static inline int check_month(const char *month) -+{ -+ int i; -+ const char * const *check = &months[0]; -+ for (i = 0; i < 12; i++) { -+ if (!strcmp(month, check[0])) { -+ return i; -+ } -+ check++; -+ } -+ return -1; -+} -+ -+/* return the time zone offset between GMT and the input one, in number -+ of seconds or -1 if the timezone wasn't found/legal */ -+ -+static inline int check_tzone(const char *tzone) -+{ -+ unsigned i; -+ const struct time_zone *check = time_zones; -+ for (i = 0; i < sizeof(time_zones) / sizeof(time_zones[0]); i++) { -+ if (!strcmp(tzone, check->name)) { -+ return check->offset * 60; -+ } -+ check++; -+ } -+ return -1; -+} -+/* }}} */ -+ -+/* {{{ char *http_date(time_t) */ -+PHP_HTTP_API char *_http_date(time_t t TSRMLS_DC) -+{ -+ char *date = NULL; -+ struct tm *gmtime = NULL, tmbuf; -+ -+ memset(&tmbuf, 0, sizeof(tmbuf)); -+ if ((gmtime = php_gmtime_r(&t, &tmbuf))) { -+ spprintf(&date, 0, -+ "%s, %02d %s %04d %02d:%02d:%02d GMT", -+ days[gmtime->tm_wday], gmtime->tm_mday, -+ months[gmtime->tm_mon], gmtime->tm_year + 1900, -+ gmtime->tm_hour, gmtime->tm_min, gmtime->tm_sec -+ ); -+ } -+ -+ return date; -+} -+/* }}} */ -+ -+/* {{{ time_t http_parse_date(char *) */ -+PHP_HTTP_API time_t _http_parse_date_ex(const char *date, zend_bool silent TSRMLS_DC) -+{ -+ time_t t = parse_date(date); -+ -+ if (-1 == t && !silent) { -+ http_error_ex(HE_NOTICE, HTTP_E_RUNTIME, "Could not parse date: %s", date); -+ } -+ -+ return t; -+} -+/* }}} */ -+ -+/* time_t parse_date(char *) -+ Originally by libcurl, Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. */ -+static inline time_t parse_date(const char *date) -+{ -+ time_t t = 0; -+ int tz_offset = -1, year = -1, month = -1, monthday = -1, weekday = -1, -+ hours = -1, minutes = -1, seconds = -1; -+ struct tm tm; -+ enum assume_next dignext = DATE_MDAY; -+ const char *indate = date; -+ -+ int part = 0; /* max 6 parts */ -+ -+ while (*date && (part < 6)) { -+ int found = 0; -+ -+ while (*date && !HTTP_IS_CTYPE(alnum, *date)) { -+ date++; -+ } -+ -+ if (HTTP_IS_CTYPE(alpha, *date)) { -+ /* a name coming up */ -+ char buf[32] = ""; -+ size_t len; -+ sscanf(date, "%31[A-Za-z]", buf); -+ len = strlen(buf); -+ -+ if (weekday == -1) { -+ weekday = check_day(buf, len); -+ if (weekday != -1) { -+ found = 1; -+ } -+ } -+ -+ if (!found && (month == -1)) { -+ month = check_month(buf); -+ if (month != -1) { -+ found = 1; -+ } -+ } -+ -+ if (!found && (tz_offset == -1)) { -+ /* this just must be a time zone string */ -+ tz_offset = check_tzone(buf); -+ if (tz_offset != -1) { -+ found = 1; -+ } -+ } -+ -+ if (!found) { -+ return -1; /* bad string */ -+ } -+ date += len; -+ } -+ else if (HTTP_IS_CTYPE(digit, *date)) { -+ /* a digit */ -+ int val; -+ char *end; -+ if ((seconds == -1) && -+ (3 == sscanf(date, "%02d:%02d:%02d", &hours, &minutes, &seconds))) { -+ /* time stamp! */ -+ date += 8; -+ found = 1; -+ } -+ else { -+ val = (int) strtol(date, &end, 10); -+ -+ if ((tz_offset == -1) && ((end - date) == 4) && (val < 1300) && -+ (indate < date) && ((date[-1] == '+' || date[-1] == '-'))) { -+ /* four digits and a value less than 1300 and it is preceeded with -+ a plus or minus. This is a time zone indication. */ -+ found = 1; -+ tz_offset = (val / 100 * 60 + val % 100) * 60; -+ -+ /* the + and - prefix indicates the local time compared to GMT, -+ this we need ther reversed math to get what we want */ -+ tz_offset = date[-1] == '+' ? -tz_offset : tz_offset; -+ } -+ -+ if (((end - date) == 8) && (year == -1) && (month == -1) && (monthday == -1)) { -+ /* 8 digits, no year, month or day yet. This is YYYYMMDD */ -+ found = 1; -+ year = val / 10000; -+ month = (val % 10000) / 100 - 1; /* month is 0 - 11 */ -+ monthday = val % 100; -+ } -+ -+ if (!found && (dignext == DATE_MDAY) && (monthday == -1)) { -+ if ((val > 0) && (val < 32)) { -+ monthday = val; -+ found = 1; -+ } -+ dignext = DATE_YEAR; -+ } -+ -+ if (!found && (dignext == DATE_YEAR) && (year == -1)) { -+ year = val; -+ found = 1; -+ if (year < 1900) { -+ year += year > 70 ? 1900 : 2000; -+ } -+ if(monthday == -1) { -+ dignext = DATE_MDAY; -+ } -+ } -+ -+ if (!found) { -+ return -1; -+ } -+ -+ date = end; -+ } -+ } -+ -+ part++; -+ } -+ -+ if (-1 == seconds) { -+ seconds = minutes = hours = 0; /* no time, make it zero */ -+ } -+ -+ if ((-1 == monthday) || (-1 == month) || (-1 == year)) { -+ /* lacks vital info, fail */ -+ return -1; -+ } -+ -+ if (sizeof(time_t) < 5) { -+ /* 32 bit time_t can only hold dates to the beginning of 2038 */ -+ if (year > 2037) { -+ return 0x7fffffff; -+ } -+ } -+ -+ tm.tm_sec = seconds; -+ tm.tm_min = minutes; -+ tm.tm_hour = hours; -+ tm.tm_mday = monthday; -+ tm.tm_mon = month; -+ tm.tm_year = year - 1900; -+ tm.tm_wday = 0; -+ tm.tm_yday = 0; -+ tm.tm_isdst = 0; -+ -+ t = mktime(&tm); -+ -+ /* time zone adjust */ -+ if (t != -1) { -+ struct tm *gmt, keeptime2; -+ long delta; -+ time_t t2; -+ -+ if((gmt = php_gmtime_r(&t, &keeptime2))) { -+ tm = *gmt; /* MSVC quirks */ -+ } else { -+ return -1; /* illegal date/time */ -+ } -+ -+ t2 = mktime(&tm); -+ -+ /* Add the time zone diff (between the given timezone and GMT) and the -+ diff between the local time zone and GMT. */ -+ delta = (tz_offset != -1 ? tz_offset : 0) + (t - t2); -+ -+ if((delta > 0) && (t + delta < t)) { -+ return -1; /* time_t overflow */ -+ } -+ -+ t += delta; -+ } -+ -+ return t; -+} -+/* }}} */ -+ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim600: sw=4 ts=4 fdm=marker -+ * vim<600: sw=4 ts=4 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_deflatestream_object.c -@@ -0,0 +1,317 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_deflatestream_object.c 323304 2012-02-17 21:13:24Z mike $ */ -+ -+#define HTTP_WANT_ZLIB -+#include "php_http.h" -+ -+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_ZLIB) -+ -+#include "php_http_api.h" -+#include "php_http_encoding_api.h" -+#include "php_http_exception_object.h" -+#include "php_http_deflatestream_object.h" -+ -+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpDeflateStream, method, 0, req_args) -+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpDeflateStream, method, 0) -+#define HTTP_DEFLATE_ME(method, visibility) PHP_ME(HttpDeflateStream, method, HTTP_ARGS(HttpDeflateStream, method), visibility) -+ -+HTTP_BEGIN_ARGS(__construct, 0) -+ HTTP_ARG_VAL(flags, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(factory, 0) -+ HTTP_ARG_VAL(flags, 0) -+ HTTP_ARG_VAL(class_name, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(update, 1) -+ HTTP_ARG_VAL(data, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(flush, 0) -+ HTTP_ARG_VAL(data, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(finish, 0) -+ HTTP_ARG_VAL(data, 0) -+HTTP_END_ARGS; -+ -+#define THIS_CE http_deflatestream_object_ce -+zend_class_entry *http_deflatestream_object_ce; -+zend_function_entry http_deflatestream_object_fe[] = { -+ HTTP_DEFLATE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) -+ HTTP_DEFLATE_ME(update, ZEND_ACC_PUBLIC) -+ HTTP_DEFLATE_ME(flush, ZEND_ACC_PUBLIC) -+ HTTP_DEFLATE_ME(finish, ZEND_ACC_PUBLIC) -+ -+ HTTP_DEFLATE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) -+ -+ EMPTY_FUNCTION_ENTRY -+}; -+static zend_object_handlers http_deflatestream_object_handlers; -+ -+PHP_MINIT_FUNCTION(http_deflatestream_object) -+{ -+ HTTP_REGISTER_CLASS_EX(HttpDeflateStream, http_deflatestream_object, NULL, 0); -+ http_deflatestream_object_handlers.clone_obj = _http_deflatestream_object_clone_obj; -+ -+#ifndef WONKY -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_GZIP")-1, HTTP_DEFLATE_TYPE_GZIP TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_ZLIB")-1, HTTP_DEFLATE_TYPE_ZLIB TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_RAW")-1, HTTP_DEFLATE_TYPE_RAW TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("LEVEL_DEF")-1, HTTP_DEFLATE_LEVEL_DEF TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("LEVEL_MIN")-1, HTTP_DEFLATE_LEVEL_MIN TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("LEVEL_MAX")-1, HTTP_DEFLATE_LEVEL_MAX TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_DEF")-1, HTTP_DEFLATE_STRATEGY_DEF TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_FILT")-1, HTTP_DEFLATE_STRATEGY_FILT TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_HUFF")-1, HTTP_DEFLATE_STRATEGY_HUFF TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_RLE")-1, HTTP_DEFLATE_STRATEGY_RLE TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("STRATEGY_FIXED")-1, HTTP_DEFLATE_STRATEGY_FIXED TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_NONE")-1, HTTP_ENCODING_STREAM_FLUSH_NONE TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_SYNC")-1, HTTP_ENCODING_STREAM_FLUSH_SYNC TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_FULL")-1, HTTP_ENCODING_STREAM_FLUSH_FULL TSRMLS_CC); -+#endif -+ -+ return SUCCESS; -+} -+ -+zend_object_value _http_deflatestream_object_new(zend_class_entry *ce TSRMLS_DC) -+{ -+ return http_deflatestream_object_new_ex(ce, NULL, NULL); -+} -+ -+zend_object_value _http_deflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_deflatestream_object **ptr TSRMLS_DC) -+{ -+ zend_object_value ov; -+ http_deflatestream_object *o; -+ -+ o = ecalloc(1, sizeof(http_deflatestream_object)); -+ o->zo.ce = ce; -+ -+ if (ptr) { -+ *ptr = o; -+ } -+ -+ if (s) { -+ o->stream = s; -+ } -+ -+#ifdef ZEND_ENGINE_2_4 -+ zend_object_std_init(o, ce TSRMLS_CC); -+ object_properties_init(o, ce); -+#else -+ ALLOC_HASHTABLE(OBJ_PROP(o)); -+ zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0); -+ zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+#endif -+ -+ ov.handle = putObject(http_deflatestream_object, o); -+ ov.handlers = &http_deflatestream_object_handlers; -+ -+ return ov; -+} -+ -+zend_object_value _http_deflatestream_object_clone_obj(zval *this_ptr TSRMLS_DC) -+{ -+ http_encoding_stream *s; -+ zend_object_value new_ov; -+ http_deflatestream_object *new_obj = NULL; -+ getObject(http_deflatestream_object, old_obj); -+ -+ s = ecalloc(1, sizeof(http_encoding_stream)); -+ s->flags = old_obj->stream->flags; -+ deflateCopy(&s->stream, &old_obj->stream->stream); -+ s->stream.opaque = phpstr_dup(s->stream.opaque); -+ -+ new_ov = http_deflatestream_object_new_ex(old_obj->zo.ce, s, &new_obj); -+ zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); -+ -+ return new_ov; -+} -+ -+void _http_deflatestream_object_free(zend_object *object TSRMLS_DC) -+{ -+ http_deflatestream_object *o = (http_deflatestream_object *) object; -+ -+ if (o->stream) { -+ http_encoding_deflate_stream_free(&o->stream); -+ } -+ freeObject(o); -+} -+ -+/* {{{ proto void HttpDeflateStream::__construct([int flags = 0]) -+ Creates a new HttpDeflateStream object instance. */ -+PHP_METHOD(HttpDeflateStream, __construct) -+{ -+ long flags = 0; -+ -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags)) { -+ getObject(http_deflatestream_object, obj); -+ -+ if (!obj->stream) { -+ obj->stream = http_encoding_deflate_stream_init(NULL, flags & 0x0fffffff); -+ } else { -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "HttpDeflateStream cannot be initialized twice"); -+ } -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+/* {{{ proto HttpDeflateStream HttpDeflateStream::factory([int flags[, string class = "HttpDeflateStream"]]) -+ Creates a new HttpDeflateStream object instance. */ -+PHP_METHOD(HttpDeflateStream, factory) -+{ -+ long flags = 0; -+ char *cn = NULL; -+ int cl = 0; -+ -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &flags, &cn, &cl)) { -+ zend_object_value ov; -+ http_encoding_stream *s = http_encoding_deflate_stream_init(NULL, flags & 0x0fffffff); -+ -+ if (SUCCESS == http_object_new(&ov, cn, cl, _http_deflatestream_object_new_ex, http_deflatestream_object_ce, s, NULL)) { -+ RETVAL_OBJVAL(ov, 0); -+ } -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+/* {{{ proto string HttpDeflateStream::update(string data) -+ Passes more data through the deflate stream. */ -+PHP_METHOD(HttpDeflateStream, update) -+{ -+ int data_len; -+ size_t encoded_len = 0; -+ char *data, *encoded = NULL; -+ getObject(http_deflatestream_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) { -+ RETURN_FALSE; -+ } -+ -+ if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) { -+ RETURN_FALSE; -+ } -+ -+ if (SUCCESS == http_encoding_deflate_stream_update(obj->stream, data, data_len, &encoded, &encoded_len)) { -+ RETURN_STRINGL(encoded, encoded_len, 0); -+ } else { -+ RETURN_FALSE; -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string HttpDeflateStream::flush([string data]) -+ Flushes the deflate stream. */ -+PHP_METHOD(HttpDeflateStream, flush) -+{ -+ int data_len = 0; -+ size_t updated_len = 0, encoded_len = 0; -+ char *updated = NULL, *encoded = NULL, *data = NULL; -+ getObject(http_deflatestream_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) { -+ RETURN_FALSE; -+ } -+ -+ if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) { -+ RETURN_FALSE; -+ } -+ -+ if (data_len) { -+ if (SUCCESS != http_encoding_deflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) { -+ RETURN_FALSE; -+ } -+ } -+ -+ if (SUCCESS == http_encoding_deflate_stream_flush(obj->stream, &encoded, &encoded_len)) { -+ if (updated_len) { -+ updated = erealloc(updated, updated_len + encoded_len + 1); -+ updated[updated_len + encoded_len] = '\0'; -+ memcpy(updated + updated_len, encoded, encoded_len); -+ STR_FREE(encoded); -+ updated_len += encoded_len; -+ RETURN_STRINGL(updated, updated_len, 0); -+ } else if (encoded) { -+ RETVAL_STRINGL(encoded, encoded_len, 0); -+ } else { -+ RETVAL_NULL(); -+ } -+ } else { -+ RETVAL_FALSE; -+ } -+ STR_FREE(updated); -+} -+/* }}} */ -+ -+/* {{{ proto string HttpDeflateStream::finish([string data]) -+ Finalizes the deflate stream. The deflate stream can be reused after finalizing. */ -+PHP_METHOD(HttpDeflateStream, finish) -+{ -+ int data_len = 0; -+ size_t updated_len = 0, encoded_len = 0; -+ char *updated = NULL, *encoded = NULL, *data = NULL; -+ getObject(http_deflatestream_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) { -+ RETURN_FALSE; -+ } -+ -+ if (!obj->stream && !(obj->stream = http_encoding_deflate_stream_init(NULL, 0))) { -+ RETURN_FALSE; -+ } -+ -+ if (data_len) { -+ if (SUCCESS != http_encoding_deflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) { -+ RETURN_FALSE; -+ } -+ } -+ -+ if (SUCCESS == http_encoding_deflate_stream_finish(obj->stream, &encoded, &encoded_len)) { -+ if (updated_len) { -+ updated = erealloc(updated, updated_len + encoded_len + 1); -+ updated[updated_len + encoded_len] = '\0'; -+ memcpy(updated + updated_len, encoded, encoded_len); -+ STR_FREE(encoded); -+ updated_len += encoded_len; -+ RETVAL_STRINGL(updated, updated_len, 0); -+ } else { -+ STR_FREE(updated); -+ RETVAL_STRINGL(encoded, encoded_len, 0); -+ } -+ } else { -+ STR_FREE(updated); -+ RETVAL_FALSE; -+ } -+ -+ http_encoding_deflate_stream_dtor(obj->stream); -+ http_encoding_deflate_stream_init(obj->stream, obj->stream->flags); -+} -+/* }}} */ -+ -+#endif /* ZEND_ENGINE_2 && HTTP_HAVE_ZLIB*/ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_encoding_api.c -@@ -0,0 +1,796 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_encoding_api.c 323304 2012-02-17 21:13:24Z mike $ */ -+ -+#define HTTP_WANT_ZLIB -+#include "php_http.h" -+ -+#include "php_http_api.h" -+#include "php_http_encoding_api.h" -+#include "php_http_send_api.h" -+#include "php_http_headers_api.h" -+ -+/* {{{ */ -+#ifdef HTTP_HAVE_ZLIB -+PHP_MINIT_FUNCTION(http_encoding) -+{ -+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_LEVEL_DEF", HTTP_DEFLATE_LEVEL_DEF); -+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_LEVEL_MIN", HTTP_DEFLATE_LEVEL_MIN); -+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_LEVEL_MAX", HTTP_DEFLATE_LEVEL_MAX); -+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_TYPE_ZLIB", HTTP_DEFLATE_TYPE_ZLIB); -+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_TYPE_GZIP", HTTP_DEFLATE_TYPE_GZIP); -+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_TYPE_RAW", HTTP_DEFLATE_TYPE_RAW); -+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_DEF", HTTP_DEFLATE_STRATEGY_DEF); -+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_FILT", HTTP_DEFLATE_STRATEGY_FILT); -+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_HUFF", HTTP_DEFLATE_STRATEGY_HUFF); -+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_RLE", HTTP_DEFLATE_STRATEGY_RLE); -+ HTTP_LONG_CONSTANT("HTTP_DEFLATE_STRATEGY_FIXED", HTTP_DEFLATE_STRATEGY_FIXED); -+ -+ HTTP_LONG_CONSTANT("HTTP_ENCODING_STREAM_FLUSH_NONE", HTTP_ENCODING_STREAM_FLUSH_NONE); -+ HTTP_LONG_CONSTANT("HTTP_ENCODING_STREAM_FLUSH_SYNC", HTTP_ENCODING_STREAM_FLUSH_SYNC); -+ HTTP_LONG_CONSTANT("HTTP_ENCODING_STREAM_FLUSH_FULL", HTTP_ENCODING_STREAM_FLUSH_FULL); -+ -+ return SUCCESS; -+} -+ -+PHP_RINIT_FUNCTION(http_encoding) -+{ -+ if (HTTP_G->send.inflate.start_auto) { -+#ifdef PHP_OUTPUT_NEWAPI -+ php_output_start_internal(ZEND_STRL("http inflate"), _http_ob_inflatehandler, HTTP_INFLATE_BUFFER_SIZE, 0 TSRMLS_CC); -+#else -+ php_ob_set_internal_handler(_http_ob_inflatehandler, HTTP_INFLATE_BUFFER_SIZE, "http inflate", 0 TSRMLS_CC); -+#endif -+ } -+ if (HTTP_G->send.deflate.start_auto) { -+#ifdef PHP_OUTPUT_NEWAPI -+ php_output_start_internal(ZEND_STRL("http deflate"), _http_ob_deflatehandler, HTTP_DEFLATE_BUFFER_SIZE, 0 TSRMLS_CC); -+#else -+ php_ob_set_internal_handler(_http_ob_deflatehandler, HTTP_DEFLATE_BUFFER_SIZE, "http deflate", 0 TSRMLS_CC); -+#endif -+ } -+ return SUCCESS; -+} -+ -+PHP_RSHUTDOWN_FUNCTION(http_encoding) -+{ -+ if (HTTP_G->send.deflate.stream) { -+ http_encoding_deflate_stream_free((http_encoding_stream **) &HTTP_G->send.deflate.stream); -+ } -+ if (HTTP_G->send.inflate.stream) { -+ http_encoding_inflate_stream_free((http_encoding_stream **) &HTTP_G->send.inflate.stream); -+ } -+ return SUCCESS; -+} -+#endif -+/* }}} */ -+ -+/* {{{ eol_match(char **, int *) */ -+static inline int eol_match(char **line, int *eol_len) -+{ -+ char *ptr = *line; -+ -+ while (' ' == *ptr) ++ptr; -+ -+ if (ptr == http_locate_eol(*line, eol_len)) { -+ *line = ptr; -+ return 1; -+ } else { -+ return 0; -+ } -+} -+/* }}} */ -+ -+/* {{{ char *http_encoding_dechunk(char *, size_t, char **, size_t *) */ -+PHP_HTTP_API const char *_http_encoding_dechunk(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC) -+{ -+ int eol_len = 0; -+ char *n_ptr = NULL; -+ const char *e_ptr = encoded; -+ -+ *decoded_len = 0; -+ *decoded = ecalloc(1, encoded_len); -+ -+ while ((encoded + encoded_len - e_ptr) > 0) { -+ ulong chunk_len = 0, rest; -+ -+ chunk_len = strtoul(e_ptr, &n_ptr, 16); -+ -+ /* we could not read in chunk size */ -+ if (n_ptr == e_ptr) { -+ /* -+ * if this is the first turn and there doesn't seem to be a chunk -+ * size at the begining of the body, do not fail on apparently -+ * not encoded data and return a copy -+ */ -+ if (e_ptr == encoded) { -+ http_error(HE_NOTICE, HTTP_E_ENCODING, "Data does not seem to be chunked encoded"); -+ memcpy(*decoded, encoded, encoded_len); -+ *decoded_len = encoded_len; -+ return encoded + encoded_len; -+ } else { -+ efree(*decoded); -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Expected chunk size at pos %tu of %zu but got trash", n_ptr - encoded, encoded_len); -+ return NULL; -+ } -+ } -+ -+ /* reached the end */ -+ if (!chunk_len) { -+ /* move over '0' chunked encoding terminator */ -+ while (*e_ptr == '0') ++e_ptr; -+ break; -+ } -+ -+ /* there should be CRLF after the chunk size, but we'll ignore SP+ too */ -+ if (*n_ptr && !eol_match(&n_ptr, &eol_len)) { -+ if (eol_len == 2) { -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Expected CRLF at pos %tu of %zu but got 0x%02X 0x%02X", n_ptr - encoded, encoded_len, *n_ptr, *(n_ptr + 1)); -+ } else { -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Expected LF at pos %tu of %zu but got 0x%02X", n_ptr - encoded, encoded_len, *n_ptr); -+ } -+ } -+ n_ptr += eol_len; -+ -+ /* chunk size pretends more data than we actually got, so it's probably a truncated message */ -+ if (chunk_len > (rest = encoded + encoded_len - n_ptr)) { -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Truncated message: chunk size %lu exceeds remaining data size %lu at pos %tu of %zu", chunk_len, rest, n_ptr - encoded, encoded_len); -+ chunk_len = rest; -+ } -+ -+ /* copy the chunk */ -+ memcpy(*decoded + *decoded_len, n_ptr, chunk_len); -+ *decoded_len += chunk_len; -+ -+ if (chunk_len == rest) { -+ e_ptr = n_ptr + chunk_len; -+ break; -+ } else { -+ /* advance to next chunk */ -+ e_ptr = n_ptr + chunk_len + eol_len; -+ } -+ } -+ -+ return e_ptr; -+} -+/* }}} */ -+ -+/* {{{ int http_encoding_response_start(size_t) */ -+PHP_HTTP_API int _http_encoding_response_start(size_t content_length, zend_bool ignore_http_ohandler TSRMLS_DC) -+{ -+ int response = HTTP_G->send.deflate.response; -+#ifdef PHP_OUTPUT_NEWAPI -+ int ohandler = php_output_handler_started(ZEND_STRL("ob_gzhandler") TSRMLS_CC) || php_output_handler_started(ZEND_STRL("zlib output compression") TSRMLS_CC); -+#else -+ int ohandler = php_ob_handler_used("ob_gzhandler" TSRMLS_CC) || php_ob_handler_used("zlib output compression" TSRMLS_CC); -+#endif -+ -+ if (!ohandler && !ignore_http_ohandler) { -+#ifdef PHP_OUTPUT_NEWAPI -+ ohandler = php_output_handler_started(ZEND_STRL("ob_defaltehandler") TSRMLS_CC) || php_output_handler_started(ZEND_STRL("http deflate") TSRMLS_CC); -+#else -+ ohandler = php_ob_handler_used("ob_deflatehandler" TSRMLS_CC) || php_ob_handler_used("http deflate" TSRMLS_CC); -+#endif -+ } -+ -+ if (response && !ohandler) { -+#ifdef HTTP_HAVE_ZLIB -+ HashTable *selected; -+ zval zsupported; -+ -+ HTTP_G->send.deflate.encoding = 0; -+ -+ INIT_PZVAL(&zsupported); -+ array_init(&zsupported); -+ add_next_index_stringl(&zsupported, "gzip", lenof("gzip"), 1); -+ add_next_index_stringl(&zsupported, "x-gzip", lenof("x-gzip"), 1); -+ add_next_index_stringl(&zsupported, "deflate", lenof("deflate"), 1); -+ -+ if ((selected = http_negotiate_encoding(&zsupported))) { -+ STATUS hs = FAILURE; -+ char *encoding = NULL; -+ ulong idx; -+ -+ if (HASH_KEY_IS_STRING == zend_hash_get_current_key(selected, &encoding, &idx, 0) && encoding) { -+ if (!strcmp(encoding, "gzip") || !strcmp(encoding, "x-gzip")) { -+ if (SUCCESS == (hs = http_send_header_string("Content-Encoding: gzip"))) { -+ HTTP_G->send.deflate.encoding = HTTP_ENCODING_GZIP; -+ } -+ } else if (!strcmp(encoding, "deflate")) { -+ if (SUCCESS == (hs = http_send_header_string("Content-Encoding: deflate"))) { -+ HTTP_G->send.deflate.encoding = HTTP_ENCODING_DEFLATE; -+ } -+ } -+ if (SUCCESS == hs) { -+ http_send_header_string("Vary: Accept-Encoding"); -+ } -+ } -+ -+ zend_hash_destroy(selected); -+ FREE_HASHTABLE(selected); -+ } -+ -+ zval_dtor(&zsupported); -+#else -+ HTTP_G->send.deflate.encoding = 0; -+ php_start_ob_buffer_named("ob_gzhandler", 0, 0 TSRMLS_CC); -+#endif /* HTTP_HAVE_ZLIB */ -+ } else if (content_length && !ohandler) { -+ /* emit a content-length header */ -+ phpstr header; -+ -+ phpstr_init(&header); -+ phpstr_appendf(&header, "Content-Length: %zu", content_length); -+ phpstr_fix(&header); -+ http_send_header_string_ex(PHPSTR_VAL(&header), PHPSTR_LEN(&header), 1); -+ phpstr_dtor(&header); -+ } else { -+ HTTP_G->send.deflate.encoding = 0; -+ } -+ -+ return HTTP_G->send.deflate.encoding; -+} -+/* }}} */ -+ -+#ifdef HTTP_HAVE_ZLIB -+ -+/* {{{ inline int http_inflate_rounds */ -+static inline int http_inflate_rounds(z_stream *Z, int flush, char **buf, size_t *len) -+{ -+ int status = 0, round = 0; -+ phpstr buffer; -+ -+ *buf = NULL; -+ *len = 0; -+ -+ phpstr_init_ex(&buffer, Z->avail_in, PHPSTR_INIT_PREALLOC); -+ -+ do { -+ if (PHPSTR_NOMEM == phpstr_resize_ex(&buffer, buffer.size, 0, 1)) { -+ status = Z_MEM_ERROR; -+ } else { -+ Z->avail_out = buffer.free; -+ Z->next_out = (Bytef *) buffer.data + buffer.used; -+#if 0 -+ fprintf(stderr, "\n%3d: %3d PRIOR: size=%7lu,\tfree=%7lu,\tused=%7lu,\tavail_in=%7lu,\tavail_out=%7lu\n", round, status, buffer.size, buffer.free, buffer.used, Z->avail_in, Z->avail_out); -+#endif -+ status = inflate(Z, flush); -+ -+ buffer.used += buffer.free - Z->avail_out; -+ buffer.free = Z->avail_out; -+#if 0 -+ fprintf(stderr, "%3d: %3d AFTER: size=%7lu,\tfree=%7lu,\tused=%7lu,\tavail_in=%7lu,\tavail_out=%7lu\n", round, status, buffer.size, buffer.free, buffer.used, Z->avail_in, Z->avail_out); -+#endif -+ HTTP_INFLATE_BUFFER_SIZE_ALIGN(buffer.size); -+ } -+ } while ((Z_BUF_ERROR == status || (Z_OK == status && Z->avail_in)) && ++round < HTTP_INFLATE_ROUNDS); -+ -+ if (status == Z_OK || status == Z_STREAM_END) { -+ phpstr_shrink(&buffer); -+ phpstr_fix(&buffer); -+ *buf = buffer.data; -+ *len = buffer.used; -+ } else { -+ phpstr_dtor(&buffer); -+ } -+ -+ return status; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_encoding_deflate(int, char *, size_t, char **, size_t *) */ -+PHP_HTTP_API STATUS _http_encoding_deflate(int flags, const char *data, size_t data_len, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC) -+{ -+ int status, level, wbits, strategy; -+ z_stream Z; -+ -+ HTTP_DEFLATE_LEVEL_SET(flags, level); -+ HTTP_DEFLATE_WBITS_SET(flags, wbits); -+ HTTP_DEFLATE_STRATEGY_SET(flags, strategy); -+ -+ memset(&Z, 0, sizeof(z_stream)); -+ *encoded = NULL; -+ *encoded_len = 0; -+ -+ status = deflateInit2(&Z, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, strategy); -+ if (Z_OK == status) { -+ *encoded_len = HTTP_DEFLATE_BUFFER_SIZE_GUESS(data_len); -+ *encoded = emalloc_rel(*encoded_len); -+ -+ Z.next_in = (Bytef *) data; -+ Z.next_out = (Bytef *) *encoded; -+ Z.avail_in = data_len; -+ Z.avail_out = *encoded_len; -+ -+ status = deflate(&Z, Z_FINISH); -+ deflateEnd(&Z); -+ -+ if (Z_STREAM_END == status) { -+ /* size buffer down to actual length */ -+ *encoded = erealloc_rel(*encoded, Z.total_out + 1); -+ (*encoded)[*encoded_len = Z.total_out] = '\0'; -+ return SUCCESS; -+ } else { -+ STR_SET(*encoded, NULL); -+ *encoded_len = 0; -+ } -+ } -+ -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not deflate data: %s", zError(status)); -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_encoding_inflate(char *, size_t, char **, size_t) */ -+PHP_HTTP_API STATUS _http_encoding_inflate(const char *data, size_t data_len, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC) -+{ -+ z_stream Z; -+ int status, wbits = HTTP_WINDOW_BITS_ANY; -+ -+ memset(&Z, 0, sizeof(z_stream)); -+ -+retry_raw_inflate: -+ status = inflateInit2(&Z, wbits); -+ if (Z_OK == status) { -+ Z.next_in = (Bytef *) data; -+ Z.avail_in = data_len; -+ -+ switch (status = http_inflate_rounds(&Z, Z_NO_FLUSH, decoded, decoded_len)) { -+ case Z_STREAM_END: -+ inflateEnd(&Z); -+ return SUCCESS; -+ -+ case Z_OK: -+ status = Z_DATA_ERROR; -+ break; -+ -+ case Z_DATA_ERROR: -+ /* raw deflated data? */ -+ if (HTTP_WINDOW_BITS_ANY == wbits) { -+ inflateEnd(&Z); -+ wbits = HTTP_WINDOW_BITS_RAW; -+ goto retry_raw_inflate; -+ } -+ } -+ inflateEnd(&Z); -+ } -+ -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not inflate data: %s", zError(status)); -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ http_encoding_stream *_http_encoding_deflate_stream_init(http_encoding_stream *, int) */ -+PHP_HTTP_API http_encoding_stream *_http_encoding_deflate_stream_init(http_encoding_stream *s, int flags ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC) -+{ -+ int status, level, wbits, strategy, free_stream; -+ -+ if ((free_stream = !s)) { -+ s = pemalloc_rel(sizeof(http_encoding_stream), (flags & HTTP_ENCODING_STREAM_PERSISTENT)); -+ } -+ memset(s, 0, sizeof(http_encoding_stream)); -+ s->flags = flags; -+ -+ HTTP_DEFLATE_LEVEL_SET(flags, level); -+ HTTP_DEFLATE_WBITS_SET(flags, wbits); -+ HTTP_DEFLATE_STRATEGY_SET(flags, strategy); -+ -+ if (Z_OK == (status = deflateInit2(&s->stream, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, strategy))) { -+ int p = (flags & HTTP_ENCODING_STREAM_PERSISTENT) ? PHPSTR_INIT_PERSISTENT:0; -+ -+ if ((s->stream.opaque = phpstr_init_ex(NULL, HTTP_DEFLATE_BUFFER_SIZE, p))) { -+ return s; -+ } -+ deflateEnd(&s->stream); -+ status = Z_MEM_ERROR; -+ } -+ -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to initialize deflate encoding stream: %s", zError(status)); -+ if (free_stream) { -+ efree(s); -+ } -+ return NULL; -+} -+/* }}} */ -+ -+/* {{{ http_encoding_stream *http_encoding_inflate_stream_init(http_encoding_stream *, int) */ -+PHP_HTTP_API http_encoding_stream *_http_encoding_inflate_stream_init(http_encoding_stream *s, int flags ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC) -+{ -+ int status, wbits, free_stream; -+ -+ if ((free_stream = !s)) { -+ s = pemalloc_rel(sizeof(http_encoding_stream), (flags & HTTP_ENCODING_STREAM_PERSISTENT)); -+ } -+ memset(s, 0, sizeof(http_encoding_stream)); -+ s->flags = flags; -+ -+ HTTP_INFLATE_WBITS_SET(flags, wbits); -+ -+ if (Z_OK == (status = inflateInit2(&s->stream, wbits))) { -+ int p = (flags & HTTP_ENCODING_STREAM_PERSISTENT) ? PHPSTR_INIT_PERSISTENT:0; -+ -+ if ((s->stream.opaque = phpstr_init_ex(NULL, HTTP_DEFLATE_BUFFER_SIZE, p))) { -+ return s; -+ } -+ inflateEnd(&s->stream); -+ status = Z_MEM_ERROR; -+ } -+ -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to initialize inflate stream: %s", zError(status)); -+ if (free_stream) { -+ efree(s); -+ } -+ return NULL; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_encoding_deflate_stream_update(http_encoding_stream *, char *, size_t, char **, size_t *) */ -+PHP_HTTP_API STATUS _http_encoding_deflate_stream_update(http_encoding_stream *s, const char *data, size_t data_len, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC) -+{ -+ int status; -+ -+ /* append input to our buffer */ -+ phpstr_append(PHPSTR(s->stream.opaque), data, data_len); -+ -+ s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque); -+ s->stream.avail_in = PHPSTR_LEN(s->stream.opaque); -+ -+ /* deflate */ -+ *encoded_len = HTTP_DEFLATE_BUFFER_SIZE_GUESS(data_len); -+ *encoded = emalloc_rel(*encoded_len); -+ s->stream.avail_out = *encoded_len; -+ s->stream.next_out = (Bytef *) *encoded; -+ -+ switch (status = deflate(&s->stream, HTTP_ENCODING_STREAM_FLUSH_FLAG(s->flags))) { -+ case Z_OK: -+ case Z_STREAM_END: -+ /* cut processed chunk off the buffer */ -+ if (s->stream.avail_in) { -+ phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in); -+ } else { -+ phpstr_reset(PHPSTR(s->stream.opaque)); -+ } -+ -+ /* size buffer down to actual size */ -+ *encoded_len -= s->stream.avail_out; -+ *encoded = erealloc_rel(*encoded, *encoded_len + 1); -+ (*encoded)[*encoded_len] = '\0'; -+ return SUCCESS; -+ } -+ -+ STR_SET(*encoded, NULL); -+ *encoded_len = 0; -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to update deflate stream: %s", zError(status)); -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_encoding_inflate_stream_update(http_encoding_stream *, char *, size_t, char **, size_t *) */ -+PHP_HTTP_API STATUS _http_encoding_inflate_stream_update(http_encoding_stream *s, const char *data, size_t data_len, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC) -+{ -+ int status; -+ -+ /* append input to buffer */ -+ phpstr_append(PHPSTR(s->stream.opaque), data, data_len); -+ -+retry_raw_inflate: -+ s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque); -+ s->stream.avail_in = PHPSTR_LEN(s->stream.opaque); -+ -+ switch (status = http_inflate_rounds(&s->stream, HTTP_ENCODING_STREAM_FLUSH_FLAG(s->flags), decoded, decoded_len)) { -+ case Z_OK: -+ case Z_STREAM_END: -+ /* cut off */ -+ if (s->stream.avail_in) { -+ phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in); -+ } else { -+ phpstr_reset(PHPSTR(s->stream.opaque)); -+ } -+ return SUCCESS; -+ -+ case Z_DATA_ERROR: -+ /* raw deflated data ? */ -+ if (!(s->flags & HTTP_INFLATE_TYPE_RAW) && !s->stream.total_out) { -+ inflateEnd(&s->stream); -+ s->flags |= HTTP_INFLATE_TYPE_RAW; -+ inflateInit2(&s->stream, HTTP_WINDOW_BITS_RAW); -+ goto retry_raw_inflate; -+ } -+ } -+ -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to update inflate stream: %s", zError(status)); -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_encoding_deflate_stream_flush(http_encoding_stream *, char **, size_t *) */ -+PHP_HTTP_API STATUS _http_encoding_deflate_stream_flush(http_encoding_stream *s, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC) -+{ -+ int status; -+ -+ *encoded_len = HTTP_DEFLATE_BUFFER_SIZE; -+ *encoded = emalloc_rel(*encoded_len); -+ -+ s->stream.avail_in = 0; -+ s->stream.next_in = NULL; -+ s->stream.avail_out = *encoded_len; -+ s->stream.next_out = (Bytef *) *encoded; -+ -+ switch (status = deflate(&s->stream, Z_FULL_FLUSH)) { -+ case Z_OK: -+ case Z_STREAM_END: -+ *encoded_len = HTTP_DEFLATE_BUFFER_SIZE - s->stream.avail_out; -+ *encoded = erealloc_rel(*encoded, *encoded_len + 1); -+ (*encoded)[*encoded_len] = '\0'; -+ return SUCCESS; -+ } -+ -+ STR_SET(*encoded, NULL); -+ *encoded_len = 0; -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to flush deflate stream: %s", zError(status)); -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_encoding_inflate_straem_flush(http_encoding_stream *, char **, size_t *) */ -+PHP_HTTP_API STATUS _http_encoding_inflate_stream_flush(http_encoding_stream *s, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC) -+{ -+ /* noop */ -+ *decoded = estrndup("", *decoded_len = 0); -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_encoding_deflate_stream_finish(http_encoding_stream *, char **, size_t *) */ -+PHP_HTTP_API STATUS _http_encoding_deflate_stream_finish(http_encoding_stream *s, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC) -+{ -+ int status; -+ -+ *encoded_len = HTTP_DEFLATE_BUFFER_SIZE; -+ *encoded = emalloc_rel(*encoded_len); -+ -+ /* deflate remaining input */ -+ s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque); -+ s->stream.avail_in = PHPSTR_LEN(s->stream.opaque); -+ -+ s->stream.avail_out = *encoded_len; -+ s->stream.next_out = (Bytef *) *encoded; -+ -+ do { -+ status = deflate(&s->stream, Z_FINISH); -+ } while (Z_OK == status); -+ -+ if (Z_STREAM_END == status) { -+ /* cut processed intp off */ -+ phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in); -+ -+ /* size down */ -+ *encoded_len -= s->stream.avail_out; -+ *encoded = erealloc_rel(*encoded, *encoded_len + 1); -+ (*encoded)[*encoded_len] = '\0'; -+ return SUCCESS; -+ } -+ -+ STR_SET(*encoded, NULL); -+ *encoded_len = 0; -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to finish deflate stream: %s", zError(status)); -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_encoding_inflate_stream_finish(http_encoding_stream *, char **, size_t *) */ -+PHP_HTTP_API STATUS _http_encoding_inflate_stream_finish(http_encoding_stream *s, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC) -+{ -+ int status; -+ -+ if (!PHPSTR_LEN(s->stream.opaque)) { -+ *decoded = NULL; -+ *decoded_len = 0; -+ return SUCCESS; -+ } -+ -+ *decoded_len = (PHPSTR_LEN(s->stream.opaque) + 1) * HTTP_INFLATE_ROUNDS; -+ *decoded = emalloc_rel(*decoded_len); -+ -+ /* inflate remaining input */ -+ s->stream.next_in = (Bytef *) PHPSTR_VAL(s->stream.opaque); -+ s->stream.avail_in = PHPSTR_LEN(s->stream.opaque); -+ -+ s->stream.avail_out = *decoded_len; -+ s->stream.next_out = (Bytef *) *decoded; -+ -+ if (Z_STREAM_END == (status = inflate(&s->stream, Z_FINISH))) { -+ /* cut processed input off */ -+ phpstr_cut(PHPSTR(s->stream.opaque), 0, PHPSTR_LEN(s->stream.opaque) - s->stream.avail_in); -+ -+ /* size down */ -+ *decoded_len -= s->stream.avail_out; -+ *decoded = erealloc_rel(*decoded, *decoded_len + 1); -+ (*decoded)[*decoded_len] = '\0'; -+ return SUCCESS; -+ } -+ -+ STR_SET(*decoded, NULL); -+ *decoded_len = 0; -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Failed to finish inflate stream: %s", zError(status)); -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ void http_encoding_deflate_stream_dtor(http_encoding_stream *) */ -+PHP_HTTP_API void _http_encoding_deflate_stream_dtor(http_encoding_stream *s TSRMLS_DC) -+{ -+ if (s) { -+ if (s->stream.opaque) { -+ phpstr_free((phpstr **) &s->stream.opaque); -+ } -+ deflateEnd(&s->stream); -+ } -+} -+/* }}} */ -+ -+/* {{{ void http_encoding_inflate_stream_dtor(http_encoding_stream *) */ -+PHP_HTTP_API void _http_encoding_inflate_stream_dtor(http_encoding_stream *s TSRMLS_DC) -+{ -+ if (s) { -+ if (s->stream.opaque) { -+ phpstr_free((phpstr **) &s->stream.opaque); -+ } -+ inflateEnd(&s->stream); -+ } -+} -+/* }}} */ -+ -+/* {{{ void http_encoding_deflate_stream_free(http_encoding_stream **) */ -+PHP_HTTP_API void _http_encoding_deflate_stream_free(http_encoding_stream **s TSRMLS_DC) -+{ -+ if (s) { -+ http_encoding_deflate_stream_dtor(*s); -+ if (*s) { -+ pefree(*s, (*s)->flags & HTTP_ENCODING_STREAM_PERSISTENT); -+ } -+ *s = NULL; -+ } -+} -+/* }}} */ -+ -+/* {{{ void http_encoding_inflate_stream_free(http_encoding_stream **) */ -+PHP_HTTP_API void _http_encoding_inflate_stream_free(http_encoding_stream **s TSRMLS_DC) -+{ -+ if (s) { -+ http_encoding_inflate_stream_dtor(*s); -+ if (*s) { -+ pefree(*s, (*s)->flags & HTTP_ENCODING_STREAM_PERSISTENT); -+ } -+ *s = NULL; -+ } -+} -+/* }}} */ -+ -+/* {{{ void http_ob_deflatehandler(char *, uint, char **, uint *, int) */ -+void _http_ob_deflatehandler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC) -+{ -+ int encoding; -+ -+ *handled_output = NULL; -+ *handled_output_len = 0; -+ -+ if (mode & PHP_OUTPUT_HANDLER_START) { -+ int flags; -+ -+ if (HTTP_G->send.deflate.stream) { -+ zend_error(E_ERROR, "ob_deflatehandler() can only be used once"); -+ return; -+ } -+ -+ HTTP_G->send.deflate.response = 1; -+ encoding = http_encoding_response_start(0, 1); -+ HTTP_G->send.deflate.response = 0; -+ -+ switch (encoding) { -+ case HTTP_ENCODING_GZIP: -+ flags = HTTP_DEFLATE_TYPE_GZIP; -+ break; -+ -+ case HTTP_ENCODING_DEFLATE: -+ flags = HTTP_DEFLATE_TYPE_ZLIB; -+ break; -+ -+ default: -+ goto deflate_passthru_plain; -+ } -+ -+ flags |= (HTTP_G->send.deflate.start_flags &~ 0xf0); -+ HTTP_G->send.deflate.stream = http_encoding_deflate_stream_init(NULL, flags); -+ } -+ -+ if (HTTP_G->send.deflate.stream) { -+ if (output_len) { -+ size_t tmp_len; -+ -+ http_encoding_deflate_stream_update((http_encoding_stream *) HTTP_G->send.deflate.stream, output, output_len, handled_output, &tmp_len); -+ *handled_output_len = tmp_len; -+ } -+ -+ if (mode & PHP_OUTPUT_HANDLER_END) { -+ char *remaining = NULL; -+ size_t remaining_len = 0; -+ -+ http_encoding_deflate_stream_finish((http_encoding_stream *) HTTP_G->send.deflate.stream, &remaining, &remaining_len); -+ http_encoding_deflate_stream_free((http_encoding_stream **) &HTTP_G->send.deflate.stream); -+ if (remaining) { -+ *handled_output = erealloc(*handled_output, *handled_output_len + remaining_len + 1); -+ memcpy(*handled_output + *handled_output_len, remaining, remaining_len); -+ (*handled_output)[*handled_output_len += remaining_len] = '\0'; -+ efree(remaining); -+ } -+ } -+ } else { -+deflate_passthru_plain: -+ *handled_output = estrndup(output, *handled_output_len = output_len); -+ } -+} -+/* }}} */ -+ -+/* {{{ void http_ob_inflatehandler(char *, uint, char **, uint *, int) */ -+void _http_ob_inflatehandler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC) -+{ -+ *handled_output = NULL; -+ *handled_output_len = 0; -+ -+ if (mode & PHP_OUTPUT_HANDLER_START) { -+ if (HTTP_G->send.inflate.stream) { -+ zend_error(E_ERROR, "ob_inflatehandler() can only be used once"); -+ return; -+ } -+ HTTP_G->send.inflate.stream = http_encoding_inflate_stream_init(NULL, (HTTP_G->send.inflate.start_flags &~ 0xf0)); -+ } -+ -+ if (HTTP_G->send.inflate.stream) { -+ if (output_len) { -+ size_t tmp_len; -+ -+ http_encoding_inflate_stream_update((http_encoding_stream *) HTTP_G->send.inflate.stream, output, output_len, handled_output, &tmp_len); -+ *handled_output_len = tmp_len; -+ } -+ -+ if (mode & PHP_OUTPUT_HANDLER_END) { -+ char *remaining = NULL; -+ size_t remaining_len = 0; -+ -+ http_encoding_inflate_stream_finish((http_encoding_stream *) HTTP_G->send.inflate.stream, &remaining, &remaining_len); -+ http_encoding_inflate_stream_free((http_encoding_stream **) &HTTP_G->send.inflate.stream); -+ if (remaining) { -+ *handled_output = erealloc(*handled_output, *handled_output_len + remaining_len + 1); -+ memcpy(*handled_output + *handled_output_len, remaining, remaining_len); -+ (*handled_output)[*handled_output_len += remaining_len] = '\0'; -+ efree(remaining); -+ } -+ } -+ } else { -+ *handled_output = estrndup(output, *handled_output_len = output_len); -+ } -+} -+/* }}} */ -+ -+#endif /* HTTP_HAVE_ZLIB */ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_exception_object.c -@@ -0,0 +1,186 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_exception_object.c 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#include "php_http.h" -+ -+#ifdef ZEND_ENGINE_2 -+ -+#ifndef HTTP_DBG_EXCEPTIONS -+# define HTTP_DBG_EXCEPTIONS 0 -+#endif -+ -+#include "zend_interfaces.h" -+#include "zend_exceptions.h" -+#include "php_http_exception_object.h" -+ -+zend_class_entry *http_exception_object_ce; -+zend_class_entry *HTTP_EX_CE(runtime); -+zend_class_entry *HTTP_EX_CE(header); -+zend_class_entry *HTTP_EX_CE(malformed_headers); -+zend_class_entry *HTTP_EX_CE(request_method); -+zend_class_entry *HTTP_EX_CE(message_type); -+zend_class_entry *HTTP_EX_CE(invalid_param); -+zend_class_entry *HTTP_EX_CE(encoding); -+zend_class_entry *HTTP_EX_CE(request); -+zend_class_entry *HTTP_EX_CE(request_pool); -+zend_class_entry *HTTP_EX_CE(socket); -+zend_class_entry *HTTP_EX_CE(response); -+zend_class_entry *HTTP_EX_CE(url); -+zend_class_entry *HTTP_EX_CE(querystring); -+ -+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpException, method, 0) -+#define HTTP_EXCEPTION_ME(method, visibility) PHP_ME(HttpException, method, HTTP_ARGS(HttpException, method), visibility) -+ -+HTTP_EMPTY_ARGS(__toString); -+ -+zend_function_entry http_exception_object_fe[] = { -+ HTTP_EXCEPTION_ME(__toString, ZEND_ACC_PUBLIC) -+ -+ EMPTY_FUNCTION_ENTRY -+}; -+ -+#if HTTP_DBG_EXCEPTIONS -+static void http_exception_hook(zval *ex TSRMLS_DC) -+{ -+ if (ex) { -+ zval *m = zend_read_property(Z_OBJCE_P(ex), ex, "message", lenof("message"), 0 TSRMLS_CC); -+ fprintf(stderr, "*** Threw exception '%s'\n", Z_STRVAL_P(m)); -+ } else { -+ fprintf(stderr, "*** Threw NULL exception\n"); -+ } -+} -+#endif -+ -+PHP_MINIT_FUNCTION(http_exception_object) -+{ -+ HTTP_REGISTER_CLASS(HttpException, http_exception_object, ZEND_EXCEPTION_GET_DEFAULT(), 0); -+ -+ zend_declare_property_null(HTTP_EX_DEF_CE, "innerException", lenof("innerException"), ZEND_ACC_PUBLIC TSRMLS_CC); -+ -+ HTTP_REGISTER_EXCEPTION(HttpRuntimeException, HTTP_EX_CE(runtime), HTTP_EX_DEF_CE); -+ HTTP_REGISTER_EXCEPTION(HttpInvalidParamException, HTTP_EX_CE(invalid_param), HTTP_EX_DEF_CE); -+ HTTP_REGISTER_EXCEPTION(HttpHeaderException, HTTP_EX_CE(header), HTTP_EX_DEF_CE); -+ HTTP_REGISTER_EXCEPTION(HttpMalformedHeadersException, HTTP_EX_CE(malformed_headers), HTTP_EX_DEF_CE); -+ HTTP_REGISTER_EXCEPTION(HttpRequestMethodException, HTTP_EX_CE(request_method), HTTP_EX_DEF_CE); -+ HTTP_REGISTER_EXCEPTION(HttpMessageTypeException, HTTP_EX_CE(message_type), HTTP_EX_DEF_CE); -+ HTTP_REGISTER_EXCEPTION(HttpEncodingException, HTTP_EX_CE(encoding), HTTP_EX_DEF_CE); -+ HTTP_REGISTER_EXCEPTION(HttpRequestException, HTTP_EX_CE(request), HTTP_EX_DEF_CE); -+ -+ zend_declare_property_long(HTTP_EX_CE(request), "curlCode", lenof("curlCode"), 0, ZEND_ACC_PUBLIC TSRMLS_CC); -+ -+ HTTP_REGISTER_EXCEPTION(HttpRequestPoolException, HTTP_EX_CE(request_pool), HTTP_EX_DEF_CE); -+ HTTP_REGISTER_EXCEPTION(HttpSocketException, HTTP_EX_CE(socket), HTTP_EX_DEF_CE); -+ HTTP_REGISTER_EXCEPTION(HttpResponseException, HTTP_EX_CE(response), HTTP_EX_DEF_CE); -+ HTTP_REGISTER_EXCEPTION(HttpUrlException, HTTP_EX_CE(url), HTTP_EX_DEF_CE); -+ HTTP_REGISTER_EXCEPTION(HttpQueryStringException, HTTP_EX_CE(querystring), HTTP_EX_DEF_CE); -+ -+ HTTP_LONG_CONSTANT("HTTP_E_RUNTIME", HTTP_E_RUNTIME); -+ HTTP_LONG_CONSTANT("HTTP_E_INVALID_PARAM", HTTP_E_INVALID_PARAM); -+ HTTP_LONG_CONSTANT("HTTP_E_HEADER", HTTP_E_HEADER); -+ HTTP_LONG_CONSTANT("HTTP_E_MALFORMED_HEADERS", HTTP_E_MALFORMED_HEADERS); -+ HTTP_LONG_CONSTANT("HTTP_E_REQUEST_METHOD", HTTP_E_REQUEST_METHOD); -+ HTTP_LONG_CONSTANT("HTTP_E_MESSAGE_TYPE", HTTP_E_MESSAGE_TYPE); -+ HTTP_LONG_CONSTANT("HTTP_E_ENCODING", HTTP_E_ENCODING); -+ HTTP_LONG_CONSTANT("HTTP_E_REQUEST", HTTP_E_REQUEST); -+ HTTP_LONG_CONSTANT("HTTP_E_REQUEST_POOL", HTTP_E_REQUEST_POOL); -+ HTTP_LONG_CONSTANT("HTTP_E_SOCKET", HTTP_E_SOCKET); -+ HTTP_LONG_CONSTANT("HTTP_E_RESPONSE", HTTP_E_RESPONSE); -+ HTTP_LONG_CONSTANT("HTTP_E_URL", HTTP_E_URL); -+ HTTP_LONG_CONSTANT("HTTP_E_QUERYSTRING", HTTP_E_QUERYSTRING); -+ -+#if HTTP_DBG_EXCEPTIONS -+ zend_throw_exception_hook=http_exception_hook; -+#endif -+ -+ return SUCCESS; -+} -+ -+zend_class_entry *_http_exception_get_default() -+{ -+ return http_exception_object_ce; -+} -+ -+zend_class_entry *_http_exception_get_for_code(long code) -+{ -+ zend_class_entry *ex = http_exception_object_ce; -+ -+ switch (code) { -+ case HTTP_E_RUNTIME: ex = HTTP_EX_CE(runtime); break; -+ case HTTP_E_INVALID_PARAM: ex = HTTP_EX_CE(invalid_param); break; -+ case HTTP_E_HEADER: ex = HTTP_EX_CE(header); break; -+ case HTTP_E_MALFORMED_HEADERS: ex = HTTP_EX_CE(malformed_headers); break; -+ case HTTP_E_REQUEST_METHOD: ex = HTTP_EX_CE(request_method); break; -+ case HTTP_E_MESSAGE_TYPE: ex = HTTP_EX_CE(message_type); break; -+ case HTTP_E_ENCODING: ex = HTTP_EX_CE(encoding); break; -+ case HTTP_E_REQUEST: ex = HTTP_EX_CE(request); break; -+ case HTTP_E_REQUEST_POOL: ex = HTTP_EX_CE(request_pool); break; -+ case HTTP_E_SOCKET: ex = HTTP_EX_CE(socket); break; -+ case HTTP_E_RESPONSE: ex = HTTP_EX_CE(response); break; -+ case HTTP_E_URL: ex = HTTP_EX_CE(url); break; -+ case HTTP_E_QUERYSTRING: ex = HTTP_EX_CE(querystring); break; -+ } -+ -+ return ex; -+} -+ -+PHP_METHOD(HttpException, __toString) -+{ -+ phpstr full_str; -+ zend_class_entry *ce; -+ zval *zobj = getThis(), *retval = NULL, *m, *f, *l; -+ -+ phpstr_init(&full_str); -+ -+ do { -+ ce = Z_OBJCE_P(zobj); -+ -+ m = zend_read_property(ce, zobj, "message", lenof("message"), 0 TSRMLS_CC); -+ f = zend_read_property(ce, zobj, "file", lenof("file"), 0 TSRMLS_CC); -+ l = zend_read_property(ce, zobj, "line", lenof("line"), 0 TSRMLS_CC); -+ -+ if (m && f && l && Z_TYPE_P(m) == IS_STRING && Z_TYPE_P(f) == IS_STRING && Z_TYPE_P(l) == IS_LONG) { -+ if (zobj != getThis()) { -+ phpstr_appends(&full_str, " inner "); -+ } -+ -+ phpstr_appendf(&full_str, "exception '%.*s' with message '%.*s' in %.*s:%ld" PHP_EOL, -+ ce->name_length, ce->name, Z_STRLEN_P(m), Z_STRVAL_P(m), Z_STRLEN_P(f), Z_STRVAL_P(f), Z_LVAL_P(l) -+ ); -+ } else { -+ break; -+ } -+ -+ zobj = zend_read_property(ce, zobj, "innerException", lenof("innerException"), 0 TSRMLS_CC); -+ } while (Z_TYPE_P(zobj) == IS_OBJECT); -+ -+ if (zend_call_method_with_0_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "gettraceasstring", &retval) && Z_TYPE_P(retval) == IS_STRING) { -+ phpstr_appends(&full_str, "Stack trace:" PHP_EOL); -+ phpstr_append(&full_str, Z_STRVAL_P(retval), Z_STRLEN_P(retval)); -+ zval_ptr_dtor(&retval); -+ } -+ -+ RETURN_PHPSTR_VAL(&full_str); -+} -+ -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_filter_api.c -@@ -0,0 +1,534 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_filter_api.c 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#define HTTP_WANT_ZLIB -+#include "php_http.h" -+ -+#ifdef ZEND_ENGINE_2 -+ -+#include "php_streams.h" -+#include "php_http_api.h" -+#include "php_http_encoding_api.h" -+#include "php_http_filter_api.h" -+ -+PHP_MINIT_FUNCTION(http_filter) -+{ -+ php_stream_filter_register_factory("http.*", &http_filter_factory TSRMLS_CC); -+ return SUCCESS; -+} -+ -+/* -+ - -+*/ -+ -+#define HTTP_FILTER_PARAMS \ -+ php_stream *stream, \ -+ php_stream_filter *this, \ -+ php_stream_bucket_brigade *buckets_in, \ -+ php_stream_bucket_brigade *buckets_out, \ -+ size_t *bytes_consumed, int flags \ -+ TSRMLS_DC -+#define HTTP_FILTER_OP(filter) \ -+ http_filter_op_ ##filter -+#define HTTP_FILTER_OPS(filter) \ -+ php_stream_filter_ops HTTP_FILTER_OP(filter) -+#define HTTP_FILTER_DTOR(filter) \ -+ http_filter_ ##filter## _dtor -+#define HTTP_FILTER_DESTRUCTOR(filter) \ -+ void HTTP_FILTER_DTOR(filter)(php_stream_filter *this TSRMLS_DC) -+#define HTTP_FILTER_FUNC(filter) \ -+ http_filter_ ##filter -+#define HTTP_FILTER_FUNCTION(filter) \ -+ php_stream_filter_status_t HTTP_FILTER_FUNC(filter)(HTTP_FILTER_PARAMS) -+#define HTTP_FILTER_BUFFER(filter) \ -+ http_filter_ ##filter## _buffer -+ -+#define NEW_BUCKET(data, length) \ -+ { \ -+ char *__data; \ -+ php_stream_bucket *__buck; \ -+ \ -+ __data = pemalloc(length, this->is_persistent); \ -+ if (!__data) { \ -+ return PSFS_ERR_FATAL; \ -+ } \ -+ memcpy(__data, data, length); \ -+ \ -+ __buck = php_stream_bucket_new(stream, __data, length, 1, this->is_persistent TSRMLS_CC); \ -+ if (!__buck) { \ -+ pefree(__data, this->is_persistent); \ -+ return PSFS_ERR_FATAL; \ -+ } \ -+ \ -+ php_stream_bucket_append(buckets_out, __buck TSRMLS_CC); \ -+ } -+ -+typedef struct _http_chunked_decode_filter_buffer_t { -+ phpstr buffer; -+ ulong hexlen; -+} HTTP_FILTER_BUFFER(chunked_decode); -+ -+#ifdef HTTP_HAVE_ZLIB -+typedef http_encoding_stream HTTP_FILTER_BUFFER(deflate); -+typedef http_encoding_stream HTTP_FILTER_BUFFER(inflate); -+#endif /* HTTP_HAVE_ZLIB */ -+ -+ -+static HTTP_FILTER_FUNCTION(chunked_decode) -+{ -+ int out_avail = 0; -+ php_stream_bucket *ptr, *nxt; -+ HTTP_FILTER_BUFFER(chunked_decode) *buffer = (HTTP_FILTER_BUFFER(chunked_decode) *) (this->abstract); -+ -+ if (bytes_consumed) { -+ *bytes_consumed = 0; -+ } -+ -+ /* new data available? */ -+ if (buckets_in->head) { -+ -+ /* fetch available bucket data */ -+ for (ptr = buckets_in->head; ptr; ptr = nxt) { -+ nxt = ptr->next; -+ if (bytes_consumed) { -+ *bytes_consumed += ptr->buflen; -+ } -+ -+ if (PHPSTR_NOMEM == phpstr_append(PHPSTR(buffer), ptr->buf, ptr->buflen)) { -+ return PSFS_ERR_FATAL; -+ } -+ -+ php_stream_bucket_unlink(ptr TSRMLS_CC); -+ php_stream_bucket_delref(ptr TSRMLS_CC); -+ } -+ } -+ if (!phpstr_fix(PHPSTR(buffer))) { -+ return PSFS_ERR_FATAL; -+ } -+ -+ /* we have data in our buffer */ -+ while (PHPSTR_LEN(buffer)) { -+ -+ /* we already know the size of the chunk and are waiting for data */ -+ if (buffer->hexlen) { -+ -+ /* not enough data buffered */ -+ if (PHPSTR_LEN(buffer) < buffer->hexlen) { -+ -+ /* flush anyway? */ -+ if (flags & PSFS_FLAG_FLUSH_INC) { -+ -+ /* flush all data (should only be chunk data) */ -+ out_avail = 1; -+ NEW_BUCKET(PHPSTR_VAL(buffer), PHPSTR_LEN(buffer)); -+ -+ /* waiting for less data now */ -+ buffer->hexlen -= PHPSTR_LEN(buffer); -+ /* no more buffered data */ -+ phpstr_reset(PHPSTR(buffer)); -+ /* break */ -+ } -+ -+ /* we have too less data and don't need to flush */ -+ else { -+ break; -+ } -+ } -+ -+ /* we seem to have all data of the chunk */ -+ else { -+ out_avail = 1; -+ NEW_BUCKET(PHPSTR_VAL(buffer), buffer->hexlen); -+ -+ /* remove outgoing data from the buffer */ -+ phpstr_cut(PHPSTR(buffer), 0, buffer->hexlen); -+ /* reset hexlen */ -+ buffer->hexlen = 0; -+ /* continue */ -+ } -+ } -+ -+ /* we don't know the length of the chunk yet */ -+ else { -+ size_t off = 0; -+ -+ /* ignore preceeding CRLFs (too loose?) */ -+ while (off < PHPSTR_LEN(buffer) && ( -+ PHPSTR_VAL(buffer)[off] == '\n' || -+ PHPSTR_VAL(buffer)[off] == '\r')) { -+ ++off; -+ } -+ if (off) { -+ phpstr_cut(PHPSTR(buffer), 0, off); -+ } -+ -+ /* still data there? */ -+ if (PHPSTR_LEN(buffer)) { -+ int eollen; -+ const char *eolstr; -+ -+ /* we need eol, so we can be sure we have all hex digits */ -+ phpstr_fix(PHPSTR(buffer)); -+ if ((eolstr = http_locate_eol(PHPSTR_VAL(buffer), &eollen))) { -+ char *stop = NULL; -+ -+ /* read in chunk size */ -+ buffer->hexlen = strtoul(PHPSTR_VAL(buffer), &stop, 16); -+ -+ /* if strtoul() stops at the beginning of the buffered data -+ there's domething oddly wrong, i.e. bad input */ -+ if (stop == PHPSTR_VAL(buffer)) { -+ return PSFS_ERR_FATAL; -+ } -+ -+ /* cut out */ -+ phpstr_cut(PHPSTR(buffer), 0, eolstr + eollen - PHPSTR_VAL(buffer)); -+ /* buffer->hexlen is 0 now or contains the size of the next chunk */ -+ /* continue */ -+ } else { -+ /* we have not enough data buffered to read in chunk size */ -+ break; -+ } -+ } -+ /* break */ -+ } -+ } -+ -+ /* flush before close, but only if we are already waiting for more data */ -+ if ((flags & PSFS_FLAG_FLUSH_CLOSE) && buffer->hexlen && PHPSTR_LEN(buffer)) { -+ out_avail = 1; -+ NEW_BUCKET(PHPSTR_VAL(buffer), PHPSTR_LEN(buffer)); -+ phpstr_reset(PHPSTR(buffer)); -+ buffer->hexlen = 0; -+ } -+ -+ return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME; -+} -+ -+static HTTP_FILTER_DESTRUCTOR(chunked_decode) -+{ -+ HTTP_FILTER_BUFFER(chunked_decode) *b = (HTTP_FILTER_BUFFER(chunked_decode) *) (this->abstract); -+ -+ phpstr_dtor(PHPSTR(b)); -+ pefree(b, this->is_persistent); -+} -+ -+static HTTP_FILTER_FUNCTION(chunked_encode) -+{ -+ int out_avail = 0; -+ php_stream_bucket *ptr, *nxt; -+ -+ if (bytes_consumed) { -+ *bytes_consumed = 0; -+ } -+ -+ /* new data available? */ -+ if (buckets_in->head) { -+ phpstr buf; -+ out_avail = 1; -+ -+ phpstr_init(&buf); -+ -+ /* fetch available bucket data */ -+ for (ptr = buckets_in->head; ptr; ptr = nxt) { -+ nxt = ptr->next; -+ if (bytes_consumed) { -+ *bytes_consumed += ptr->buflen; -+ } -+ -+ phpstr_appendf(&buf, "%x" HTTP_CRLF, ptr->buflen); -+ phpstr_append(&buf, ptr->buf, ptr->buflen); -+ phpstr_appends(&buf, HTTP_CRLF); -+ -+ /* pass through */ -+ NEW_BUCKET(PHPSTR_VAL(&buf), PHPSTR_LEN(&buf)); -+ /* reset */ -+ phpstr_reset(&buf); -+ -+ php_stream_bucket_unlink(ptr TSRMLS_CC); -+ php_stream_bucket_delref(ptr TSRMLS_CC); -+ } -+ -+ /* free buffer */ -+ phpstr_dtor(&buf); -+ } -+ -+ /* terminate with "0" */ -+ if (flags & PSFS_FLAG_FLUSH_CLOSE) { -+ out_avail = 1; -+ NEW_BUCKET("0" HTTP_CRLF, lenof("0" HTTP_CRLF)); -+ } -+ -+ return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME; -+} -+ -+static HTTP_FILTER_OPS(chunked_decode) = { -+ HTTP_FILTER_FUNC(chunked_decode), -+ HTTP_FILTER_DTOR(chunked_decode), -+ "http.chunked_decode" -+}; -+ -+static HTTP_FILTER_OPS(chunked_encode) = { -+ HTTP_FILTER_FUNC(chunked_encode), -+ NULL, -+ "http.chunked_encode" -+}; -+ -+#ifdef HTTP_HAVE_ZLIB -+ -+static HTTP_FILTER_FUNCTION(deflate) -+{ -+ int out_avail = 0; -+ php_stream_bucket *ptr, *nxt; -+ HTTP_FILTER_BUFFER(inflate) *buffer = (HTTP_FILTER_BUFFER(deflate) *) this->abstract; -+ -+ if (bytes_consumed) { -+ *bytes_consumed = 0; -+ } -+ -+ /* new data available? */ -+ if (buckets_in->head) { -+ -+ /* fetch available bucket data */ -+ for (ptr = buckets_in->head; ptr; ptr = nxt) { -+ char *encoded = NULL; -+ size_t encoded_len = 0; -+ -+ nxt = ptr->next; -+ if (bytes_consumed) { -+ *bytes_consumed += ptr->buflen; -+ } -+ -+ if (ptr->buflen) { -+ http_encoding_deflate_stream_update(buffer, ptr->buf, ptr->buflen, &encoded, &encoded_len); -+ if (encoded) { -+ if (encoded_len) { -+ out_avail = 1; -+ NEW_BUCKET(encoded, encoded_len); -+ } -+ efree(encoded); -+ } -+ } -+ -+ php_stream_bucket_unlink(ptr TSRMLS_CC); -+ php_stream_bucket_delref(ptr TSRMLS_CC); -+ } -+ } -+ -+ /* flush & close */ -+ if (flags & PSFS_FLAG_FLUSH_INC) { -+ char *encoded = NULL; -+ size_t encoded_len = 0; -+ -+ http_encoding_deflate_stream_flush(buffer, &encoded, &encoded_len); -+ if (encoded) { -+ if (encoded_len) { -+ out_avail = 1; -+ NEW_BUCKET(encoded, encoded_len); -+ } -+ efree(encoded); -+ } -+ } -+ -+ if (flags & PSFS_FLAG_FLUSH_CLOSE) { -+ char *encoded = NULL; -+ size_t encoded_len = 0; -+ -+ http_encoding_deflate_stream_finish(buffer, &encoded, &encoded_len); -+ if (encoded) { -+ if (encoded_len) { -+ out_avail = 1; -+ NEW_BUCKET(encoded, encoded_len); -+ } -+ efree(encoded); -+ } -+ } -+ -+ return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME; -+} -+ -+static HTTP_FILTER_FUNCTION(inflate) -+{ -+ int out_avail = 0; -+ php_stream_bucket *ptr, *nxt; -+ HTTP_FILTER_BUFFER(inflate) *buffer = (HTTP_FILTER_BUFFER(inflate) *) this->abstract; -+ -+ if (bytes_consumed) { -+ *bytes_consumed = 0; -+ } -+ -+ /* new data available? */ -+ if (buckets_in->head) { -+ -+ /* fetch available bucket data */ -+ for (ptr = buckets_in->head; ptr; ptr = nxt) { -+ char *decoded = NULL; -+ size_t decoded_len = 0; -+ -+ nxt = ptr->next; -+ if (bytes_consumed) { -+ *bytes_consumed += ptr->buflen; -+ } -+ -+ if (ptr->buflen) { -+ http_encoding_inflate_stream_update(buffer, ptr->buf, ptr->buflen, &decoded, &decoded_len); -+ if (decoded) { -+ if (decoded_len) { -+ out_avail = 1; -+ NEW_BUCKET(decoded, decoded_len); -+ } -+ efree(decoded); -+ } -+ } -+ -+ php_stream_bucket_unlink(ptr TSRMLS_CC); -+ php_stream_bucket_delref(ptr TSRMLS_CC); -+ } -+ } -+ -+ /* flush & close */ -+ if (flags & PSFS_FLAG_FLUSH_INC) { -+ char *decoded = NULL; -+ size_t decoded_len = 0; -+ -+ http_encoding_inflate_stream_flush(buffer, &decoded, &decoded_len); -+ if (decoded) { -+ if (decoded_len) { -+ out_avail = 1; -+ NEW_BUCKET(decoded, decoded_len); -+ } -+ efree(decoded); -+ } -+ } -+ -+ if (flags & PSFS_FLAG_FLUSH_CLOSE) { -+ char *decoded = NULL; -+ size_t decoded_len = 0; -+ -+ http_encoding_inflate_stream_finish(buffer, &decoded, &decoded_len); -+ if (decoded) { -+ if (decoded_len) { -+ out_avail = 1; -+ NEW_BUCKET(decoded, decoded_len); -+ } -+ efree(decoded); -+ } -+ } -+ -+ return out_avail ? PSFS_PASS_ON : PSFS_FEED_ME; -+} -+ -+static HTTP_FILTER_DESTRUCTOR(deflate) -+{ -+ HTTP_FILTER_BUFFER(deflate) *buffer = (HTTP_FILTER_BUFFER(deflate) *) this->abstract; -+ http_encoding_deflate_stream_free(&buffer); -+} -+ -+static HTTP_FILTER_DESTRUCTOR(inflate) -+{ -+ HTTP_FILTER_BUFFER(inflate) *buffer = (HTTP_FILTER_BUFFER(inflate) *) this->abstract; -+ http_encoding_inflate_stream_free(&buffer); -+} -+ -+static HTTP_FILTER_OPS(deflate) = { -+ HTTP_FILTER_FUNC(deflate), -+ HTTP_FILTER_DTOR(deflate), -+ "http.deflate" -+}; -+ -+static HTTP_FILTER_OPS(inflate) = { -+ HTTP_FILTER_FUNC(inflate), -+ HTTP_FILTER_DTOR(inflate), -+ "http.inflate" -+}; -+ -+#endif /* HTTP_HAVE_ZLIB */ -+ -+static php_stream_filter *http_filter_create(const char *name, zval *params, int p TSRMLS_DC) -+{ -+ zval **tmp = ¶ms; -+ php_stream_filter *f = NULL; -+ -+ if (!strcasecmp(name, "http.chunked_decode")) { -+ HTTP_FILTER_BUFFER(chunked_decode) *b = NULL; -+ -+ if ((b = pecalloc(1, sizeof(HTTP_FILTER_BUFFER(chunked_decode)), p))) { -+ phpstr_init_ex(PHPSTR(b), 4096, p ? PHPSTR_INIT_PERSISTENT : 0); -+ if (!(f = php_stream_filter_alloc(&HTTP_FILTER_OP(chunked_decode), b, p))) { -+ pefree(b, p); -+ } -+ } -+ } else -+ -+ if (!strcasecmp(name, "http.chunked_encode")) { -+ f = php_stream_filter_alloc(&HTTP_FILTER_OP(chunked_encode), NULL, p); -+#ifdef HTTP_HAVE_ZLIB -+ } else -+ -+ if (!strcasecmp(name, "http.inflate")) { -+ int flags = p ? HTTP_ENCODING_STREAM_PERSISTENT : 0; -+ HTTP_FILTER_BUFFER(inflate) *b = NULL; -+ -+ if ((b = http_encoding_inflate_stream_init(NULL, flags))) { -+ if (!(f = php_stream_filter_alloc(&HTTP_FILTER_OP(inflate), b, p))) { -+ http_encoding_inflate_stream_free(&b); -+ } -+ } -+ } else -+ -+ if (!strcasecmp(name, "http.deflate")) { -+ int flags = p ? HTTP_ENCODING_STREAM_PERSISTENT : 0; -+ HTTP_FILTER_BUFFER(deflate) *b = NULL; -+ -+ if (params) { -+ switch (Z_TYPE_P(params)) { -+ case IS_ARRAY: -+ case IS_OBJECT: -+ if (SUCCESS != zend_hash_find(HASH_OF(params), "flags", sizeof("flags"), (void *) &tmp)) { -+ break; -+ } -+ default: -+ { -+ zval *num = http_zsep(IS_LONG, *tmp); -+ -+ flags |= (Z_LVAL_P(num) & 0x0fffffff); -+ zval_ptr_dtor(&num); -+ } -+ } -+ } -+ if ((b = http_encoding_deflate_stream_init(NULL, flags))) { -+ if (!(f = php_stream_filter_alloc(&HTTP_FILTER_OP(deflate), b, p))) { -+ http_encoding_deflate_stream_free(&b); -+ } -+ } -+#endif /* HTTP_HAVE_ZLIB */ -+ } -+ -+ return f; -+} -+ -+php_stream_filter_factory http_filter_factory = { -+ http_filter_create -+}; -+ -+#endif /* ZEND_ENGINE_2 */ -+ -+/* -+ * 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 -+ */ ---- /dev/null -+++ b/ext/http/http_functions.c -@@ -0,0 +1,1424 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_functions.c 300301 2010-06-09 08:30:34Z mike $ */ -+ -+#define HTTP_WANT_SAPI -+#define HTTP_WANT_CURL -+#define HTTP_WANT_ZLIB -+#include "php_http.h" -+ -+#include "php_ini.h" -+#include "ext/standard/php_string.h" -+#include "zend_operators.h" -+ -+#ifdef HTTP_HAVE_SESSION -+# include "ext/session/php_session.h" -+#endif -+ -+#include "php_http_api.h" -+#include "php_http_cache_api.h" -+#include "php_http_cookie_api.h" -+#include "php_http_date_api.h" -+#include "php_http_encoding_api.h" -+#include "php_http_headers_api.h" -+#include "php_http_message_api.h" -+#include "php_http_request_api.h" -+#include "php_http_request_method_api.h" -+#include "php_http_persistent_handle_api.h" -+#include "php_http_send_api.h" -+#include "php_http_url_api.h" -+ -+/* {{{ proto string http_date([int timestamp]) -+ Compose a valid HTTP date regarding RFC 1123 looking like: "Wed, 22 Dec 2004 11:34:47 GMT" */ -+PHP_FUNCTION(http_date) -+{ -+ long t = -1; -+ char *date; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ if (t == -1) { -+ t = HTTP_G->request.time; -+ } -+ -+ if (!(date = http_date(t))) { -+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Could not compose date of timestamp %ld", t); -+ RETURN_FALSE; -+ } -+ -+ RETURN_STRING(date, 0); -+} -+/* }}} */ -+ -+/* {{{ proto string http_build_url([mixed url[, mixed parts[, int flags = HTTP_URL_REPLACE|HTTP_URL_FROM_ENV[, array &new_url]]]]) -+ Build an URL. */ -+PHP_FUNCTION(http_build_url) -+{ -+ char *url_str = NULL; -+ size_t url_len = 0; -+ long flags = HTTP_URL_REPLACE|HTTP_URL_FROM_ENV; -+ zval *z_old_url = NULL, *z_new_url = NULL, *z_composed_url = NULL; -+ php_url *old_url = NULL, *new_url = NULL, *composed_url = NULL; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z!/z!/lz", &z_old_url, &z_new_url, &flags, &z_composed_url) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ if (z_new_url) { -+ if (Z_TYPE_P(z_new_url) == IS_ARRAY || Z_TYPE_P(z_new_url) == IS_OBJECT) { -+ new_url = http_url_from_struct(NULL, HASH_OF(z_new_url)); -+ } else { -+ convert_to_string(z_new_url); -+ if (!(new_url = php_url_parse_ex(Z_STRVAL_P(z_new_url), Z_STRLEN_P(z_new_url)))) { -+ http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", Z_STRVAL_P(z_new_url)); -+ RETURN_FALSE; -+ } -+ } -+ } -+ -+ if (z_old_url) { -+ if (Z_TYPE_P(z_old_url) == IS_ARRAY || Z_TYPE_P(z_old_url) == IS_OBJECT) { -+ old_url = http_url_from_struct(NULL, HASH_OF(z_old_url)); -+ } else { -+ convert_to_string(z_old_url); -+ if (!(old_url = php_url_parse_ex(Z_STRVAL_P(z_old_url), Z_STRLEN_P(z_old_url)))) { -+ if (new_url) { -+ php_url_free(new_url); -+ } -+ http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", Z_STRVAL_P(z_old_url)); -+ RETURN_FALSE; -+ } -+ } -+ } -+ -+ if (z_composed_url) { -+ http_build_url(flags, old_url, new_url, &composed_url, &url_str, &url_len); -+ http_url_tostruct(composed_url, z_composed_url); -+ php_url_free(composed_url); -+ } else { -+ http_build_url(flags, old_url, new_url, NULL, &url_str, &url_len); -+ } -+ -+ if (new_url) { -+ php_url_free(new_url); -+ } -+ if (old_url) { -+ php_url_free(old_url); -+ } -+ -+ RETURN_STRINGL(url_str, url_len, 0); -+} -+/* }}} */ -+ -+/* {{{ proto string http_build_str(array query [, string prefix[, string arg_separator]]) -+ Opponent to parse_str(). */ -+PHP_FUNCTION(http_build_str) -+{ -+ zval *formdata; -+ char *prefix = NULL, *arg_sep = INI_STR("arg_separator.output"); -+ int prefix_len = 0, arg_sep_len = strlen(arg_sep); -+ phpstr formstr; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|ss", &formdata, &prefix, &prefix_len, &arg_sep, &arg_sep_len) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ if (!arg_sep_len) { -+ arg_sep = HTTP_URL_ARGSEP; -+ arg_sep_len = lenof(HTTP_URL_ARGSEP); -+ } -+ -+ phpstr_init(&formstr); -+ if (SUCCESS != http_urlencode_hash_recursive(HASH_OF(formdata), &formstr, arg_sep, arg_sep_len, prefix, prefix_len)) { -+ RETURN_FALSE; -+ } -+ -+ if (!formstr.used) { -+ phpstr_dtor(&formstr); -+ RETURN_NULL(); -+ } -+ -+ RETURN_PHPSTR_VAL(&formstr); -+} -+/* }}} */ -+ -+#define HTTP_DO_NEGOTIATE_DEFAULT(supported) \ -+ { \ -+ zval **value; \ -+ \ -+ zend_hash_internal_pointer_reset(Z_ARRVAL_P(supported)); \ -+ if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(supported), (void *) &value)) { \ -+ RETVAL_ZVAL(*value, 1, 0); \ -+ } else { \ -+ RETVAL_NULL(); \ -+ } \ -+ } -+ -+#define HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array) \ -+ HTTP_DO_NEGOTIATE_DEFAULT(supported); \ -+ if (rs_array) { \ -+ HashPosition pos; \ -+ zval **value_ptr; \ -+ \ -+ FOREACH_VAL(pos, supported, value_ptr) { \ -+ zval *value = http_zsep(IS_STRING, *value_ptr); \ -+ add_assoc_double(rs_array, Z_STRVAL_P(value), 1.0); \ -+ zval_ptr_dtor(&value); \ -+ } \ -+ } -+ -+#define HTTP_DO_NEGOTIATE_HANDLE_RESULT(result, supported, rs_array) \ -+ { \ -+ char *key; \ -+ uint key_len; \ -+ ulong idx; \ -+ \ -+ if (zend_hash_num_elements(result) && HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(result, &key, &key_len, &idx, 1, NULL)) { \ -+ RETVAL_STRINGL(key, key_len-1, 0); \ -+ } else { \ -+ HTTP_DO_NEGOTIATE_DEFAULT(supported); \ -+ } \ -+ \ -+ if (rs_array) { \ -+ zend_hash_copy(Z_ARRVAL_P(rs_array), result, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); \ -+ } \ -+ \ -+ zend_hash_destroy(result); \ -+ FREE_HASHTABLE(result); \ -+ } -+ -+#define HTTP_DO_NEGOTIATE(type, supported, rs_array) \ -+ { \ -+ HashTable *result; \ -+ if ((result = http_negotiate_ ##type(supported))) { \ -+ HTTP_DO_NEGOTIATE_HANDLE_RESULT(result, supported, rs_array); \ -+ } else { \ -+ HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array); \ -+ } \ -+ } -+ -+/* {{{ proto string http_negotiate_language(array supported[, array &result]) -+ Negotiate the clients preferred language. */ -+PHP_FUNCTION(http_negotiate_language) -+{ -+ zval *supported, *rs_array = NULL; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ if (rs_array) { -+ zval_dtor(rs_array); -+ array_init(rs_array); -+ } -+ -+ HTTP_DO_NEGOTIATE(language, supported, rs_array); -+} -+/* }}} */ -+ -+/* {{{ proto string http_negotiate_charset(array supported[, array &result]) -+ Negotiate the clients preferred charset. */ -+PHP_FUNCTION(http_negotiate_charset) -+{ -+ zval *supported, *rs_array = NULL; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ if (rs_array) { -+ zval_dtor(rs_array); -+ array_init(rs_array); -+ } -+ -+ HTTP_DO_NEGOTIATE(charset, supported, rs_array); -+} -+/* }}} */ -+ -+/* {{{ proto string http_negotiate_content_type(array supported[, array &result]) -+ Negotiate the clients preferred content type. */ -+PHP_FUNCTION(http_negotiate_content_type) -+{ -+ zval *supported, *rs_array = NULL; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &supported, &rs_array)) { -+ RETURN_FALSE; -+ } -+ -+ if (rs_array) { -+ zval_dtor(rs_array); -+ array_init(rs_array); -+ } -+ -+ HTTP_DO_NEGOTIATE(content_type, supported, rs_array); -+} -+/* }}} */ -+ -+/* {{{ proto string http_negotiate(mixed value, array supported[, array &result]) -+ Negotiate the user supplied value. */ -+PHP_FUNCTION(http_negotiate) -+{ -+ zval *value, *supported, *rs_array = NULL; -+ HashTable *rs; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za|z", &value, &supported, &rs_array)) { -+ RETURN_FALSE; -+ } -+ -+ if (rs_array) { -+ zval_dtor(rs_array); -+ array_init(rs_array); -+ } -+ -+ if ((rs = http_negotiate_z(value, Z_ARRVAL_P(supported), http_negotiate_default_func))) { -+ HTTP_DO_NEGOTIATE_HANDLE_RESULT(rs, supported, rs_array); -+ } else { -+ HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool http_send_status(int status) -+ Send HTTP status code. */ -+PHP_FUNCTION(http_send_status) -+{ -+ long status = 0; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ if (status < 100 || status > 510) { -+ http_error_ex(HE_WARNING, HTTP_E_HEADER, "Invalid HTTP status code (100-510): %d", status); -+ RETURN_FALSE; -+ } -+ -+ RETURN_SUCCESS(http_send_status(status)); -+} -+/* }}} */ -+ -+/* {{{ proto bool http_send_last_modified([int timestamp]) -+ Send a "Last-Modified" header with a valid HTTP date. */ -+PHP_FUNCTION(http_send_last_modified) -+{ -+ long t = -1; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ if (t == -1) { -+ t = HTTP_G->request.time; -+ } -+ -+ RETURN_SUCCESS(http_send_last_modified(t)); -+} -+/* }}} */ -+ -+/* {{{ proto bool http_send_content_type([string content_type = 'application/x-octetstream']) -+ Send the Content-Type of the sent entity. This is particularly important if you use the http_send() API. */ -+PHP_FUNCTION(http_send_content_type) -+{ -+ char *ct = "application/x-octetstream"; -+ int ct_len = lenof("application/x-octetstream"); -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ct, &ct_len) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ RETURN_SUCCESS(http_send_content_type(ct, ct_len)); -+} -+/* }}} */ -+ -+/* {{{ proto bool http_send_content_disposition(string filename[, bool inline = false]) -+ Send the Content-Disposition. */ -+PHP_FUNCTION(http_send_content_disposition) -+{ -+ char *filename; -+ int f_len; -+ zend_bool send_inline = 0; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &filename, &f_len, &send_inline) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ RETURN_SUCCESS(http_send_content_disposition(filename, f_len, send_inline)); -+} -+/* }}} */ -+ -+/* {{{ proto bool http_match_modified([int timestamp[, bool for_range = false]]) -+ Matches the given unix timestamp against the clients "If-Modified-Since" resp. "If-Unmodified-Since" HTTP headers. */ -+PHP_FUNCTION(http_match_modified) -+{ -+ long t = -1; -+ zend_bool for_range = 0; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &t, &for_range) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ // current time if not supplied (senseless though) -+ if (t == -1) { -+ t = HTTP_G->request.time; -+ } -+ -+ if (for_range) { -+ RETURN_BOOL(http_match_last_modified("HTTP_IF_UNMODIFIED_SINCE", t)); -+ } -+ RETURN_BOOL(http_match_last_modified("HTTP_IF_MODIFIED_SINCE", t)); -+} -+/* }}} */ -+ -+/* {{{ proto bool http_match_etag(string etag[, bool for_range = false]) -+ Matches the given ETag against the clients "If-Match" resp. "If-None-Match" HTTP headers. */ -+PHP_FUNCTION(http_match_etag) -+{ -+ int etag_len; -+ char *etag; -+ zend_bool for_range = 0; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &etag, &etag_len, &for_range) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ if (for_range) { -+ RETURN_BOOL(http_match_etag("HTTP_IF_MATCH", etag)); -+ } -+ RETURN_BOOL(http_match_etag("HTTP_IF_NONE_MATCH", etag)); -+} -+/* }}} */ -+ -+/* {{{ proto bool http_cache_last_modified([int timestamp_or_expires]]) -+ Attempts to cache the sent entity by its last modification date. */ -+PHP_FUNCTION(http_cache_last_modified) -+{ -+ long last_modified = 0, send_modified = 0, t; -+ zval *zlm; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &last_modified) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ HTTP_CHECK_HEADERS_SENT(RETURN_FALSE); -+ -+ t = HTTP_G->request.time; -+ -+ /* 0 or omitted */ -+ if (!last_modified) { -+ /* does the client have? (att: caching "forever") */ -+ if ((zlm = http_get_server_var("HTTP_IF_MODIFIED_SINCE", 1))) { -+ last_modified = send_modified = http_parse_date(Z_STRVAL_P(zlm)); -+ /* send current time */ -+ } else { -+ send_modified = t; -+ } -+ /* negative value is supposed to be expiration time */ -+ } else if (last_modified < 0) { -+ last_modified += t; -+ send_modified = t; -+ /* send supplied time explicitly */ -+ } else { -+ send_modified = last_modified; -+ } -+ -+ RETURN_SUCCESS(http_cache_last_modified(last_modified, send_modified, HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL))); -+} -+/* }}} */ -+ -+/* {{{ proto bool http_cache_etag([string etag]) -+ Attempts to cache the sent entity by its ETag, either supplied or generated by the hash algorithm specified by the INI setting "http.etag.mode". */ -+PHP_FUNCTION(http_cache_etag) -+{ -+ char *etag = NULL; -+ int etag_len = 0; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &etag, &etag_len) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ HTTP_CHECK_HEADERS_SENT(RETURN_FALSE); -+ -+ RETURN_SUCCESS(http_cache_etag(etag, etag_len, HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL))); -+} -+/* }}} */ -+ -+/* {{{ proto string ob_etaghandler(string data, int mode) -+ For use with ob_start(). Output buffer handler generating an ETag with the hash algorithm specified with the INI setting "http.etag.mode". */ -+PHP_FUNCTION(ob_etaghandler) -+{ -+ char *data; -+ int data_len; -+ long mode; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) { -+ RETURN_FALSE; -+ } -+ -+ Z_TYPE_P(return_value) = IS_STRING; -+ http_ob_etaghandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode); -+} -+/* }}} */ -+ -+/* {{{ proto void http_throttle(double sec[, int bytes = 40960]) -+ Sets the throttle delay and send buffer size for use with http_send() API. */ -+PHP_FUNCTION(http_throttle) -+{ -+ long chunk_size = HTTP_SENDBUF_SIZE; -+ double interval; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|l", &interval, &chunk_size)) { -+ return; -+ } -+ -+ HTTP_G->send.throttle_delay = interval; -+ HTTP_G->send.buffer_size = chunk_size; -+} -+/* }}} */ -+ -+/* {{{ proto void http_redirect([string url[, array params[, bool session = false[, int status = 302]]]]) -+ Redirect to the given url. */ -+PHP_FUNCTION(http_redirect) -+{ -+ int url_len = 0; -+ size_t query_len = 0; -+ zend_bool session = 0, free_params = 0; -+ zval *params = NULL; -+ long status = HTTP_REDIRECT; -+ char *query = NULL, *url = NULL, *URI, *LOC, *RED = NULL; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sa!/bl", &url, &url_len, ¶ms, &session, &status) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+#ifdef HTTP_HAVE_SESSION -+ /* append session info */ -+ if (session) { -+ if (!params) { -+ free_params = 1; -+ MAKE_STD_ZVAL(params); -+ array_init(params); -+ } -+ if (PS(session_status) == php_session_active) { -+ if (add_assoc_string(params, PS(session_name), PS(id), 1) != SUCCESS) { -+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Could not append session information"); -+ } -+ } -+ } -+#endif -+ -+ /* treat params array with http_build_query() */ -+ if (params) { -+ if (SUCCESS != http_urlencode_hash_ex(Z_ARRVAL_P(params), 0, NULL, 0, &query, &query_len)) { -+ if (free_params) { -+ zval_dtor(params); -+ FREE_ZVAL(params); -+ } -+ if (query) { -+ efree(query); -+ } -+ RETURN_FALSE; -+ } -+ } -+ -+ URI = http_absolute_url_ex(url, HTTP_URL_FROM_ENV); -+ -+ if (query_len) { -+ spprintf(&LOC, 0, "Location: %s?%s", URI, query); -+ if (status != 300) { -+ spprintf(&RED, 0, "Redirecting to %s?%s.\n", URI, query, URI, query); -+ } -+ } else { -+ spprintf(&LOC, 0, "Location: %s", URI); -+ if (status != 300) { -+ spprintf(&RED, 0, "Redirecting to %s.\n", URI, URI); -+ } -+ } -+ -+ efree(URI); -+ if (query) { -+ efree(query); -+ } -+ if (free_params) { -+ zval_dtor(params); -+ FREE_ZVAL(params); -+ } -+ -+ switch (status) { -+ case 300: -+ RETVAL_SUCCESS(http_send_status_header(status, LOC)); -+ efree(LOC); -+ return; -+ -+ case HTTP_REDIRECT_PERM: -+ case HTTP_REDIRECT_FOUND: -+ case HTTP_REDIRECT_POST: -+ case HTTP_REDIRECT_PROXY: -+ case HTTP_REDIRECT_TEMP: -+ break; -+ -+ case 306: -+ default: -+ http_error_ex(HE_NOTICE, HTTP_E_RUNTIME, "Unsupported redirection status code: %ld", status); -+ case HTTP_REDIRECT: -+ if ( SG(request_info).request_method && -+ strcasecmp(SG(request_info).request_method, "HEAD") && -+ strcasecmp(SG(request_info).request_method, "GET")) { -+ status = HTTP_REDIRECT_POST; -+ } else { -+ status = HTTP_REDIRECT_FOUND; -+ } -+ break; -+ } -+ -+ RETURN_SUCCESS(http_exit_ex(status, LOC, RED, 1)); -+} -+/* }}} */ -+ -+/* {{{ proto bool http_send_data(string data) -+ Sends raw data with support for (multiple) range requests. */ -+PHP_FUNCTION(http_send_data) -+{ -+ int data_len; -+ char *data_buf; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data_buf, &data_len) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ RETURN_SUCCESS(http_send_data(data_buf, data_len)); -+} -+/* }}} */ -+ -+/* {{{ proto bool http_send_file(string file) -+ Sends a file with support for (multiple) range requests. */ -+PHP_FUNCTION(http_send_file) -+{ -+ char *file; -+ int flen = 0; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &flen) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ if (!flen) { -+ RETURN_FALSE; -+ } -+ -+ RETURN_SUCCESS(http_send_file(file)); -+} -+/* }}} */ -+ -+/* {{{ proto bool http_send_stream(resource stream) -+ Sends an already opened stream with support for (multiple) range requests. */ -+PHP_FUNCTION(http_send_stream) -+{ -+ zval *zstream; -+ php_stream *file; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ php_stream_from_zval(file, &zstream); -+ RETURN_SUCCESS(http_send_stream(file)); -+} -+/* }}} */ -+ -+/* {{{ proto string http_chunked_decode(string encoded) -+ Decodes a string that was HTTP-chunked encoded. */ -+PHP_FUNCTION(http_chunked_decode) -+{ -+ char *encoded = NULL, *decoded = NULL; -+ size_t decoded_len = 0; -+ int encoded_len = 0; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &encoded, &encoded_len) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ if (NULL != http_encoding_dechunk(encoded, encoded_len, &decoded, &decoded_len)) { -+ RETURN_STRINGL(decoded, (int) decoded_len, 0); -+ } else { -+ RETURN_FALSE; -+ } -+} -+/* }}} */ -+ -+/* {{{ proto object http_parse_message(string message) -+ Parses (a) http_message(s) into a simple recursive object structure. */ -+PHP_FUNCTION(http_parse_message) -+{ -+ char *message; -+ int message_len; -+ http_message *msg = NULL; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &message, &message_len)) { -+ RETURN_NULL(); -+ } -+ -+ if ((msg = http_message_parse(message, message_len))) { -+ object_init(return_value); -+ http_message_tostruct_recursive(msg, return_value); -+ http_message_free(&msg); -+ } else { -+ RETURN_NULL(); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto array http_parse_headers(string header) -+ Parses HTTP headers into an associative array. */ -+PHP_FUNCTION(http_parse_headers) -+{ -+ char *header; -+ int header_len; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &header, &header_len)) { -+ RETURN_FALSE; -+ } -+ -+ array_init(return_value); -+ if (SUCCESS != http_parse_headers(header, return_value)) { -+ zval_dtor(return_value); -+ http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Failed to parse headers"); -+ RETURN_FALSE; -+ } -+} -+/* }}}*/ -+ -+/* {{{ proto object http_parse_cookie(string cookie[, int flags[, array allowed_extras]]) -+ Parses HTTP cookies like sent in a response into a struct. */ -+PHP_FUNCTION(http_parse_cookie) -+{ -+ char *cookie, **allowed_extras = NULL; -+ int i = 0, cookie_len; -+ long flags = 0; -+ zval *allowed_extras_array = NULL, **entry = NULL; -+ HashPosition pos; -+ http_cookie_list list; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|la!", &cookie, &cookie_len, &flags, &allowed_extras_array)) { -+ RETURN_FALSE; -+ } -+ -+ if (allowed_extras_array) { -+ allowed_extras = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(allowed_extras_array)) + 1, sizeof(char *)); -+ FOREACH_VAL(pos, allowed_extras_array, entry) { -+ zval *data = http_zsep(IS_STRING, *entry); -+ allowed_extras[i++] = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data)); -+ zval_ptr_dtor(&data); -+ } -+ } -+ -+ if (http_parse_cookie_ex(&list, cookie, flags, allowed_extras)) { -+ object_init(return_value); -+ http_cookie_list_tostruct(&list, return_value); -+ http_cookie_list_dtor(&list); -+ } else { -+ RETVAL_FALSE; -+ } -+ -+ if (allowed_extras) { -+ for (i = 0; allowed_extras[i]; ++i) { -+ efree(allowed_extras[i]); -+ } -+ efree(allowed_extras); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string http_build_cookie(array cookie) -+ Build a cookie string from an array/object like returned by http_parse_cookie(). */ -+PHP_FUNCTION(http_build_cookie) -+{ -+ char *str = NULL; -+ size_t len = 0; -+ zval *strct; -+ http_cookie_list list; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &strct)) { -+ RETURN_FALSE; -+ } -+ -+ http_cookie_list_fromstruct(&list, strct); -+ http_cookie_list_tostring(&list, &str, &len); -+ http_cookie_list_dtor(&list); -+ -+ RETURN_STRINGL(str, len, 0); -+} -+/* }}} */ -+ -+/* {{{ proto object http_parse_params(string param[, int flags = HTTP_PARAMS_DEFAULT]) -+ Parse parameter list. */ -+PHP_FUNCTION(http_parse_params) -+{ -+ char *param; -+ int param_len; -+ zval *params; -+ long flags = HTTP_PARAMS_DEFAULT; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", ¶m, ¶m_len, &flags)) { -+ RETURN_FALSE; -+ } -+ -+ MAKE_STD_ZVAL(params); -+ array_init(params); -+ if (SUCCESS != http_parse_params(param, flags, Z_ARRVAL_P(params))) { -+ zval_ptr_dtor(¶ms); -+ RETURN_FALSE; -+ } -+ -+ object_init(return_value); -+ add_property_zval(return_value, "params", params); -+#ifdef ZEND_ENGINE_2 -+ zval_ptr_dtor(¶ms); -+#endif -+} -+/* }}} */ -+ -+/* {{{ proto array http_get_request_headers(void) -+ Get a list of incoming HTTP headers. */ -+PHP_FUNCTION(http_get_request_headers) -+{ -+ NO_ARGS; -+ -+ array_init(return_value); -+ http_get_request_headers(Z_ARRVAL_P(return_value)); -+} -+/* }}} */ -+ -+/* {{{ proto string http_get_request_body(void) -+ Get the raw request body (e.g. POST or PUT data). */ -+PHP_FUNCTION(http_get_request_body) -+{ -+ char *body; -+ size_t length; -+ -+ NO_ARGS; -+ -+ if (SUCCESS == http_get_request_body(&body, &length)) { -+ RETURN_STRINGL(body, (int) length, 0); -+ } else { -+ RETURN_NULL(); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto resource http_get_request_body_stream(void) -+ Create a stream to read the raw request body (e.g. POST or PUT data). This function can only be used once if the request method was another than POST. */ -+PHP_FUNCTION(http_get_request_body_stream) -+{ -+ php_stream *s; -+ -+ NO_ARGS; -+ -+ if ((s = http_get_request_body_stream())) { -+ php_stream_to_zval(s, return_value); -+ } else { -+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Failed to create request body stream"); -+ RETURN_NULL(); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool http_match_request_header(string header, string value[, bool match_case = false]) -+ Match an incoming HTTP header. */ -+PHP_FUNCTION(http_match_request_header) -+{ -+ char *header, *value; -+ int header_len, value_len; -+ zend_bool match_case = 0; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &header, &header_len, &value, &value_len, &match_case)) { -+ RETURN_FALSE; -+ } -+ -+ RETURN_BOOL(http_match_request_header_ex(header, value, match_case)); -+} -+/* }}} */ -+ -+/* {{{ proto object http_persistent_handles_count() */ -+PHP_FUNCTION(http_persistent_handles_count) -+{ -+ NO_ARGS; -+ object_init(return_value); -+ if (!http_persistent_handle_statall_ex(HASH_OF(return_value))) { -+ zval_dtor(return_value); -+ RETURN_NULL(); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto void http_persistent_handles_clean([string name]) */ -+PHP_FUNCTION(http_persistent_handles_clean) -+{ -+ char *name_str = NULL; -+ int name_len = 0; -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name_str, &name_len)) { -+ http_persistent_handle_cleanup_ex(name_str, name_len, 1); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string http_persistent_handles_ident([string ident]) */ -+PHP_FUNCTION(http_persistent_handles_ident) -+{ -+ char *ident_str = NULL; -+ int ident_len = 0; -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ident_str, &ident_len)) { -+ RETVAL_STRING(zend_ini_string(ZEND_STRS("http.persistent.handles.ident"), 0), 1); -+ if (ident_str && ident_len) { -+ zend_alter_ini_entry(ZEND_STRS("http.persistent.handles.ident"), ident_str, ident_len, ZEND_INI_USER, PHP_INI_STAGE_RUNTIME); -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ HAVE_CURL */ -+#ifdef HTTP_HAVE_CURL -+ -+#define RETVAL_RESPONSE_OR_BODY(request) \ -+ { \ -+ zval **bodyonly; \ -+ \ -+ /* check if only the body should be returned */ \ -+ if (options && (SUCCESS == zend_hash_find(Z_ARRVAL_P(options), "bodyonly", sizeof("bodyonly"), (void *) &bodyonly)) && i_zend_is_true(*bodyonly)) { \ -+ http_message *msg = http_message_parse(PHPSTR_VAL(&request.conv.response), PHPSTR_LEN(&request.conv.response)); \ -+ \ -+ if (msg) { \ -+ RETVAL_STRINGL(PHPSTR_VAL(&msg->body), PHPSTR_LEN(&msg->body), 1); \ -+ http_message_free(&msg); \ -+ } \ -+ } else { \ -+ RETVAL_STRINGL(request.conv.response.data, request.conv.response.used, 1); \ -+ } \ -+ } -+ -+/* {{{ proto string http_get(string url[, array options[, array &info]]) -+ Performs an HTTP GET request on the supplied url. */ -+PHP_FUNCTION(http_get) -+{ -+ zval *options = NULL, *info = NULL; -+ char *URL; -+ int URL_len; -+ http_request request; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ if (info) { -+ zval_dtor(info); -+ array_init(info); -+ } -+ -+ RETVAL_FALSE; -+ -+ http_request_init_ex(&request, NULL, HTTP_GET, URL); -+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) { -+ http_request_exec(&request); -+ if (info) { -+ http_request_info(&request, Z_ARRVAL_P(info)); -+ } -+ RETVAL_RESPONSE_OR_BODY(request); -+ } -+ http_request_dtor(&request); -+} -+/* }}} */ -+ -+/* {{{ proto string http_head(string url[, array options[, array &info]]) -+ Performs an HTTP HEAD request on the supplied url. */ -+PHP_FUNCTION(http_head) -+{ -+ zval *options = NULL, *info = NULL; -+ char *URL; -+ int URL_len; -+ http_request request; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ if (info) { -+ zval_dtor(info); -+ array_init(info); -+ } -+ -+ RETVAL_FALSE; -+ -+ http_request_init_ex(&request, NULL, HTTP_HEAD, URL); -+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) { -+ http_request_exec(&request); -+ if (info) { -+ http_request_info(&request, Z_ARRVAL_P(info)); -+ } -+ RETVAL_RESPONSE_OR_BODY(request); -+ } -+ http_request_dtor(&request); -+} -+/* }}} */ -+ -+/* {{{ proto string http_post_data(string url, string data[, array options[, array &info]]) -+ Performs an HTTP POST request on the supplied url. */ -+PHP_FUNCTION(http_post_data) -+{ -+ zval *options = NULL, *info = NULL; -+ char *URL, *postdata; -+ int postdata_len, URL_len; -+ http_request_body body; -+ http_request request; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &postdata, &postdata_len, &options, &info) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ if (info) { -+ zval_dtor(info); -+ array_init(info); -+ } -+ -+ RETVAL_FALSE; -+ -+ http_request_init_ex(&request, NULL, HTTP_POST, URL); -+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, postdata, postdata_len, 0); -+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) { -+ http_request_exec(&request); -+ if (info) { -+ http_request_info(&request, Z_ARRVAL_P(info)); -+ } -+ RETVAL_RESPONSE_OR_BODY(request); -+ } -+ http_request_dtor(&request); -+} -+/* }}} */ -+ -+/* {{{ proto string http_post_fields(string url, array data[, array files[, array options[, array &info]]]) -+ Performs an HTTP POST request on the supplied url. */ -+PHP_FUNCTION(http_post_fields) -+{ -+ zval *options = NULL, *info = NULL, *fields = NULL, *files = NULL; -+ char *URL; -+ int URL_len; -+ http_request_body body; -+ http_request request; -+ -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa!|a!a/!z", &URL, &URL_len, &fields, &files, &options, &info) != SUCCESS) { -+ RETURN_FALSE; -+ } -+ -+ if (!http_request_body_fill(&body, fields ? Z_ARRVAL_P(fields) : NULL, files ? Z_ARRVAL_P(files) : NULL)) { -+ RETURN_FALSE; -+ } -+ -+ if (info) { -+ zval_dtor(info); -+ array_init(info); -+ } -+ -+ RETVAL_FALSE; -+ -+ http_request_init_ex(&request, NULL, HTTP_POST, URL); -+ request.body = &body; -+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) { -+ http_request_exec(&request); -+ if (info) { -+ http_request_info(&request, Z_ARRVAL_P(info)); -+ } -+ RETVAL_RESPONSE_OR_BODY(request); -+ } -+ http_request_dtor(&request); -+} -+/* }}} */ -+ -+/* {{{ proto string http_put_file(string url, string file[, array options[, array &info]]) -+ Performs an HTTP PUT request on the supplied url. */ -+PHP_FUNCTION(http_put_file) -+{ -+ char *URL, *file; -+ int URL_len, f_len; -+ zval *options = NULL, *info = NULL; -+ php_stream *stream; -+ php_stream_statbuf ssb; -+ http_request_body body; -+ http_request request; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &file, &f_len, &options, &info)) { -+ RETURN_FALSE; -+ } -+ -+ if (!(stream = php_stream_open_wrapper_ex(file, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT))) { -+ RETURN_FALSE; -+ } -+ if (php_stream_stat(stream, &ssb)) { -+ php_stream_close(stream); -+ RETURN_FALSE; -+ } -+ -+ if (info) { -+ zval_dtor(info); -+ array_init(info); -+ } -+ -+ RETVAL_FALSE; -+ -+ http_request_init_ex(&request, NULL, HTTP_PUT, URL); -+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 1); -+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) { -+ http_request_exec(&request); -+ if (info) { -+ http_request_info(&request, Z_ARRVAL_P(info)); -+ } -+ RETVAL_RESPONSE_OR_BODY(request); -+ } -+ http_request_dtor(&request); -+} -+/* }}} */ -+ -+/* {{{ proto string http_put_stream(string url, resource stream[, array options[, array &info]]) -+ Performs an HTTP PUT request on the supplied url. */ -+PHP_FUNCTION(http_put_stream) -+{ -+ zval *resource, *options = NULL, *info = NULL; -+ char *URL; -+ int URL_len; -+ php_stream *stream; -+ php_stream_statbuf ssb; -+ http_request_body body; -+ http_request request; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sr|a/!z", &URL, &URL_len, &resource, &options, &info)) { -+ RETURN_FALSE; -+ } -+ -+ php_stream_from_zval(stream, &resource); -+ if (php_stream_stat(stream, &ssb)) { -+ RETURN_FALSE; -+ } -+ -+ if (info) { -+ zval_dtor(info); -+ array_init(info); -+ } -+ -+ RETVAL_FALSE; -+ -+ http_request_init_ex(&request, NULL, HTTP_PUT, URL); -+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 0); -+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) { -+ http_request_exec(&request); -+ if (info) { -+ http_request_info(&request, Z_ARRVAL_P(info)); -+ } -+ RETVAL_RESPONSE_OR_BODY(request); -+ } -+ http_request_dtor(&request); -+} -+/* }}} */ -+ -+/* {{{ proto string http_put_data(string url, string data[, array options[, array &info]]) -+ Performs an HTTP PUT request on the supplied url. */ -+PHP_FUNCTION(http_put_data) -+{ -+ char *URL, *data; -+ int URL_len, data_len; -+ zval *options = NULL, *info = NULL; -+ http_request_body body; -+ http_request request; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &data, &data_len, &options, &info)) { -+ RETURN_FALSE; -+ } -+ -+ if (info) { -+ zval_dtor(info); -+ array_init(info); -+ } -+ -+ RETVAL_FALSE; -+ -+ http_request_init_ex(&request, NULL, HTTP_PUT, URL); -+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, data, data_len, 0); -+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) { -+ http_request_exec(&request); -+ if (info) { -+ http_request_info(&request, Z_ARRVAL_P(info)); -+ } -+ RETVAL_RESPONSE_OR_BODY(request); -+ } -+ http_request_dtor(&request); -+} -+/* }}} */ -+ -+/* {{{ proto string http_request(int method, string url[, string body[, array options[, array &info]]]) -+ Performs a custom HTTP request on the supplied url. */ -+PHP_FUNCTION(http_request) -+{ -+ long meth; -+ char *URL, *data = NULL; -+ int URL_len, data_len = 0; -+ zval *options = NULL, *info = NULL; -+ http_request_body body; -+ http_request request; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls|sa/!z", &meth, &URL, &URL_len, &data, &data_len, &options, &info)) { -+ RETURN_FALSE; -+ } -+ -+ if (info) { -+ zval_dtor(info); -+ array_init(info); -+ } -+ -+ RETVAL_FALSE; -+ -+ http_request_init_ex(&request, NULL, meth, URL); -+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, data, data_len, 0); -+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) { -+ http_request_exec(&request); -+ if (info) { -+ http_request_info(&request, Z_ARRVAL_P(info)); -+ } -+ RETVAL_RESPONSE_OR_BODY(request); -+ } -+ http_request_dtor(&request); -+} -+/* }}} */ -+ -+/* {{{ proto string http_request_body_encode(array fields, array files) -+ Generate x-www-form-urlencoded resp. form-data encoded request body. */ -+PHP_FUNCTION(http_request_body_encode) -+{ -+ zval *fields = NULL, *files = NULL; -+ HashTable *fields_ht, *files_ht; -+ http_request_body body; -+ char *buf; -+ size_t len; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!", &fields, &files)) { -+ RETURN_FALSE; -+ } -+ -+ fields_ht = (fields && Z_TYPE_P(fields) == IS_ARRAY) ? Z_ARRVAL_P(fields) : NULL; -+ files_ht = (files && Z_TYPE_P(files) == IS_ARRAY) ? Z_ARRVAL_P(files) : NULL; -+ if (http_request_body_fill(&body, fields_ht, files_ht) && (SUCCESS == http_request_body_encode(&body, &buf, &len))) { -+ RETVAL_STRINGL(buf, len, 0); -+ } else { -+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Could not encode request body"); -+ RETVAL_FALSE; -+ } -+ http_request_body_dtor(&body); -+} -+#endif /* HTTP_HAVE_CURL */ -+/* }}} HAVE_CURL */ -+ -+/* {{{ proto int http_request_method_register(string method) -+ Register a custom request method. */ -+PHP_FUNCTION(http_request_method_register) -+{ -+ char *method; -+ int method_len; -+ ulong existing; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) { -+ RETURN_FALSE; -+ } -+ if ((existing = http_request_method_exists(1, 0, method))) { -+ RETURN_LONG((long) existing); -+ } -+ -+ RETVAL_LONG((long) http_request_method_register(method, method_len)); -+} -+/* }}} */ -+ -+/* {{{ proto bool http_request_method_unregister(mixed method) -+ Unregister a previously registered custom request method. */ -+PHP_FUNCTION(http_request_method_unregister) -+{ -+ zval *method; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &method)) { -+ RETURN_FALSE; -+ } -+ -+ switch (Z_TYPE_P(method)) { -+ case IS_OBJECT: -+ convert_to_string(method); -+ case IS_STRING: -+ if (is_numeric_string(Z_STRVAL_P(method), Z_STRLEN_P(method), NULL, NULL, 1)) { -+ convert_to_long(method); -+ } else { -+ int mn; -+ if (!(mn = http_request_method_exists(1, 0, Z_STRVAL_P(method)))) { -+ RETURN_FALSE; -+ } -+ zval_dtor(method); -+ ZVAL_LONG(method, (long)mn); -+ } -+ case IS_LONG: -+ RETURN_SUCCESS(http_request_method_unregister(Z_LVAL_P(method))); -+ default: -+ RETURN_FALSE; -+ } -+} -+/* }}} */ -+ -+/* {{{ proto int http_request_method_exists(mixed method) -+ Check if a request method is registered (or available by default). */ -+PHP_FUNCTION(http_request_method_exists) -+{ -+ if (return_value_used) { -+ zval *method; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &method)) { -+ RETURN_FALSE; -+ } -+ -+ switch (Z_TYPE_P(method)) { -+ case IS_OBJECT: -+ convert_to_string(method); -+ case IS_STRING: -+ if (is_numeric_string(Z_STRVAL_P(method), Z_STRLEN_P(method), NULL, NULL, 1)) { -+ convert_to_long(method); -+ } else { -+ RETURN_LONG((long) http_request_method_exists(1, 0, Z_STRVAL_P(method))); -+ } -+ case IS_LONG: -+ RETURN_LONG((long) http_request_method_exists(0, (int) Z_LVAL_P(method), NULL)); -+ default: -+ RETURN_FALSE; -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string http_request_method_name(int method) -+ Get the literal string representation of a standard or registered request method. */ -+PHP_FUNCTION(http_request_method_name) -+{ -+ if (return_value_used) { -+ long method; -+ -+ if ((SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method)) || (method < 0)) { -+ RETURN_FALSE; -+ } -+ -+ RETURN_STRING(estrdup(http_request_method_name((int) method)), 0); -+ } -+} -+/* }}} */ -+ -+/* {{{ */ -+#ifdef HTTP_HAVE_ZLIB -+ -+/* {{{ proto string http_deflate(string data[, int flags = 0]) -+ Compress data with gzip, zlib AKA deflate or raw deflate encoding. */ -+PHP_FUNCTION(http_deflate) -+{ -+ char *data; -+ int data_len; -+ long flags = 0; -+ -+ RETVAL_NULL(); -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &flags)) { -+ char *encoded; -+ size_t encoded_len; -+ -+ if (SUCCESS == http_encoding_deflate(flags, data, data_len, &encoded, &encoded_len)) { -+ RETURN_STRINGL(encoded, (int) encoded_len, 0); -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string http_inflate(string data) -+ Decompress data compressed with either gzip, deflate AKA zlib or raw deflate encoding. */ -+PHP_FUNCTION(http_inflate) -+{ -+ char *data; -+ int data_len; -+ -+ RETVAL_NULL(); -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) { -+ char *decoded; -+ size_t decoded_len; -+ -+ if (SUCCESS == http_encoding_inflate(data, data_len, &decoded, &decoded_len)) { -+ RETURN_STRINGL(decoded, (int) decoded_len, 0); -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string ob_deflatehandler(string data, int mode) -+ For use with ob_start(). The deflate output buffer handler can only be used once. */ -+PHP_FUNCTION(ob_deflatehandler) -+{ -+ char *data; -+ int data_len; -+ long mode; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) { -+ RETURN_FALSE; -+ } -+ -+ http_ob_deflatehandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode); -+ Z_TYPE_P(return_value) = Z_STRVAL_P(return_value) ? IS_STRING : IS_NULL; -+} -+/* }}} */ -+ -+/* {{{ proto string ob_inflatehandler(string data, int mode) -+ For use with ob_start(). Same restrictions as with ob_deflatehandler apply. */ -+PHP_FUNCTION(ob_inflatehandler) -+{ -+ char *data; -+ int data_len; -+ long mode; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) { -+ RETURN_FALSE; -+ } -+ -+ http_ob_inflatehandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode); -+ Z_TYPE_P(return_value) = Z_STRVAL_P(return_value) ? IS_STRING : IS_NULL; -+} -+/* }}} */ -+ -+#endif /* HTTP_HAVE_ZLIB */ -+/* }}} */ -+ -+/* {{{ proto int http_support([int feature = 0]) -+ Check for feature that require external libraries. */ -+PHP_FUNCTION(http_support) -+{ -+ long feature = 0; -+ -+ RETVAL_LONG(0L); -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &feature)) { -+ RETVAL_LONG(http_support(feature)); -+ } -+} -+/* }}} */ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_headers_api.c -@@ -0,0 +1,534 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_headers_api.c 300300 2010-06-09 07:29:35Z mike $ */ -+ -+#define HTTP_WANT_SAPI -+#include "php_http.h" -+ -+#include "ext/standard/url.h" -+#include "ext/standard/php_string.h" -+ -+#include "php_http_api.h" -+#include "php_http_headers_api.h" -+ -+#ifndef HTTP_DBG_NEG -+# define HTTP_DBG_NEG 0 -+#endif -+ -+/* {{{ static void http_grab_response_headers(void *, void *) */ -+static void http_grab_response_headers(void *data, void *arg TSRMLS_DC) -+{ -+ phpstr_appendl(PHPSTR(arg), ((sapi_header_struct *)data)->header); -+ phpstr_appends(PHPSTR(arg), HTTP_CRLF); -+} -+/* }}} */ -+ -+/* {{{ static int http_sort_q(const void *, const void *) */ -+static int http_sort_q(const void *a, const void *b TSRMLS_DC) -+{ -+ Bucket *f, *s; -+ zval result, *first, *second; -+ -+ f = *((Bucket **) a); -+ s = *((Bucket **) b); -+ -+ first = *((zval **) f->pData); -+ second= *((zval **) s->pData); -+ -+ if (numeric_compare_function(&result, first, second TSRMLS_CC) != SUCCESS) { -+ return 0; -+ } -+ return (Z_LVAL(result) > 0 ? -1 : (Z_LVAL(result) < 0 ? 1 : 0)); -+} -+/* }}} */ -+ -+/* {{{ char *http_negotiate_language_func */ -+char *_http_negotiate_language_func(const char *test, double *quality, HashTable *supported TSRMLS_DC) -+{ -+ zval **value; -+ HashPosition pos; -+ const char *dash_test; -+ -+ FOREACH_HASH_VAL(pos, supported, value) { -+#if HTTP_DBG_NEG -+ fprintf(stderr, "strcasecmp('%s', '%s')\n", Z_STRVAL_PP(value), test); -+#endif -+ if (!strcasecmp(Z_STRVAL_PP(value), test)) { -+ return Z_STRVAL_PP(value); -+ } -+ } -+ -+ /* no distinct match found, so try primaries */ -+ if ((dash_test = strchr(test, '-'))) { -+ FOREACH_HASH_VAL(pos, supported, value) { -+ int len = dash_test - test; -+#if HTTP_DBG_NEG -+ fprintf(stderr, "strncasecmp('%s', '%s', %d)\n", Z_STRVAL_PP(value), test, len); -+#endif -+ if ( (!strncasecmp(Z_STRVAL_PP(value), test, len)) && -+ ( (Z_STRVAL_PP(value)[len] == '\0') || -+ (Z_STRVAL_PP(value)[len] == '-'))) { -+ *quality *= .9; -+ return Z_STRVAL_PP(value); -+ } -+ } -+ } -+ -+ return NULL; -+} -+/* }}} */ -+ -+/* {{{ char *http_negotiate_default_func */ -+char *_http_negotiate_default_func(const char *test, double *quality, HashTable *supported TSRMLS_DC) -+{ -+ zval **value; -+ HashPosition pos; -+ -+ FOREACH_HASH_VAL(pos, supported, value) { -+#if HTTP_DBG_NEG -+ fprintf(stderr, "strcasecmp('%s', '%s')\n", Z_STRVAL_PP(value), test); -+#endif -+ if (!strcasecmp(Z_STRVAL_PP(value), test)) { -+ return Z_STRVAL_PP(value); -+ } -+ } -+ -+ return NULL; -+} -+/* }}} */ -+ -+/* {{{ HashTable *http_negotiate_z(zval *, HashTable *, negotiate_func_t) */ -+PHP_HTTP_API HashTable *_http_negotiate_z(zval *value, HashTable *supported, negotiate_func_t neg TSRMLS_DC) -+{ -+ zval *accept = http_zsep(IS_STRING, value); -+ HashTable *result = NULL; -+ -+ if (Z_STRLEN_P(accept)) { -+ zval ex_arr, ex_del; -+ -+ INIT_PZVAL(&ex_del); -+ INIT_PZVAL(&ex_arr); -+ ZVAL_STRINGL(&ex_del, ",", 1, 0); -+ array_init(&ex_arr); -+ -+ php_explode(&ex_del, accept, &ex_arr, INT_MAX); -+ -+ if (zend_hash_num_elements(Z_ARRVAL(ex_arr)) > 0) { -+ int i = 0; -+ HashPosition pos; -+ zval **entry, array; -+ -+ INIT_PZVAL(&array); -+ array_init(&array); -+ -+ FOREACH_HASH_VAL(pos, Z_ARRVAL(ex_arr), entry) { -+ int ident_len; -+ double quality; -+ char *selected, *identifier, *freeme; -+ const char *separator; -+ -+#if HTTP_DBG_NEG -+ fprintf(stderr, "Checking %s\n", Z_STRVAL_PP(entry)); -+#endif -+ -+ if ((separator = strchr(Z_STRVAL_PP(entry), ';'))) { -+ const char *ptr = separator; -+ -+ while (*++ptr && !HTTP_IS_CTYPE(digit, *ptr) && '.' != *ptr); -+ -+ quality = zend_strtod(ptr, NULL); -+ identifier = estrndup(Z_STRVAL_PP(entry), ident_len = separator - Z_STRVAL_PP(entry)); -+ } else { -+ quality = 1000.0 - i++; -+ identifier = estrndup(Z_STRVAL_PP(entry), ident_len = Z_STRLEN_PP(entry)); -+ } -+ freeme = identifier; -+ -+ while (HTTP_IS_CTYPE(space, *identifier)) { -+ ++identifier; -+ --ident_len; -+ } -+ while (ident_len && HTTP_IS_CTYPE(space, identifier[ident_len - 1])) { -+ identifier[--ident_len] = '\0'; -+ } -+ -+ if ((selected = neg(identifier, &quality, supported TSRMLS_CC))) { -+ /* don't overwrite previously set with higher quality */ -+ if (!zend_hash_exists(Z_ARRVAL(array), selected, strlen(selected) + 1)) { -+ add_assoc_double(&array, selected, quality); -+ } -+ } -+ -+ efree(freeme); -+ } -+ -+ result = Z_ARRVAL(array); -+ zend_hash_sort(result, zend_qsort, http_sort_q, 0 TSRMLS_CC); -+ } -+ -+ zval_dtor(&ex_arr); -+ } -+ -+ zval_ptr_dtor(&accept); -+ -+ return result; -+} -+/* }}} */ -+ -+/* {{{ HashTable *http_negotiate_q(const char *, HashTable *, negotiate_func_t) */ -+PHP_HTTP_API HashTable *_http_negotiate_q(const char *header, HashTable *supported, negotiate_func_t neg TSRMLS_DC) -+{ -+ zval *accept; -+ -+#if HTTP_DBG_NEG -+ fprintf(stderr, "Reading header %s: ", header); -+#endif -+ if (!(accept = http_get_server_var(header, 1))) { -+ return NULL; -+ } -+#if HTTP_DBG_NEG -+ fprintf(stderr, "%s\n", Z_STRVAL_P(accept)); -+#endif -+ -+ return http_negotiate_z(accept, supported, neg); -+} -+/* }}} */ -+ -+/* {{{ http_range_status http_get_request_ranges(HashTable *ranges, size_t) */ -+PHP_HTTP_API http_range_status _http_get_request_ranges(HashTable *ranges, size_t length TSRMLS_DC) -+{ -+ zval *zrange; -+ char *range, c; -+ long begin = -1, end = -1, *ptr; -+ -+ if ( !(zrange = http_get_server_var("HTTP_RANGE", 1)) || -+ (size_t) Z_STRLEN_P(zrange) < lenof("bytes=") || strncmp(Z_STRVAL_P(zrange), "bytes=", lenof("bytes="))) { -+ return RANGE_NO; -+ } -+ range = Z_STRVAL_P(zrange) + lenof("bytes="); -+ ptr = &begin; -+ -+ do { -+ switch (c = *(range++)) { -+ case '0': -+ /* allow 000... - shall we? */ -+ if (*ptr != -10) { -+ *ptr *= 10; -+ } -+ break; -+ -+ case '1': case '2': case '3': -+ case '4': case '5': case '6': -+ case '7': case '8': case '9': -+ /* -+ * If the value of the pointer is already set (non-negative) -+ * then multiply its value by ten and add the current value, -+ * else initialise the pointers value with the current value -+ * -- -+ * This let us recognize empty fields when validating the -+ * ranges, i.e. a "-10" for begin and "12345" for the end -+ * was the following range request: "Range: bytes=0-12345"; -+ * While a "-1" for begin and "12345" for the end would -+ * have been: "Range: bytes=-12345". -+ */ -+ if (*ptr > 0) { -+ *ptr *= 10; -+ *ptr += c - '0'; -+ } else { -+ *ptr = c - '0'; -+ } -+ break; -+ -+ case '-': -+ ptr = &end; -+ break; -+ -+ case ' ': -+ break; -+ -+ case 0: -+ case ',': -+ -+ if (length) { -+ /* validate ranges */ -+ switch (begin) { -+ /* "0-12345" */ -+ case -10: -+ switch (end) { -+ /* "0-" */ -+ case -1: -+ return RANGE_NO; -+ -+ /* "0-0" */ -+ case -10: -+ end = 0; -+ break; -+ -+ default: -+ if (length <= (size_t) end) { -+ return RANGE_ERR; -+ } -+ break; -+ } -+ begin = 0; -+ break; -+ -+ /* "-12345" */ -+ case -1: -+ /* "-", "-0" or overflow */ -+ if (end == -1 || end == -10 || length <= (size_t) end) { -+ return RANGE_ERR; -+ } -+ begin = length - end; -+ end = length - 1; -+ break; -+ -+ /* "12345-(xxx)" */ -+ default: -+ switch (end) { -+ /* "12345-0" */ -+ case -10: -+ return RANGE_ERR; -+ -+ /* "12345-" */ -+ case -1: -+ if (length <= (size_t) begin) { -+ return RANGE_ERR; -+ } -+ end = length - 1; -+ break; -+ -+ /* "12345-67890" */ -+ default: -+ if ( (length <= (size_t) begin) || -+ (length <= (size_t) end) || -+ (end < begin)) { -+ return RANGE_ERR; -+ } -+ break; -+ } -+ break; -+ } -+ } -+ { -+ zval *zentry; -+ MAKE_STD_ZVAL(zentry); -+ array_init(zentry); -+ add_index_long(zentry, 0, begin); -+ add_index_long(zentry, 1, end); -+ zend_hash_next_index_insert(ranges, &zentry, sizeof(zval *), NULL); -+ -+ begin = -1; -+ end = -1; -+ ptr = &begin; -+ } -+ break; -+ -+ default: -+ return RANGE_NO; -+ } -+ } while (c != 0); -+ -+ return RANGE_OK; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_parse_headers(char *, HashTable *, zend_bool) */ -+PHP_HTTP_API STATUS _http_parse_headers_ex(const char *header, HashTable *headers, zend_bool prettify, -+ http_info_callback callback_func, void **callback_data TSRMLS_DC) -+{ -+ const char *colon = NULL, *line = NULL; -+ zval array; -+ -+ INIT_ZARR(array, headers); -+ -+ /* skip leading ws */ -+ while (HTTP_IS_CTYPE(space, *header)) ++header; -+ line = header; -+ -+#define MORE_HEADERS (*(line-1) && !(*(line-1) == '\n' && (*line == '\n' || *line == '\r'))) -+ do { -+ int value_len = 0; -+ -+ switch (*line++) { -+ case ':': -+ if (!colon) { -+ colon = line - 1; -+ } -+ break; -+ -+ case 0: -+ --value_len; /* we don't have CR so value length is one char less */ -+ case '\n': -+ if ((!*(line - 1)) || ((*line != ' ') && (*line != '\t'))) { -+ http_info i; -+ -+ if (SUCCESS == http_info_parse(header, &i)) { -+ /* response/request line */ -+ callback_func(callback_data, &headers, &i TSRMLS_CC); -+ http_info_dtor(&i); -+ Z_ARRVAL(array) = headers; -+ } else if (colon) { -+ /* "header: value" pair */ -+ if (header != colon) { -+ int keylen = colon - header; -+ const char *key = header; -+ -+ /* skip leading ws */ -+ while (keylen && HTTP_IS_CTYPE(space, *key)) --keylen, ++key; -+ /* skip trailing ws */ -+ while (keylen && HTTP_IS_CTYPE(space, key[keylen - 1])) --keylen; -+ -+ if (keylen > 0) { -+ zval **previous = NULL; -+ char *value; -+ char *keydup = estrndup(key, keylen); -+ -+ if (prettify) { -+ keydup = pretty_key(keydup, keylen, 1, 1); -+ } -+ -+ value_len += line - colon - 1; -+ -+ /* skip leading ws */ -+ while (HTTP_IS_CTYPE(space, *(++colon))) --value_len; -+ /* skip trailing ws */ -+ while (HTTP_IS_CTYPE(space, colon[value_len - 1])) --value_len; -+ -+ if (value_len > 0) { -+ value = estrndup(colon, value_len); -+ } else { -+ value = estrdup(""); -+ value_len = 0; -+ } -+ -+ /* if we already have got such a header make an array of those */ -+ if (SUCCESS == zend_hash_find(headers, keydup, keylen + 1, (void *) &previous)) { -+ /* convert to array */ -+ if (Z_TYPE_PP(previous) != IS_ARRAY) { -+ convert_to_array(*previous); -+ } -+ add_next_index_stringl(*previous, value, value_len, 0); -+ } else { -+ add_assoc_stringl(&array, keydup, value, value_len, 0); -+ } -+ efree(keydup); -+ } else { -+ /* empty key (" : ...") */ -+ return FAILURE; -+ } -+ } else { -+ /* empty key (": ...") */ -+ return FAILURE; -+ } -+ } else if (MORE_HEADERS) { -+ /* a line without a colon */ -+ return FAILURE; -+ } -+ colon = NULL; -+ value_len = 0; -+ header += line - header; -+ } -+ break; -+ } -+ } while (MORE_HEADERS); -+ -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ void http_get_request_headers(HashTable *) */ -+PHP_HTTP_API void _http_get_request_headers(HashTable *headers TSRMLS_DC) -+{ -+ HashKey key = initHashKey(0); -+ zval **hsv, **header; -+ HashPosition pos; -+ -+ if (!HTTP_G->request.headers) { -+ ALLOC_HASHTABLE(HTTP_G->request.headers); -+ zend_hash_init(HTTP_G->request.headers, 0, NULL, ZVAL_PTR_DTOR, 0); -+ -+#ifdef ZEND_ENGINE_2 -+ zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC); -+#endif -+ -+ if (SUCCESS == zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &hsv) && Z_TYPE_PP(hsv) == IS_ARRAY) { -+ FOREACH_KEY(pos, *hsv, key) { -+ if (key.type == HASH_KEY_IS_STRING && key.len > 6 && !strncmp(key.str, "HTTP_", 5)) { -+ key.len -= 5; -+ key.str = pretty_key(estrndup(key.str + 5, key.len - 1), key.len - 1, 1, 1); -+ -+ zend_hash_get_current_data_ex(Z_ARRVAL_PP(hsv), (void *) &header, &pos); -+ ZVAL_ADDREF(*header); -+ zend_hash_add(HTTP_G->request.headers, key.str, key.len, (void *) header, sizeof(zval *), NULL); -+ -+ efree(key.str); -+ } -+ } -+ } -+ } -+ -+ if (headers) { -+ zend_hash_copy(headers, HTTP_G->request.headers, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+ } -+} -+/* }}} */ -+ -+/* {{{ STATUS http_get_response_headers(HashTable *) */ -+PHP_HTTP_API STATUS _http_get_response_headers(HashTable *headers_ht TSRMLS_DC) -+{ -+ STATUS status; -+ phpstr headers; -+ -+ phpstr_init(&headers); -+ zend_llist_apply_with_argument(&SG(sapi_headers).headers, http_grab_response_headers, &headers TSRMLS_CC); -+ phpstr_fix(&headers); -+ -+ status = http_parse_headers_ex(PHPSTR_VAL(&headers), headers_ht, 1); -+ phpstr_dtor(&headers); -+ -+ return status; -+} -+/* }}} */ -+ -+/* {{{ zend_bool http_match_request_header(char *, char *) */ -+PHP_HTTP_API zend_bool _http_match_request_header_ex(const char *header, const char *value, zend_bool match_case TSRMLS_DC) -+{ -+ char *name; -+ uint name_len = strlen(header); -+ zend_bool result = 0; -+ zval **data, *zvalue; -+ -+ http_get_request_headers(NULL); -+ name = pretty_key(estrndup(header, name_len), name_len, 1, 1); -+ if (SUCCESS == zend_hash_find(HTTP_G->request.headers, name, name_len+1, (void *) &data)) { -+ zvalue = http_zsep(IS_STRING, *data); -+ result = (match_case ? strcmp(Z_STRVAL_P(zvalue), value) : strcasecmp(Z_STRVAL_P(zvalue), value)) ? 0 : 1; -+ zval_ptr_dtor(&zvalue); -+ } -+ efree(name); -+ -+ return result; -+} -+/* }}} */ -+ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_inflatestream_object.c -@@ -0,0 +1,297 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_inflatestream_object.c 323304 2012-02-17 21:13:24Z mike $ */ -+ -+#define HTTP_WANT_ZLIB -+#include "php_http.h" -+ -+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_ZLIB) -+ -+#include "php_http_api.h" -+#include "php_http_encoding_api.h" -+#include "php_http_exception_object.h" -+#include "php_http_inflatestream_object.h" -+ -+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpInflateStream, method, 0, req_args) -+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpInflateStream, method, 0) -+#define HTTP_INFLATE_ME(method, visibility) PHP_ME(HttpInflateStream, method, HTTP_ARGS(HttpInflateStream, method), visibility) -+ -+HTTP_BEGIN_ARGS(__construct, 0) -+ HTTP_ARG_VAL(flags, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(factory, 0) -+ HTTP_ARG_VAL(flags, 0) -+ HTTP_ARG_VAL(class_name, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(update, 1) -+ HTTP_ARG_VAL(data, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(flush, 0) -+ HTTP_ARG_VAL(data, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(finish, 0) -+ HTTP_ARG_VAL(data, 0) -+HTTP_END_ARGS; -+ -+#define THIS_CE http_inflatestream_object_ce -+zend_class_entry *http_inflatestream_object_ce; -+zend_function_entry http_inflatestream_object_fe[] = { -+ HTTP_INFLATE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) -+ HTTP_INFLATE_ME(update, ZEND_ACC_PUBLIC) -+ HTTP_INFLATE_ME(flush, ZEND_ACC_PUBLIC) -+ HTTP_INFLATE_ME(finish, ZEND_ACC_PUBLIC) -+ -+ HTTP_INFLATE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) -+ -+ EMPTY_FUNCTION_ENTRY -+}; -+static zend_object_handlers http_inflatestream_object_handlers; -+ -+PHP_MINIT_FUNCTION(http_inflatestream_object) -+{ -+ HTTP_REGISTER_CLASS_EX(HttpInflateStream, http_inflatestream_object, NULL, 0); -+ http_inflatestream_object_handlers.clone_obj = _http_inflatestream_object_clone_obj; -+ -+#ifndef WONKY -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_NONE")-1, HTTP_ENCODING_STREAM_FLUSH_NONE TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_SYNC")-1, HTTP_ENCODING_STREAM_FLUSH_SYNC TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("FLUSH_FULL")-1, HTTP_ENCODING_STREAM_FLUSH_FULL TSRMLS_CC); -+#endif -+ -+ return SUCCESS; -+} -+ -+zend_object_value _http_inflatestream_object_new(zend_class_entry *ce TSRMLS_DC) -+{ -+ return http_inflatestream_object_new_ex(ce, NULL, NULL); -+} -+ -+zend_object_value _http_inflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_inflatestream_object **ptr TSRMLS_DC) -+{ -+ zend_object_value ov; -+ http_inflatestream_object *o; -+ -+ o = ecalloc(1, sizeof(http_inflatestream_object)); -+ o->zo.ce = ce; -+ -+ if (ptr) { -+ *ptr = o; -+ } -+ -+ if (s) { -+ o->stream = s; -+ } -+ -+#ifdef ZEND_ENGINE_2_4 -+ zend_object_std_init(o, ce TSRMLS_CC); -+ object_properties_init(o, ce); -+#else -+ ALLOC_HASHTABLE(OBJ_PROP(o)); -+ zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0); -+ zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+#endif -+ -+ ov.handle = putObject(http_inflatestream_object, o); -+ ov.handlers = &http_inflatestream_object_handlers; -+ -+ return ov; -+} -+ -+zend_object_value _http_inflatestream_object_clone_obj(zval *this_ptr TSRMLS_DC) -+{ -+ http_encoding_stream *s; -+ zend_object_value new_ov; -+ http_inflatestream_object *new_obj = NULL; -+ getObject(http_inflatestream_object, old_obj); -+ -+ s = ecalloc(1, sizeof(http_encoding_stream)); -+ s->flags = old_obj->stream->flags; -+ inflateCopy(&s->stream, &old_obj->stream->stream); -+ s->stream.opaque = phpstr_dup(s->stream.opaque); -+ -+ new_ov = http_inflatestream_object_new_ex(old_obj->zo.ce, s, &new_obj); -+ zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); -+ -+ return new_ov; -+} -+ -+void _http_inflatestream_object_free(zend_object *object TSRMLS_DC) -+{ -+ http_inflatestream_object *o = (http_inflatestream_object *) object; -+ -+ if (o->stream) { -+ http_encoding_inflate_stream_free(&o->stream); -+ } -+ freeObject(o); -+} -+ -+/* {{{ proto void HttpInflateStream::__construct([int flags = 0]) -+ Creates a new HttpInflateStream object instance. */ -+PHP_METHOD(HttpInflateStream, __construct) -+{ -+ long flags = 0; -+ -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags)) { -+ getObject(http_inflatestream_object, obj); -+ -+ if (!obj->stream) { -+ obj->stream = http_encoding_inflate_stream_init(NULL, flags & 0x0fffffff); -+ } else { -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "HttpInflateStream cannot be initialized twice"); -+ } -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+/* {{{ proto HttpInflateStream HttpInflateStream::factory([int flags[, string class = "HttpInflateStream"]]) -+ Creates a new HttpInflateStream object instance. */ -+PHP_METHOD(HttpInflateStream, factory) -+{ -+ long flags = 0; -+ char *cn = NULL; -+ int cl = 0; -+ -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &flags, &cn, &cl)) { -+ zend_object_value ov; -+ http_encoding_stream *s = http_encoding_inflate_stream_init(NULL, flags & 0x0fffffff); -+ -+ if (SUCCESS == http_object_new(&ov, cn, cl, _http_inflatestream_object_new_ex, http_inflatestream_object_ce, s, NULL)) { -+ RETVAL_OBJVAL(ov, 0); -+ } -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+/* {{{ proto string HttpInflateStream::update(string data) -+ Passes more data through the inflate stream. */ -+PHP_METHOD(HttpInflateStream, update) -+{ -+ int data_len; -+ size_t decoded_len = 0; -+ char *data, *decoded = NULL; -+ getObject(http_inflatestream_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) { -+ RETURN_FALSE; -+ } -+ -+ if (!data_len) { -+ RETURN_STRING("", 1); -+ } -+ -+ if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) { -+ RETURN_FALSE; -+ } -+ -+ if (SUCCESS == http_encoding_inflate_stream_update(obj->stream, data, data_len, &decoded, &decoded_len)) { -+ RETURN_STRINGL(decoded, decoded_len, 0); -+ } else { -+ RETURN_FALSE; -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string HttpInflateStream::flush([string data]) -+ Flush the inflate stream. */ -+PHP_METHOD(HttpInflateStream, flush) -+{ -+ int data_len = 0; -+ size_t decoded_len = 0; -+ char *decoded = NULL, *data = NULL; -+ getObject(http_inflatestream_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) { -+ RETURN_FALSE; -+ } -+ -+ if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) { -+ RETURN_FALSE; -+ } -+ -+ /* flushing the inflate stream is a no-op */ -+ if (!data_len) { -+ RETURN_STRINGL("", 0, 1); -+ } else if (SUCCESS == http_encoding_inflate_stream_update(obj->stream, data, data_len, &decoded, &decoded_len)) { -+ RETURN_STRINGL(decoded, decoded_len, 0); -+ } else { -+ RETURN_FALSE; -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string HttpInflateStream::finish([string data]) -+ Finalizes the inflate stream. The inflate stream can be reused after finalizing. */ -+PHP_METHOD(HttpInflateStream, finish) -+{ -+ int data_len = 0; -+ size_t updated_len = 0, decoded_len = 0; -+ char *updated = NULL, *decoded = NULL, *data = NULL; -+ getObject(http_inflatestream_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &data, &data_len)) { -+ RETURN_FALSE; -+ } -+ -+ if (!obj->stream && !(obj->stream = http_encoding_inflate_stream_init(NULL, 0))) { -+ RETURN_FALSE; -+ } -+ -+ if (data_len) { -+ if (SUCCESS != http_encoding_inflate_stream_update(obj->stream, data, data_len, &updated, &updated_len)) { -+ RETURN_FALSE; -+ } -+ } -+ -+ if (SUCCESS == http_encoding_inflate_stream_finish(obj->stream, &decoded, &decoded_len)) { -+ if (updated_len) { -+ updated = erealloc(updated, updated_len + decoded_len + 1); -+ updated[updated_len + decoded_len] = '\0'; -+ memcpy(updated + updated_len, decoded, decoded_len); -+ STR_FREE(decoded); -+ updated_len += decoded_len; -+ RETVAL_STRINGL(updated, updated_len, 0); -+ } else if (decoded) { -+ STR_FREE(updated); -+ RETVAL_STRINGL(decoded, decoded_len, 0); -+ } else { -+ RETVAL_NULL(); -+ } -+ } else { -+ STR_FREE(updated); -+ RETVAL_FALSE; -+ } -+ -+ http_encoding_inflate_stream_dtor(obj->stream); -+ http_encoding_inflate_stream_init(obj->stream, obj->stream->flags); -+} -+/* }}} */ -+ -+#endif /* ZEND_ENGINE_2 && HTTP_HAVE_ZLIB*/ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_info_api.c -@@ -0,0 +1,155 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_info_api.c 304921 2010-10-26 15:27:36Z iliaa $ */ -+ -+#include "php_http.h" -+ -+#include "php_http_api.h" -+#include "php_http_info_api.h" -+ -+PHP_HTTP_API void _http_info_default_callback(void **nothing, HashTable **headers, http_info *info TSRMLS_DC) -+{ -+ zval array; -+ -+ INIT_ZARR(array, *headers); -+ -+ switch (info->type) { -+ case IS_HTTP_REQUEST: -+ add_assoc_string(&array, "Request Method", HTTP_INFO(info).request.method, 1); -+ add_assoc_string(&array, "Request Url", HTTP_INFO(info).request.url, 1); -+ break; -+ -+ case IS_HTTP_RESPONSE: -+ add_assoc_long(&array, "Response Code", (long) HTTP_INFO(info).response.code); -+ if (HTTP_INFO(info).response.status) { -+ add_assoc_string(&array, "Response Status", HTTP_INFO(info).response.status, 1); -+ } -+ break; -+ } -+} -+ -+PHP_HTTP_API void _http_info_dtor(http_info *i) -+{ -+ switch (i->type) { -+ case IS_HTTP_REQUEST: -+ STR_SET(HTTP_INFO(i).request.method, NULL); -+ STR_SET(HTTP_INFO(i).request.url, NULL); -+ break; -+ -+ case IS_HTTP_RESPONSE: -+ STR_SET(HTTP_INFO(i).response.status, NULL); -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+PHP_HTTP_API STATUS _http_info_parse_ex(const char *pre_header, http_info *info, zend_bool silent TSRMLS_DC) -+{ -+ const char *end, *http; -+ -+ /* sane parameter */ -+ if ((!pre_header) || (!*pre_header)) { -+ return FAILURE; -+ } -+ -+ /* where's the end of the line */ -+ if (!(end = http_locate_eol(pre_header, NULL))) { -+ end = pre_header + strlen(pre_header); -+ } -+ -+ /* there must be HTTP/1.x in the line */ -+ if (!(http = http_locate_str(pre_header, end - pre_header, "HTTP/1.", lenof("HTTP/1.")))) { -+ return FAILURE; -+ } -+ -+ /* and nothing than SPACE or NUL after HTTP/1.x */ -+ if ( (!HTTP_IS_CTYPE(digit, http[lenof("HTTP/1.")])) || -+ (http[lenof("HTTP/1.1")] && (!HTTP_IS_CTYPE(space, http[lenof("HTTP/1.1")])))) { -+ if (!silent) { -+ http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Invalid HTTP/1.x protocol identification"); -+ } -+ return FAILURE; -+ } -+ -+#if 0 -+ { -+ char *line = estrndup(pre_header, end - pre_header); -+ fprintf(stderr, "http_parse_info('%s')\n", line); -+ efree(line); -+ } -+#endif -+ -+ info->http.version = zend_strtod(http + lenof("HTTP/"), NULL); -+ -+ /* is response */ -+ if (pre_header == http) { -+ char *status = NULL; -+ const char *code = http + sizeof("HTTP/1.1"); -+ -+ info->type = IS_HTTP_RESPONSE; -+ while (' ' == *code) ++code; -+ if (code && end > code) { -+ HTTP_INFO(info).response.code = strtol(code, &status, 10); -+ } else { -+ HTTP_INFO(info).response.code = 0; -+ } -+ if (status && end > status) { -+ while (' ' == *status) ++status; -+ HTTP_INFO(info).response.status = estrndup(status, end - status); -+ } else { -+ HTTP_INFO(info).response.status = NULL; -+ } -+ -+ return SUCCESS; -+ } -+ -+ /* is request */ -+ else if (!http[lenof("HTTP/1.x")] || http[lenof("HTTP/1.x")] == '\r' || http[lenof("HTTP/1.x")] == '\n') { -+ const char *url = strchr(pre_header, ' '); -+ -+ info->type = IS_HTTP_REQUEST; -+ if (url && http > url) { -+ HTTP_INFO(info).request.method = estrndup(pre_header, url - pre_header); -+ while (' ' == *url) ++url; -+ while (' ' == *(http-1)) --http; -+ if (http > url) { -+ HTTP_INFO(info).request.url = estrndup(url, http - url); -+ } else { -+ efree(HTTP_INFO(info).request.method); -+ return FAILURE; -+ } -+ } else { -+ HTTP_INFO(info).request.method = NULL; -+ HTTP_INFO(info).request.url = NULL; -+ } -+ -+ return SUCCESS; -+ } -+ -+ /* some darn header containing HTTP/1.x */ -+ else { -+ return FAILURE; -+ } -+} -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_message_api.c -@@ -0,0 +1,739 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_message_api.c 323304 2012-02-17 21:13:24Z mike $ */ -+ -+#define HTTP_WANT_SAPI -+#define HTTP_WANT_CURL -+#define HTTP_WANT_ZLIB -+#include "php_http.h" -+ -+#include "php_http_api.h" -+#include "php_http_encoding_api.h" -+#include "php_http_headers_api.h" -+#include "php_http_message_api.h" -+#include "php_http_request_api.h" -+#include "php_http_send_api.h" -+#include "php_http_url_api.h" -+ -+#define http_message_info_callback _http_message_info_callback -+static void _http_message_info_callback(http_message **message, HashTable **headers, http_info *info TSRMLS_DC) -+{ -+ http_message *old = *message; -+ -+ /* advance message */ -+ if (old->type || zend_hash_num_elements(&old->hdrs) || PHPSTR_LEN(old)) { -+ (*message) = http_message_new(); -+ (*message)->parent = old; -+ (*headers) = &((*message)->hdrs); -+ } -+ -+ http_message_set_info(*message, info); -+} -+ -+#define http_message_init_type _http_message_init_type -+static inline void _http_message_init_type(http_message *message, http_message_type type) -+{ -+ message->http.version = .0; -+ -+ switch (message->type = type) { -+ case HTTP_MSG_RESPONSE: -+ message->http.info.response.code = 0; -+ message->http.info.response.status = NULL; -+ break; -+ -+ case HTTP_MSG_REQUEST: -+ message->http.info.request.method = NULL; -+ message->http.info.request.url = NULL; -+ break; -+ -+ case HTTP_MSG_NONE: -+ default: -+ break; -+ } -+} -+ -+PHP_HTTP_API http_message *_http_message_init_ex(http_message *message, http_message_type type ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) -+{ -+ if (!message) { -+ message = ecalloc_rel(1, sizeof(http_message)); -+ } -+ -+ http_message_init_type(message, type); -+ message->parent = NULL; -+ phpstr_init(&message->body); -+ zend_hash_init(&message->hdrs, 0, NULL, ZVAL_PTR_DTOR, 0); -+ -+ return message; -+} -+ -+PHP_HTTP_API http_message *_http_message_init_env(http_message *message, http_message_type type TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) -+{ -+ int free_msg; -+ http_info inf; -+ zval *sval, tval; -+ char *body_str; -+ size_t body_len; -+ -+ if ((free_msg = !message)) { -+ message = http_message_init_rel(NULL, HTTP_MSG_NONE); -+ } -+ -+ memset(&inf, 0, sizeof(http_info)); -+ switch (inf.type = type) { -+ case HTTP_MSG_REQUEST: -+ if ((sval = http_get_server_var("SERVER_PROTOCOL", 1)) && !strncmp(Z_STRVAL_P(sval), "HTTP/", lenof("HTTP/"))) { -+ inf.http.version = zend_strtod(Z_STRVAL_P(sval) + lenof("HTTP/"), NULL); -+ } else { -+ inf.http.version = 1.1; -+ } -+ if ((sval = http_get_server_var("REQUEST_METHOD", 1))) { -+ inf.http.info.request.method = estrdup(Z_STRVAL_P(sval)); -+ } -+ if ((sval = http_get_server_var("REQUEST_URI", 1))) { -+ inf.http.info.request.url = estrdup(Z_STRVAL_P(sval)); -+ } -+ -+ http_message_set_info(message, &inf); -+ http_get_request_headers(&message->hdrs); -+ if (SUCCESS == http_get_request_body_ex(&body_str, &body_len, 0)) { -+ phpstr_from_string_ex(&message->body, body_str, body_len); -+ } -+ break; -+ -+ case HTTP_MSG_RESPONSE: -+ if (!SG(sapi_headers).http_status_line || SUCCESS != http_info_parse_ex(SG(sapi_headers).http_status_line, &inf, 0)) { -+ inf.http.version = 1.1; -+ inf.http.info.response.code = 200; -+ inf.http.info.response.status = estrdup("Ok"); -+ } -+ -+ http_message_set_info(message, &inf); -+ http_get_response_headers(&message->hdrs); -+#ifdef PHP_OUTPUT_NEWAPI -+ if (SUCCESS == php_output_get_contents(&tval TSRMLS_CC)) { -+#else -+ if (SUCCESS == php_ob_get_buffer(&tval TSRMLS_CC)) { -+#endif -+ message->body.data = Z_STRVAL(tval); -+ message->body.used = Z_STRLEN(tval); -+ message->body.free = 1; /* "\0" */ -+ } -+ break; -+ -+ default: -+ if (free_msg) { -+ http_message_free(&message); -+ } else { -+ message = NULL; -+ } -+ break; -+ } -+ http_info_dtor(&inf); -+ -+ return message; -+} -+ -+PHP_HTTP_API void _http_message_set_type(http_message *message, http_message_type type) -+{ -+ /* just act if different */ -+ if (type != message->type) { -+ -+ /* free request info */ -+ switch (message->type) { -+ case HTTP_MSG_REQUEST: -+ STR_FREE(message->http.info.request.method); -+ STR_FREE(message->http.info.request.url); -+ break; -+ -+ case HTTP_MSG_RESPONSE: -+ STR_FREE(message->http.info.response.status); -+ break; -+ -+ default: -+ break; -+ } -+ -+ /* init */ -+ http_message_init_type(message, type); -+ } -+} -+ -+PHP_HTTP_API void _http_message_set_info(http_message *message, http_info *info) -+{ -+ http_message_set_type(message, info->type); -+ message->http.version = info->http.version; -+ switch (message->type) { -+ case IS_HTTP_REQUEST: -+ STR_SET(HTTP_INFO(message).request.url, HTTP_INFO(info).request.url ? estrdup(HTTP_INFO(info).request.url) : NULL); -+ STR_SET(HTTP_INFO(message).request.method, HTTP_INFO(info).request.method ? estrdup(HTTP_INFO(info).request.method) : NULL); -+ break; -+ -+ case IS_HTTP_RESPONSE: -+ HTTP_INFO(message).response.code = HTTP_INFO(info).response.code; -+ STR_SET(HTTP_INFO(message).response.status, HTTP_INFO(info).response.status ? estrdup(HTTP_INFO(info).response.status) : NULL); -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+#define http_message_body_parse(m, ms, ml, c) _http_message_body_parse((m), (ms), (ml), (c) TSRMLS_CC) -+static inline void _http_message_body_parse(http_message *msg, const char *message, size_t message_length, const char **continue_at TSRMLS_DC) -+{ -+ zval *c; -+ size_t remaining; -+ const char *body; -+ -+ *continue_at = NULL; -+ if ((body = http_locate_body(message))) { -+ remaining = message + message_length - body; -+ -+ if ((c = http_message_header(msg, "Transfer-Encoding"))) { -+ if (strstr(Z_STRVAL_P(c), "chunked")) { -+ /* message has chunked transfer encoding */ -+ char *decoded; -+ size_t decoded_len; -+ -+ /* decode and replace Transfer-Encoding with Content-Length header */ -+ if ((*continue_at = http_encoding_dechunk(body, message + message_length - body, &decoded, &decoded_len))) { -+ zval *len; -+ char *tmp; -+ int tmp_len; -+ -+ tmp_len = (int) spprintf(&tmp, 0, "%zu", decoded_len); -+ MAKE_STD_ZVAL(len); -+ ZVAL_STRINGL(len, tmp, tmp_len, 0); -+ -+ ZVAL_ADDREF(c); -+ zend_hash_update(&msg->hdrs, "X-Original-Transfer-Encoding", sizeof("X-Original-Transfer-Encoding"), (void *) &c, sizeof(zval *), NULL); -+ zend_hash_del(&msg->hdrs, "Transfer-Encoding", sizeof("Transfer-Encoding")); -+ zend_hash_del(&msg->hdrs, "Content-Length", sizeof("Content-Length")); -+ zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL); -+ -+ phpstr_from_string_ex(PHPSTR(msg), decoded, decoded_len); -+ efree(decoded); -+ } -+ } -+ zval_ptr_dtor(&c); -+ } -+ -+ if (!*continue_at && (c = http_message_header(msg, "Content-Length"))) { -+ /* message has content-length header */ -+ ulong len = strtoul(Z_STRVAL_P(c), NULL, 10); -+ if (len > remaining) { -+ http_error_ex(HE_NOTICE, HTTP_E_MALFORMED_HEADERS, "The Content-Length header pretends a larger body than actually received (expected %lu bytes; got %lu bytes)", len, remaining); -+ len = remaining; -+ } -+ phpstr_from_string_ex(PHPSTR(msg), body, len); -+ *continue_at = body + len; -+ zval_ptr_dtor(&c); -+ } -+ -+ if (!*continue_at && (c = http_message_header(msg, "Content-Range"))) { -+ /* message has content-range header */ -+ ulong total = 0, start = 0, end = 0, len = 0; -+ -+ if (!strncasecmp(Z_STRVAL_P(c), "bytes", lenof("bytes")) && -+ ( Z_STRVAL_P(c)[lenof("bytes")] == ':' || -+ Z_STRVAL_P(c)[lenof("bytes")] == ' ' || -+ Z_STRVAL_P(c)[lenof("bytes")] == '=')) { -+ char *total_at = NULL, *end_at = NULL; -+ char *start_at = Z_STRVAL_P(c) + sizeof("bytes"); -+ -+ start = strtoul(start_at, &end_at, 10); -+ if (end_at) { -+ end = strtoul(end_at + 1, &total_at, 10); -+ if (total_at && strncmp(total_at + 1, "*", 1)) { -+ total = strtoul(total_at + 1, NULL, 10); -+ } -+ if ((len = (end + 1 - start)) > remaining) { -+ http_error_ex(HE_NOTICE, HTTP_E_MALFORMED_HEADERS, "The Content-Range header pretends a larger body than actually received (expected %lu bytes; got %lu bytes)", len, remaining); -+ len = remaining; -+ } -+ if (end >= start && (!total || end < total)) { -+ phpstr_from_string_ex(PHPSTR(msg), body, len); -+ *continue_at = body + len; -+ } -+ } -+ } -+ -+ if (!*continue_at) { -+ http_error_ex(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Invalid Content-Range header: %s", Z_STRVAL_P(c)); -+ } -+ zval_ptr_dtor(&c); -+ } -+ -+ if (!*continue_at) { -+ /* no headers that indicate content length */ -+ if (HTTP_MSG_TYPE(RESPONSE, msg)) { -+ phpstr_from_string_ex(PHPSTR(msg), body, remaining); -+ } else { -+ *continue_at = body; -+ } -+ } -+ -+#ifdef HTTP_HAVE_ZLIB -+ /* check for compressed data */ -+ if ((c = http_message_header(msg, "Content-Encoding"))) { -+ char *decoded = NULL; -+ size_t decoded_len = 0; -+ -+ if ( !strcasecmp(Z_STRVAL_P(c), "gzip") || -+ !strcasecmp(Z_STRVAL_P(c), "x-gzip") || -+ !strcasecmp(Z_STRVAL_P(c), "deflate")) { -+ http_encoding_inflate(PHPSTR_VAL(msg), PHPSTR_LEN(msg), &decoded, &decoded_len); -+ } -+ -+ if (decoded) { -+ zval *len, **original_len; -+ char *tmp; -+ int tmp_len; -+ -+ tmp_len = (int) spprintf(&tmp, 0, "%zu", decoded_len); -+ MAKE_STD_ZVAL(len); -+ ZVAL_STRINGL(len, tmp, tmp_len, 0); -+ -+ ZVAL_ADDREF(c); -+ zend_hash_update(&msg->hdrs, "X-Original-Content-Encoding", sizeof("X-Original-Content-Encoding"), (void *) &c, sizeof(zval *), NULL); -+ zend_hash_del(&msg->hdrs, "Content-Encoding", sizeof("Content-Encoding")); -+ if (SUCCESS == zend_hash_find(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &original_len)) { -+ ZVAL_ADDREF(*original_len); -+ zend_hash_update(&msg->hdrs, "X-Original-Content-Length", sizeof("X-Original-Content-Length"), (void *) original_len, sizeof(zval *), NULL); -+ zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL); -+ } else { -+ zend_hash_update(&msg->hdrs, "Content-Length", sizeof("Content-Length"), (void *) &len, sizeof(zval *), NULL); -+ } -+ -+ phpstr_dtor(PHPSTR(msg)); -+ PHPSTR(msg)->data = decoded; -+ PHPSTR(msg)->used = decoded_len; -+ PHPSTR(msg)->free = 1; -+ } -+ -+ zval_ptr_dtor(&c); -+ } -+#endif /* HTTP_HAVE_ZLIB */ -+ } -+} -+ -+PHP_HTTP_API http_message *_http_message_parse_ex(http_message *msg, const char *message, size_t message_length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC) -+{ -+ const char *continue_at; -+ zend_bool free_msg = msg ? 0 : 1; -+ -+ if ((!message) || (message_length < HTTP_MSG_MIN_SIZE)) { -+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Empty or too short HTTP message: '%s'", message); -+ return NULL; -+ } -+ -+ msg = http_message_init_rel(msg, 0); -+ -+ if (SUCCESS != http_parse_headers_cb(message, &msg->hdrs, 1, (http_info_callback) http_message_info_callback, (void *) &msg)) { -+ if (free_msg) { -+ http_message_free(&msg); -+ } -+ http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Failed to parse message headers"); -+ return NULL; -+ } -+ -+ http_message_body_parse(msg, message, message_length, &continue_at); -+ -+ /* check for following messages */ -+ if (continue_at && (continue_at < (message + message_length))) { -+ while (HTTP_IS_CTYPE(space, *continue_at)) ++continue_at; -+ if (continue_at < (message + message_length)) { -+ http_message *next = NULL, *most = NULL; -+ -+ /* set current message to parent of most parent following messages and return deepest */ -+ if ((most = next = http_message_parse_rel(NULL, continue_at, message + message_length - continue_at))) { -+ while (most->parent) most = most->parent; -+ most->parent = msg; -+ msg = next; -+ } -+ } -+ } -+ -+ return msg; -+} -+ -+PHP_HTTP_API void _http_message_tostring(http_message *msg, char **string, size_t *length) -+{ -+ phpstr str; -+ HashKey key = initHashKey(0); -+ zval **header; -+ char *data; -+ HashPosition pos1; -+ -+ phpstr_init_ex(&str, 4096, 0); -+ -+ switch (msg->type) { -+ case HTTP_MSG_REQUEST: -+ phpstr_appendf(&str, HTTP_INFO_REQUEST_FMT_ARGS(&msg->http, HTTP_CRLF)); -+ break; -+ -+ case HTTP_MSG_RESPONSE: -+ phpstr_appendf(&str, HTTP_INFO_RESPONSE_FMT_ARGS(&msg->http, HTTP_CRLF)); -+ break; -+ -+ case HTTP_MSG_NONE: -+ default: -+ break; -+ } -+ -+ FOREACH_HASH_KEYVAL(pos1, &msg->hdrs, key, header) { -+ if (key.type == HASH_KEY_IS_STRING) { -+ HashPosition pos2; -+ zval **single_header; -+ -+ switch (Z_TYPE_PP(header)) { -+ case IS_BOOL: -+ phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_BVAL_PP(header)?"true":"false"); -+ break; -+ -+ case IS_LONG: -+ phpstr_appendf(&str, "%s: %ld" HTTP_CRLF, key.str, Z_LVAL_PP(header)); -+ break; -+ -+ case IS_DOUBLE: -+ phpstr_appendf(&str, "%s: %f" HTTP_CRLF, key.str, Z_DVAL_PP(header)); -+ break; -+ -+ case IS_STRING: -+ phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_STRVAL_PP(header)); -+ break; -+ -+ case IS_ARRAY: -+ FOREACH_VAL(pos2, *header, single_header) { -+ switch (Z_TYPE_PP(single_header)) { -+ case IS_BOOL: -+ phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_BVAL_PP(single_header)?"true":"false"); -+ break; -+ -+ case IS_LONG: -+ phpstr_appendf(&str, "%s: %ld" HTTP_CRLF, key.str, Z_LVAL_PP(single_header)); -+ break; -+ -+ case IS_DOUBLE: -+ phpstr_appendf(&str, "%s: %f" HTTP_CRLF, key.str, Z_DVAL_PP(single_header)); -+ break; -+ -+ case IS_STRING: -+ phpstr_appendf(&str, "%s: %s" HTTP_CRLF, key.str, Z_STRVAL_PP(single_header)); -+ break; -+ } -+ } -+ break; -+ } -+ } -+ } -+ -+ if (PHPSTR_LEN(msg)) { -+ phpstr_appends(&str, HTTP_CRLF); -+ phpstr_append(&str, PHPSTR_VAL(msg), PHPSTR_LEN(msg)); -+ phpstr_appends(&str, HTTP_CRLF); -+ } -+ -+ data = phpstr_data(&str, string, length); -+ if (!string) { -+ efree(data); -+ } -+ -+ phpstr_dtor(&str); -+} -+ -+PHP_HTTP_API void _http_message_serialize(http_message *message, char **string, size_t *length) -+{ -+ char *buf; -+ size_t len; -+ phpstr str; -+ -+ phpstr_init(&str); -+ -+ do { -+ http_message_tostring(message, &buf, &len); -+ phpstr_prepend(&str, buf, len); -+ efree(buf); -+ } while ((message = message->parent)); -+ -+ buf = phpstr_data(&str, string, length); -+ if (!string) { -+ efree(buf); -+ } -+ -+ phpstr_dtor(&str); -+} -+ -+PHP_HTTP_API http_message *_http_message_reverse(http_message *msg) -+{ -+ int i, c; -+ -+ http_message_count(c, msg); -+ -+ if (c > 1) { -+ http_message *tmp = msg, **arr = ecalloc(c, sizeof(http_message *)); -+ -+ for (i = 0; i < c; ++i) { -+ arr[i] = tmp; -+ tmp = tmp->parent; -+ } -+ arr[0]->parent = NULL; -+ for (i = 0; i < c-1; ++i) { -+ arr[i+1]->parent = arr[i]; -+ } -+ -+ msg = arr[c-1]; -+ efree(arr); -+ } -+ -+ return msg; -+} -+ -+PHP_HTTP_API http_message *_http_message_interconnect(http_message *m1, http_message *m2) -+{ -+ if (m1 && m2) { -+ int i = 0, c1, c2; -+ http_message *t1 = m1, *t2 = m2, *p1, *p2; -+ -+ http_message_count(c1, m1); -+ http_message_count(c2, m2); -+ -+ while (i++ < (c1 - c2)) { -+ t1 = t1->parent; -+ } -+ while (i++ <= c1) { -+ p1 = t1->parent; -+ p2 = t2->parent; -+ t1->parent = t2; -+ t2->parent = p1; -+ t1 = p1; -+ t2 = p2; -+ } -+ } else if (!m1 && m2) { -+ m1 = m2; -+ } -+ return m1; -+} -+ -+PHP_HTTP_API void _http_message_tostruct_recursive(http_message *msg, zval *obj TSRMLS_DC) -+{ -+ zval strct; -+ zval *headers; -+ -+ INIT_ZARR(strct, HASH_OF(obj)); -+ -+ add_assoc_long(&strct, "type", msg->type); -+ add_assoc_double(&strct, "httpVersion", msg->http.version); -+ switch (msg->type) -+ { -+ case HTTP_MSG_RESPONSE: -+ add_assoc_long(&strct, "responseCode", msg->http.info.response.code); -+ add_assoc_string(&strct, "responseStatus", STR_PTR(msg->http.info.response.status), 1); -+ break; -+ -+ case HTTP_MSG_REQUEST: -+ add_assoc_string(&strct, "requestMethod", STR_PTR(msg->http.info.request.method), 1); -+ add_assoc_string(&strct, "requestUrl", STR_PTR(msg->http.info.request.url), 1); -+ break; -+ -+ case HTTP_MSG_NONE: -+ /* avoid compiler warning */ -+ break; -+ } -+ -+ MAKE_STD_ZVAL(headers); -+ array_init(headers); -+ zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+ add_assoc_zval(&strct, "headers", headers); -+ -+ add_assoc_stringl(&strct, "body", PHPSTR_VAL(msg), PHPSTR_LEN(msg), 1); -+ -+ if (msg->parent) { -+ zval *parent; -+ -+ MAKE_STD_ZVAL(parent); -+ if (Z_TYPE_P(obj) == IS_ARRAY) { -+ array_init(parent); -+ } else { -+ object_init(parent); -+ } -+ add_assoc_zval(&strct, "parentMessage", parent); -+ http_message_tostruct_recursive(msg->parent, parent); -+ } else { -+ add_assoc_null(&strct, "parentMessage"); -+ } -+} -+ -+PHP_HTTP_API STATUS _http_message_send(http_message *message TSRMLS_DC) -+{ -+ STATUS rs = FAILURE; -+ -+ switch (message->type) { -+ case HTTP_MSG_RESPONSE: -+ { -+ HashKey key = initHashKey(0); -+ zval **val; -+ HashPosition pos; -+ -+ FOREACH_HASH_KEYVAL(pos, &message->hdrs, key, val) { -+ if (key.type == HASH_KEY_IS_STRING) { -+ http_send_header_zval_ex(key.str, key.len-1, val, 1); -+ } -+ } -+ rs = SUCCESS == http_send_status(message->http.info.response.code) && -+ SUCCESS == http_send_data(PHPSTR_VAL(message), PHPSTR_LEN(message)) ? -+ SUCCESS : FAILURE; -+ break; -+ } -+ -+ case HTTP_MSG_REQUEST: -+ { -+#ifdef HTTP_HAVE_CURL -+ char *uri = NULL; -+ http_request request; -+ zval **zhost, *options, *headers; -+ -+ MAKE_STD_ZVAL(options); -+ MAKE_STD_ZVAL(headers); -+ array_init(options); -+ array_init(headers); -+ zend_hash_copy(Z_ARRVAL_P(headers), &message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+ add_assoc_zval(options, "headers", headers); -+ -+ /* check host header */ -+ if (SUCCESS == zend_hash_find(&message->hdrs, "Host", sizeof("Host"), (void *) &zhost) && Z_TYPE_PP(zhost) == IS_STRING) { -+ char *colon = NULL; -+ php_url parts, *url = php_url_parse(message->http.info.request.url); -+ -+ memset(&parts, 0, sizeof(php_url)); -+ -+ /* check for port */ -+ if ((colon = strchr(Z_STRVAL_PP(zhost), ':'))) { -+ parts.port = atoi(colon + 1); -+ parts.host = estrndup(Z_STRVAL_PP(zhost), (Z_STRVAL_PP(zhost) - colon - 1)); -+ } else { -+ parts.host = estrndup(Z_STRVAL_PP(zhost), Z_STRLEN_PP(zhost)); -+ } -+ -+ http_build_url(HTTP_URL_REPLACE, url, &parts, NULL, &uri, NULL); -+ php_url_free(url); -+ efree(parts.host); -+ } else { -+ uri = http_absolute_url(message->http.info.request.url); -+ } -+ -+ if ((request.meth = http_request_method_exists(1, 0, message->http.info.request.method))) { -+ http_request_body body; -+ -+ http_request_init_ex(&request, NULL, request.meth, uri); -+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, PHPSTR_VAL(message), PHPSTR_LEN(message), 0); -+ if (SUCCESS == (rs = http_request_prepare(&request, Z_ARRVAL_P(options)))) { -+ http_request_exec(&request); -+ } -+ http_request_dtor(&request); -+ } else { -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, -+ "Cannot send HttpMessage. Request method %s not supported", -+ message->http.info.request.method); -+ } -+ efree(uri); -+ zval_ptr_dtor(&options); -+#else -+ http_error(HE_WARNING, HTTP_E_RUNTIME, "HTTP requests not supported - ext/http was not linked against libcurl."); -+#endif -+ break; -+ } -+ -+ case HTTP_MSG_NONE: -+ default: -+ http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "HttpMessage is neither of type HTTP_MSG_REQUEST nor HTTP_MSG_RESPONSE"); -+ break; -+ } -+ -+ return rs; -+} -+ -+PHP_HTTP_API http_message *_http_message_dup(http_message *orig TSRMLS_DC) -+{ -+ http_message *temp, *copy = NULL; -+ http_info info; -+ -+ if (orig) { -+ info.type = orig->type; -+ info.http = orig->http; -+ -+ copy = temp = http_message_new(); -+ http_message_set_info(temp, &info); -+ zend_hash_copy(&temp->hdrs, &orig->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+ phpstr_append(&temp->body, orig->body.data, orig->body.used); -+ -+ while (orig->parent) { -+ info.type = orig->parent->type; -+ info.http = orig->parent->http; -+ -+ temp->parent = http_message_new(); -+ http_message_set_info(temp->parent, &info); -+ zend_hash_copy(&temp->parent->hdrs, &orig->parent->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+ phpstr_append(&temp->parent->body, orig->parent->body.data, orig->parent->body.used); -+ -+ temp = temp->parent; -+ orig = orig->parent; -+ } -+ } -+ -+ return copy; -+} -+ -+PHP_HTTP_API void _http_message_dtor(http_message *message) -+{ -+ if (message) { -+ zend_hash_destroy(&message->hdrs); -+ phpstr_dtor(PHPSTR(message)); -+ -+ switch (message->type) { -+ case HTTP_MSG_REQUEST: -+ STR_SET(message->http.info.request.method, NULL); -+ STR_SET(message->http.info.request.url, NULL); -+ break; -+ -+ case HTTP_MSG_RESPONSE: -+ STR_SET(message->http.info.response.status, NULL); -+ break; -+ -+ default: -+ break; -+ } -+ } -+} -+ -+PHP_HTTP_API void _http_message_free(http_message **message) -+{ -+ if (*message) { -+ if ((*message)->parent) { -+ http_message_free(&(*message)->parent); -+ } -+ http_message_dtor(*message); -+ efree(*message); -+ *message = NULL; -+ } -+} -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_message_object.c -@@ -0,0 +1,1555 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_message_object.c 323304 2012-02-17 21:13:24Z mike $ */ -+ -+#define HTTP_WANT_SAPI -+#define HTTP_WANT_CURL -+#define HTTP_WANT_MAGIC -+#include "php_http.h" -+ -+#ifdef ZEND_ENGINE_2 -+ -+#include "zend_interfaces.h" -+#include "ext/standard/url.h" -+#include "php_variables.h" -+ -+#include "php_http_api.h" -+#include "php_http_send_api.h" -+#include "php_http_url_api.h" -+#include "php_http_message_api.h" -+#include "php_http_message_object.h" -+#include "php_http_exception_object.h" -+#include "php_http_response_object.h" -+#include "php_http_request_method_api.h" -+#include "php_http_request_api.h" -+#include "php_http_request_object.h" -+#include "php_http_headers_api.h" -+ -+#if defined(HTTP_HAVE_SPL) && !defined(WONKY) -+/* SPL doesn't install its headers */ -+extern PHPAPI zend_class_entry *spl_ce_Countable; -+#endif -+ -+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpMessage, method, 0, req_args) -+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpMessage, method, 0) -+#define HTTP_MESSAGE_ME(method, visibility) PHP_ME(HttpMessage, method, HTTP_ARGS(HttpMessage, method), visibility) -+ -+HTTP_BEGIN_ARGS(__construct, 0) -+ HTTP_ARG_VAL(message, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(factory, 0) -+ HTTP_ARG_VAL(message, 0) -+ HTTP_ARG_VAL(class_name, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(fromEnv, 1) -+ HTTP_ARG_VAL(type, 0) -+ HTTP_ARG_VAL(class_name, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getBody); -+HTTP_BEGIN_ARGS(setBody, 1) -+ HTTP_ARG_VAL(body, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(getHeader, 1) -+ HTTP_ARG_VAL(header, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getHeaders); -+HTTP_BEGIN_ARGS(setHeaders, 1) -+ HTTP_ARG_VAL(headers, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(addHeaders, 1) -+ HTTP_ARG_VAL(headers, 0) -+ HTTP_ARG_VAL(append, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getType); -+HTTP_BEGIN_ARGS(setType, 1) -+ HTTP_ARG_VAL(type, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getInfo); -+HTTP_BEGIN_ARGS(setInfo, 1) -+ HTTP_ARG_VAL(http_info, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getResponseCode); -+HTTP_BEGIN_ARGS(setResponseCode, 1) -+ HTTP_ARG_VAL(response_code, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getResponseStatus); -+HTTP_BEGIN_ARGS(setResponseStatus, 1) -+ HTTP_ARG_VAL(response_status, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getRequestMethod); -+HTTP_BEGIN_ARGS(setRequestMethod, 1) -+ HTTP_ARG_VAL(request_method, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getRequestUrl); -+HTTP_BEGIN_ARGS(setRequestUrl, 1) -+ HTTP_ARG_VAL(url, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getHttpVersion); -+HTTP_BEGIN_ARGS(setHttpVersion, 1) -+ HTTP_ARG_VAL(http_version, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(guessContentType, 1) -+ HTTP_ARG_VAL(magic_file, 0) -+ HTTP_ARG_VAL(magic_mode, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getParentMessage); -+HTTP_EMPTY_ARGS(send); -+HTTP_EMPTY_ARGS(__toString); -+HTTP_BEGIN_ARGS(toString, 0) -+ HTTP_ARG_VAL(include_parent, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(toMessageTypeObject); -+ -+HTTP_EMPTY_ARGS(count); -+ -+HTTP_EMPTY_ARGS(serialize); -+HTTP_BEGIN_ARGS(unserialize, 1) -+ HTTP_ARG_VAL(serialized, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(rewind); -+HTTP_EMPTY_ARGS(valid); -+HTTP_EMPTY_ARGS(key); -+HTTP_EMPTY_ARGS(current); -+HTTP_EMPTY_ARGS(next); -+ -+HTTP_EMPTY_ARGS(detach); -+HTTP_BEGIN_ARGS(prepend, 1) -+ HTTP_ARG_OBJ(HttpMessage, message, 0) -+HTTP_END_ARGS; -+HTTP_EMPTY_ARGS(reverse); -+ -+#define http_message_object_read_prop _http_message_object_read_prop -+static zval *_http_message_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC); -+#define http_message_object_write_prop _http_message_object_write_prop -+static void _http_message_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC); -+#define http_message_object_get_prop_ptr _http_message_object_get_prop_ptr -+static zval **_http_message_object_get_prop_ptr(zval *object, zval *member ZEND_LITERAL_KEY_DC TSRMLS_DC); -+#define http_message_object_get_props _http_message_object_get_props -+static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC); -+ -+#define THIS_CE http_message_object_ce -+zend_class_entry *http_message_object_ce; -+zend_function_entry http_message_object_fe[] = { -+ HTTP_MESSAGE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) -+ HTTP_MESSAGE_ME(getBody, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(setBody, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(getHeader, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(getHeaders, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(setHeaders, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(addHeaders, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(getType, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(setType, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(getInfo, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(setInfo, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(getResponseCode, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(setResponseCode, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(getResponseStatus, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(setResponseStatus, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(getRequestMethod, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(setRequestMethod, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(getRequestUrl, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(setRequestUrl, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(getHttpVersion, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(setHttpVersion, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(guessContentType, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(getParentMessage, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(send, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(toString, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(toMessageTypeObject, ZEND_ACC_PUBLIC) -+ -+ /* implements Countable */ -+ HTTP_MESSAGE_ME(count, ZEND_ACC_PUBLIC) -+ -+ /* implements Serializable */ -+ HTTP_MESSAGE_ME(serialize, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(unserialize, ZEND_ACC_PUBLIC) -+ -+ /* implements Iterator */ -+ HTTP_MESSAGE_ME(rewind, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(valid, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(current, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(key, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(next, ZEND_ACC_PUBLIC) -+ -+ ZEND_MALIAS(HttpMessage, __toString, toString, HTTP_ARGS(HttpMessage, __toString), ZEND_ACC_PUBLIC) -+ -+ HTTP_MESSAGE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) -+ ZEND_MALIAS(HttpMessage, fromString, factory, HTTP_ARGS(HttpMessage, factory), ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) -+ HTTP_MESSAGE_ME(fromEnv, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) -+ -+ HTTP_MESSAGE_ME(detach, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(prepend, ZEND_ACC_PUBLIC) -+ HTTP_MESSAGE_ME(reverse, ZEND_ACC_PUBLIC) -+ -+ EMPTY_FUNCTION_ENTRY -+}; -+static zend_object_handlers http_message_object_handlers; -+ -+static HashTable http_message_object_prophandlers; -+ -+typedef void (*http_message_object_prophandler_func)(http_message_object *o, zval *v TSRMLS_DC); -+ -+typedef struct _http_message_object_prophandler { -+ http_message_object_prophandler_func read; -+ http_message_object_prophandler_func write; -+} http_message_object_prophandler; -+ -+static STATUS http_message_object_add_prophandler(const char *prop_str, size_t prop_len, http_message_object_prophandler_func read, http_message_object_prophandler_func write) { -+ http_message_object_prophandler h = { read, write }; -+ return zend_hash_add(&http_message_object_prophandlers, prop_str, prop_len, (void *) &h, sizeof(h), NULL); -+} -+static STATUS http_message_object_get_prophandler(const char *prop_str, size_t prop_len, http_message_object_prophandler **handler) { -+ return zend_hash_find(&http_message_object_prophandlers, prop_str, prop_len, (void *) handler); -+} -+static void http_message_object_prophandler_get_type(http_message_object *obj, zval *return_value TSRMLS_DC) { -+ RETVAL_LONG(obj->message->type); -+} -+static void http_message_object_prophandler_set_type(http_message_object *obj, zval *value TSRMLS_DC) { -+ zval *cpy = http_zsep(IS_LONG, value); -+ http_message_set_type(obj->message, Z_LVAL_P(cpy)); -+ zval_ptr_dtor(&cpy); -+} -+static void http_message_object_prophandler_get_body(http_message_object *obj, zval *return_value TSRMLS_DC) { -+ phpstr_fix(PHPSTR(obj->message)); -+ RETVAL_PHPSTR(PHPSTR(obj->message), 0, 1); -+} -+static void http_message_object_prophandler_set_body(http_message_object *obj, zval *value TSRMLS_DC) { -+ zval *cpy = http_zsep(IS_STRING, value); -+ phpstr_dtor(PHPSTR(obj->message)); -+ phpstr_from_string_ex(PHPSTR(obj->message), Z_STRVAL_P(cpy), Z_STRLEN_P(cpy)); -+ zval_ptr_dtor(&cpy); -+} -+static void http_message_object_prophandler_get_request_method(http_message_object *obj, zval *return_value TSRMLS_DC) { -+ if (HTTP_MSG_TYPE(REQUEST, obj->message) && obj->message->http.info.request.method) { -+ RETVAL_STRING(obj->message->http.info.request.method, 1); -+ } else { -+ RETVAL_NULL(); -+ } -+} -+static void http_message_object_prophandler_set_request_method(http_message_object *obj, zval *value TSRMLS_DC) { -+ if (HTTP_MSG_TYPE(REQUEST, obj->message)) { -+ zval *cpy = http_zsep(IS_STRING, value); -+ STR_SET(obj->message->http.info.request.method, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy))); -+ zval_ptr_dtor(&cpy); -+ } -+} -+static void http_message_object_prophandler_get_request_url(http_message_object *obj, zval *return_value TSRMLS_DC) { -+ if (HTTP_MSG_TYPE(REQUEST, obj->message) && obj->message->http.info.request.url) { -+ RETVAL_STRING(obj->message->http.info.request.url, 1); -+ } else { -+ RETVAL_NULL(); -+ } -+} -+static void http_message_object_prophandler_set_request_url(http_message_object *obj, zval *value TSRMLS_DC) { -+ if (HTTP_MSG_TYPE(REQUEST, obj->message)) { -+ zval *cpy = http_zsep(IS_STRING, value); -+ STR_SET(obj->message->http.info.request.url, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy))); -+ zval_ptr_dtor(&cpy); -+ } -+} -+static void http_message_object_prophandler_get_response_status(http_message_object *obj, zval *return_value TSRMLS_DC) { -+ if (HTTP_MSG_TYPE(RESPONSE, obj->message) && obj->message->http.info.response.status) { -+ RETVAL_STRING(obj->message->http.info.response.status, 1); -+ } else { -+ RETVAL_NULL(); -+ } -+} -+static void http_message_object_prophandler_set_response_status(http_message_object *obj, zval *value TSRMLS_DC) { -+ if (HTTP_MSG_TYPE(RESPONSE, obj->message)) { -+ zval *cpy = http_zsep(IS_STRING, value); -+ STR_SET(obj->message->http.info.response.status, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy))); -+ zval_ptr_dtor(&cpy); -+ } -+} -+static void http_message_object_prophandler_get_response_code(http_message_object *obj, zval *return_value TSRMLS_DC) { -+ if (HTTP_MSG_TYPE(RESPONSE, obj->message)) { -+ RETVAL_LONG(obj->message->http.info.response.code); -+ } else { -+ RETVAL_NULL(); -+ } -+} -+static void http_message_object_prophandler_set_response_code(http_message_object *obj, zval *value TSRMLS_DC) { -+ if (HTTP_MSG_TYPE(RESPONSE, obj->message)) { -+ zval *cpy = http_zsep(IS_LONG, value); -+ obj->message->http.info.response.code = Z_LVAL_P(cpy); -+ zval_ptr_dtor(&cpy); -+ } -+} -+static void http_message_object_prophandler_get_http_version(http_message_object *obj, zval *return_value TSRMLS_DC) { -+ RETVAL_DOUBLE(obj->message->http.version); -+} -+static void http_message_object_prophandler_set_http_version(http_message_object *obj, zval *value TSRMLS_DC) { -+ zval *cpy = http_zsep(IS_DOUBLE, value); -+ obj->message->http.version = Z_DVAL_P(cpy); -+ zval_ptr_dtor(&cpy); -+} -+static void http_message_object_prophandler_get_headers(http_message_object *obj, zval *return_value TSRMLS_DC) { -+ array_init(return_value); -+ zend_hash_copy(Z_ARRVAL_P(return_value), &obj->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+} -+static void http_message_object_prophandler_set_headers(http_message_object *obj, zval *value TSRMLS_DC) { -+ zval *cpy = http_zsep(IS_ARRAY, value); -+ zend_hash_clean(&obj->message->hdrs); -+ zend_hash_copy(&obj->message->hdrs, Z_ARRVAL_P(cpy), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+ zval_ptr_dtor(&cpy); -+} -+static void http_message_object_prophandler_get_parent_message(http_message_object *obj, zval *return_value TSRMLS_DC) { -+ if (obj->message->parent) { -+ RETVAL_OBJVAL(obj->parent, 1); -+ } else { -+ RETVAL_NULL(); -+ } -+} -+static void http_message_object_prophandler_set_parent_message(http_message_object *obj, zval *value TSRMLS_DC) { -+ if (Z_TYPE_P(value) == IS_OBJECT && instanceof_function(Z_OBJCE_P(value), http_message_object_ce TSRMLS_CC)) { -+ if (obj->message->parent) { -+ zval tmp; -+ tmp.value.obj = obj->parent; -+ Z_OBJ_DELREF(tmp); -+ } -+ Z_OBJ_ADDREF_P(value); -+ obj->parent = value->value.obj; -+ } -+} -+ -+PHP_MINIT_FUNCTION(http_message_object) -+{ -+ HTTP_REGISTER_CLASS_EX(HttpMessage, http_message_object, NULL, 0); -+ -+#ifndef WONKY -+# ifdef HTTP_HAVE_SPL -+ zend_class_implements(http_message_object_ce TSRMLS_CC, 3, spl_ce_Countable, zend_ce_serializable, zend_ce_iterator); -+# else -+ zend_class_implements(http_message_object_ce TSRMLS_CC, 2, zend_ce_serializable, zend_ce_iterator); -+# endif -+#else -+ zend_class_implements(http_message_object_ce TSRMLS_CC, 1, zend_ce_iterator); -+#endif -+ -+ http_message_object_handlers.clone_obj = _http_message_object_clone_obj; -+ http_message_object_handlers.read_property = http_message_object_read_prop; -+ http_message_object_handlers.write_property = http_message_object_write_prop; -+ http_message_object_handlers.get_properties = http_message_object_get_props; -+ http_message_object_handlers.get_property_ptr_ptr = http_message_object_get_prop_ptr; -+ -+ zend_hash_init(&http_message_object_prophandlers, 9, NULL, NULL, 1); -+ zend_declare_property_long(THIS_CE, ZEND_STRS("type")-1, HTTP_MSG_NONE, ZEND_ACC_PROTECTED TSRMLS_CC); -+ http_message_object_add_prophandler(ZEND_STRS("type")-1, http_message_object_prophandler_get_type, http_message_object_prophandler_set_type); -+ zend_declare_property_string(THIS_CE, ZEND_STRS("body")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC); -+ http_message_object_add_prophandler(ZEND_STRS("body")-1, http_message_object_prophandler_get_body, http_message_object_prophandler_set_body); -+ zend_declare_property_string(THIS_CE, ZEND_STRS("requestMethod")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC); -+ http_message_object_add_prophandler(ZEND_STRS("requestMethod")-1, http_message_object_prophandler_get_request_method, http_message_object_prophandler_set_request_method); -+ zend_declare_property_string(THIS_CE, ZEND_STRS("requestUrl")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC); -+ http_message_object_add_prophandler(ZEND_STRS("requestUrl")-1, http_message_object_prophandler_get_request_url, http_message_object_prophandler_set_request_url); -+ zend_declare_property_string(THIS_CE, ZEND_STRS("responseStatus")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC); -+ http_message_object_add_prophandler(ZEND_STRS("responseStatus")-1, http_message_object_prophandler_get_response_status, http_message_object_prophandler_set_response_status); -+ zend_declare_property_long(THIS_CE, ZEND_STRS("responseCode")-1, 0, ZEND_ACC_PROTECTED TSRMLS_CC); -+ http_message_object_add_prophandler(ZEND_STRS("responseCode")-1, http_message_object_prophandler_get_response_code, http_message_object_prophandler_set_response_code); -+ zend_declare_property_null(THIS_CE, ZEND_STRS("httpVersion")-1, ZEND_ACC_PROTECTED TSRMLS_CC); -+ http_message_object_add_prophandler(ZEND_STRS("httpVersion")-1, http_message_object_prophandler_get_http_version, http_message_object_prophandler_set_http_version); -+ zend_declare_property_null(THIS_CE, ZEND_STRS("headers")-1, ZEND_ACC_PROTECTED TSRMLS_CC); -+ http_message_object_add_prophandler(ZEND_STRS("headers")-1, http_message_object_prophandler_get_headers, http_message_object_prophandler_set_headers); -+ zend_declare_property_null(THIS_CE, ZEND_STRS("parentMessage")-1, ZEND_ACC_PROTECTED TSRMLS_CC); -+ http_message_object_add_prophandler(ZEND_STRS("parentMessage")-1, http_message_object_prophandler_get_parent_message, http_message_object_prophandler_set_parent_message); -+ -+#ifndef WONKY -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_NONE")-1, HTTP_MSG_NONE TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_REQUEST")-1, HTTP_MSG_REQUEST TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_RESPONSE")-1, HTTP_MSG_RESPONSE TSRMLS_CC); -+#endif -+ -+ HTTP_LONG_CONSTANT("HTTP_MSG_NONE", HTTP_MSG_NONE); -+ HTTP_LONG_CONSTANT("HTTP_MSG_REQUEST", HTTP_MSG_REQUEST); -+ HTTP_LONG_CONSTANT("HTTP_MSG_RESPONSE", HTTP_MSG_RESPONSE); -+ -+ return SUCCESS; -+} -+ -+PHP_MSHUTDOWN_FUNCTION(http_message_object) -+{ -+ zend_hash_destroy(&http_message_object_prophandlers); -+ -+ return SUCCESS; -+} -+ -+void _http_message_object_reverse(zval *this_ptr, zval *return_value TSRMLS_DC) -+{ -+ int i; -+ getObject(http_message_object, obj); -+ -+ /* count */ -+ http_message_count(i, obj->message); -+ -+ if (i > 1) { -+ zval o; -+ zend_object_value *ovalues = NULL; -+ http_message_object **objects = NULL; -+ int last = i - 1; -+ -+ objects = ecalloc(i, sizeof(http_message_object *)); -+ ovalues = ecalloc(i, sizeof(zend_object_value)); -+ -+ /* we are the first message */ -+ objects[0] = obj; -+ ovalues[0] = getThis()->value.obj; -+ -+ /* fetch parents */ -+ INIT_PZVAL(&o); -+ o.type = IS_OBJECT; -+ for (i = 1; obj->parent.handle; ++i) { -+ o.value.obj = obj->parent; -+ ovalues[i] = o.value.obj; -+ objects[i] = obj = zend_object_store_get_object(&o TSRMLS_CC); -+ } -+ -+ /* reorder parents */ -+ for (last = --i; i; --i) { -+ objects[i]->message->parent = objects[i-1]->message; -+ objects[i]->parent = ovalues[i-1]; -+ } -+ objects[0]->message->parent = NULL; -+ objects[0]->parent.handle = 0; -+ objects[0]->parent.handlers = NULL; -+ -+ /* add ref (why?) */ -+ Z_OBJ_ADDREF_P(getThis()); -+ RETVAL_OBJVAL(ovalues[last], 1); -+ -+ efree(objects); -+ efree(ovalues); -+ } else { -+ RETURN_ZVAL(getThis(), 1, 0); -+ } -+} -+ -+void _http_message_object_prepend_ex(zval *this_ptr, zval *prepend, zend_bool top TSRMLS_DC) -+{ -+ zval m; -+ http_message *save_parent_msg = NULL; -+ zend_object_value save_parent_obj = {0, NULL}; -+ getObject(http_message_object, obj); -+ getObjectEx(http_message_object, prepend_obj, prepend); -+ -+ INIT_PZVAL(&m); -+ m.type = IS_OBJECT; -+ -+ if (!top) { -+ save_parent_obj = obj->parent; -+ save_parent_msg = obj->message->parent; -+ } else { -+ /* iterate to the most parent object */ -+ while (obj->parent.handle) { -+ m.value.obj = obj->parent; -+ obj = zend_object_store_get_object(&m TSRMLS_CC); -+ } -+ } -+ -+ /* prepend */ -+ obj->parent = prepend->value.obj; -+ obj->message->parent = prepend_obj->message; -+ -+ /* add ref */ -+ zend_objects_store_add_ref(prepend TSRMLS_CC); -+ while (prepend_obj->parent.handle) { -+ m.value.obj = prepend_obj->parent; -+ zend_objects_store_add_ref(&m TSRMLS_CC); -+ prepend_obj = zend_object_store_get_object(&m TSRMLS_CC); -+ } -+ -+ if (!top) { -+ prepend_obj->parent = save_parent_obj; -+ prepend_obj->message->parent = save_parent_msg; -+ } -+} -+ -+zend_object_value _http_message_object_new(zend_class_entry *ce TSRMLS_DC) -+{ -+ return http_message_object_new_ex(ce, NULL, NULL); -+} -+ -+zend_object_value _http_message_object_new_ex(zend_class_entry *ce, http_message *msg, http_message_object **ptr TSRMLS_DC) -+{ -+ zend_object_value ov; -+ http_message_object *o; -+ -+ o = ecalloc(1, sizeof(http_message_object)); -+ o->zo.ce = ce; -+ -+ if (ptr) { -+ *ptr = o; -+ } -+ -+ if (msg) { -+ o->message = msg; -+ if (msg->parent) { -+ o->parent = http_message_object_new_ex(ce, msg->parent, NULL); -+ } -+ } -+ -+ -+#ifdef ZEND_ENGINE_2_4 -+ zend_object_std_init(o, ce TSRMLS_CC); -+ object_properties_init(o, ce); -+#else -+ ALLOC_HASHTABLE(OBJ_PROP(o)); -+ zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0); -+ zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+#endif -+ -+ ov.handle = putObject(http_message_object, o); -+ ov.handlers = &http_message_object_handlers; -+ -+ return ov; -+} -+ -+zend_object_value _http_message_object_clone_obj(zval *this_ptr TSRMLS_DC) -+{ -+ zend_object_value new_ov; -+ http_message_object *new_obj = NULL; -+ getObject(http_message_object, old_obj); -+ -+ new_ov = http_message_object_new_ex(old_obj->zo.ce, http_message_dup(old_obj->message), &new_obj); -+ zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); -+ -+ return new_ov; -+} -+ -+void _http_message_object_free(zend_object *object TSRMLS_DC) -+{ -+ http_message_object *o = (http_message_object *) object; -+ -+ if (o->iterator) { -+ zval_ptr_dtor(&o->iterator); -+ o->iterator = NULL; -+ } -+ if (o->message) { -+ http_message_dtor(o->message); -+ efree(o->message); -+ } -+ if (o->parent.handle) { -+ zval p; -+ -+ INIT_PZVAL(&p); -+ p.type = IS_OBJECT; -+ p.value.obj = o->parent; -+ zend_objects_store_del_ref(&p TSRMLS_CC); -+ } -+ freeObject(o); -+} -+ -+static zval **_http_message_object_get_prop_ptr(zval *object, zval *member ZEND_LITERAL_KEY_DC TSRMLS_DC) { -+ getObjectEx(http_message_object, obj, object); -+ http_message_object_prophandler *handler; -+ -+ if (SUCCESS == http_message_object_get_prophandler(Z_STRVAL_P(member), Z_STRLEN_P(member), &handler)) { -+ zend_error(E_ERROR, "Cannot access HttpMessage properties by reference or array key/index"); -+ return NULL; -+ } -+ -+ return zend_get_std_object_handlers()->get_property_ptr_ptr(object, member ZEND_LITERAL_KEY_CC TSRMLS_CC); -+} -+ -+static zval *_http_message_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC) -+{ -+ getObjectEx(http_message_object, obj, object); -+ http_message_object_prophandler *handler; -+ zval *return_value; -+ -+ if (SUCCESS == http_message_object_get_prophandler(Z_STRVAL_P(member), Z_STRLEN_P(member), &handler)) { -+ if (type == BP_VAR_W) { -+ zend_error(E_ERROR, "Cannot access HttpMessage properties by reference or array key/index"); -+ return NULL; -+ } -+ -+ ALLOC_ZVAL(return_value); -+#ifdef Z_SET_REFCOUNT -+ Z_SET_REFCOUNT_P(return_value, 0); -+ Z_UNSET_ISREF_P(return_value); -+#else -+ return_value->refcount = 0; -+ return_value->is_ref = 0; -+#endif -+ -+ handler->read(obj, return_value TSRMLS_CC); -+ -+ } else { -+ return_value = zend_get_std_object_handlers()->read_property(object, member, type ZEND_LITERAL_KEY_CC TSRMLS_CC); -+ } -+ -+ return return_value; -+} -+ -+static void _http_message_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC) -+{ -+ getObjectEx(http_message_object, obj, object); -+ http_message_object_prophandler *handler; -+ -+ if (SUCCESS == http_message_object_get_prophandler(Z_STRVAL_P(member), Z_STRLEN_P(member), &handler)) { -+ handler->write(obj, value TSRMLS_CC); -+ } else { -+ zend_get_std_object_handlers()->write_property(object, member, value ZEND_LITERAL_KEY_CC TSRMLS_CC); -+ } -+} -+ -+static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC) -+{ -+ zval *headers; -+ getObjectEx(http_message_object, obj, object); -+ http_message *msg = obj->message; -+ zval array, *parent; -+#ifdef ZEND_ENGINE_2_4 -+ HashTable *props = zend_get_std_object_handlers()->get_properties(object TSRMLS_CC); -+#else -+ HashTable *props = OBJ_PROP(obj); -+#endif -+ INIT_ZARR(array, props); -+ -+#define ASSOC_PROP(array, ptype, name, val) \ -+ { \ -+ char *m_prop_name; \ -+ int m_prop_len; \ -+ zend_mangle_property_name(&m_prop_name, &m_prop_len, "*", 1, name, lenof(name), 0); \ -+ add_assoc_ ##ptype## _ex(&array, m_prop_name, sizeof(name)+3, val); \ -+ efree(m_prop_name); \ -+ } -+#define ASSOC_STRING(array, name, val) ASSOC_STRINGL(array, name, val, strlen(val)) -+#define ASSOC_STRINGL(array, name, val, len) \ -+ { \ -+ char *m_prop_name; \ -+ int m_prop_len; \ -+ zend_mangle_property_name(&m_prop_name, &m_prop_len, "*", 1, name, lenof(name), 0); \ -+ add_assoc_stringl_ex(&array, m_prop_name, sizeof(name)+3, val, len, 1); \ -+ efree(m_prop_name); \ -+ } -+ -+ ASSOC_PROP(array, long, "type", msg->type); -+ ASSOC_PROP(array, double, "httpVersion", msg->http.version); -+ -+ switch (msg->type) { -+ case HTTP_MSG_REQUEST: -+ ASSOC_PROP(array, long, "responseCode", 0); -+ ASSOC_STRINGL(array, "responseStatus", "", 0); -+ ASSOC_STRING(array, "requestMethod", STR_PTR(msg->http.info.request.method)); -+ ASSOC_STRING(array, "requestUrl", STR_PTR(msg->http.info.request.url)); -+ break; -+ -+ case HTTP_MSG_RESPONSE: -+ ASSOC_PROP(array, long, "responseCode", msg->http.info.response.code); -+ ASSOC_STRING(array, "responseStatus", STR_PTR(msg->http.info.response.status)); -+ ASSOC_STRINGL(array, "requestMethod", "", 0); -+ ASSOC_STRINGL(array, "requestUrl", "", 0); -+ break; -+ -+ case HTTP_MSG_NONE: -+ default: -+ ASSOC_PROP(array, long, "responseCode", 0); -+ ASSOC_STRINGL(array, "responseStatus", "", 0); -+ ASSOC_STRINGL(array, "requestMethod", "", 0); -+ ASSOC_STRINGL(array, "requestUrl", "", 0); -+ break; -+ } -+ -+ MAKE_STD_ZVAL(headers); -+ array_init(headers); -+ zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+ ASSOC_PROP(array, zval, "headers", headers); -+ ASSOC_STRINGL(array, "body", PHPSTR_VAL(msg), PHPSTR_LEN(msg)); -+ -+ MAKE_STD_ZVAL(parent); -+ if (msg->parent) { -+ ZVAL_OBJVAL(parent, obj->parent, 1); -+ } else { -+ ZVAL_NULL(parent); -+ } -+ ASSOC_PROP(array, zval, "parentMessage", parent); -+ -+ return props; -+} -+ -+/* ### USERLAND ### */ -+ -+/* {{{ proto void HttpMessage::__construct([string message]) -+ Create a new HttpMessage object instance. */ -+PHP_METHOD(HttpMessage, __construct) -+{ -+ int length = 0; -+ char *message = NULL; -+ -+ getObject(http_message_object, obj); -+ -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &message, &length) && message && length) { -+ http_message *msg = obj->message; -+ -+ http_message_dtor(msg); -+ if ((obj->message = http_message_parse_ex(msg, message, length))) { -+ if (obj->message->parent) { -+ obj->parent = http_message_object_new_ex(Z_OBJCE_P(getThis()), obj->message->parent, NULL); -+ } -+ } else { -+ obj->message = http_message_init(msg); -+ } -+ } -+ if (!obj->message) { -+ obj->message = http_message_new(); -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+/* {{{ proto static HttpMessage HttpMessage::factory([string raw_message[, string class_name = "HttpMessage"]]) -+ Create a new HttpMessage object instance. */ -+PHP_METHOD(HttpMessage, factory) -+{ -+ char *string = NULL, *cn = NULL; -+ int length = 0, cl = 0; -+ http_message *msg = NULL; -+ zend_object_value ov; -+ http_message_object *obj = NULL; -+ -+ RETVAL_NULL(); -+ -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ss", &string, &length, &cn, &cl)) { -+ if (length) { -+ msg = http_message_parse(string, length); -+ } -+ if ((msg || !length) && SUCCESS == http_object_new(&ov, cn, cl, _http_message_object_new_ex, http_message_object_ce, msg, &obj)) { -+ RETVAL_OBJVAL(ov, 0); -+ } -+ if (obj && !obj->message) { -+ obj->message = http_message_new(); -+ } -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+/* {{{ proto static HttpMessage HttpMessage::fromEnv(int type[, string class_name = "HttpMessage"]) -+ Create a new HttpMessage object from environment representing either current request or response */ -+PHP_METHOD(HttpMessage, fromEnv) -+{ -+ char *cn = NULL; -+ int cl = 0; -+ long type; -+ http_message_object *obj = NULL; -+ zend_object_value ov; -+ -+ RETVAL_NULL(); -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s", &type, &cn, &cl)) { -+ if (SUCCESS == http_object_new(&ov, cn, cl, _http_message_object_new_ex, http_message_object_ce, http_message_init_env(NULL, type), &obj)) { -+ RETVAL_OBJVAL(ov, 0); -+ } -+ if (obj && !obj->message) { -+ obj->message = http_message_new(); -+ } -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+/* {{{ proto string HttpMessage::getBody() -+ Get the body of the parsed HttpMessage. */ -+PHP_METHOD(HttpMessage, getBody) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ getObject(http_message_object, obj); -+ RETURN_PHPSTR(&obj->message->body, PHPSTR_FREE_NOT, 1); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto void HttpMessage::setBody(string body) -+ Set the body of the HttpMessage. NOTE: Don't forget to update any headers accordingly. */ -+PHP_METHOD(HttpMessage, setBody) -+{ -+ char *body; -+ int len; -+ getObject(http_message_object, obj); -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &body, &len)) { -+ phpstr_dtor(PHPSTR(obj->message)); -+ phpstr_from_string_ex(PHPSTR(obj->message), body, len); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string HttpMessage::getHeader(string header) -+ Get message header. */ -+PHP_METHOD(HttpMessage, getHeader) -+{ -+ zval *header; -+ char *orig_header, *nice_header; -+ int header_len; -+ getObject(http_message_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &orig_header, &header_len)) { -+ RETURN_FALSE; -+ } -+ -+ nice_header = pretty_key(estrndup(orig_header, header_len), header_len, 1, 1); -+ if ((header = http_message_header_ex(obj->message, nice_header, header_len + 1, 0))) { -+ RETVAL_ZVAL(header, 1, 1); -+ } -+ efree(nice_header); -+} -+/* }}} */ -+ -+/* {{{ proto array HttpMessage::getHeaders() -+ Get Message Headers. */ -+PHP_METHOD(HttpMessage, getHeaders) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ getObject(http_message_object, obj); -+ -+ array_init(return_value); -+ array_copy(&obj->message->hdrs, Z_ARRVAL_P(return_value)); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto void HttpMessage::setHeaders(array headers) -+ Sets new headers. */ -+PHP_METHOD(HttpMessage, setHeaders) -+{ -+ zval *new_headers = NULL; -+ getObject(http_message_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!", &new_headers)) { -+ return; -+ } -+ -+ zend_hash_clean(&obj->message->hdrs); -+ if (new_headers) { -+ array_copy(Z_ARRVAL_P(new_headers), &obj->message->hdrs); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto void HttpMessage::addHeaders(array headers[, bool append = false]) -+ Add headers. If append is true, headers with the same name will be separated, else overwritten. */ -+PHP_METHOD(HttpMessage, addHeaders) -+{ -+ zval *new_headers; -+ zend_bool append = 0; -+ getObject(http_message_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &new_headers, &append)) { -+ return; -+ } -+ -+ array_join(Z_ARRVAL_P(new_headers), &obj->message->hdrs, append, ARRAY_JOIN_STRONLY|ARRAY_JOIN_PRETTIFY); -+} -+/* }}} */ -+ -+/* {{{ proto int HttpMessage::getType() -+ Get Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE) */ -+PHP_METHOD(HttpMessage, getType) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ getObject(http_message_object, obj); -+ RETURN_LONG(obj->message->type); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto void HttpMessage::setType(int type) -+ Set Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE) */ -+PHP_METHOD(HttpMessage, setType) -+{ -+ long type; -+ getObject(http_message_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type)) { -+ return; -+ } -+ http_message_set_type(obj->message, type); -+} -+/* }}} */ -+ -+/* {{{ proto string HttpMessage::getInfo(void) -+ Get the HTTP request/response line */ -+PHP_METHOD(HttpMessage, getInfo) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ getObject(http_message_object, obj); -+ -+ switch (obj->message->type) { -+ case HTTP_MSG_REQUEST: -+ Z_STRLEN_P(return_value) = spprintf(&Z_STRVAL_P(return_value), 0, HTTP_INFO_REQUEST_FMT_ARGS(&obj->message->http, "")); -+ break; -+ case HTTP_MSG_RESPONSE: -+ Z_STRLEN_P(return_value) = spprintf(&Z_STRVAL_P(return_value), 0, HTTP_INFO_RESPONSE_FMT_ARGS(&obj->message->http, "")); -+ break; -+ default: -+ RETURN_NULL(); -+ break; -+ } -+ Z_TYPE_P(return_value) = IS_STRING; -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpMessage::setInfo(string http_info) -+ Set type and request or response info with a standard HTTP request or response line */ -+PHP_METHOD(HttpMessage, setInfo) -+{ -+ char *str; -+ int len; -+ http_info inf; -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len) && SUCCESS == http_info_parse_ex(str, &inf, 0)) { -+ getObject(http_message_object, obj); -+ -+ http_message_set_info(obj->message, &inf); -+ http_info_dtor(&inf); -+ RETURN_TRUE; -+ } -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+/* {{{ proto int HttpMessage::getResponseCode() -+ Get the Response Code of the Message. */ -+PHP_METHOD(HttpMessage, getResponseCode) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ getObject(http_message_object, obj); -+ HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE); -+ RETURN_LONG(obj->message->http.info.response.code); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpMessage::setResponseCode(int code) -+ Set the response code of an HTTP Response Message. */ -+PHP_METHOD(HttpMessage, setResponseCode) -+{ -+ long code; -+ getObject(http_message_object, obj); -+ -+ HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) { -+ RETURN_FALSE; -+ } -+ if (code < 100 || code > 599) { -+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid response code (100-599): %ld", code); -+ RETURN_FALSE; -+ } -+ -+ obj->message->http.info.response.code = code; -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto string HttpMessage::getResponseStatus() -+ Get the Response Status of the message (i.e. the string following the response code). */ -+PHP_METHOD(HttpMessage, getResponseStatus) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ getObject(http_message_object, obj); -+ HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE); -+ if (obj->message->http.info.response.status) { -+ RETURN_STRING(obj->message->http.info.response.status, 1); -+ } else { -+ RETURN_EMPTY_STRING(); -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpMessage::setResponseStatus(string status) -+ Set the Response Status of the HTTP message (i.e. the string following the response code). */ -+PHP_METHOD(HttpMessage, setResponseStatus) -+{ -+ char *status; -+ int status_len; -+ getObject(http_message_object, obj); -+ -+ HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &status, &status_len)) { -+ RETURN_FALSE; -+ } -+ STR_SET(obj->message->http.info.response.status, estrndup(status, status_len)); -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto string HttpMessage::getRequestMethod() -+ Get the Request Method of the Message. */ -+PHP_METHOD(HttpMessage, getRequestMethod) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ getObject(http_message_object, obj); -+ HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE); -+ if (obj->message->http.info.request.method) { -+ RETURN_STRING(obj->message->http.info.request.method, 1); -+ } else { -+ RETURN_EMPTY_STRING(); -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpMessage::setRequestMethod(string method) -+ Set the Request Method of the HTTP Message. */ -+PHP_METHOD(HttpMessage, setRequestMethod) -+{ -+ char *method; -+ int method_len; -+ getObject(http_message_object, obj); -+ -+ HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) { -+ RETURN_FALSE; -+ } -+ if (method_len < 1) { -+ http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Cannot set HttpMessage::requestMethod to an empty string"); -+ RETURN_FALSE; -+ } -+ if (!http_request_method_exists(1, 0, method)) { -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Unknown request method: %s", method); -+ RETURN_FALSE; -+ } -+ -+ STR_SET(obj->message->http.info.request.method, estrndup(method, method_len)); -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto string HttpMessage::getRequestUrl() -+ Get the Request URL of the Message. */ -+PHP_METHOD(HttpMessage, getRequestUrl) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ getObject(http_message_object, obj); -+ HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE); -+ if (obj->message->http.info.request.url) { -+ RETURN_STRING(obj->message->http.info.request.url, 1); -+ } else { -+ RETURN_EMPTY_STRING(); -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpMessage::setRequestUrl(string url) -+ Set the Request URL of the HTTP Message. */ -+PHP_METHOD(HttpMessage, setRequestUrl) -+{ -+ char *URI; -+ int URIlen; -+ getObject(http_message_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URI, &URIlen)) { -+ RETURN_FALSE; -+ } -+ HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE); -+ if (URIlen < 1) { -+ http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Cannot set HttpMessage::requestUrl to an empty string"); -+ RETURN_FALSE; -+ } -+ -+ STR_SET(obj->message->http.info.request.url, estrndup(URI, URIlen)); -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto string HttpMessage::getHttpVersion() -+ Get the HTTP Protocol Version of the Message. */ -+PHP_METHOD(HttpMessage, getHttpVersion) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ char *version; -+ getObject(http_message_object, obj); -+ -+ spprintf(&version, 0, "%1.1F", obj->message->http.version); -+ RETURN_STRING(version, 0); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpMessage::setHttpVersion(string version) -+ Set the HTTP Protocol version of the Message. */ -+PHP_METHOD(HttpMessage, setHttpVersion) -+{ -+ zval *zv; -+ char *version; -+ getObject(http_message_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &zv)) { -+ return; -+ } -+ -+ convert_to_double(zv); -+ spprintf(&version, 0, "%1.1F", Z_DVAL_P(zv)); -+ if (strcmp(version, "1.0") && strcmp(version, "1.1")) { -+ efree(version); -+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid HTTP protocol version (1.0 or 1.1): %g", Z_DVAL_P(zv)); -+ RETURN_FALSE; -+ } -+ efree(version); -+ obj->message->http.version = Z_DVAL_P(zv); -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto string HttpMessage::guessContentType(string magic_file[, int magic_mode = MAGIC_MIME]) -+ Attempts to guess the content type of supplied payload through libmagic. */ -+PHP_METHOD(HttpMessage, guessContentType) -+{ -+#ifdef HTTP_HAVE_MAGIC -+ char *magic_file, *ct = NULL; -+ int magic_file_len; -+ long magic_mode = MAGIC_MIME; -+ -+ RETVAL_FALSE; -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &magic_file, &magic_file_len, &magic_mode)) { -+ getObject(http_message_object, obj); -+ if ((ct = http_guess_content_type(magic_file, magic_mode, PHPSTR_VAL(&obj->message->body), PHPSTR_LEN(&obj->message->body), SEND_DATA))) { -+ RETVAL_STRING(ct, 0); -+ } -+ } -+ SET_EH_NORMAL(); -+#else -+ http_error(HE_THROW, HTTP_E_RUNTIME, "Cannot guess Content-Type; libmagic not available"); -+ RETURN_FALSE; -+#endif -+} -+/* }}} */ -+ -+/* {{{ proto HttpMessage HttpMessage::getParentMessage() -+ Get parent Message. */ -+PHP_METHOD(HttpMessage, getParentMessage) -+{ -+ SET_EH_THROW_HTTP(); -+ NO_ARGS { -+ getObject(http_message_object, obj); -+ -+ if (obj->message->parent) { -+ RETVAL_OBJVAL(obj->parent, 1); -+ } else { -+ http_error(HE_WARNING, HTTP_E_RUNTIME, "HttpMessage does not have a parent message"); -+ } -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpMessage::send() -+ Send the Message according to its type as Response or Request. */ -+PHP_METHOD(HttpMessage, send) -+{ -+ getObject(http_message_object, obj); -+ -+ NO_ARGS; -+ -+ RETURN_SUCCESS(http_message_send(obj->message)); -+} -+/* }}} */ -+ -+/* {{{ proto string HttpMessage::toString([bool include_parent = false]) -+ Get the string representation of the Message. */ -+PHP_METHOD(HttpMessage, toString) -+{ -+ if (return_value_used) { -+ char *string; -+ size_t length; -+ zend_bool include_parent = 0; -+ getObject(http_message_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &include_parent)) { -+ RETURN_FALSE; -+ } -+ -+ if (include_parent) { -+ http_message_serialize(obj->message, &string, &length); -+ } else { -+ http_message_tostring(obj->message, &string, &length); -+ } -+ RETURN_STRINGL(string, length, 0); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto HttpRequest|HttpResponse HttpMessage::toMessageTypeObject(void) -+ Creates an object regarding to the type of the message. Returns either an HttpRequest or HttpResponse object on success, or NULL on failure. */ -+PHP_METHOD(HttpMessage, toMessageTypeObject) -+{ -+ SET_EH_THROW_HTTP(); -+ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ getObject(http_message_object, obj); -+ -+ switch (obj->message->type) { -+ case HTTP_MSG_REQUEST: -+ { -+#ifdef HTTP_HAVE_CURL -+ int method; -+ char *url; -+ zval post, body, *array, *headers, *host = http_message_header(obj->message, "Host"); -+ php_url hurl, *purl = php_url_parse(STR_PTR(obj->message->http.info.request.url)); -+ -+ MAKE_STD_ZVAL(array); -+ array_init(array); -+ -+ memset(&hurl, 0, sizeof(php_url)); -+ if (host) { -+ hurl.host = Z_STRVAL_P(host); -+ zval_ptr_dtor(&host); -+ } -+ http_build_url(HTTP_URL_REPLACE, purl, &hurl, NULL, &url, NULL); -+ php_url_free(purl); -+ add_assoc_string(array, "url", url, 0); -+ -+ if ( obj->message->http.info.request.method && -+ ((method = http_request_method_exists(1, 0, obj->message->http.info.request.method)) || -+ (method = http_request_method_register(obj->message->http.info.request.method, strlen(obj->message->http.info.request.method))))) { -+ add_assoc_long(array, "method", method); -+ } -+ -+ if (10 == (int) (obj->message->http.version * 10)) { -+ add_assoc_long(array, "protocol", CURL_HTTP_VERSION_1_0); -+ } -+ -+ MAKE_STD_ZVAL(headers); -+ array_init(headers); -+ array_copy(&obj->message->hdrs, Z_ARRVAL_P(headers)); -+ add_assoc_zval(array, "headers", headers); -+ -+ object_init_ex(return_value, http_request_object_ce); -+ zend_call_method_with_1_params(&return_value, http_request_object_ce, NULL, "setoptions", NULL, array); -+ zval_ptr_dtor(&array); -+ -+ if (PHPSTR_VAL(obj->message) && PHPSTR_LEN(obj->message)) { -+ phpstr_fix(PHPSTR(obj->message)); -+ INIT_PZVAL(&body); -+ ZVAL_STRINGL(&body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message), 0); -+ if (method != HTTP_POST) { -+ zend_call_method_with_1_params(&return_value, http_request_object_ce, NULL, "setbody", NULL, &body); -+ } else { -+ INIT_PZVAL(&post); -+ array_init(&post); -+ -+ zval_copy_ctor(&body); -+ sapi_module.treat_data(PARSE_STRING, Z_STRVAL(body), &post TSRMLS_CC); -+ zend_call_method_with_1_params(&return_value, http_request_object_ce, NULL, "setpostfields", NULL, &post); -+ zval_dtor(&post); -+ } -+ } -+#else -+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot transform HttpMessage to HttpRequest (missing curl support)"); -+#endif -+ break; -+ } -+ -+ case HTTP_MSG_RESPONSE: -+ { -+#ifndef WONKY -+ HashPosition pos1, pos2; -+ HashKey key = initHashKey(0); -+ zval **header, **h, *body; -+ -+ if (obj->message->http.info.response.code) { -+ http_send_status(obj->message->http.info.response.code); -+ } -+ -+ object_init_ex(return_value, http_response_object_ce); -+ -+ FOREACH_HASH_KEYVAL(pos1, &obj->message->hdrs, key, header) { -+ if (key.type == HASH_KEY_IS_STRING) { -+ zval *zkey; -+ -+ MAKE_STD_ZVAL(zkey); -+ ZVAL_STRINGL(zkey, key.str, key.len - 1, 1); -+ -+ switch (Z_TYPE_PP(header)) { -+ case IS_ARRAY: -+ case IS_OBJECT: -+ FOREACH_HASH_VAL(pos2, HASH_OF(*header), h) { -+ ZVAL_ADDREF(*h); -+ zend_call_method_with_2_params(&return_value, http_response_object_ce, NULL, "setheader", NULL, zkey, *h); -+ zval_ptr_dtor(h); -+ } -+ break; -+ -+ default: -+ ZVAL_ADDREF(*header); -+ zend_call_method_with_2_params(&return_value, http_response_object_ce, NULL, "setheader", NULL, zkey, *header); -+ zval_ptr_dtor(header); -+ break; -+ } -+ zval_ptr_dtor(&zkey); -+ } -+ } -+ -+ MAKE_STD_ZVAL(body); -+ ZVAL_STRINGL(body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message), 1); -+ zend_call_method_with_1_params(&return_value, http_response_object_ce, NULL, "setdata", NULL, body); -+ zval_ptr_dtor(&body); -+#else -+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot transform HttpMessage to HttpResponse (need PHP 5.1+)"); -+#endif -+ break; -+ } -+ -+ default: -+ http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "HttpMessage is neither of type HttpMessage::TYPE_REQUEST nor HttpMessage::TYPE_RESPONSE"); -+ break; -+ } -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+/* {{{ proto int HttpMessage::count() -+ Implements Countable::count(). Returns the number of parent messages + 1. */ -+PHP_METHOD(HttpMessage, count) -+{ -+ NO_ARGS { -+ long i; -+ getObject(http_message_object, obj); -+ -+ http_message_count(i, obj->message); -+ RETURN_LONG(i); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string HttpMessage::serialize() -+ Implements Serializable::serialize(). Returns the serialized representation of the HttpMessage. */ -+PHP_METHOD(HttpMessage, serialize) -+{ -+ NO_ARGS { -+ char *string; -+ size_t length; -+ getObject(http_message_object, obj); -+ -+ http_message_serialize(obj->message, &string, &length); -+ RETURN_STRINGL(string, length, 0); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto void HttpMessage::unserialize(string serialized) -+ Implements Serializable::unserialize(). Re-constructs the HttpMessage based upon the serialized string. */ -+PHP_METHOD(HttpMessage, unserialize) -+{ -+ int length; -+ char *serialized; -+ getObject(http_message_object, obj); -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &serialized, &length)) { -+ http_message *msg; -+ -+ http_message_dtor(obj->message); -+ if ((msg = http_message_parse_ex(obj->message, serialized, (size_t) length))) { -+ obj->message = msg; -+ } else { -+ http_message_init(obj->message); -+ http_error(HE_ERROR, HTTP_E_RUNTIME, "Could not unserialize HttpMessage"); -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ proto HttpMessage HttpMessage::detach(void) -+ Returns a clone of an HttpMessage object detached from any parent messages. */ -+PHP_METHOD(HttpMessage, detach) -+{ -+ http_info info; -+ http_message *msg; -+ getObject(http_message_object, obj); -+ -+ NO_ARGS; -+ -+ info.type = obj->message->type; -+ memcpy(&HTTP_INFO(&info), &HTTP_INFO(obj->message), sizeof(struct http_info)); -+ -+ msg = http_message_new(); -+ http_message_set_info(msg, &info); -+ -+ zend_hash_copy(&msg->hdrs, &obj->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+ phpstr_append(&msg->body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message)); -+ -+ RETVAL_OBJVAL(http_message_object_new_ex(Z_OBJCE_P(getThis()), msg, NULL), 0); -+} -+/* }}} */ -+ -+/* {{{ proto void HttpMessage::prepend(HttpMessage message[, bool top = true]) -+ Prepends message(s) to the HTTP message. Throws HttpInvalidParamException if the message is located within the same message chain. */ -+PHP_METHOD(HttpMessage, prepend) -+{ -+ zval *prepend; -+ zend_bool top = 1; -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|b", &prepend, http_message_object_ce, &top)) { -+ http_message *msg[2]; -+ getObject(http_message_object, obj); -+ getObjectEx(http_message_object, prepend_obj, prepend); -+ -+ /* safety check */ -+ for (msg[0] = obj->message; msg[0]; msg[0] = msg[0]->parent) { -+ for (msg[1] = prepend_obj->message; msg[1]; msg[1] = msg[1]->parent) { -+ if (msg[0] == msg[1]) { -+ http_error(HE_THROW, HTTP_E_INVALID_PARAM, "Cannot prepend a message located within the same message chain"); -+ return; -+ } -+ } -+ } -+ -+ http_message_object_prepend_ex(getThis(), prepend, top); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto HttpMessage HttpMessage::reverse() -+ Reorders the message chain in reverse order. Returns the most parent HttpMessage object. */ -+PHP_METHOD(HttpMessage, reverse) -+{ -+ NO_ARGS { -+ http_message_object_reverse(getThis(), return_value); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto void HttpMessage::rewind(void) -+ Implements Iterator::rewind(). */ -+PHP_METHOD(HttpMessage, rewind) -+{ -+ NO_ARGS { -+ getObject(http_message_object, obj); -+ -+ if (obj->iterator) { -+ zval_ptr_dtor(&obj->iterator); -+ } -+ ZVAL_ADDREF(getThis()); -+ obj->iterator = getThis(); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpMessage::valid(void) -+ Implements Iterator::valid(). */ -+PHP_METHOD(HttpMessage, valid) -+{ -+ NO_ARGS { -+ getObject(http_message_object, obj); -+ -+ RETURN_BOOL(obj->iterator != NULL); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto void HttpMessage::next(void) -+ Implements Iterator::next(). */ -+PHP_METHOD(HttpMessage, next) -+{ -+ NO_ARGS { -+ getObject(http_message_object, obj); -+ if (obj->iterator) { -+ getObjectEx(http_message_object, itr, obj->iterator); -+ -+ if (itr && itr->parent.handle) { -+ zval *old = obj->iterator; -+ MAKE_STD_ZVAL(obj->iterator); -+ ZVAL_OBJVAL(obj->iterator, itr->parent, 1); -+ zval_ptr_dtor(&old); -+ } else { -+ zval_ptr_dtor(&obj->iterator); -+ obj->iterator = NULL; -+ } -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ proto int HttpMessage::key(void) -+ Implements Iterator::key(). */ -+PHP_METHOD(HttpMessage, key) -+{ -+ NO_ARGS { -+ getObject(http_message_object, obj); -+ -+ RETURN_LONG(obj->iterator ? obj->iterator->value.obj.handle:0); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto HttpMessage HttpMessage::current(void) -+ Implements Iterator::current(). */ -+PHP_METHOD(HttpMessage, current) -+{ -+ NO_ARGS { -+ getObject(http_message_object, obj); -+ -+ if (obj->iterator) { -+ RETURN_ZVAL(obj->iterator, 1, 0); -+ } -+ } -+} -+/* }}} */ -+ -+#endif /* ZEND_ENGINE_2 */ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_persistent_handle_api.c -@@ -0,0 +1,388 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_persistent_handle_api.c 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#include "php_http.h" -+#include "php_http_api.h" -+ -+#include "php_http_persistent_handle_api.h" -+ -+#ifndef HTTP_DEBUG_PHANDLES -+# define HTTP_DEBUG_PHANDLES 0 -+#endif -+#if HTTP_DEBUG_PHANDLES -+# undef inline -+# define inline -+#endif -+ -+static HashTable http_persistent_handles_hash; -+#ifdef ZTS -+# define LOCK() tsrm_mutex_lock(http_persistent_handles_lock) -+# define UNLOCK() tsrm_mutex_unlock(http_persistent_handles_lock) -+static MUTEX_T http_persistent_handles_lock; -+#else -+# define LOCK() -+# define UNLOCK() -+#endif -+ -+typedef struct _http_persistent_handle_list_t { -+ HashTable free; -+ ulong used; -+} http_persistent_handle_list; -+ -+typedef struct _http_persistent_handle_provider_t { -+ http_persistent_handle_list list; /* "ident" => array(handles) entries */ -+ http_persistent_handle_ctor ctor; -+ http_persistent_handle_dtor dtor; -+ http_persistent_handle_copy copy; -+} http_persistent_handle_provider; -+ -+static inline http_persistent_handle_list *http_persistent_handle_list_init(http_persistent_handle_list *list) -+{ -+ int free_list; -+ -+ if ((free_list = !list)) { -+ list = pemalloc(sizeof(http_persistent_handle_list), 1); -+ } -+ -+ list->used = 0; -+ -+ if (SUCCESS != zend_hash_init(&list->free, 0, NULL, NULL, 1)) { -+ if (free_list) { -+ pefree(list, 1); -+ } -+ list = NULL; -+ } -+ -+ return list; -+} -+ -+static inline void http_persistent_handle_list_dtor(http_persistent_handle_list *list, http_persistent_handle_dtor dtor) -+{ -+ HashPosition pos; -+ void **handle; -+ -+#if HTTP_DEBUG_PHANDLES -+ fprintf(stderr, "LSTDTOR: %p\n", list); -+#endif -+ FOREACH_HASH_VAL(pos, &list->free, handle) { -+#if HTTP_DEBUG_PHANDLES -+ fprintf(stderr, "DESTROY: %p\n", *handle); -+#endif -+ -+ dtor(*handle); -+ } -+ zend_hash_destroy(&list->free); -+} -+ -+static inline void http_persistent_handle_list_free(http_persistent_handle_list **list, http_persistent_handle_dtor dtor) -+{ -+ http_persistent_handle_list_dtor(*list, dtor); -+#if HTTP_DEBUG_PHANDLES -+ fprintf(stderr, "LSTFREE: %p\n", *list); -+#endif -+ pefree(*list, 1); -+ *list = NULL; -+} -+ -+static inline http_persistent_handle_list *http_persistent_handle_list_find(http_persistent_handle_provider *provider TSRMLS_DC) -+{ -+ http_persistent_handle_list **list, *new_list; -+ -+ if (SUCCESS == zend_hash_quick_find(&provider->list.free, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &list)) { -+#if HTTP_DEBUG_PHANDLES -+ fprintf(stderr, "LSTFIND: %p\n", *list); -+#endif -+ return *list; -+ } -+ -+ if ((new_list = http_persistent_handle_list_init(NULL))) { -+ if (SUCCESS == zend_hash_quick_add(&provider->list.free, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &new_list, sizeof(http_persistent_handle_list *), (void *) &list)) { -+#if HTTP_DEBUG_PHANDLES -+ fprintf(stderr, "LSTFIND: %p (new)\n", *list); -+#endif -+ return *list; -+ } -+ http_persistent_handle_list_free(&new_list, provider->dtor); -+ } -+ -+ return NULL; -+} -+ -+static inline STATUS http_persistent_handle_do_acquire(http_persistent_handle_provider *provider, void **handle TSRMLS_DC) -+{ -+ ulong index; -+ void **handle_ptr; -+ http_persistent_handle_list *list; -+ -+ if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) { -+ zend_hash_internal_pointer_end(&list->free); -+ if (HASH_KEY_NON_EXISTANT != zend_hash_get_current_key(&list->free, NULL, &index, 0) && SUCCESS == zend_hash_get_current_data(&list->free, (void *) &handle_ptr)) { -+ *handle = *handle_ptr; -+ zend_hash_index_del(&list->free, index); -+ } else { -+ *handle = provider->ctor(); -+ } -+ -+ if (*handle) { -+ ++provider->list.used; -+ ++list->used; -+ return SUCCESS; -+ } -+ } else { -+ *handle = NULL; -+ } -+ -+ return FAILURE; -+} -+ -+static inline STATUS http_persistent_handle_do_release(http_persistent_handle_provider *provider, void **handle TSRMLS_DC) -+{ -+ http_persistent_handle_list *list; -+ -+ if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) { -+ if (provider->list.used >= HTTP_G->persistent.handles.limit) { -+ provider->dtor(*handle); -+ } else { -+ if (SUCCESS != zend_hash_next_index_insert(&list->free, (void *) handle, sizeof(void *), NULL)) { -+ return FAILURE; -+ } -+ } -+ -+ *handle = NULL; -+ --provider->list.used; -+ --list->used; -+ return SUCCESS; -+ } -+ -+ return FAILURE; -+} -+ -+static inline STATUS http_persistent_handle_do_accrete(http_persistent_handle_provider *provider, void *old_handle, void **new_handle TSRMLS_DC) -+{ -+ http_persistent_handle_list *list; -+ -+ if (provider->copy && (*new_handle = provider->copy(old_handle))) { -+ if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) { -+ ++list->used; -+ } -+ ++provider->list.used; -+ return SUCCESS; -+ } -+ return FAILURE; -+} -+ -+static void http_persistent_handles_hash_dtor(void *p) -+{ -+ http_persistent_handle_provider *provider = (http_persistent_handle_provider *) p; -+ http_persistent_handle_list **list, *list_tmp; -+ HashPosition pos; -+ -+ FOREACH_HASH_VAL(pos, &provider->list.free, list) { -+ /* fix shutdown crash in PHP4 */ -+ list_tmp = *list; -+ http_persistent_handle_list_free(&list_tmp, provider->dtor); -+ } -+ -+ zend_hash_destroy(&provider->list.free); -+} -+ -+PHP_MINIT_FUNCTION(http_persistent_handle) -+{ -+ zend_hash_init(&http_persistent_handles_hash, 0, NULL, http_persistent_handles_hash_dtor, 1); -+#ifdef ZTS -+ http_persistent_handles_lock = tsrm_mutex_alloc(); -+#endif -+ return SUCCESS; -+} -+ -+PHP_MSHUTDOWN_FUNCTION(http_persistent_handle) -+{ -+ zend_hash_destroy(&http_persistent_handles_hash); -+#ifdef ZTS -+ tsrm_mutex_free(http_persistent_handles_lock); -+#endif -+ return SUCCESS; -+} -+ -+PHP_HTTP_API STATUS _http_persistent_handle_provide_ex(const char *name_str, size_t name_len, http_persistent_handle_ctor ctor, http_persistent_handle_dtor dtor, http_persistent_handle_copy copy) -+{ -+ STATUS status = FAILURE; -+ http_persistent_handle_provider provider; -+ -+ LOCK(); -+ if (http_persistent_handle_list_init(&provider.list)) { -+ provider.ctor = ctor; -+ provider.dtor = dtor; -+ provider.copy = copy; -+ -+#if HTTP_DEBUG_PHANDLES -+ fprintf(stderr, "PROVIDE: %s\n", name_str); -+#endif -+ -+ if (SUCCESS == zend_hash_add(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider, sizeof(http_persistent_handle_provider), NULL)) { -+ status = SUCCESS; -+ } -+ } -+ UNLOCK(); -+ -+ return status; -+} -+ -+PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC) -+{ -+ STATUS status = FAILURE; -+ http_persistent_handle_provider *provider; -+ -+ *handle = NULL; -+ LOCK(); -+ if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) { -+ status = http_persistent_handle_do_acquire(provider, handle TSRMLS_CC); -+ } -+ UNLOCK(); -+ -+#if HTTP_DEBUG_PHANDLES -+ fprintf(stderr, "ACQUIRE: %p (%s)\n", *handle, name_str); -+#endif -+ -+ return status; -+} -+ -+PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC) -+{ -+ STATUS status = FAILURE; -+ http_persistent_handle_provider *provider; -+#if HTTP_DEBUG_PHANDLES -+ void *handle_tmp = *handle; -+#endif -+ -+ LOCK(); -+ if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) { -+ status = http_persistent_handle_do_release(provider, handle TSRMLS_CC); -+ } -+ UNLOCK(); -+ -+#if HTTP_DEBUG_PHANDLES -+ fprintf(stderr, "RELEASE: %p (%s)\n", handle_tmp, name_str); -+#endif -+ -+ return status; -+} -+ -+PHP_HTTP_API STATUS _http_persistent_handle_accrete_ex(const char *name_str, size_t name_len, void *old_handle, void **new_handle TSRMLS_DC) -+{ -+ STATUS status = FAILURE; -+ http_persistent_handle_provider *provider; -+ -+ *new_handle = NULL; -+ LOCK(); -+ if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) { -+ status = http_persistent_handle_do_accrete(provider, old_handle, new_handle TSRMLS_CC); -+ } -+ UNLOCK(); -+ -+#if HTTP_DEBUG_PHANDLES -+ fprintf(stderr, "ACCRETE: %p > %p (%s)\n", old_handle, *new_handle, name_str); -+#endif -+ -+ return status; -+} -+ -+PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len, int current_ident_only TSRMLS_DC) -+{ -+ http_persistent_handle_provider *provider; -+ http_persistent_handle_list *list, **listp; -+ HashPosition pos1, pos2; -+ -+ LOCK(); -+ if (name_str && name_len) { -+ if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, HTTP_ZAPI_CONST_CAST(char *) name_str, name_len+1, (void *) &provider)) { -+ if (current_ident_only) { -+ if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) { -+ http_persistent_handle_list_dtor(list, provider->dtor); -+ http_persistent_handle_list_init(list); -+ } -+ } else { -+ FOREACH_HASH_VAL(pos1, &provider->list.free, listp) { -+ http_persistent_handle_list_dtor(*listp, provider->dtor); -+ http_persistent_handle_list_init(*listp); -+ } -+ } -+ } -+ } else { -+ FOREACH_HASH_VAL(pos1, &http_persistent_handles_hash, provider) { -+ if (current_ident_only) { -+ if ((list = http_persistent_handle_list_find(provider TSRMLS_CC))) { -+ http_persistent_handle_list_dtor(list, provider->dtor); -+ http_persistent_handle_list_init(list); -+ } -+ } else { -+ FOREACH_HASH_VAL(pos2, &provider->list.free, listp) { -+ http_persistent_handle_list_dtor(*listp, provider->dtor); -+ http_persistent_handle_list_init(*listp); -+ } -+ } -+ } -+ } -+ UNLOCK(); -+} -+ -+PHP_HTTP_API HashTable *_http_persistent_handle_statall_ex(HashTable *ht TSRMLS_DC) -+{ -+ zval *zentry[2]; -+ HashPosition pos1, pos2; -+ HashKey key1 = initHashKey(0), key2 = initHashKey(0); -+ http_persistent_handle_provider *provider; -+ http_persistent_handle_list **list; -+ -+ LOCK(); -+ if (zend_hash_num_elements(&http_persistent_handles_hash)) { -+ if (!ht) { -+ ALLOC_HASHTABLE(ht); -+ zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0); -+ } -+ -+ FOREACH_HASH_KEYVAL(pos1, &http_persistent_handles_hash, key1, provider) { -+ MAKE_STD_ZVAL(zentry[0]); -+ array_init(zentry[0]); -+ -+ FOREACH_HASH_KEYVAL(pos2, &provider->list.free, key2, list) { -+ MAKE_STD_ZVAL(zentry[1]); -+ array_init(zentry[1]); -+ add_assoc_long_ex(zentry[1], ZEND_STRS("used"), (*list)->used); -+ add_assoc_long_ex(zentry[1], ZEND_STRS("free"), zend_hash_num_elements(&(*list)->free)); -+ -+ /* use zend_hash_* not add_assoc_* (which is zend_symtable_*) as we want a string even for numbers */ -+ zend_hash_add(Z_ARRVAL_P(zentry[0]), key2.str, key2.len, &zentry[1], sizeof(zval *), NULL); -+ } -+ -+ zend_hash_add(ht, key1.str, key1.len, &zentry[0], sizeof(zval *), NULL); -+ } -+ } else if (ht) { -+ ht = NULL; -+ } -+ UNLOCK(); -+ -+ return ht; -+} -+ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_querystring_api.c -@@ -0,0 +1,220 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_querystring_api.c 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#define HTTP_WANT_SAPI -+#include "php_http.h" -+ -+#include "php_variables.h" -+#ifdef HTTP_HAVE_ICONV -+# undef PHP_ATOM_INC -+# include "ext/iconv/php_iconv.h" -+# include "ext/standard/url.h" -+#endif -+ -+#include "php_http_api.h" -+#include "php_http_url_api.h" -+#include "php_http_querystring_api.h" -+ -+#ifdef ZEND_ENGINE_2 -+#define THIS_CE http_querystring_object_ce -+extern zend_class_entry *http_querystring_object_ce; -+#endif -+ -+ -+#define http_querystring_modify_array_ex(q, t, k, kl, i, pe) _http_querystring_modify_array_ex((q), (t), (k), (kl), (i), (pe) TSRMLS_CC) -+static inline int _http_querystring_modify_array_ex(zval *qarray, int key_type, char *key, int keylen, ulong idx, zval *params_entry TSRMLS_DC); -+#define http_querystring_modify_array(q, p) _http_querystring_modify_array((q), (p) TSRMLS_CC) -+static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC); -+ -+ -+#ifdef HTTP_HAVE_ICONV -+PHP_HTTP_API int _http_querystring_xlate(zval *array, zval *param, const char *ie, const char *oe TSRMLS_DC) -+{ -+ HashPosition pos; -+ zval **entry = NULL; -+ char *xlate_str = NULL, *xkey; -+ size_t xlate_len = 0, xlen; -+ HashKey key = initHashKey(0); -+ -+ FOREACH_KEYVAL(pos, param, key, entry) { -+ if (key.type == HASH_KEY_IS_STRING) { -+ if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(key.str, key.len-1, &xkey, &xlen, oe, ie)) { -+ http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", key.len-1, key.str, ie, oe); -+ return FAILURE; -+ } -+ } -+ -+ if (Z_TYPE_PP(entry) == IS_STRING) { -+ if (PHP_ICONV_ERR_SUCCESS != php_iconv_string(Z_STRVAL_PP(entry), Z_STRLEN_PP(entry), &xlate_str, &xlate_len, oe, ie)) { -+ if (key.type == HASH_KEY_IS_STRING) { -+ efree(xkey); -+ } -+ http_error_ex(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to convert '%.*s' from '%s' to '%s'", Z_STRLEN_PP(entry), Z_STRVAL_PP(entry), ie, oe); -+ return FAILURE; -+ } -+ if (key.type == HASH_KEY_IS_STRING) { -+ add_assoc_stringl_ex(array, xkey, xlen+1, xlate_str, xlate_len, 0); -+ } else { -+ add_index_stringl(array, key.num, xlate_str, xlate_len, 0); -+ } -+ } else if (Z_TYPE_PP(entry) == IS_ARRAY) { -+ zval *subarray; -+ -+ MAKE_STD_ZVAL(subarray); -+ array_init(subarray); -+ if (key.type == HASH_KEY_IS_STRING) { -+ add_assoc_zval_ex(array, xkey, xlen+1, subarray); -+ } else { -+ add_index_zval(array, key.num, subarray); -+ } -+ if (SUCCESS != http_querystring_xlate(subarray, *entry, ie, oe)) { -+ if (key.type == HASH_KEY_IS_STRING) { -+ efree(xkey); -+ } -+ return FAILURE; -+ } -+ } -+ -+ if (key.type == HASH_KEY_IS_STRING) { -+ efree(xkey); -+ } -+ } -+ return SUCCESS; -+} -+#endif /* HAVE_ICONV */ -+ -+PHP_HTTP_API void _http_querystring_update(zval *qarray, zval *qstring TSRMLS_DC) -+{ -+ char *s = NULL; -+ size_t l = 0; -+ -+ if (Z_TYPE_P(qarray) != IS_ARRAY) { -+ convert_to_array(qarray); -+ } -+ if (SUCCESS == http_urlencode_hash_ex(Z_ARRVAL_P(qarray), 0, NULL, 0, &s, &l)) { -+ zval_dtor(qstring); -+ ZVAL_STRINGL(qstring, s, l, 0); -+ } else { -+ http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Failed to update query string"); -+ } -+} -+ -+PHP_HTTP_API int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC) -+{ -+ if (Z_TYPE_P(params) == IS_ARRAY) { -+ return http_querystring_modify_array(qarray, params); -+ } else if (Z_TYPE_P(params) == IS_OBJECT) { -+#ifdef ZEND_ENGINE_2 -+ if (instanceof_function(Z_OBJCE_P(params), http_querystring_object_ce TSRMLS_CC)) { -+ return http_querystring_modify_array(qarray, zend_read_property(THIS_CE, params, ZEND_STRS("queryArray")-1, 0 TSRMLS_CC)); -+ } else { -+#endif -+ return http_querystring_modify_array(qarray, params); -+#ifdef ZEND_ENGINE_2 -+ } -+#endif -+ } else { -+ int rv; -+ zval array; -+ zval *qstring = http_zsep(IS_STRING, params); -+ -+ INIT_PZVAL(&array); -+ array_init(&array); -+ -+ sapi_module.treat_data(PARSE_STRING, estrdup(Z_STRVAL_P(qstring)), &array TSRMLS_CC); -+ zval_ptr_dtor(&qstring); -+ -+ rv = http_querystring_modify_array(qarray, &array); -+ zval_dtor(&array); -+ return rv; -+ } -+} -+ -+static inline int _http_querystring_modify_array(zval *qarray, zval *params TSRMLS_DC) -+{ -+ int rv = 0; -+ HashKey key = initHashKey(0); -+ HashPosition pos; -+ zval **params_entry = NULL; -+ -+ FOREACH_HASH_KEYVAL(pos, HASH_OF(params), key, params_entry) { -+ /* only public properties */ -+ if ((key.type != HASH_KEY_IS_STRING || *key.str) && http_querystring_modify_array_ex(qarray, key.type, key.str, key.len, key.num, *params_entry)) { -+ rv = 1; -+ } -+ } -+ -+ return rv; -+} -+ -+static inline int _http_querystring_modify_array_ex(zval *qarray, int key_type, char *key, int keylen, ulong idx, zval *params_entry TSRMLS_DC) -+{ -+ zval **qarray_entry; -+ -+ /* ensure array type */ -+ if (Z_TYPE_P(qarray) != IS_ARRAY) { -+ convert_to_array(qarray); -+ } -+ -+ /* delete */ -+ if (Z_TYPE_P(params_entry) == IS_NULL) { -+ if (key_type == HASH_KEY_IS_STRING) { -+ return (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarray), key, keylen)); -+ } else { -+ return (SUCCESS == zend_hash_index_del(Z_ARRVAL_P(qarray), idx)); -+ } -+ } -+ -+ /* update */ -+ if ( ((key_type == HASH_KEY_IS_STRING) && (SUCCESS == zend_hash_find(Z_ARRVAL_P(qarray), key, keylen, (void *) &qarray_entry))) || -+ ((key_type == HASH_KEY_IS_LONG) && (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(qarray), idx, (void *) &qarray_entry)))) { -+ zval equal; -+ -+ /* recursive */ -+ if (Z_TYPE_P(params_entry) == IS_ARRAY || Z_TYPE_P(params_entry) == IS_OBJECT) { -+ return http_querystring_modify(*qarray_entry, params_entry); -+ } -+ /* equal */ -+ if ((SUCCESS == is_equal_function(&equal, *qarray_entry, params_entry TSRMLS_CC)) && Z_BVAL(equal)) { -+ return 0; -+ } -+ } -+ -+ /* add */ -+ if (Z_TYPE_P(params_entry) == IS_OBJECT) { -+ zval *new_array; -+ -+ MAKE_STD_ZVAL(new_array); -+ array_init(new_array); -+ http_querystring_modify_array(new_array, params_entry); -+ params_entry = new_array; -+ } else { -+ ZVAL_ADDREF(params_entry); -+ } -+ if (key_type == HASH_KEY_IS_STRING) { -+ add_assoc_zval_ex(qarray, key, keylen, params_entry); -+ } else { -+ add_index_zval(qarray, idx, params_entry); -+ } -+ return 1; -+} -+ -+/* -+ * 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 -+ */ ---- /dev/null -+++ b/ext/http/http_querystring_object.c -@@ -0,0 +1,633 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_querystring_object.c 323304 2012-02-17 21:13:24Z mike $ */ -+ -+#define HTTP_WANT_SAPI -+#include "php_http.h" -+ -+#ifdef ZEND_ENGINE_2 -+ -+#include "php_variables.h" -+#include "zend_interfaces.h" -+ -+#include "php_http_api.h" -+#include "php_http_querystring_api.h" -+#include "php_http_querystring_object.h" -+#include "php_http_exception_object.h" -+ -+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpQueryString, method, 0, req_args) -+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpQueryString, method, 0) -+#define HTTP_QUERYSTRING_ME(method, visibility) PHP_ME(HttpQueryString, method, HTTP_ARGS(HttpQueryString, method), visibility) -+#define HTTP_QUERYSTRING_GME(method, visibility) PHP_ME(HttpQueryString, method, HTTP_ARGS(HttpQueryString, __getter), visibility) -+ -+HTTP_BEGIN_ARGS(__construct, 0) -+ HTTP_ARG_VAL(global, 0) -+ HTTP_ARG_VAL(params, 0) -+HTTP_END_ARGS; -+ -+#ifndef WONKY -+HTTP_BEGIN_ARGS(singleton, 0) -+ HTTP_ARG_VAL(global, 0) -+HTTP_END_ARGS; -+#endif -+ -+HTTP_BEGIN_ARGS(factory, 0) -+ HTTP_ARG_VAL(global, 0) -+ HTTP_ARG_VAL(params, 0) -+ HTTP_ARG_VAL(class_name, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(toArray); -+HTTP_EMPTY_ARGS(toString); -+ -+HTTP_BEGIN_ARGS(get, 0) -+ HTTP_ARG_VAL(name, 0) -+ HTTP_ARG_VAL(type, 0) -+ HTTP_ARG_VAL(defval, 0) -+ HTTP_ARG_VAL(delete, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(set, 1) -+ HTTP_ARG_VAL(params, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(mod, 0) -+ HTTP_ARG_VAL(params, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(__getter, 1) -+ HTTP_ARG_VAL(name, 0) -+ HTTP_ARG_VAL(defval, 0) -+ HTTP_ARG_VAL(delete, 0) -+HTTP_END_ARGS; -+ -+#ifdef HTTP_HAVE_ICONV -+HTTP_BEGIN_ARGS(xlate, 2) -+ HTTP_ARG_VAL(from_encoding, 0) -+ HTTP_ARG_VAL(to_encoding, 0) -+HTTP_END_ARGS; -+#endif -+ -+HTTP_EMPTY_ARGS(serialize); -+HTTP_BEGIN_ARGS(unserialize, 1) -+ HTTP_ARG_VAL(serialized, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(offsetGet, 1) -+ HTTP_ARG_VAL(offset, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(offsetSet, 2) -+ HTTP_ARG_VAL(offset, 0) -+ HTTP_ARG_VAL(value, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(offsetExists, 1) -+ HTTP_ARG_VAL(offset, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(offsetUnset, 1) -+ HTTP_ARG_VAL(offset, 0) -+HTTP_END_ARGS; -+ -+ -+#define THIS_CE http_querystring_object_ce -+zend_class_entry *http_querystring_object_ce; -+zend_function_entry http_querystring_object_fe[] = { -+ HTTP_QUERYSTRING_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR|ZEND_ACC_FINAL) -+ -+ HTTP_QUERYSTRING_ME(toArray, ZEND_ACC_PUBLIC) -+ HTTP_QUERYSTRING_ME(toString, ZEND_ACC_PUBLIC) -+ ZEND_MALIAS(HttpQueryString, __toString, toString, HTTP_ARGS(HttpQueryString, toString), ZEND_ACC_PUBLIC) -+ -+ HTTP_QUERYSTRING_ME(get, ZEND_ACC_PUBLIC) -+ HTTP_QUERYSTRING_ME(set, ZEND_ACC_PUBLIC) -+ HTTP_QUERYSTRING_ME(mod, ZEND_ACC_PUBLIC) -+ -+ HTTP_QUERYSTRING_GME(getBool, ZEND_ACC_PUBLIC) -+ HTTP_QUERYSTRING_GME(getInt, ZEND_ACC_PUBLIC) -+ HTTP_QUERYSTRING_GME(getFloat, ZEND_ACC_PUBLIC) -+ HTTP_QUERYSTRING_GME(getString, ZEND_ACC_PUBLIC) -+ HTTP_QUERYSTRING_GME(getArray, ZEND_ACC_PUBLIC) -+ HTTP_QUERYSTRING_GME(getObject, ZEND_ACC_PUBLIC) -+ -+ HTTP_QUERYSTRING_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) -+#ifndef WONKY -+ HTTP_QUERYSTRING_ME(singleton, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) -+#endif -+#ifdef HTTP_HAVE_ICONV -+ HTTP_QUERYSTRING_ME(xlate, ZEND_ACC_PUBLIC) -+#endif -+ -+ /* Implements Serializable */ -+ HTTP_QUERYSTRING_ME(serialize, ZEND_ACC_PUBLIC) -+ HTTP_QUERYSTRING_ME(unserialize, ZEND_ACC_PUBLIC) -+ -+ /* Implements ArrayAccess */ -+ HTTP_QUERYSTRING_ME(offsetGet, ZEND_ACC_PUBLIC) -+ HTTP_QUERYSTRING_ME(offsetSet, ZEND_ACC_PUBLIC) -+ HTTP_QUERYSTRING_ME(offsetExists, ZEND_ACC_PUBLIC) -+ HTTP_QUERYSTRING_ME(offsetUnset, ZEND_ACC_PUBLIC) -+ -+ EMPTY_FUNCTION_ENTRY -+}; -+static zend_object_handlers http_querystring_object_handlers; -+ -+PHP_MINIT_FUNCTION(http_querystring_object) -+{ -+ HTTP_REGISTER_CLASS_EX(HttpQueryString, http_querystring_object, NULL, 0); -+ -+#ifndef WONKY -+ zend_class_implements(http_querystring_object_ce TSRMLS_CC, 2, zend_ce_serializable, zend_ce_arrayaccess); -+#endif -+ -+ zend_declare_property_null(THIS_CE, ZEND_STRS("instance")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC); -+ zend_declare_property_null(THIS_CE, ZEND_STRS("queryArray")-1, ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_string(THIS_CE, ZEND_STRS("queryString")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC); -+ -+#ifndef WONKY -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_BOOL")-1, HTTP_QUERYSTRING_TYPE_BOOL TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_INT")-1, HTTP_QUERYSTRING_TYPE_INT TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_FLOAT")-1, HTTP_QUERYSTRING_TYPE_FLOAT TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_STRING")-1, HTTP_QUERYSTRING_TYPE_STRING TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_ARRAY")-1, HTTP_QUERYSTRING_TYPE_ARRAY TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_OBJECT")-1, HTTP_QUERYSTRING_TYPE_OBJECT TSRMLS_CC); -+#endif -+ -+ HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_BOOL", HTTP_QUERYSTRING_TYPE_BOOL); -+ HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_INT", HTTP_QUERYSTRING_TYPE_INT); -+ HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_FLOAT", HTTP_QUERYSTRING_TYPE_FLOAT); -+ HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_STRING", HTTP_QUERYSTRING_TYPE_STRING); -+ HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_ARRAY", HTTP_QUERYSTRING_TYPE_ARRAY); -+ HTTP_LONG_CONSTANT("HTTP_QUERYSTRING_TYPE_OBJECT", HTTP_QUERYSTRING_TYPE_OBJECT); -+ -+ return SUCCESS; -+} -+ -+zend_object_value _http_querystring_object_new(zend_class_entry *ce TSRMLS_DC) -+{ -+ return http_querystring_object_new_ex(ce, NULL, NULL); -+} -+ -+zend_object_value _http_querystring_object_new_ex(zend_class_entry *ce, void *nothing, http_querystring_object **ptr TSRMLS_DC) -+{ -+ zend_object_value ov; -+ http_querystring_object *o; -+ -+ o = ecalloc(1, sizeof(http_querystring_object)); -+ o->zo.ce = ce; -+ -+ if (ptr) { -+ *ptr = o; -+ } -+ -+#ifdef ZEND_ENGINE_2_4 -+ zend_object_std_init(o, ce TSRMLS_CC); -+ object_properties_init(o, ce); -+#else -+ ALLOC_HASHTABLE(OBJ_PROP(o)); -+ zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0); -+ zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+#endif -+ -+ ov.handle = putObject(http_querystring_object, o); -+ ov.handlers = &http_querystring_object_handlers; -+ -+ return ov; -+} -+ -+void _http_querystring_object_free(zend_object *object TSRMLS_DC) -+{ -+ http_querystring_object *o = (http_querystring_object *) object; -+ -+ freeObject(o); -+} -+ -+/* {{{ querystring helpers */ -+#define http_querystring_instantiate(t, g, p, u) _http_querystring_instantiate((t), (g), (p), (u) TSRMLS_CC) -+static inline zval *_http_querystring_instantiate(zval *this_ptr, zend_bool global, zval *params, zend_bool defer_update TSRMLS_DC) -+{ -+ zval *qarray = NULL, *qstring = NULL, **_SERVER = NULL, **_GET = NULL, **QUERY_STRING = NULL;; -+ -+ if (!this_ptr) { -+ MAKE_STD_ZVAL(this_ptr); -+ Z_TYPE_P(this_ptr) = IS_OBJECT; -+ this_ptr->value.obj = http_querystring_object_new(http_querystring_object_ce); -+ } -+ if (global) { -+#ifdef ZEND_ENGINE_2 -+ zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC); -+#endif -+ if ( (SUCCESS == zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &_SERVER)) && -+ (Z_TYPE_PP(_SERVER) == IS_ARRAY) && -+ (SUCCESS == zend_hash_find(Z_ARRVAL_PP(_SERVER), "QUERY_STRING", sizeof("QUERY_STRING"), (void *) &QUERY_STRING))) { -+ -+ qstring = *QUERY_STRING; -+#ifdef ZEND_ENGINE_2 -+ zend_is_auto_global("_GET", lenof("_GET") TSRMLS_CC); -+#endif -+ if ((SUCCESS == zend_hash_find(&EG(symbol_table), "_GET", sizeof("_GET"), (void *) &_GET)) && (Z_TYPE_PP(_GET) == IS_ARRAY)) { -+ qarray = *_GET; -+ } else { -+ http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Could not acquire reference to superglobal GET array"); -+ } -+ } else { -+ http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Could not acquire reference to QUERY_STRING"); -+ } -+ -+ if (qarray && qstring) { -+ if (Z_TYPE_P(qstring) != IS_STRING) { -+ convert_to_string(qstring); -+ } -+ -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, qarray TSRMLS_CC); -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, qstring TSRMLS_CC); -+#ifdef Z_SET_ISREF -+ Z_SET_ISREF_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC)); -+ Z_SET_ISREF_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC)); -+#else -+ zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC)->is_ref = 1; -+ zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC)->is_ref = 1; -+#endif -+ -+ if (params) { -+ http_querystring_modify(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC), params); -+ } -+ if (!defer_update) { -+ http_querystring_update(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC), zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC)); -+ } -+ } -+ } else { -+ MAKE_STD_ZVAL(qarray); -+ array_init(qarray); -+ -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, qarray TSRMLS_CC); -+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryString")-1, "", 0 TSRMLS_CC); -+ -+ if (params && http_querystring_modify(qarray, params) && !defer_update) { -+ http_querystring_update(qarray, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC)); -+ } -+ -+ zval_ptr_dtor(&qarray); -+ } -+ -+ return this_ptr; -+} -+ -+#define http_querystring_get(o, t, n, l, def, del, r) _http_querystring_get((o), (t), (n), (l), (def), (del), (r) TSRMLS_CC) -+static inline void _http_querystring_get(zval *this_ptr, int type, char *name, uint name_len, zval *defval, zend_bool del, zval *return_value TSRMLS_DC) -+{ -+ zval **arrval, *qarray = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC); -+ -+ if ((Z_TYPE_P(qarray) == IS_ARRAY) && (SUCCESS == zend_hash_find(Z_ARRVAL_P(qarray), name, name_len + 1, (void *) &arrval))) { -+ if (type) { -+ zval *value = http_zsep(type, *arrval); -+ RETVAL_ZVAL(value, 1, 1); -+ } else { -+ RETVAL_ZVAL(*arrval, 1, 0); -+ } -+ -+ if (del && (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarray), name, name_len + 1))) { -+ http_querystring_update(qarray, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC)); -+ } -+ } else if(defval) { -+ RETURN_ZVAL(defval, 1, 0); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto final void HttpQueryString::__construct([bool global = true[, mixed add]) -+ Creates a new HttpQueryString object instance. Operates on and modifies $_GET and $_SERVER['QUERY_STRING'] if global is TRUE. */ -+PHP_METHOD(HttpQueryString, __construct) -+{ -+ zend_bool global = 1; -+ zval *params = NULL; -+ -+ SET_EH_THROW_HTTP(); -+ if (!sapi_module.treat_data) { -+ http_error(HE_ERROR, HTTP_E_QUERYSTRING, "The SAPI does not have a treat_data function registered"); -+ } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bz", &global, ¶ms)) { -+ http_querystring_instantiate(getThis(), global, params, 0); -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+/* {{{ proto HttpQueryString HttpQueryString::factory([bool global = TRUE[, mixed params[, string class_name = "HttpQueryString"]) -+ Creates a new HttpQueryString object instance. */ -+PHP_METHOD(HttpQueryString, factory) -+{ -+ zend_bool global = 1; -+ zval *params = NULL; -+ char *cn = NULL; -+ int cl = 0; -+ zend_object_value ov; -+ -+ SET_EH_THROW_HTTP(); -+ if (!sapi_module.treat_data) { -+ http_error(HE_ERROR, HTTP_E_QUERYSTRING, "The SAPI does not have a treat_data function registered"); -+ } else if ( SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bzs", &global, ¶ms, &cn, &cl) && -+ SUCCESS == http_object_new(&ov, cn, cl, _http_querystring_object_new_ex, http_querystring_object_ce, NULL, NULL)) { -+ RETVAL_OBJVAL(ov, 0); -+ http_querystring_instantiate(return_value, global, params, 0); -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+/* {{{ proto string HttpQueryString::toString() -+ Returns the string representation. */ -+PHP_METHOD(HttpQueryString, toString) -+{ -+ NO_ARGS; -+ RETURN_PROP(queryString); -+} -+/* }}} */ -+ -+/* {{{ proto array HttpQueryString::toArray() -+ Returns the array representation. */ -+PHP_METHOD(HttpQueryString, toArray) -+{ -+ NO_ARGS; -+ RETURN_PROP(queryArray); -+} -+/* }}} */ -+ -+/* {{{ proto mixed HttpQueryString::get([string key[, mixed type = 0[, mixed defval = NULL[, bool delete = false]]]]) -+ Get (part of) the query string. The type parameter is either one of the HttpQueryString::TYPE_* constants or a type abbreviation like "b" for bool, "i" for int, "f" for float, "s" for string, "a" for array and "o" for a stdClass object. */ -+PHP_METHOD(HttpQueryString, get) -+{ -+ char *name = NULL; -+ int name_len = 0; -+ long type = 0; -+ zend_bool del = 0; -+ zval *ztype = NULL, *defval = NULL; -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|szzb", &name, &name_len, &ztype, &defval, &del)) { -+ if (name && name_len) { -+ if (ztype) { -+ if (Z_TYPE_P(ztype) == IS_LONG) { -+ type = Z_LVAL_P(ztype); -+ } else if(Z_TYPE_P(ztype) == IS_STRING) { -+ switch (Z_STRVAL_P(ztype)[0]) { -+ case 'B': -+ case 'b': type = HTTP_QUERYSTRING_TYPE_BOOL; break; -+ case 'I': -+ case 'i': type = HTTP_QUERYSTRING_TYPE_INT; break; -+ case 'F': -+ case 'f': type = HTTP_QUERYSTRING_TYPE_FLOAT; break; -+ case 'S': -+ case 's': type = HTTP_QUERYSTRING_TYPE_STRING; break; -+ case 'A': -+ case 'a': type = HTTP_QUERYSTRING_TYPE_ARRAY; break; -+ case 'O': -+ case 'o': type = HTTP_QUERYSTRING_TYPE_OBJECT; break; -+ } -+ } -+ } -+ http_querystring_get(getThis(), type, name, name_len, defval, del, return_value); -+ } else { -+ RETURN_PROP(queryString); -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string HttpQueryString::set(mixed params) -+ Set query string entry/entries. NULL values will unset the variable. */ -+PHP_METHOD(HttpQueryString, set) -+{ -+ zval *params; -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶ms)) { -+ zval *qarray = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC); -+ if (http_querystring_modify(qarray, params)) { -+ http_querystring_update(qarray, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC)); -+ } -+ } -+ -+ if (return_value_used) { -+ RETURN_PROP(queryString); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto HttpQueryString HttpQueryString::mod(mixed params) -+ Copies the query string object and sets provided params at the clone. */ -+PHP_METHOD(HttpQueryString, mod) -+{ -+ zval *zobj, *qarr, *qstr, *params; -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶ms)) { -+ zobj = http_querystring_instantiate(NULL, 0, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC), 1); -+ qarr = zend_read_property(THIS_CE, zobj, ZEND_STRS("queryArray")-1, 0 TSRMLS_CC); -+ qstr = zend_read_property(THIS_CE, zobj, ZEND_STRS("queryString")-1, 0 TSRMLS_CC); -+ -+ http_querystring_modify(qarr, params); -+ http_querystring_update(qarr, qstr); -+ -+ RETURN_ZVAL(zobj, 1, 1); -+ } -+} -+/* }}} */ -+ -+#ifndef WONKY -+/* {{{ proto static HttpQueryString HttpQueryString::singleton([bool global = true]) -+ Get a single instance (differentiates between the global setting). */ -+PHP_METHOD(HttpQueryString, singleton) -+{ -+ zend_bool global = 1; -+ zval *instance = *zend_std_get_static_property(THIS_CE, ZEND_STRS("instance")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC); -+ -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &global)) { -+ zval **zobj_ptr = NULL, *zobj = NULL; -+ -+ if (Z_TYPE_P(instance) == IS_ARRAY) { -+ if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(instance), global, (void *) &zobj_ptr)) { -+ RETVAL_ZVAL(*zobj_ptr, 1, 0); -+ } else { -+ zobj = http_querystring_instantiate(NULL, global, NULL, (zend_bool) !global); -+ add_index_zval(instance, global, zobj); -+ RETVAL_OBJECT(zobj, 1); -+ } -+ } else { -+ MAKE_STD_ZVAL(instance); -+ array_init(instance); -+ -+ zobj = http_querystring_instantiate(NULL, global, NULL, (zend_bool) !global); -+ add_index_zval(instance, global, zobj); -+ RETVAL_OBJECT(zobj, 1); -+ -+ zend_update_static_property(THIS_CE, ZEND_STRS("instance")-1, instance TSRMLS_CC); -+ zval_ptr_dtor(&instance); -+ } -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+#endif -+ -+/* {{{ Getters by type */ -+#define HTTP_QUERYSTRING_GETTER(method, TYPE) \ -+PHP_METHOD(HttpQueryString, method) \ -+{ \ -+ char *name; \ -+ int name_len; \ -+ zval *defval = NULL; \ -+ zend_bool del = 0; \ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zb", &name, &name_len, &defval, &del)) { \ -+ http_querystring_get(getThis(), TYPE, name, name_len, defval, del, return_value); \ -+ } \ -+} -+HTTP_QUERYSTRING_GETTER(getBool, IS_BOOL); -+HTTP_QUERYSTRING_GETTER(getInt, IS_LONG); -+HTTP_QUERYSTRING_GETTER(getFloat, IS_DOUBLE); -+HTTP_QUERYSTRING_GETTER(getString, IS_STRING); -+HTTP_QUERYSTRING_GETTER(getArray, IS_ARRAY); -+HTTP_QUERYSTRING_GETTER(getObject, IS_OBJECT); -+/* }}} */ -+ -+#ifdef HTTP_HAVE_ICONV -+/* {{{ proto bool HttpQueryString::xlate(string ie, string oe) -+ Converts the query string from the source encoding ie to the target encoding oe. WARNING: Don't use any character set that can contain NUL bytes like UTF-16. */ -+PHP_METHOD(HttpQueryString, xlate) -+{ -+ char *ie, *oe; -+ int ie_len, oe_len; -+ zval xa, *qa, *qs; -+ STATUS rs; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &ie, &ie_len, &oe, &oe_len)) { -+ RETURN_FALSE; -+ } -+ -+ qa = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC); -+ qs = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC); -+ INIT_PZVAL(&xa); -+ array_init(&xa); -+ -+ if (SUCCESS == (rs = http_querystring_xlate(&xa, qa, ie, oe))) { -+ zend_hash_clean(Z_ARRVAL_P(qa)); -+ zend_hash_copy(Z_ARRVAL_P(qa), Z_ARRVAL(xa), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+ http_querystring_update(qa, qs); -+ } -+ zval_dtor(&xa); -+ -+ RETURN_SUCCESS(rs); -+} -+/* }}} */ -+#endif /* HAVE_ICONV */ -+ -+/* {{{ proto string HttpQueryString::serialize() -+ Implements Serializable::serialize(). */ -+PHP_METHOD(HttpQueryString, serialize) -+{ -+ NO_ARGS; -+ RETURN_PROP(queryString); -+} -+/* }}} */ -+ -+/* {{{ proto void HttpQueryString::unserialize(string serialized) -+ Implements Serializable::unserialize(). */ -+PHP_METHOD(HttpQueryString, unserialize) -+{ -+ zval *serialized; -+ -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &serialized)) { -+ if (Z_TYPE_P(serialized) == IS_STRING) { -+ http_querystring_instantiate(getThis(), 0, serialized, 0); -+ } else { -+ http_error(HE_WARNING, HTTP_E_QUERYSTRING, "Expected a string as parameter"); -+ } -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+/* {{{ proto mixed HttpQueryString::offsetGet(string offset) -+ Implements ArrayAccess::offsetGet(). */ -+PHP_METHOD(HttpQueryString, offsetGet) -+{ -+ char *offset_str; -+ int offset_len; -+ zval **value; -+ -+ if ( (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) && -+ (SUCCESS == zend_hash_find(Z_ARRVAL_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC)), offset_str, offset_len + 1, (void *) &value))) { -+ RETVAL_ZVAL(*value, 1, 0); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto void HttpQueryString::offsetSet(string offset, mixed value) -+ Implements ArrayAccess::offsetGet(). */ -+PHP_METHOD(HttpQueryString, offsetSet) -+{ -+ char *offset_str; -+ int offset_len; -+ zval *value; -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &offset_str, &offset_len, &value)) { -+ zval *qarr = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC), *qstr = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC); -+ -+ ZVAL_ADDREF(value); -+ add_assoc_zval_ex(qarr, offset_str, offset_len + 1, value); -+ http_querystring_update(qarr, qstr); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpQueryString::offsetExists(string offset) -+ Implements ArrayAccess::offsetExists(). */ -+PHP_METHOD(HttpQueryString, offsetExists) -+{ -+ char *offset_str; -+ int offset_len; -+ zval **value; -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) { -+ RETURN_BOOL((SUCCESS == zend_hash_find(Z_ARRVAL_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC)), offset_str, offset_len + 1, (void *) &value)) && (Z_TYPE_PP(value) != IS_NULL)); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto void HttpQueryString::offsetUnset(string offset) -+ Implements ArrayAccess::offsetUnset(). */ -+PHP_METHOD(HttpQueryString, offsetUnset) -+{ -+ char *offset_str; -+ int offset_len; -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &offset_str, &offset_len)) { -+ zval *qarr = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryArray")-1, 0 TSRMLS_CC); -+ -+ if (SUCCESS == zend_hash_del(Z_ARRVAL_P(qarr), offset_str, offset_len + 1)) { -+ http_querystring_update(qarr, zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryString")-1, 0 TSRMLS_CC)); -+ } -+ } -+} -+/* }}} */ -+ -+#endif /* ZEND_ENGINE_2 */ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_request_api.c -@@ -0,0 +1,1326 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_request_api.c 310775 2011-05-05 06:02:50Z mike $ */ -+ -+#define HTTP_WANT_SAPI -+#define HTTP_WANT_CURL -+#include "php_http.h" -+ -+#ifdef HTTP_HAVE_CURL -+ -+#include "php_http_api.h" -+#include "php_http_persistent_handle_api.h" -+#include "php_http_request_api.h" -+#include "php_http_url_api.h" -+ -+#ifdef ZEND_ENGINE_2 -+# include "php_http_request_object.h" -+#endif -+ -+#include "php_http_request_int.h" -+ -+/* {{{ cruft for thread safe SSL crypto locks */ -+#ifdef HTTP_NEED_OPENSSL_TSL -+static MUTEX_T *http_openssl_tsl = NULL; -+ -+static void http_openssl_thread_lock(int mode, int n, const char * file, int line) -+{ -+ if (mode & CRYPTO_LOCK) { -+ tsrm_mutex_lock(http_openssl_tsl[n]); -+ } else { -+ tsrm_mutex_unlock(http_openssl_tsl[n]); -+ } -+} -+ -+static ulong http_openssl_thread_id(void) -+{ -+ return (ulong) tsrm_thread_id(); -+} -+#endif -+#ifdef HTTP_NEED_GNUTLS_TSL -+static int http_gnutls_mutex_create(void **m) -+{ -+ if (*((MUTEX_T *) m) = tsrm_mutex_alloc()) { -+ return SUCCESS; -+ } else { -+ return FAILURE; -+ } -+} -+ -+static int http_gnutls_mutex_destroy(void **m) -+{ -+ tsrm_mutex_free(*((MUTEX_T *) m)); -+ return SUCCESS; -+} -+ -+static int http_gnutls_mutex_lock(void **m) -+{ -+ return tsrm_mutex_lock(*((MUTEX_T *) m)); -+} -+ -+static int http_gnutls_mutex_unlock(void **m) -+{ -+ return tsrm_mutex_unlock(*((MUTEX_T *) m)); -+} -+ -+static struct gcry_thread_cbs http_gnutls_tsl = { -+ GCRY_THREAD_OPTION_USER, -+ NULL, -+ http_gnutls_mutex_create, -+ http_gnutls_mutex_destroy, -+ http_gnutls_mutex_lock, -+ http_gnutls_mutex_unlock -+}; -+#endif -+/* }}} */ -+ -+/* safe curl wrappers */ -+#define init_curl_storage(ch) \ -+ {\ -+ http_request_storage *st = pecalloc(1, sizeof(http_request_storage), 1); \ -+ curl_easy_setopt(ch, CURLOPT_PRIVATE, st); \ -+ curl_easy_setopt(ch, CURLOPT_ERRORBUFFER, st->errorbuffer); \ -+ } -+ -+static void *safe_curl_init(void) -+{ -+ CURL *ch; -+ -+ if ((ch = curl_easy_init())) { -+ init_curl_storage(ch); -+ return ch; -+ } -+ return NULL; -+} -+static void *safe_curl_copy(void *p) -+{ -+ CURL *ch; -+ -+ if ((ch = curl_easy_duphandle(p))) { -+ init_curl_storage(ch); -+ return ch; -+ } -+ return NULL; -+} -+static void safe_curl_dtor(void *p) { -+ http_request_storage *st = http_request_storage_get(p); -+ -+ curl_easy_cleanup(p); -+ -+ if (st) { -+ if (st->url) { -+ pefree(st->url, 1); -+ } -+ if (st->cookiestore) { -+ pefree(st->cookiestore, 1); -+ } -+ pefree(st, 1); -+ } -+} -+/* }}} */ -+ -+/* {{{ MINIT */ -+PHP_MINIT_FUNCTION(http_request) -+{ -+#ifdef HTTP_NEED_OPENSSL_TSL -+ /* mod_ssl, libpq or ext/curl might already have set thread lock callbacks */ -+ if (!CRYPTO_get_id_callback()) { -+ int i, c = CRYPTO_num_locks(); -+ -+ http_openssl_tsl = malloc(c * sizeof(MUTEX_T)); -+ -+ for (i = 0; i < c; ++i) { -+ http_openssl_tsl[i] = tsrm_mutex_alloc(); -+ } -+ -+ CRYPTO_set_id_callback(http_openssl_thread_id); -+ CRYPTO_set_locking_callback(http_openssl_thread_lock); -+ } -+#endif -+#ifdef HTTP_NEED_GNUTLS_TSL -+ gcry_control(GCRYCTL_SET_THREAD_CBS, &http_gnutls_tsl); -+#endif -+ -+ if (CURLE_OK != curl_global_init(CURL_GLOBAL_ALL)) { -+ return FAILURE; -+ } -+ -+ if (SUCCESS != http_persistent_handle_provide("http_request", safe_curl_init, safe_curl_dtor, safe_curl_copy)) { -+ return FAILURE; -+ } -+ -+ HTTP_LONG_CONSTANT("HTTP_AUTH_BASIC", CURLAUTH_BASIC); -+ HTTP_LONG_CONSTANT("HTTP_AUTH_DIGEST", CURLAUTH_DIGEST); -+#if HTTP_CURL_VERSION(7,19,3) -+ HTTP_LONG_CONSTANT("HTTP_AUTH_DIGEST_IE", CURLAUTH_DIGEST_IE); -+#endif -+ HTTP_LONG_CONSTANT("HTTP_AUTH_NTLM", CURLAUTH_NTLM); -+ HTTP_LONG_CONSTANT("HTTP_AUTH_GSSNEG", CURLAUTH_GSSNEGOTIATE); -+ HTTP_LONG_CONSTANT("HTTP_AUTH_ANY", CURLAUTH_ANY); -+ -+ HTTP_LONG_CONSTANT("HTTP_VERSION_NONE", CURL_HTTP_VERSION_NONE); /* to be removed */ -+ HTTP_LONG_CONSTANT("HTTP_VERSION_1_0", CURL_HTTP_VERSION_1_0); -+ HTTP_LONG_CONSTANT("HTTP_VERSION_1_1", CURL_HTTP_VERSION_1_1); -+ HTTP_LONG_CONSTANT("HTTP_VERSION_ANY", CURL_HTTP_VERSION_NONE); -+ -+ HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_TLSv1", CURL_SSLVERSION_TLSv1); -+ HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_SSLv2", CURL_SSLVERSION_SSLv2); -+ HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_SSLv3", CURL_SSLVERSION_SSLv3); -+ HTTP_LONG_CONSTANT("HTTP_SSL_VERSION_ANY", CURL_SSLVERSION_DEFAULT); -+ -+ HTTP_LONG_CONSTANT("HTTP_IPRESOLVE_V4", CURL_IPRESOLVE_V4); -+ HTTP_LONG_CONSTANT("HTTP_IPRESOLVE_V6", CURL_IPRESOLVE_V6); -+ HTTP_LONG_CONSTANT("HTTP_IPRESOLVE_ANY", CURL_IPRESOLVE_WHATEVER); -+ -+#if HTTP_CURL_VERSION(7,15,2) -+ HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS4", CURLPROXY_SOCKS4); -+#endif -+#if HTTP_CURL_VERSION(7,18,0) -+ HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS4A", CURLPROXY_SOCKS4A); -+ HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS5_HOSTNAME", CURLPROXY_SOCKS5_HOSTNAME); -+#endif -+ HTTP_LONG_CONSTANT("HTTP_PROXY_SOCKS5", CURLPROXY_SOCKS5); -+ HTTP_LONG_CONSTANT("HTTP_PROXY_HTTP", CURLPROXY_HTTP); -+#if HTTP_CURL_VERSION(7,19,4) -+ HTTP_LONG_CONSTANT("HTTP_PROXY_HTTP_1_0", CURLPROXY_HTTP_1_0); -+#endif -+ -+#if HTTP_CURL_VERSION(7,19,1) -+ HTTP_LONG_CONSTANT("HTTP_POSTREDIR_301", CURL_REDIR_POST_301); -+ HTTP_LONG_CONSTANT("HTTP_POSTREDIR_302", CURL_REDIR_POST_302); -+ HTTP_LONG_CONSTANT("HTTP_POSTREDIR_ALL", CURL_REDIR_POST_ALL); -+#endif -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ MSHUTDOWN */ -+PHP_MSHUTDOWN_FUNCTION(http_request) -+{ -+ curl_global_cleanup(); -+#ifdef HTTP_NEED_OPENSSL_TSL -+ if (http_openssl_tsl) { -+ int i, c = CRYPTO_num_locks(); -+ -+ CRYPTO_set_id_callback(NULL); -+ CRYPTO_set_locking_callback(NULL); -+ -+ for (i = 0; i < c; ++i) { -+ tsrm_mutex_free(http_openssl_tsl[i]); -+ } -+ -+ free(http_openssl_tsl); -+ http_openssl_tsl = NULL; -+ } -+#endif -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ forward declarations */ -+#define http_request_option(r, o, k, t) _http_request_option_ex((r), (o), (k), sizeof(k), (t) TSRMLS_CC) -+#define http_request_option_ex(r, o, k, l, t) _http_request_option_ex((r), (o), (k), (l), (t) TSRMLS_CC) -+static inline zval *_http_request_option_ex(http_request *request, HashTable *options, char *key, size_t keylen, int type TSRMLS_DC); -+#define http_request_option_cache(r, k, z) _http_request_option_cache_ex((r), (k), sizeof(k), 0, (z) TSRMLS_CC) -+#define http_request_option_cache_ex(r, k, kl, h, z) _http_request_option_cache_ex((r), (k), (kl), (h), (z) TSRMLS_CC) -+static inline zval *_http_request_option_cache_ex(http_request *r, char *key, size_t keylen, ulong h, zval *opt TSRMLS_DC); -+ -+#define http_request_cookies_enabled(r) _http_request_cookies_enabled((r)) -+static inline int _http_request_cookies_enabled(http_request *r); -+ -+static size_t http_curl_read_callback(void *, size_t, size_t, void *); -+static int http_curl_progress_callback(void *, double, double, double, double); -+static int http_curl_raw_callback(CURL *, curl_infotype, char *, size_t, void *); -+static int http_curl_dummy_callback(char *data, size_t n, size_t l, void *s) { return n*l; } -+static curlioerr http_curl_ioctl_callback(CURL *, curliocmd, void *); -+/* }}} */ -+ -+/* {{{ CURL *http_curl_init(http_request *) */ -+PHP_HTTP_API CURL * _http_curl_init_ex(CURL *ch, http_request *request TSRMLS_DC) -+{ -+ if (ch || (SUCCESS == http_persistent_handle_acquire("http_request", &ch))) { -+#if defined(ZTS) -+ curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L); -+#endif -+ curl_easy_setopt(ch, CURLOPT_HEADER, 0L); -+ curl_easy_setopt(ch, CURLOPT_FILETIME, 1L); -+ curl_easy_setopt(ch, CURLOPT_AUTOREFERER, 1L); -+ curl_easy_setopt(ch, CURLOPT_VERBOSE, 1L); -+ curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, NULL); -+ curl_easy_setopt(ch, CURLOPT_DEBUGFUNCTION, http_curl_raw_callback); -+ curl_easy_setopt(ch, CURLOPT_READFUNCTION, http_curl_read_callback); -+ curl_easy_setopt(ch, CURLOPT_IOCTLFUNCTION, http_curl_ioctl_callback); -+ curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, http_curl_dummy_callback); -+ -+ /* set context */ -+ if (request) { -+ curl_easy_setopt(ch, CURLOPT_DEBUGDATA, request); -+ -+ /* attach curl handle */ -+ request->ch = ch; -+ /* set defaults (also in http_request_reset()) */ -+ http_request_defaults(request); -+ } -+ } -+ -+ return ch; -+} -+/* }}} */ -+ -+/* {{{ CURL *http_curl_copy(CURL *) */ -+PHP_HTTP_API CURL *_http_curl_copy(CURL *ch TSRMLS_DC) -+{ -+ CURL *copy; -+ -+ if (SUCCESS == http_persistent_handle_accrete("http_request", ch, ©)) { -+ return copy; -+ } -+ return NULL; -+} -+/* }}} */ -+ -+/* {{{ void http_curl_free(CURL **) */ -+PHP_HTTP_API void _http_curl_free(CURL **ch TSRMLS_DC) -+{ -+ if (*ch) { -+ curl_easy_setopt(*ch, CURLOPT_NOPROGRESS, 1L); -+ curl_easy_setopt(*ch, CURLOPT_PROGRESSFUNCTION, NULL); -+ curl_easy_setopt(*ch, CURLOPT_VERBOSE, 0L); -+ curl_easy_setopt(*ch, CURLOPT_DEBUGFUNCTION, NULL); -+ -+ http_persistent_handle_release("http_request", ch); -+ } -+} -+/* }}} */ -+ -+/* {{{ http_request *http_request_init(http_request *) */ -+PHP_HTTP_API http_request *_http_request_init_ex(http_request *request, CURL *ch, http_request_method meth, const char *url ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC) -+{ -+ http_request *r; -+ -+ if (request) { -+ r = request; -+ } else { -+ r = emalloc_rel(sizeof(http_request)); -+ } -+ memset(r, 0, sizeof(http_request)); -+ -+ r->ch = ch; -+ r->url = (url) ? http_absolute_url(url) : NULL; -+ r->meth = (meth > 0) ? meth : HTTP_GET; -+ -+ phpstr_init(&r->conv.request); -+ phpstr_init_ex(&r->conv.response, HTTP_CURLBUF_SIZE, 0); -+ phpstr_init(&r->_cache.cookies); -+ zend_hash_init(&r->_cache.options, 0, NULL, ZVAL_PTR_DTOR, 0); -+ -+ TSRMLS_SET_CTX(r->tsrm_ls); -+ -+ return r; -+} -+/* }}} */ -+ -+/* {{{ void http_request_dtor(http_request *) */ -+PHP_HTTP_API void _http_request_dtor(http_request *request) -+{ -+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls); -+ -+ http_request_reset(request); -+ http_curl_free(&request->ch); -+ -+ phpstr_dtor(&request->_cache.cookies); -+ zend_hash_destroy(&request->_cache.options); -+ if (request->_cache.headers) { -+ curl_slist_free_all(request->_cache.headers); -+ request->_cache.headers = NULL; -+ } -+ if (request->_progress_callback) { -+ zval_ptr_dtor(&request->_progress_callback); -+ request->_progress_callback = NULL; -+ } -+} -+/* }}} */ -+ -+/* {{{ void http_request_free(http_request **) */ -+PHP_HTTP_API void _http_request_free(http_request **request) -+{ -+ if (*request) { -+ TSRMLS_FETCH_FROM_CTX((*request)->tsrm_ls); -+ http_request_body_free(&(*request)->body); -+ http_request_dtor(*request); -+ efree(*request); -+ *request = NULL; -+ } -+} -+/* }}} */ -+ -+/* {{{ void http_request_reset(http_request *) */ -+PHP_HTTP_API void _http_request_reset(http_request *request) -+{ -+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls); -+ STR_SET(request->url, NULL); -+ request->conv.last_type = 0; -+ phpstr_dtor(&request->conv.request); -+ phpstr_dtor(&request->conv.response); -+ http_request_body_dtor(request->body); -+ http_request_defaults(request); -+ -+ if (request->ch) { -+ http_request_storage *st = http_request_storage_get(request->ch); -+ -+ if (st) { -+ if (st->url) { -+ pefree(st->url, 1); -+ st->url = NULL; -+ } -+ if (st->cookiestore) { -+ pefree(st->cookiestore, 1); -+ st->cookiestore = NULL; -+ } -+ st->errorbuffer[0] = '\0'; -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ STATUS http_request_enable_cookies(http_request *) */ -+PHP_HTTP_API STATUS _http_request_enable_cookies(http_request *request) -+{ -+ int initialized = 1; -+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls); -+ -+ HTTP_CHECK_CURL_INIT(request->ch, http_curl_init_ex(request->ch, request), initialized = 0); -+ if (initialized && (http_request_cookies_enabled(request) || (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIEFILE, "")))) { -+ return SUCCESS; -+ } -+ http_error(HE_WARNING, HTTP_E_REQUEST, "Could not enable cookies for this session"); -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_request_reset_cookies(http_request *, int) */ -+PHP_HTTP_API STATUS _http_request_reset_cookies(http_request *request, int session_only) -+{ -+ int initialized = 1; -+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls); -+ -+ HTTP_CHECK_CURL_INIT(request->ch, http_curl_init_ex(request->ch, request), initialized = 0); -+ if (initialized) { -+ if (!http_request_cookies_enabled(request)) { -+ if (SUCCESS != http_request_enable_cookies(request)) { -+ return FAILURE; -+ } -+ } -+ if (session_only) { -+#if HTTP_CURL_VERSION(7,15,4) -+ if (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "SESS")) { -+ return SUCCESS; -+ } -+#else -+ http_error(HE_WARNING, HTTP_E_REQUEST, "Could not reset session cookies (need libcurl >= v7.15.4)"); -+#endif -+ } else { -+#if HTTP_CURL_VERSION(7,14,1) -+ if (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "ALL")) { -+ return SUCCESS; -+ } -+#else -+ http_error(HE_WARNING, HTTP_E_REQUEST, "Could not reset cookies (need libcurl >= v7.14.1)"); -+#endif -+ } -+ } -+ return FAILURE; -+} -+/* }}} */ -+ -+PHP_HTTP_API STATUS _http_request_flush_cookies(http_request *request) -+{ -+ int initialized = 1; -+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls); -+ -+ HTTP_CHECK_CURL_INIT(request->ch, http_curl_init_ex(request->ch, request), initialized = 0); -+ if (initialized) { -+ if (!http_request_cookies_enabled(request)) { -+ return FAILURE; -+ } -+#if HTTP_CURL_VERSION(7,17,1) -+ if (CURLE_OK == curl_easy_setopt(request->ch, CURLOPT_COOKIELIST, "FLUSH")) { -+ return SUCCESS; -+ } -+#else -+ http_error(HE_WARNING, HTTP_E_REQUEST, "Could not flush cookies (need libcurl >= v7.17.1)"); -+#endif -+ } -+ return FAILURE; -+} -+ -+/* {{{ void http_request_defaults(http_request *) */ -+PHP_HTTP_API void _http_request_defaults(http_request *request) -+{ -+ if (request->ch) { -+ HTTP_CURL_OPT(CURLOPT_PROGRESSFUNCTION, NULL); -+ HTTP_CURL_OPT(CURLOPT_URL, NULL); -+ HTTP_CURL_OPT(CURLOPT_NOPROGRESS, 1L); -+#if HTTP_CURL_VERSION(7,19,4) -+ HTTP_CURL_OPT(CURLOPT_NOPROXY, NULL); -+#endif -+ HTTP_CURL_OPT(CURLOPT_PROXY, NULL); -+ HTTP_CURL_OPT(CURLOPT_PROXYPORT, 0L); -+ HTTP_CURL_OPT(CURLOPT_PROXYTYPE, 0L); -+ /* libcurl < 7.19.6 does not clear auth info with USERPWD set to NULL */ -+#if HTTP_CURL_VERSION(7,19,1) -+ HTTP_CURL_OPT(CURLOPT_PROXYUSERNAME, NULL); -+ HTTP_CURL_OPT(CURLOPT_PROXYPASSWORD, NULL); -+#endif -+ HTTP_CURL_OPT(CURLOPT_PROXYAUTH, 0L); -+ HTTP_CURL_OPT(CURLOPT_HTTPPROXYTUNNEL, 0L); -+ HTTP_CURL_OPT(CURLOPT_DNS_CACHE_TIMEOUT, 60L); -+ HTTP_CURL_OPT(CURLOPT_IPRESOLVE, 0); -+ HTTP_CURL_OPT(CURLOPT_LOW_SPEED_LIMIT, 0L); -+ HTTP_CURL_OPT(CURLOPT_LOW_SPEED_TIME, 0L); -+#if HTTP_CURL_VERSION(7,15,5) -+ /* LFS weirdance -+ HTTP_CURL_OPT(CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t) 0); -+ HTTP_CURL_OPT(CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) 0); -+ */ -+#endif -+ /* crashes -+ HTTP_CURL_OPT(CURLOPT_MAXCONNECTS, 5L); */ -+ HTTP_CURL_OPT(CURLOPT_FRESH_CONNECT, 0L); -+ HTTP_CURL_OPT(CURLOPT_FORBID_REUSE, 0L); -+ HTTP_CURL_OPT(CURLOPT_INTERFACE, NULL); -+ HTTP_CURL_OPT(CURLOPT_PORT, 0L); -+#if HTTP_CURL_VERSION(7,19,0) -+ HTTP_CURL_OPT(CURLOPT_ADDRESS_SCOPE, 0L); -+#endif -+#if HTTP_CURL_VERSION(7,15,2) -+ HTTP_CURL_OPT(CURLOPT_LOCALPORT, 0L); -+ HTTP_CURL_OPT(CURLOPT_LOCALPORTRANGE, 0L); -+#endif -+ /* libcurl < 7.19.6 does not clear auth info with USERPWD set to NULL */ -+#if HTTP_CURL_VERSION(7,19,1) -+ HTTP_CURL_OPT(CURLOPT_USERNAME, NULL); -+ HTTP_CURL_OPT(CURLOPT_PASSWORD, NULL); -+#endif -+ HTTP_CURL_OPT(CURLOPT_HTTPAUTH, 0L); -+ HTTP_CURL_OPT(CURLOPT_ENCODING, NULL); -+#if HTTP_CURL_VERSION(7,16,2) -+ /* we do this ourself anyway */ -+ HTTP_CURL_OPT(CURLOPT_HTTP_CONTENT_DECODING, 0L); -+ HTTP_CURL_OPT(CURLOPT_HTTP_TRANSFER_DECODING, 0L); -+#endif -+ HTTP_CURL_OPT(CURLOPT_FOLLOWLOCATION, 0L); -+#if HTTP_CURL_VERSION(7,19,1) -+ HTTP_CURL_OPT(CURLOPT_POSTREDIR, 0L); -+#elif HTTP_CURL_VERSION(7,17,1) -+ HTTP_CURL_OPT(CURLOPT_POST301, 0L); -+#endif -+ HTTP_CURL_OPT(CURLOPT_UNRESTRICTED_AUTH, 0L); -+ HTTP_CURL_OPT(CURLOPT_REFERER, NULL); -+ HTTP_CURL_OPT(CURLOPT_USERAGENT, "PECL::HTTP/" PHP_HTTP_VERSION " (PHP/" PHP_VERSION ")"); -+ HTTP_CURL_OPT(CURLOPT_HTTPHEADER, NULL); -+ HTTP_CURL_OPT(CURLOPT_COOKIE, NULL); -+ HTTP_CURL_OPT(CURLOPT_COOKIESESSION, 0L); -+ /* these options would enable curl's cookie engine by default which we don't want -+ HTTP_CURL_OPT(CURLOPT_COOKIEFILE, NULL); -+ HTTP_CURL_OPT(CURLOPT_COOKIEJAR, NULL); */ -+#if HTTP_CURL_VERSION(7,14,1) -+ HTTP_CURL_OPT(CURLOPT_COOKIELIST, NULL); -+#endif -+ HTTP_CURL_OPT(CURLOPT_RANGE, NULL); -+ HTTP_CURL_OPT(CURLOPT_RESUME_FROM, 0L); -+ HTTP_CURL_OPT(CURLOPT_MAXFILESIZE, 0L); -+ HTTP_CURL_OPT(CURLOPT_TIMECONDITION, 0L); -+ HTTP_CURL_OPT(CURLOPT_TIMEVALUE, 0L); -+ HTTP_CURL_OPT(CURLOPT_TIMEOUT, 0L); -+ HTTP_CURL_OPT(CURLOPT_CONNECTTIMEOUT, 3); -+ HTTP_CURL_OPT(CURLOPT_SSLCERT, NULL); -+ HTTP_CURL_OPT(CURLOPT_SSLCERTTYPE, NULL); -+ HTTP_CURL_OPT(CURLOPT_SSLCERTPASSWD, NULL); -+ HTTP_CURL_OPT(CURLOPT_SSLKEY, NULL); -+ HTTP_CURL_OPT(CURLOPT_SSLKEYTYPE, NULL); -+ HTTP_CURL_OPT(CURLOPT_SSLKEYPASSWD, NULL); -+ HTTP_CURL_OPT(CURLOPT_SSLENGINE, NULL); -+ HTTP_CURL_OPT(CURLOPT_SSLVERSION, 0L); -+ HTTP_CURL_OPT(CURLOPT_SSL_VERIFYPEER, 0L); -+ HTTP_CURL_OPT(CURLOPT_SSL_VERIFYHOST, 0L); -+ HTTP_CURL_OPT(CURLOPT_SSL_CIPHER_LIST, NULL); -+#if HTTP_CURL_VERSION(7,19,0) -+ HTTP_CURL_OPT(CURLOPT_ISSUERCERT, NULL); -+ #if defined(HTTP_HAVE_OPENSSL) -+ HTTP_CURL_OPT(CURLOPT_CRLFILE, NULL); -+ #endif -+#endif -+#if HTTP_CURL_VERSION(7,19,1) && defined(HTTP_HAVE_OPENSSL) -+ HTTP_CURL_OPT(CURLOPT_CERTINFO, NULL); -+#endif -+#ifdef HTTP_CURL_CAINFO -+ HTTP_CURL_OPT(CURLOPT_CAINFO, HTTP_CURL_CAINFO); -+#else -+ HTTP_CURL_OPT(CURLOPT_CAINFO, NULL); -+#endif -+ HTTP_CURL_OPT(CURLOPT_CAPATH, NULL); -+ HTTP_CURL_OPT(CURLOPT_RANDOM_FILE, NULL); -+ HTTP_CURL_OPT(CURLOPT_EGDSOCKET, NULL); -+ HTTP_CURL_OPT(CURLOPT_POSTFIELDS, NULL); -+ HTTP_CURL_OPT(CURLOPT_POSTFIELDSIZE, 0L); -+ HTTP_CURL_OPT(CURLOPT_HTTPPOST, NULL); -+ HTTP_CURL_OPT(CURLOPT_IOCTLDATA, NULL); -+ HTTP_CURL_OPT(CURLOPT_READDATA, NULL); -+ HTTP_CURL_OPT(CURLOPT_INFILESIZE, 0L); -+ HTTP_CURL_OPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_NONE); -+ HTTP_CURL_OPT(CURLOPT_CUSTOMREQUEST, NULL); -+ HTTP_CURL_OPT(CURLOPT_NOBODY, 0L); -+ HTTP_CURL_OPT(CURLOPT_POST, 0L); -+ HTTP_CURL_OPT(CURLOPT_UPLOAD, 0L); -+ HTTP_CURL_OPT(CURLOPT_HTTPGET, 1L); -+ } -+} -+/* }}} */ -+ -+PHP_HTTP_API void _http_request_set_progress_callback(http_request *request, zval *cb) -+{ -+ if (request->_progress_callback) { -+ zval_ptr_dtor(&request->_progress_callback); -+ } -+ if ((request->_progress_callback = cb)) { -+ ZVAL_ADDREF(cb); -+ HTTP_CURL_OPT(CURLOPT_NOPROGRESS, 0); -+ HTTP_CURL_OPT(CURLOPT_PROGRESSDATA, request); -+ HTTP_CURL_OPT(CURLOPT_PROGRESSFUNCTION, http_curl_progress_callback); -+ } else { -+ HTTP_CURL_OPT(CURLOPT_NOPROGRESS, 1); -+ HTTP_CURL_OPT(CURLOPT_PROGRESSDATA, NULL); -+ HTTP_CURL_OPT(CURLOPT_PROGRESSFUNCTION, NULL); -+ } -+} -+ -+/* {{{ STATUS http_request_prepare(http_request *, HashTable *) */ -+PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *options) -+{ -+ zval *zoption; -+ zend_bool range_req = 0; -+ http_request_storage *storage; -+ -+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls); -+ -+ HTTP_CHECK_CURL_INIT(request->ch, http_curl_init(request), return FAILURE); -+ -+ if (!request->url) { -+ return FAILURE; -+ } -+ if (!(storage = http_request_storage_get(request->ch))) { -+ return FAILURE; -+ } -+ storage->errorbuffer[0] = '\0'; -+ /* set options */ -+ if (storage->url) { -+ pefree(storage->url, 1); -+ } -+ storage->url = pestrdup(request->url, 1); -+ HTTP_CURL_OPT(CURLOPT_URL, storage->url); -+ -+ /* progress callback */ -+ if ((zoption = http_request_option(request, options, "onprogress", -1))) { -+ http_request_set_progress_callback(request, zoption); -+ } -+ -+ /* proxy */ -+ if ((zoption = http_request_option(request, options, "proxyhost", IS_STRING))) { -+ HTTP_CURL_OPT(CURLOPT_PROXY, Z_STRVAL_P(zoption)); -+ /* type */ -+ if ((zoption = http_request_option(request, options, "proxytype", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_PROXYTYPE, Z_LVAL_P(zoption)); -+ } -+ /* port */ -+ if ((zoption = http_request_option(request, options, "proxyport", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_PROXYPORT, Z_LVAL_P(zoption)); -+ } -+ /* user:pass */ -+ if ((zoption = http_request_option(request, options, "proxyauth", IS_STRING)) && Z_STRLEN_P(zoption)) { -+ HTTP_CURL_OPT(CURLOPT_PROXYUSERPWD, Z_STRVAL_P(zoption)); -+ } -+ /* auth method */ -+ if ((zoption = http_request_option(request, options, "proxyauthtype", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_PROXYAUTH, Z_LVAL_P(zoption)); -+ } -+ /* tunnel */ -+ if ((zoption = http_request_option(request, options, "proxytunnel", IS_BOOL)) && Z_BVAL_P(zoption)) { -+ HTTP_CURL_OPT(CURLOPT_HTTPPROXYTUNNEL, 1L); -+ } -+ } -+#if HTTP_CURL_VERSION(7,19,4) -+ if ((zoption = http_request_option(request, options, "noproxy", IS_STRING))) { -+ HTTP_CURL_OPT(CURLOPT_NOPROXY, Z_STRVAL_P(zoption)); -+ } -+#endif -+ -+ /* dns */ -+ if ((zoption = http_request_option(request, options, "dns_cache_timeout", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_DNS_CACHE_TIMEOUT, Z_LVAL_P(zoption)); -+ } -+ if ((zoption = http_request_option(request, options, "ipresolve", IS_LONG)) && Z_LVAL_P(zoption)) { -+ HTTP_CURL_OPT(CURLOPT_IPRESOLVE, Z_LVAL_P(zoption)); -+ } -+ -+ /* limits */ -+ if ((zoption = http_request_option(request, options, "low_speed_limit", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_LOW_SPEED_LIMIT, Z_LVAL_P(zoption)); -+ } -+ if ((zoption = http_request_option(request, options, "low_speed_time", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_LOW_SPEED_TIME, Z_LVAL_P(zoption)); -+ } -+#if HTTP_CURL_VERSION(7,15,5) -+ /* LSF weirdance -+ if ((zoption = http_request_option(request, options, "max_send_speed", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t) Z_LVAL_P(zoption)); -+ } -+ if ((zoption = http_request_option(request, options, "max_recv_speed", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t) Z_LVAL_P(zoption)); -+ } -+ */ -+#endif -+ /* crashes -+ if ((zoption = http_request_option(request, options, "maxconnects", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_MAXCONNECTS, Z_LVAL_P(zoption)); -+ } */ -+ if ((zoption = http_request_option(request, options, "fresh_connect", IS_BOOL)) && Z_BVAL_P(zoption)) { -+ HTTP_CURL_OPT(CURLOPT_FRESH_CONNECT, 1L); -+ } -+ if ((zoption = http_request_option(request, options, "forbid_reuse", IS_BOOL)) && Z_BVAL_P(zoption)) { -+ HTTP_CURL_OPT(CURLOPT_FORBID_REUSE, 1L); -+ } -+ -+ /* outgoing interface */ -+ if ((zoption = http_request_option(request, options, "interface", IS_STRING))) { -+ HTTP_CURL_OPT(CURLOPT_INTERFACE, Z_STRVAL_P(zoption)); -+ -+#if HTTP_CURL_VERSION(7,15,2) -+ if ((zoption = http_request_option(request, options, "portrange", IS_ARRAY))) { -+ zval **prs, **pre; -+ -+ zend_hash_internal_pointer_reset(Z_ARRVAL_P(zoption)); -+ if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void *) &prs)) { -+ zend_hash_move_forward(Z_ARRVAL_P(zoption)); -+ if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void *) &pre)) { -+ zval *prs_cpy = http_zsep(IS_LONG, *prs); -+ zval *pre_cpy = http_zsep(IS_LONG, *pre); -+ -+ if (Z_LVAL_P(prs_cpy) && Z_LVAL_P(pre_cpy)) { -+ HTTP_CURL_OPT(CURLOPT_LOCALPORT, MIN(Z_LVAL_P(prs_cpy), Z_LVAL_P(pre_cpy))); -+ HTTP_CURL_OPT(CURLOPT_LOCALPORTRANGE, labs(Z_LVAL_P(prs_cpy)-Z_LVAL_P(pre_cpy))+1L); -+ } -+ zval_ptr_dtor(&prs_cpy); -+ zval_ptr_dtor(&pre_cpy); -+ } -+ } -+ } -+#endif -+ } -+ -+ /* another port */ -+ if ((zoption = http_request_option(request, options, "port", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_PORT, Z_LVAL_P(zoption)); -+ } -+ -+ /* RFC4007 zone_id */ -+#if HTTP_CURL_VERSION(7,19,0) -+ if ((zoption = http_request_option(request, options, "address_scope", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_ADDRESS_SCOPE, Z_LVAL_P(zoption)); -+ } -+#endif -+ -+ /* auth */ -+ if ((zoption = http_request_option(request, options, "httpauth", IS_STRING)) && Z_STRLEN_P(zoption)) { -+ HTTP_CURL_OPT(CURLOPT_USERPWD, Z_STRVAL_P(zoption)); -+ } -+ if ((zoption = http_request_option(request, options, "httpauthtype", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_HTTPAUTH, Z_LVAL_P(zoption)); -+ } -+ -+ /* redirects, defaults to 0 */ -+ if ((zoption = http_request_option(request, options, "redirect", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_FOLLOWLOCATION, Z_LVAL_P(zoption) ? 1L : 0L); -+ HTTP_CURL_OPT(CURLOPT_MAXREDIRS, Z_LVAL_P(zoption)); -+ if ((zoption = http_request_option(request, options, "unrestrictedauth", IS_BOOL))) { -+ HTTP_CURL_OPT(CURLOPT_UNRESTRICTED_AUTH, Z_LVAL_P(zoption)); -+ } -+#if HTTP_CURL_VERSION(7,17,1) -+ if ((zoption = http_request_option(request, options, "postredir", IS_BOOL))) { -+# if HTTP_CURL_VERSION(7,19,1) -+ HTTP_CURL_OPT(CURLOPT_POSTREDIR, Z_BVAL_P(zoption) ? 1L : 0L); -+# else -+ HTTP_CURL_OPT(CURLOPT_POST301, Z_BVAL_P(zoption) ? 1L : 0L); -+# endif -+ } -+#endif -+ } -+ -+ /* retries, defaults to 0 */ -+ if ((zoption = http_request_option(request, options, "retrycount", IS_LONG))) { -+ request->_retry.count = Z_LVAL_P(zoption); -+ if ((zoption = http_request_option(request, options, "retrydelay", IS_DOUBLE))) { -+ request->_retry.delay = Z_DVAL_P(zoption); -+ } else { -+ request->_retry.delay = 0; -+ } -+ } else { -+ request->_retry.count = 0; -+ } -+ -+ /* referer */ -+ if ((zoption = http_request_option(request, options, "referer", IS_STRING)) && Z_STRLEN_P(zoption)) { -+ HTTP_CURL_OPT(CURLOPT_REFERER, Z_STRVAL_P(zoption)); -+ } -+ -+ /* useragent, default "PECL::HTTP/version (PHP/version)" */ -+ if ((zoption = http_request_option(request, options, "useragent", IS_STRING))) { -+ /* allow to send no user agent, not even default one */ -+ if (Z_STRLEN_P(zoption)) { -+ HTTP_CURL_OPT(CURLOPT_USERAGENT, Z_STRVAL_P(zoption)); -+ } else { -+ HTTP_CURL_OPT(CURLOPT_USERAGENT, NULL); -+ } -+ } -+ -+ /* resume */ -+ if ((zoption = http_request_option(request, options, "resume", IS_LONG)) && (Z_LVAL_P(zoption) > 0)) { -+ range_req = 1; -+ HTTP_CURL_OPT(CURLOPT_RESUME_FROM, Z_LVAL_P(zoption)); -+ } -+ /* or range of kind array(array(0,499), array(100,1499)) */ -+ else if ((zoption = http_request_option(request, options, "range", IS_ARRAY)) && zend_hash_num_elements(Z_ARRVAL_P(zoption))) { -+ HashPosition pos1, pos2; -+ zval **rr, **rb, **re; -+ phpstr rs; -+ -+ phpstr_init(&rs); -+ FOREACH_VAL(pos1, zoption, rr) { -+ if (Z_TYPE_PP(rr) == IS_ARRAY) { -+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(rr), &pos2); -+ if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(rr), (void *) &rb, &pos2)) { -+ zend_hash_move_forward_ex(Z_ARRVAL_PP(rr), &pos2); -+ if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(rr), (void *) &re, &pos2)) { -+ if ( ((Z_TYPE_PP(rb) == IS_LONG) || ((Z_TYPE_PP(rb) == IS_STRING) && is_numeric_string(Z_STRVAL_PP(rb), Z_STRLEN_PP(rb), NULL, NULL, 1))) && -+ ((Z_TYPE_PP(re) == IS_LONG) || ((Z_TYPE_PP(re) == IS_STRING) && is_numeric_string(Z_STRVAL_PP(re), Z_STRLEN_PP(re), NULL, NULL, 1)))) { -+ zval *rbl = http_zsep(IS_LONG, *rb); -+ zval *rel = http_zsep(IS_LONG, *re); -+ -+ if ((Z_LVAL_P(rbl) >= 0) && (Z_LVAL_P(rel) >= 0)) { -+ phpstr_appendf(&rs, "%ld-%ld,", Z_LVAL_P(rbl), Z_LVAL_P(rel)); -+ } -+ zval_ptr_dtor(&rbl); -+ zval_ptr_dtor(&rel); -+ } -+ } -+ } -+ } -+ } -+ -+ if (PHPSTR_LEN(&rs)) { -+ zval *cached_range; -+ -+ /* ditch last comma */ -+ PHPSTR_VAL(&rs)[PHPSTR_LEN(&rs)-- -1] = '\0'; -+ /* cache string */ -+ MAKE_STD_ZVAL(cached_range); -+ ZVAL_STRINGL(cached_range, PHPSTR_VAL(&rs), PHPSTR_LEN(&rs), 0); -+ HTTP_CURL_OPT(CURLOPT_RANGE, Z_STRVAL_P(http_request_option_cache(request, "range", cached_range))); -+ zval_ptr_dtor(&cached_range); -+ } -+ } -+ -+ /* additional headers, array('name' => 'value') */ -+ if (request->_cache.headers) { -+ curl_slist_free_all(request->_cache.headers); -+ request->_cache.headers = NULL; -+ } -+ if ((zoption = http_request_option(request, options, "headers", IS_ARRAY))) { -+ HashKey header_key = initHashKey(0); -+ zval **header_val; -+ HashPosition pos; -+ phpstr header; -+ -+ phpstr_init(&header); -+ FOREACH_KEYVAL(pos, zoption, header_key, header_val) { -+ if (header_key.type == HASH_KEY_IS_STRING) { -+ zval *header_cpy = http_zsep(IS_STRING, *header_val); -+ -+ if (!strcasecmp(header_key.str, "range")) { -+ range_req = 1; -+ } -+ -+ phpstr_appendf(&header, "%s: %s", header_key.str, Z_STRVAL_P(header_cpy)); -+ phpstr_fix(&header); -+ request->_cache.headers = curl_slist_append(request->_cache.headers, PHPSTR_VAL(&header)); -+ phpstr_reset(&header); -+ -+ zval_ptr_dtor(&header_cpy); -+ } -+ } -+ phpstr_dtor(&header); -+ } -+ /* etag */ -+ if ((zoption = http_request_option(request, options, "etag", IS_STRING)) && Z_STRLEN_P(zoption)) { -+ zend_bool is_quoted = !((Z_STRVAL_P(zoption)[0] != '"') || (Z_STRVAL_P(zoption)[Z_STRLEN_P(zoption)-1] != '"')); -+ phpstr header; -+ -+ phpstr_init(&header); -+ phpstr_appendf(&header, is_quoted?"%s: %s":"%s: \"%s\"", range_req?"If-Match":"If-None-Match", Z_STRVAL_P(zoption)); -+ phpstr_fix(&header); -+ request->_cache.headers = curl_slist_append(request->_cache.headers, PHPSTR_VAL(&header)); -+ phpstr_dtor(&header); -+ } -+ /* compression */ -+ if ((zoption = http_request_option(request, options, "compress", IS_BOOL)) && Z_LVAL_P(zoption)) { -+ request->_cache.headers = curl_slist_append(request->_cache.headers, "Accept-Encoding: gzip;q=1.0,deflate;q=0.5"); -+ } -+ HTTP_CURL_OPT(CURLOPT_HTTPHEADER, request->_cache.headers); -+ -+ /* lastmodified */ -+ if ((zoption = http_request_option(request, options, "lastmodified", IS_LONG))) { -+ if (Z_LVAL_P(zoption)) { -+ if (Z_LVAL_P(zoption) > 0) { -+ HTTP_CURL_OPT(CURLOPT_TIMEVALUE, Z_LVAL_P(zoption)); -+ } else { -+ HTTP_CURL_OPT(CURLOPT_TIMEVALUE, (long) HTTP_G->request.time + Z_LVAL_P(zoption)); -+ } -+ HTTP_CURL_OPT(CURLOPT_TIMECONDITION, (long) (range_req ? CURL_TIMECOND_IFUNMODSINCE : CURL_TIMECOND_IFMODSINCE)); -+ } else { -+ HTTP_CURL_OPT(CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE); -+ } -+ } -+ -+ /* cookies, array('name' => 'value') */ -+ if ((zoption = http_request_option(request, options, "cookies", IS_ARRAY))) { -+ phpstr_dtor(&request->_cache.cookies); -+ if (zend_hash_num_elements(Z_ARRVAL_P(zoption))) { -+ zval *urlenc_cookies = NULL; -+ /* check whether cookies should not be urlencoded; default is to urlencode them */ -+ if ((!(urlenc_cookies = http_request_option(request, options, "encodecookies", IS_BOOL))) || Z_BVAL_P(urlenc_cookies)) { -+ if (SUCCESS == http_urlencode_hash_recursive(HASH_OF(zoption), &request->_cache.cookies, "; ", lenof("; "), NULL, 0)) { -+ phpstr_fix(&request->_cache.cookies); -+ HTTP_CURL_OPT(CURLOPT_COOKIE, request->_cache.cookies.data); -+ } -+ } else { -+ HashPosition pos; -+ HashKey cookie_key = initHashKey(0); -+ zval **cookie_val; -+ -+ FOREACH_KEYVAL(pos, zoption, cookie_key, cookie_val) { -+ if (cookie_key.type == HASH_KEY_IS_STRING) { -+ zval *val = http_zsep(IS_STRING, *cookie_val); -+ phpstr_appendf(&request->_cache.cookies, "%s=%s; ", cookie_key.str, Z_STRVAL_P(val)); -+ zval_ptr_dtor(&val); -+ } -+ } -+ -+ phpstr_fix(&request->_cache.cookies); -+ if (PHPSTR_LEN(&request->_cache.cookies)) { -+ HTTP_CURL_OPT(CURLOPT_COOKIE, PHPSTR_VAL(&request->_cache.cookies)); -+ } -+ } -+ } -+ } -+ -+ /* don't load session cookies from cookiestore */ -+ if ((zoption = http_request_option(request, options, "cookiesession", IS_BOOL)) && Z_BVAL_P(zoption)) { -+ HTTP_CURL_OPT(CURLOPT_COOKIESESSION, 1L); -+ } -+ -+ /* cookiestore, read initial cookies from that file and store cookies back into that file */ -+ if ((zoption = http_request_option(request, options, "cookiestore", IS_STRING))) { -+ if (Z_STRLEN_P(zoption)) { -+ HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(zoption), return FAILURE); -+ } -+ if (storage->cookiestore) { -+ pefree(storage->cookiestore, 1); -+ } -+ storage->cookiestore = pestrndup(Z_STRVAL_P(zoption), Z_STRLEN_P(zoption), 1); -+ HTTP_CURL_OPT(CURLOPT_COOKIEFILE, storage->cookiestore); -+ HTTP_CURL_OPT(CURLOPT_COOKIEJAR, storage->cookiestore); -+ } -+ -+ /* maxfilesize */ -+ if ((zoption = http_request_option(request, options, "maxfilesize", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_MAXFILESIZE, Z_LVAL_P(zoption)); -+ } -+ -+ /* http protocol */ -+ if ((zoption = http_request_option(request, options, "protocol", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_HTTP_VERSION, Z_LVAL_P(zoption)); -+ } -+ -+#if HTTP_CURL_VERSION(7,16,2) -+ /* timeout, defaults to 0 */ -+ if ((zoption = http_request_option(request, options, "timeout", IS_DOUBLE))) { -+ HTTP_CURL_OPT(CURLOPT_TIMEOUT_MS, (long)(Z_DVAL_P(zoption)*1000)); -+ } -+ /* connecttimeout, defaults to 0 */ -+ if ((zoption = http_request_option(request, options, "connecttimeout", IS_DOUBLE))) { -+ HTTP_CURL_OPT(CURLOPT_CONNECTTIMEOUT_MS, (long)(Z_DVAL_P(zoption)*1000)); -+ } -+#else -+ /* timeout, defaults to 0 */ -+ if ((zoption = http_request_option(request, options, "timeout", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_TIMEOUT, Z_LVAL_P(zoption)); -+ } -+ /* connecttimeout, defaults to 0 */ -+ if ((zoption = http_request_option(request, options, "connecttimeout", IS_LONG))) { -+ HTTP_CURL_OPT(CURLOPT_CONNECTTIMEOUT, Z_LVAL_P(zoption)); -+ } -+#endif -+ -+ /* ssl */ -+ if ((zoption = http_request_option(request, options, "ssl", IS_ARRAY))) { -+ HashKey key = initHashKey(0); -+ zval **param; -+ HashPosition pos; -+ -+ FOREACH_KEYVAL(pos, zoption, key, param) { -+ if (key.type == HASH_KEY_IS_STRING) { -+ HTTP_CURL_OPT_STRING(CURLOPT_SSLCERT, 0, 1); -+ HTTP_CURL_OPT_STRING(CURLOPT_SSLCERTTYPE, 0, 0); -+ HTTP_CURL_OPT_STRING(CURLOPT_SSLCERTPASSWD, 0, 0); -+ -+ HTTP_CURL_OPT_STRING(CURLOPT_SSLKEY, 0, 0); -+ HTTP_CURL_OPT_STRING(CURLOPT_SSLKEYTYPE, 0, 0); -+ HTTP_CURL_OPT_STRING(CURLOPT_SSLKEYPASSWD, 0, 0); -+ -+ HTTP_CURL_OPT_STRING(CURLOPT_SSLENGINE, 0, 0); -+ HTTP_CURL_OPT_LONG(CURLOPT_SSLVERSION, 0); -+ -+ HTTP_CURL_OPT_LONG(CURLOPT_SSL_VERIFYPEER, 1); -+ HTTP_CURL_OPT_LONG(CURLOPT_SSL_VERIFYHOST, 1); -+ HTTP_CURL_OPT_STRING(CURLOPT_SSL_CIPHER_LIST, 1, 0); -+ -+ HTTP_CURL_OPT_STRING(CURLOPT_CAINFO, -3, 1); -+ HTTP_CURL_OPT_STRING(CURLOPT_CAPATH, -3, 1); -+ HTTP_CURL_OPT_STRING(CURLOPT_RANDOM_FILE, -3, 1); -+ HTTP_CURL_OPT_STRING(CURLOPT_EGDSOCKET, -3, 1); -+#if HTTP_CURL_VERSION(7,19,0) -+ HTTP_CURL_OPT_STRING(CURLOPT_ISSUERCERT, -3, 1); -+ #if defined(HTTP_HAVE_OPENSSL) -+ HTTP_CURL_OPT_STRING(CURLOPT_CRLFILE, -3, 1); -+ #endif -+#endif -+#if HTTP_CURL_VERSION(7,19,1) && defined(HTTP_HAVE_OPENSSL) -+ HTTP_CURL_OPT_LONG(CURLOPT_CERTINFO, -3); -+#endif -+ } -+ } -+ } -+ -+ /* request method */ -+ switch (request->meth) { -+ case HTTP_GET: -+ HTTP_CURL_OPT(CURLOPT_HTTPGET, 1L); -+ break; -+ -+ case HTTP_HEAD: -+ HTTP_CURL_OPT(CURLOPT_NOBODY, 1L); -+ break; -+ -+ case HTTP_POST: -+ HTTP_CURL_OPT(CURLOPT_POST, 1L); -+ break; -+ -+ case HTTP_PUT: -+ HTTP_CURL_OPT(CURLOPT_UPLOAD, 1L); -+ break; -+ -+ default: -+ if (http_request_method_exists(0, request->meth, NULL)) { -+ HTTP_CURL_OPT(CURLOPT_CUSTOMREQUEST, http_request_method_name(request->meth)); -+ } else { -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Unsupported request method: %d (%s)", request->meth, request->url); -+ return FAILURE; -+ } -+ break; -+ } -+ -+ /* attach request body */ -+ if (request->body && (request->meth != HTTP_GET) && (request->meth != HTTP_HEAD) && (request->meth != HTTP_OPTIONS)) { -+ switch (request->body->type) { -+ case HTTP_REQUEST_BODY_EMPTY: -+ /* nothing */ -+ break; -+ -+ case HTTP_REQUEST_BODY_CURLPOST: -+ HTTP_CURL_OPT(CURLOPT_HTTPPOST, (struct curl_httppost *) request->body->data); -+ break; -+ -+ case HTTP_REQUEST_BODY_CSTRING: -+ if (request->meth != HTTP_PUT) { -+ HTTP_CURL_OPT(CURLOPT_POSTFIELDS, request->body->data); -+ HTTP_CURL_OPT(CURLOPT_POSTFIELDSIZE, request->body->size); -+ break; -+ } -+ /* fallthrough, PUT/UPLOAD _needs_ READDATA */ -+ case HTTP_REQUEST_BODY_UPLOADFILE: -+ HTTP_CURL_OPT(CURLOPT_IOCTLDATA, request); -+ HTTP_CURL_OPT(CURLOPT_READDATA, request); -+ HTTP_CURL_OPT(CURLOPT_INFILESIZE, request->body->size); -+ break; -+ -+ default: -+ /* shouldn't ever happen */ -+ http_error_ex(HE_ERROR, 0, "Unknown request body type: %d (%s)", request->body->type, request->url); -+ return FAILURE; -+ } -+ } -+ -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ void http_request_exec(http_request *) */ -+PHP_HTTP_API void _http_request_exec(http_request *request) -+{ -+ uint tries = 0; -+ CURLcode result; -+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls); -+ -+retry: -+ if (CURLE_OK != (result = curl_easy_perform(request->ch))) { -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "%s; %s (%s)", curl_easy_strerror(result), http_request_storage_get(request->ch)->errorbuffer, request->url); -+#ifdef ZEND_ENGINE_2 -+ if ((HTTP_G->only_exceptions || GLOBAL_ERROR_HANDLING == EH_THROW) && EG(exception)) { -+ add_property_long(EG(exception), "curlCode", result); -+ } -+#endif -+ -+ if (request->_retry.count > tries++) { -+ switch (result) { -+ case CURLE_COULDNT_RESOLVE_PROXY: -+ case CURLE_COULDNT_RESOLVE_HOST: -+ case CURLE_COULDNT_CONNECT: -+ case CURLE_WRITE_ERROR: -+ case CURLE_READ_ERROR: -+ case CURLE_OPERATION_TIMEDOUT: -+ case CURLE_SSL_CONNECT_ERROR: -+ case CURLE_GOT_NOTHING: -+ case CURLE_SSL_ENGINE_SETFAILED: -+ case CURLE_SEND_ERROR: -+ case CURLE_RECV_ERROR: -+ case CURLE_SSL_ENGINE_INITFAILED: -+ case CURLE_LOGIN_DENIED: -+ if (request->_retry.delay >= HTTP_DIFFSEC) { -+ http_sleep(request->_retry.delay); -+ } -+ goto retry; -+ default: -+ break; -+ } -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ static size_t http_curl_read_callback(void *, size_t, size_t, void *) */ -+static size_t http_curl_read_callback(void *data, size_t len, size_t n, void *ctx) -+{ -+ http_request *request = (http_request *) ctx; -+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls); -+ -+ if (request->body) { -+ switch (request->body->type) { -+ case HTTP_REQUEST_BODY_CSTRING: -+ { -+ size_t out = MIN(len * n, request->body->size - request->body->priv); -+ -+ if (out) { -+ memcpy(data, ((char *) request->body->data) + request->body->priv, out); -+ request->body->priv += out; -+ return out; -+ } -+ break; -+ } -+ -+ case HTTP_REQUEST_BODY_UPLOADFILE: -+ return php_stream_read((php_stream *) request->body->data, data, len * n); -+ } -+ } -+ return 0; -+} -+/* }}} */ -+ -+/* {{{ static int http_curl_progress_callback(void *, double, double, double, double) */ -+static int http_curl_progress_callback(void *ctx, double dltotal, double dlnow, double ultotal, double ulnow) -+{ -+ zval *param, retval; -+ http_request *request = (http_request *) ctx; -+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls); -+ -+ INIT_PZVAL(&retval); -+ ZVAL_NULL(&retval); -+ -+ MAKE_STD_ZVAL(param); -+ array_init(param); -+ add_assoc_double(param, "dltotal", dltotal); -+ add_assoc_double(param, "dlnow", dlnow); -+ add_assoc_double(param, "ultotal", ultotal); -+ add_assoc_double(param, "ulnow", ulnow); -+ -+ with_error_handling(EH_NORMAL, NULL) { -+ request->_in_progress_cb = 1; -+ call_user_function(EG(function_table), NULL, request->_progress_callback, &retval, 1, ¶m TSRMLS_CC); -+ request->_in_progress_cb = 0; -+ } end_error_handling(); -+ -+ zval_ptr_dtor(¶m); -+ zval_dtor(&retval); -+ -+ return 0; -+} -+/* }}} */ -+ -+/* {{{ static curlioerr http_curl_ioctl_callback(CURL *, curliocmd, void *) */ -+static curlioerr http_curl_ioctl_callback(CURL *ch, curliocmd cmd, void *ctx) -+{ -+ http_request *request = (http_request *) ctx; -+ TSRMLS_FETCH_FROM_CTX(request->tsrm_ls); -+ -+ if (cmd != CURLIOCMD_RESTARTREAD) { -+ return CURLIOE_UNKNOWNCMD; -+ } -+ -+ if (request->body) { -+ switch (request->body->type) { -+ case HTTP_REQUEST_BODY_CSTRING: -+ request->body->priv = 0; -+ return CURLIOE_OK; -+ break; -+ -+ case HTTP_REQUEST_BODY_UPLOADFILE: -+ if (SUCCESS == php_stream_rewind((php_stream *) request->body->data)) { -+ return CURLIOE_OK; -+ } -+ break; -+ } -+ } -+ -+ return CURLIOE_FAILRESTART; -+} -+/* }}} */ -+ -+/* {{{ static int http_curl_raw_callback(CURL *, curl_infotype, char *, size_t, void *) */ -+static int http_curl_raw_callback(CURL *ch, curl_infotype type, char *data, size_t length, void *ctx) -+{ -+ http_request *request = (http_request *) ctx; -+ -+#define EMPTY_HEADER(d, l) (!l || (l == 1 && d[0] == '\n') || (l == 2 && d[0] == '\r' && d[1] == '\n')) -+ switch (type) { -+ case CURLINFO_DATA_IN: -+ if (request->conv.last_type == CURLINFO_HEADER_IN) { -+ phpstr_appends(&request->conv.response, HTTP_CRLF); -+ } -+ phpstr_append(&request->conv.response, data, length); -+ break; -+ case CURLINFO_HEADER_IN: -+ if (!EMPTY_HEADER(data, length)) { -+ phpstr_append(&request->conv.response, data, length); -+ } -+ break; -+ case CURLINFO_DATA_OUT: -+ case CURLINFO_HEADER_OUT: -+ phpstr_append(&request->conv.request, data, length); -+ break; -+ default: -+ break; -+ } -+ -+#if 0 -+ { -+ const char _sym[] = "><><><"; -+ if (type) { -+ for (fprintf(stderr, "%c ", _sym[type-1]); length--; data++) { -+ fprintf(stderr, HTTP_IS_CTYPE(print, *data)?"%c":"\\x%02X", (int) *data); -+ if (*data == '\n' && length) { -+ fprintf(stderr, "\n%c ", _sym[type-1]); -+ } -+ } -+ fprintf(stderr, "\n"); -+ } else { -+ fprintf(stderr, "# %s", data); -+ } -+ } -+#endif -+ -+ if (type) { -+ request->conv.last_type = type; -+ } -+ return 0; -+} -+/* }}} */ -+ -+/* {{{ static inline zval *http_request_option(http_request *, HashTable *, char *, size_t, int) */ -+static inline zval *_http_request_option_ex(http_request *r, HashTable *options, char *key, size_t keylen, int type TSRMLS_DC) -+{ -+ if (options) { -+ zval **zoption; -+ ulong h = zend_hash_func(key, keylen); -+ -+ if (SUCCESS == zend_hash_quick_find(options, key, keylen, h, (void *) &zoption)) { -+ zval *option, *cached; -+ -+ option = http_zsep(type, *zoption); -+ cached = http_request_option_cache_ex(r, key, keylen, h, option); -+ -+ zval_ptr_dtor(&option); -+ return cached; -+ } -+ } -+ -+ return NULL; -+} -+/* }}} */ -+ -+/* {{{ static inline zval *http_request_option_cache(http_request *, char *key, zval *) */ -+static inline zval *_http_request_option_cache_ex(http_request *r, char *key, size_t keylen, ulong h, zval *opt TSRMLS_DC) -+{ -+ ZVAL_ADDREF(opt); -+ -+ if (h) { -+ zend_hash_quick_update(&r->_cache.options, key, keylen, h, &opt, sizeof(zval *), NULL); -+ } else { -+ zend_hash_update(&r->_cache.options, key, keylen, &opt, sizeof(zval *), NULL); -+ } -+ -+ return opt; -+} -+/* }}} */ -+ -+/* {{{ static inline int http_request_cookies_enabled(http_request *) */ -+static inline int _http_request_cookies_enabled(http_request *request) { -+ http_request_storage *st; -+ -+ if (request->ch && (st = http_request_storage_get(request->ch)) && st->cookiestore) { -+ /* cookies are enabled */ -+ return 1; -+ } -+ return 0; -+} -+/* }}} */ -+ -+#endif /* HTTP_HAVE_CURL */ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_request_body_api.c -@@ -0,0 +1,332 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_request_body_api.c 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#define HTTP_WANT_CURL -+#include "php_http.h" -+ -+#ifdef HTTP_HAVE_CURL -+ -+#include "php_http_api.h" -+#include "php_http_url_api.h" -+#include "php_http_request_body_api.h" -+ -+/* {{{ */ -+typedef struct curl_httppost *post_data[2]; -+static STATUS recursive_fields(post_data http_post_data, HashTable *fields, const char *prefix TSRMLS_DC); -+static STATUS recursive_files(post_data http_post_data, HashTable *files, const char *prefix TSRMLS_DC); -+/* }}} */ -+ -+/* {{{ http_request_body *http_request_body_new() */ -+PHP_HTTP_API http_request_body *_http_request_body_init_ex(http_request_body *body, int type, void *data, size_t size, zend_bool free ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC) -+{ -+ if (!body) { -+ body = emalloc_rel(sizeof(http_request_body)); -+ } -+ -+ body->type = type; -+ body->free = free; -+ body->priv = 0; -+ body->data = data; -+ body->size = size; -+ -+ return body; -+} -+/* }}} */ -+ -+/* {{{ http_request_body *http_request_body_fill(http_request_body *body, HashTable *, HashTable *) */ -+PHP_HTTP_API http_request_body *_http_request_body_fill(http_request_body *body, HashTable *fields, HashTable *files ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC) -+{ -+ if (files && (zend_hash_num_elements(files) > 0)) { -+ struct curl_httppost *http_post_data[2] = {NULL, NULL}; -+ -+ if (fields && SUCCESS != recursive_fields(http_post_data, fields, NULL TSRMLS_CC)) { -+ return NULL; -+ } -+ if (SUCCESS != recursive_files(http_post_data, files, NULL TSRMLS_CC)) { -+ return NULL; -+ } -+ return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CURLPOST, http_post_data[0], 0, 1); -+ } else if (fields) { -+ char *encoded; -+ size_t encoded_len; -+ -+ if (SUCCESS != http_urlencode_hash_ex(fields, 1, NULL, 0, &encoded, &encoded_len)) { -+ http_error(HE_WARNING, HTTP_E_ENCODING, "Could not encode post data"); -+ return NULL; -+ } -+ -+ return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CSTRING, encoded, encoded_len, 1); -+ } else { -+ return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CSTRING, estrndup("", 0), 0, 1); -+ } -+} -+ -+/* STATUS http_request_body_encode(http_request_body *, char**, size_t *) */ -+PHP_HTTP_API STATUS _http_request_body_encode(http_request_body *body, char **buf, size_t *len TSRMLS_DC) -+{ -+ switch (body->type) { -+ case HTTP_REQUEST_BODY_CURLPOST: -+ { -+#ifdef HAVE_CURL_FORMGET -+ phpstr str; -+ -+ phpstr_init_ex(&str, 0x8000, 0); -+ if (curl_formget(body->data, &str, (curl_formget_callback) phpstr_append)) { -+ phpstr_dtor(&str); -+ } else { -+ phpstr_fix(&str); -+ *buf = PHPSTR_VAL(&str); -+ *len = PHPSTR_LEN(&str); -+ return SUCCESS; -+ } -+#endif -+ break; -+ } -+ -+ case HTTP_REQUEST_BODY_CSTRING: -+ *buf = estrndup(body->data, *len = body->size); -+ return SUCCESS; -+ -+ default: -+ break; -+ } -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ void http_request_body_dtor(http_request_body *) */ -+PHP_HTTP_API void _http_request_body_dtor(http_request_body *body TSRMLS_DC) -+{ -+ if (body) { -+ if (body->free) { -+ switch (body->type) { -+ case HTTP_REQUEST_BODY_CSTRING: -+ if (body->data) { -+ efree(body->data); -+ } -+ break; -+ -+ case HTTP_REQUEST_BODY_CURLPOST: -+ curl_formfree(body->data); -+ break; -+ -+ case HTTP_REQUEST_BODY_UPLOADFILE: -+ php_stream_close(body->data); -+ break; -+ } -+ } -+ memset(body, 0, sizeof(http_request_body)); -+ } -+} -+/* }}} */ -+ -+/* {{{ void http_request_body_free(http_request_body *) */ -+PHP_HTTP_API void _http_request_body_free(http_request_body **body TSRMLS_DC) -+{ -+ if (*body) { -+ http_request_body_dtor(*body); -+ efree(*body); -+ *body = NULL; -+ } -+} -+/* }}} */ -+ -+static inline char *format_key(uint type, char *str, ulong num, const char *prefix, int numeric_key_for_empty_prefix) { -+ char *new_key = NULL; -+ -+ if (prefix && *prefix) { -+ if (type == HASH_KEY_IS_STRING) { -+ spprintf(&new_key, 0, "%s[%s]", prefix, str); -+ } else { -+ spprintf(&new_key, 0, "%s[%lu]", prefix, num); -+ } -+ } else if (type == HASH_KEY_IS_STRING) { -+ new_key = estrdup(str); -+ } else if (numeric_key_for_empty_prefix) { -+ spprintf(&new_key, 0, "%lu", num); -+ } -+ -+ return new_key; -+} -+ -+/* {{{ static STATUS recursive_fields(post_data d, HashTable *f, const char *p TSRMLS_DC) */ -+static STATUS recursive_fields(post_data http_post_data, HashTable *fields, const char *prefix TSRMLS_DC) { -+ HashKey key = initHashKey(0); -+ zval **data_ptr; -+ HashPosition pos; -+ char *new_key = NULL; -+ CURLcode err = 0; -+ -+ if (fields && !fields->nApplyCount) { -+ FOREACH_HASH_KEYVAL(pos, fields, key, data_ptr) { -+ if (key.type != HASH_KEY_IS_STRING || *key.str) { -+ new_key = format_key(key.type, key.str, key.num, prefix, 1); -+ -+ switch (Z_TYPE_PP(data_ptr)) { -+ case IS_ARRAY: -+ case IS_OBJECT: { -+ STATUS status; -+ -+ ++fields->nApplyCount; -+ status = recursive_fields(http_post_data, HASH_OF(*data_ptr), new_key TSRMLS_CC); -+ --fields->nApplyCount; -+ -+ if (SUCCESS != status) { -+ goto error; -+ } -+ break; -+ } -+ -+ default: { -+ zval *data = http_zsep(IS_STRING, *data_ptr); -+ -+ err = curl_formadd(&http_post_data[0], &http_post_data[1], -+ CURLFORM_COPYNAME, new_key, -+ CURLFORM_COPYCONTENTS, Z_STRVAL_P(data), -+ CURLFORM_CONTENTSLENGTH, (long) Z_STRLEN_P(data), -+ CURLFORM_END -+ ); -+ -+ zval_ptr_dtor(&data); -+ -+ if (CURLE_OK != err) { -+ goto error; -+ } -+ break; -+ } -+ } -+ STR_FREE(new_key); -+ } -+ } -+ } -+ -+ return SUCCESS; -+ -+error: -+ if (new_key) { -+ efree(new_key); -+ } -+ if (http_post_data[0]) { -+ curl_formfree(http_post_data[0]); -+ } -+ if (err) { -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post fields: %s", curl_easy_strerror(err)); -+ } else { -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post fields: unknown error"); -+ } -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ static STATUS recursive_files(post_data d, HashTable *f, const char *p TSRMLS_DC) */ -+static STATUS recursive_files(post_data http_post_data, HashTable *files, const char *prefix TSRMLS_DC) { -+ HashKey key = initHashKey(0); -+ zval **data_ptr; -+ HashPosition pos; -+ char *new_key = NULL; -+ CURLcode err = 0; -+ -+ if (files && !files->nApplyCount) { -+ FOREACH_HASH_KEYVAL(pos, files, key, data_ptr) { -+ zval **file_ptr, **type_ptr, **name_ptr; -+ -+ if (key.type != HASH_KEY_IS_STRING || *key.str) { -+ new_key = format_key(key.type, key.str, key.num, prefix, 0); -+ -+ if (Z_TYPE_PP(data_ptr) != IS_ARRAY && Z_TYPE_PP(data_ptr) != IS_OBJECT) { -+ if (new_key || key.type == HASH_KEY_IS_STRING) { -+ http_error_ex(HE_NOTICE, HTTP_E_INVALID_PARAM, "Unrecognized type of post file array entry '%s'", new_key ? new_key : key.str); -+ } else { -+ http_error_ex(HE_NOTICE, HTTP_E_INVALID_PARAM, "Unrecognized type of post file array entry '%lu'", key.num); -+ } -+ } else if ( SUCCESS != zend_hash_find(HASH_OF(*data_ptr), "name", sizeof("name"), (void *) &name_ptr) || -+ SUCCESS != zend_hash_find(HASH_OF(*data_ptr), "type", sizeof("type"), (void *) &type_ptr) || -+ SUCCESS != zend_hash_find(HASH_OF(*data_ptr), "file", sizeof("file"), (void *) &file_ptr)) { -+ STATUS status; -+ -+ ++files->nApplyCount; -+ status = recursive_files(http_post_data, HASH_OF(*data_ptr), new_key TSRMLS_CC); -+ --files->nApplyCount; -+ -+ if (SUCCESS != status) { -+ goto error; -+ } -+ } else { -+ const char *path; -+ zval *file = http_zsep(IS_STRING, *file_ptr); -+ zval *type = http_zsep(IS_STRING, *type_ptr); -+ zval *name = http_zsep(IS_STRING, *name_ptr); -+ -+ HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(file), goto error); -+ -+ /* this is blatant but should be sufficient for most cases */ -+ if (strncasecmp(Z_STRVAL_P(file), "file://", lenof("file://"))) { -+ path = Z_STRVAL_P(file); -+ } else { -+ path = Z_STRVAL_P(file) + lenof("file://"); -+ } -+ -+ if (new_key) { -+ char *tmp_key = format_key(HASH_KEY_IS_STRING, Z_STRVAL_P(name), 0, new_key, 0); -+ STR_SET(new_key, tmp_key); -+ } -+ -+ err = curl_formadd(&http_post_data[0], &http_post_data[1], -+ CURLFORM_COPYNAME, new_key ? new_key : Z_STRVAL_P(name), -+ CURLFORM_FILE, path, -+ CURLFORM_CONTENTTYPE, Z_STRVAL_P(type), -+ CURLFORM_END -+ ); -+ -+ zval_ptr_dtor(&file); -+ zval_ptr_dtor(&type); -+ zval_ptr_dtor(&name); -+ -+ if (CURLE_OK != err) { -+ goto error; -+ } -+ } -+ STR_FREE(new_key); -+ } -+ } -+ } -+ -+ return SUCCESS; -+ -+error: -+ if (new_key) { -+ efree(new_key); -+ } -+ if (http_post_data[0]) { -+ curl_formfree(http_post_data[0]); -+ } -+ if (err) { -+ http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post files: %s", curl_easy_strerror(err)); -+ } else { -+ http_error(HE_WARNING, HTTP_E_ENCODING, "Could not encode post files: unknown error"); -+ } -+ return FAILURE; -+} -+/* }}} */ -+ -+#endif /* HTTP_HAVE_CURL */ -+ -+/* -+ * 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 -+ */ ---- /dev/null -+++ b/ext/http/http_request_datashare_api.c -@@ -0,0 +1,288 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_request_datashare_api.c 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#define HTTP_WANT_CURL -+#include "php_http.h" -+ -+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) -+ -+#include "php_http_api.h" -+#include "php_http_persistent_handle_api.h" -+#include "php_http_request_datashare_api.h" -+#include "php_http_request_api.h" -+#include "php_http_request_object.h" -+ -+static HashTable http_request_datashare_options; -+static http_request_datashare http_request_datashare_global; -+static int http_request_datashare_compare_handles(void *h1, void *h2); -+static void http_request_datashare_destroy_handles(void *el); -+#ifdef ZTS -+static void *http_request_datashare_locks_init(void); -+static void http_request_datashare_locks_dtor(void *l); -+static void http_request_datashare_lock_func(CURL *handle, curl_lock_data data, curl_lock_access locktype, void *userptr); -+static void http_request_datashare_unlock_func(CURL *handle, curl_lock_data data, void *userptr); -+#endif -+ -+http_request_datashare *_http_request_datashare_global_get(void) -+{ -+ return &http_request_datashare_global; -+} -+ -+PHP_MINIT_FUNCTION(http_request_datashare) -+{ -+ curl_lock_data val; -+ -+ if (SUCCESS != http_persistent_handle_provide("http_request_datashare", curl_share_init, (http_persistent_handle_dtor) curl_share_cleanup, NULL)) { -+ return FAILURE; -+ } -+#ifdef ZTS -+ if (SUCCESS != http_persistent_handle_provide("http_request_datashare_lock", http_request_datashare_locks_init, http_request_datashare_locks_dtor, NULL)) { -+ return FAILURE; -+ } -+#endif -+ -+ if (!http_request_datashare_init_ex(&http_request_datashare_global, 1)) { -+ return FAILURE; -+ } -+ -+ zend_hash_init(&http_request_datashare_options, 4, NULL, NULL, 1); -+#define ADD_DATASHARE_OPT(name, opt) \ -+ val = opt; \ -+ zend_hash_add(&http_request_datashare_options, name, sizeof(name), &val, sizeof(curl_lock_data), NULL) -+ ADD_DATASHARE_OPT("cookie", CURL_LOCK_DATA_COOKIE); -+ ADD_DATASHARE_OPT("dns", CURL_LOCK_DATA_DNS); -+ ADD_DATASHARE_OPT("ssl", CURL_LOCK_DATA_SSL_SESSION); -+ ADD_DATASHARE_OPT("connect", CURL_LOCK_DATA_CONNECT); -+ -+ return SUCCESS; -+} -+ -+PHP_MSHUTDOWN_FUNCTION(http_request_datashare) -+{ -+ http_request_datashare_dtor(&http_request_datashare_global); -+ zend_hash_destroy(&http_request_datashare_options); -+ -+ return SUCCESS; -+} -+ -+PHP_RINIT_FUNCTION(http_request_datashare) -+{ -+ zend_llist_init(&HTTP_G->request.datashare.handles, sizeof(zval *), http_request_datashare_destroy_handles, 0); -+ -+ return SUCCESS; -+} -+ -+PHP_RSHUTDOWN_FUNCTION(http_request_datashare) -+{ -+ zend_llist_destroy(&HTTP_G->request.datashare.handles); -+ -+ return SUCCESS; -+} -+ -+PHP_HTTP_API http_request_datashare *_http_request_datashare_init_ex(http_request_datashare *share, zend_bool persistent TSRMLS_DC) -+{ -+ zend_bool free_share; -+ -+ if ((free_share = !share)) { -+ share = pemalloc(sizeof(http_request_datashare), persistent); -+ } -+ memset(share, 0, sizeof(http_request_datashare)); -+ -+ if (SUCCESS != http_persistent_handle_acquire("http_request_datashare", &share->ch)) { -+ if (free_share) { -+ pefree(share, persistent); -+ } -+ return NULL; -+ } -+ -+ if (!(share->persistent = persistent)) { -+ share->handle.list = emalloc(sizeof(zend_llist)); -+ zend_llist_init(share->handle.list, sizeof(zval *), ZVAL_PTR_DTOR, 0); -+#ifdef ZTS -+ } else { -+ if (SUCCESS == http_persistent_handle_acquire("http_request_datashare_lock", (void *) &share->handle.locks)) { -+ curl_share_setopt(share->ch, CURLSHOPT_LOCKFUNC, http_request_datashare_lock_func); -+ curl_share_setopt(share->ch, CURLSHOPT_UNLOCKFUNC, http_request_datashare_unlock_func); -+ curl_share_setopt(share->ch, CURLSHOPT_USERDATA, share->handle.locks); -+ } -+#endif -+ } -+ -+ return share; -+} -+ -+PHP_HTTP_API STATUS _http_request_datashare_attach(http_request_datashare *share, zval *request TSRMLS_DC) -+{ -+ CURLcode rc; -+ getObjectEx(http_request_object, obj, request); -+ -+ if (obj->share) { -+ if (obj->share == share) { -+ return SUCCESS; -+ } else if (SUCCESS != http_request_datashare_detach(obj->share, request)) { -+ return FAILURE; -+ } -+ } -+ -+ HTTP_CHECK_CURL_INIT(obj->request->ch, http_curl_init_ex(obj->request->ch, obj->request), return FAILURE); -+ if (CURLE_OK != (rc = curl_easy_setopt(obj->request->ch, CURLOPT_SHARE, share->ch))) { -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "Could not attach HttpRequest object(#%d) to the HttpRequestDataShare: %s", Z_OBJ_HANDLE_P(request), curl_easy_strerror(rc)); -+ return FAILURE; -+ } -+ -+ obj->share = share; -+ ZVAL_ADDREF(request); -+ zend_llist_add_element(HTTP_RSHARE_HANDLES(share), (void *) &request); -+ -+ return SUCCESS; -+} -+ -+PHP_HTTP_API STATUS _http_request_datashare_detach(http_request_datashare *share, zval *request TSRMLS_DC) -+{ -+ CURLcode rc; -+ getObjectEx(http_request_object, obj, request); -+ -+ if (!obj->share) { -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "HttpRequest object(#%d) is not attached to any HttpRequestDataShare", Z_OBJ_HANDLE_P(request)); -+ } else if (obj->share != share) { -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "HttpRequest object(#%d) is not attached to this HttpRequestDataShare", Z_OBJ_HANDLE_P(request)); -+ } else if (CURLE_OK != (rc = curl_easy_setopt(obj->request->ch, CURLOPT_SHARE, NULL))) { -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "Could not detach HttpRequest object(#%d) from the HttpRequestDataShare: %s", Z_OBJ_HANDLE_P(request), curl_share_strerror(rc)); -+ } else { -+ obj->share = NULL; -+ zend_llist_del_element(HTTP_RSHARE_HANDLES(share), request, http_request_datashare_compare_handles); -+ return SUCCESS; -+ } -+ return FAILURE; -+} -+ -+PHP_HTTP_API void _http_request_datashare_detach_all(http_request_datashare *share TSRMLS_DC) -+{ -+ zval **r; -+ -+ while ((r = zend_llist_get_first(HTTP_RSHARE_HANDLES(share)))) { -+ http_request_datashare_detach(share, *r); -+ } -+} -+ -+PHP_HTTP_API void _http_request_datashare_dtor(http_request_datashare *share TSRMLS_DC) -+{ -+ if (!share->persistent) { -+ zend_llist_destroy(share->handle.list); -+ efree(share->handle.list); -+ } -+ http_persistent_handle_release("http_request_datashare", &share->ch); -+#ifdef ZTS -+ if (share->persistent) { -+ http_persistent_handle_release("http_request_datashare_lock", (void *) &share->handle.locks); -+ } -+#endif -+} -+ -+PHP_HTTP_API void _http_request_datashare_free(http_request_datashare **share TSRMLS_DC) -+{ -+ http_request_datashare_dtor(*share); -+ pefree(*share, (*share)->persistent); -+ *share = NULL; -+} -+ -+PHP_HTTP_API STATUS _http_request_datashare_set(http_request_datashare *share, const char *option, size_t option_len, zend_bool enable TSRMLS_DC) -+{ -+ curl_lock_data *opt; -+ CURLSHcode rc; -+ -+ if (SUCCESS == zend_hash_find(&http_request_datashare_options, (char *) option, option_len + 1, (void *) &opt)) { -+ if (CURLSHE_OK == (rc = curl_share_setopt(share->ch, enable ? CURLSHOPT_SHARE : CURLSHOPT_UNSHARE, *opt))) { -+ return SUCCESS; -+ } -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "Could not %s sharing of %s data: %s", enable ? "enable" : "disable", option, curl_share_strerror(rc)); -+ } -+ return FAILURE; -+} -+ -+static int http_request_datashare_compare_handles(void *h1, void *h2) -+{ -+ return (Z_OBJ_HANDLE_PP((zval **) h1) == Z_OBJ_HANDLE_P((zval *) h2)); -+} -+ -+static void http_request_datashare_destroy_handles(void *el) -+{ -+ zval **r = (zval **) el; -+ TSRMLS_FETCH(); -+ -+ { /* gcc 2.95 needs these braces */ -+ getObjectEx(http_request_object, obj, *r); -+ -+ curl_easy_setopt(obj->request->ch, CURLOPT_SHARE, NULL); -+ zval_ptr_dtor(r); -+ } -+} -+ -+#ifdef ZTS -+static void *http_request_datashare_locks_init(void) -+{ -+ int i; -+ http_request_datashare_lock *locks = pecalloc(CURL_LOCK_DATA_LAST, sizeof(http_request_datashare_lock), 1); -+ -+ if (locks) { -+ for (i = 0; i < CURL_LOCK_DATA_LAST; ++i) { -+ locks[i].mx = tsrm_mutex_alloc(); -+ } -+ } -+ -+ return locks; -+} -+ -+static void http_request_datashare_locks_dtor(void *l) -+{ -+ int i; -+ http_request_datashare_lock *locks = (http_request_datashare_lock *) l; -+ -+ for (i = 0; i < CURL_LOCK_DATA_LAST; ++i) { -+ tsrm_mutex_free(locks[i].mx); -+ } -+ pefree(locks, 1); -+} -+ -+static void http_request_datashare_lock_func(CURL *handle, curl_lock_data data, curl_lock_access locktype, void *userptr) -+{ -+ http_request_datashare_lock *locks = (http_request_datashare_lock *) userptr; -+ -+ /* TSRM can't distinguish shared/exclusive locks */ -+ tsrm_mutex_lock(locks[data].mx); -+ locks[data].ch = handle; -+} -+ -+static void http_request_datashare_unlock_func(CURL *handle, curl_lock_data data, void *userptr) -+{ -+ http_request_datashare_lock *locks = (http_request_datashare_lock *) userptr; -+ -+ if (locks[data].ch == handle) { -+ tsrm_mutex_unlock(locks[data].mx); -+ } -+} -+#endif -+ -+#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */ -+ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_request_info.c -@@ -0,0 +1,213 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_request_info.c 323304 2012-02-17 21:13:24Z mike $ */ -+ -+#define HTTP_WANT_CURL -+#include "php_http.h" -+ -+#ifdef HTTP_HAVE_CURL -+#include "php_http_request_api.h" -+ -+/* {{{ void http_request_info(http_request *, HashTable *) */ -+PHP_HTTP_API void _http_request_info(http_request *request, HashTable *info) -+{ -+ char *c; -+ long l; -+ double d; -+ struct curl_slist *s, *p; -+ zval *subarray, array; -+ INIT_ZARR(array, info); -+ -+ /* BEGIN */ -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_EFFECTIVE_URL, &c)) { -+ add_assoc_string_ex(&array, "effective_url", sizeof("effective_url"), c ? c : "", 1); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_RESPONSE_CODE, &l)) { -+ add_assoc_long_ex(&array, "response_code", sizeof("response_code"), l); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_TOTAL_TIME, &d)) { -+ add_assoc_double_ex(&array, "total_time", sizeof("total_time"), d); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_NAMELOOKUP_TIME, &d)) { -+ add_assoc_double_ex(&array, "namelookup_time", sizeof("namelookup_time"), d); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONNECT_TIME, &d)) { -+ add_assoc_double_ex(&array, "connect_time", sizeof("connect_time"), d); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_PRETRANSFER_TIME, &d)) { -+ add_assoc_double_ex(&array, "pretransfer_time", sizeof("pretransfer_time"), d); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SIZE_UPLOAD, &d)) { -+ add_assoc_double_ex(&array, "size_upload", sizeof("size_upload"), d); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SIZE_DOWNLOAD, &d)) { -+ add_assoc_double_ex(&array, "size_download", sizeof("size_download"), d); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SPEED_DOWNLOAD, &d)) { -+ add_assoc_double_ex(&array, "speed_download", sizeof("speed_download"), d); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SPEED_UPLOAD, &d)) { -+ add_assoc_double_ex(&array, "speed_upload", sizeof("speed_upload"), d); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_HEADER_SIZE, &l)) { -+ add_assoc_long_ex(&array, "header_size", sizeof("header_size"), l); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REQUEST_SIZE, &l)) { -+ add_assoc_long_ex(&array, "request_size", sizeof("request_size"), l); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SSL_VERIFYRESULT, &l)) { -+ add_assoc_long_ex(&array, "ssl_verifyresult", sizeof("ssl_verifyresult"), l); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_FILETIME, &l)) { -+ add_assoc_long_ex(&array, "filetime", sizeof("filetime"), l); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d)) { -+ add_assoc_double_ex(&array, "content_length_download", sizeof("content_length_download"), d); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONTENT_LENGTH_UPLOAD, &d)) { -+ add_assoc_double_ex(&array, "content_length_upload", sizeof("content_length_upload"), d); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_STARTTRANSFER_TIME, &d)) { -+ add_assoc_double_ex(&array, "starttransfer_time", sizeof("starttransfer_time"), d); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONTENT_TYPE, &c)) { -+ add_assoc_string_ex(&array, "content_type", sizeof("content_type"), c ? c : "", 1); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REDIRECT_TIME, &d)) { -+ add_assoc_double_ex(&array, "redirect_time", sizeof("redirect_time"), d); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REDIRECT_COUNT, &l)) { -+ add_assoc_long_ex(&array, "redirect_count", sizeof("redirect_count"), l); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_HTTP_CONNECTCODE, &l)) { -+ add_assoc_long_ex(&array, "connect_code", sizeof("connect_code"), l); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_HTTPAUTH_AVAIL, &l)) { -+ add_assoc_long_ex(&array, "httpauth_avail", sizeof("httpauth_avail"), l); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_PROXYAUTH_AVAIL, &l)) { -+ add_assoc_long_ex(&array, "proxyauth_avail", sizeof("proxyauth_avail"), l); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_OS_ERRNO, &l)) { -+ add_assoc_long_ex(&array, "os_errno", sizeof("os_errno"), l); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_NUM_CONNECTS, &l)) { -+ add_assoc_long_ex(&array, "num_connects", sizeof("num_connects"), l); -+ } -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_SSL_ENGINES, &s)) { -+ MAKE_STD_ZVAL(subarray); -+ array_init(subarray); -+ for (p = s; p; p = p->next) { -+ if (p->data) { -+ add_next_index_string(subarray, p->data, 1); -+ } -+ } -+ add_assoc_zval_ex(&array, "ssl_engines", sizeof("ssl_engines"), subarray); -+ curl_slist_free_all(s); -+ } -+#if HTTP_CURL_VERSION(7,14,1) -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_COOKIELIST, &s)) { -+ MAKE_STD_ZVAL(subarray); -+ array_init(subarray); -+ for (p = s; p; p = p->next) { -+ if (p->data) { -+ add_next_index_string(subarray, p->data, 1); -+ } -+ } -+ add_assoc_zval_ex(&array, "cookies", sizeof("cookies"), subarray); -+ curl_slist_free_all(s); -+ } -+#endif -+#if HTTP_CURL_VERSION(7,18,2) -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_REDIRECT_URL, &c)) { -+ add_assoc_string_ex(&array, "redirect_url", sizeof("redirect_url"), c ? c : "", 1); -+ } -+#endif -+#if HTTP_CURL_VERSION(7,19,0) -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_PRIMARY_IP, &c)) { -+ add_assoc_string_ex(&array, "primary_ip", sizeof("primary_ip"), c ? c : "", 1); -+ } -+#endif -+#if HTTP_CURL_VERSION(7,19,0) -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_APPCONNECT_TIME, &d)) { -+ add_assoc_double_ex(&array, "appconnect_time", sizeof("appconnect_time"), d); -+ } -+#endif -+#if HTTP_CURL_VERSION(7,19,4) -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CONDITION_UNMET, &l)) { -+ add_assoc_long_ex(&array, "condition_unmet", sizeof("condition_unmet"), l); -+ } -+#endif -+#if HTTP_CURL_VERSION(7,21,0) -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_PRIMARY_PORT, &l)) { -+ add_assoc_long_ex(&array, "primary_port", sizeof("primary_port"), l); -+ } -+#endif -+#if HTTP_CURL_VERSION(7,21,0) -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_LOCAL_IP, &c)) { -+ add_assoc_string_ex(&array, "local_ip", sizeof("local_ip"), c ? c : "", 1); -+ } -+#endif -+#if HTTP_CURL_VERSION(7,21,0) -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_LOCAL_PORT, &l)) { -+ add_assoc_long_ex(&array, "local_port", sizeof("local_port"), l); -+ } -+#endif -+/* END */ -+#if HTTP_CURL_VERSION(7,19,1) && defined(HTTP_HAVE_OPENSSL) -+ { -+ int i; -+ zval *ci_array; -+ struct curl_certinfo *ci; -+ char *colon, *keyname; -+ -+ if (CURLE_OK == curl_easy_getinfo(request->ch, CURLINFO_CERTINFO, &ci)) { -+ MAKE_STD_ZVAL(ci_array); -+ array_init(ci_array); -+ -+ for (i = 0; i < ci->num_of_certs; ++i) { -+ s = ci->certinfo[i]; -+ -+ MAKE_STD_ZVAL(subarray); -+ array_init(subarray); -+ for (p = s; p; p = p->next) { -+ if (p->data) { -+ if ((colon = strchr(p->data, ':'))) { -+ keyname = estrndup(p->data, colon - p->data); -+ add_assoc_string_ex(subarray, keyname, colon - p->data + 1, colon + 1, 1); -+ efree(keyname); -+ } else { -+ add_next_index_string(subarray, p->data, 1); -+ } -+ } -+ } -+ add_next_index_zval(ci_array, subarray); -+ } -+ add_assoc_zval_ex(&array, "certinfo", sizeof("certinfo"), ci_array); -+ } -+ } -+#endif -+ add_assoc_string_ex(&array, "error", sizeof("error"), http_request_storage_get(request->ch)->errorbuffer, 1); -+} -+/* }}} */ -+ -+#endif /* HTTP_HAVE_CURL */ -+ -+/* -+ * 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 -+ */ ---- /dev/null -+++ b/ext/http/http_request_method_api.c -@@ -0,0 +1,322 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_request_method_api.c 323406 2012-02-21 10:05:52Z mike $ */ -+ -+#define HTTP_WANT_CURL -+#include "php_http.h" -+ -+#include "php_http_api.h" -+#include "php_http_request_api.h" -+#include "php_http_request_method_api.h" -+ -+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY) -+# include "php_http_request_object.h" -+#endif -+ -+/* {{{ char *http_request_methods[] */ -+static const char *const http_request_methods[] = { -+ "UNKNOWN", -+ /* HTTP/1.1 */ -+ "GET", -+ "HEAD", -+ "POST", -+ "PUT", -+ "DELETE", -+ "OPTIONS", -+ "TRACE", -+ "CONNECT", -+ /* WebDAV - RFC 2518 */ -+ "PROPFIND", -+ "PROPPATCH", -+ "MKCOL", -+ "COPY", -+ "MOVE", -+ "LOCK", -+ "UNLOCK", -+ /* WebDAV Versioning - RFC 3253 */ -+ "VERSION-CONTROL", -+ "REPORT", -+ "CHECKOUT", -+ "CHECKIN", -+ "UNCHECKOUT", -+ "MKWORKSPACE", -+ "UPDATE", -+ "LABEL", -+ "MERGE", -+ "BASELINE-CONTROL", -+ "MKACTIVITY", -+ /* WebDAV Access Control - RFC 3744 */ -+ "ACL", -+ NULL -+}; -+/* }}} */ -+ -+/* {{{ */ -+PHP_MINIT_FUNCTION(http_request_method) -+{ -+ /* HTTP/1.1 */ -+ HTTP_LONG_CONSTANT("HTTP_METH_GET", HTTP_GET); -+ HTTP_LONG_CONSTANT("HTTP_METH_HEAD", HTTP_HEAD); -+ HTTP_LONG_CONSTANT("HTTP_METH_POST", HTTP_POST); -+ HTTP_LONG_CONSTANT("HTTP_METH_PUT", HTTP_PUT); -+ HTTP_LONG_CONSTANT("HTTP_METH_DELETE", HTTP_DELETE); -+ HTTP_LONG_CONSTANT("HTTP_METH_OPTIONS", HTTP_OPTIONS); -+ HTTP_LONG_CONSTANT("HTTP_METH_TRACE", HTTP_TRACE); -+ HTTP_LONG_CONSTANT("HTTP_METH_CONNECT", HTTP_CONNECT); -+ /* WebDAV - RFC 2518 */ -+ HTTP_LONG_CONSTANT("HTTP_METH_PROPFIND", HTTP_PROPFIND); -+ HTTP_LONG_CONSTANT("HTTP_METH_PROPPATCH", HTTP_PROPPATCH); -+ HTTP_LONG_CONSTANT("HTTP_METH_MKCOL", HTTP_MKCOL); -+ HTTP_LONG_CONSTANT("HTTP_METH_COPY", HTTP_COPY); -+ HTTP_LONG_CONSTANT("HTTP_METH_MOVE", HTTP_MOVE); -+ HTTP_LONG_CONSTANT("HTTP_METH_LOCK", HTTP_LOCK); -+ HTTP_LONG_CONSTANT("HTTP_METH_UNLOCK", HTTP_UNLOCK); -+ /* WebDAV Versioning - RFC 3253 */ -+ HTTP_LONG_CONSTANT("HTTP_METH_VERSION_CONTROL", HTTP_VERSION_CONTROL); -+ HTTP_LONG_CONSTANT("HTTP_METH_REPORT", HTTP_REPORT); -+ HTTP_LONG_CONSTANT("HTTP_METH_CHECKOUT", HTTP_CHECKOUT); -+ HTTP_LONG_CONSTANT("HTTP_METH_CHECKIN", HTTP_CHECKIN); -+ HTTP_LONG_CONSTANT("HTTP_METH_UNCHECKOUT", HTTP_UNCHECKOUT); -+ HTTP_LONG_CONSTANT("HTTP_METH_MKWORKSPACE", HTTP_MKWORKSPACE); -+ HTTP_LONG_CONSTANT("HTTP_METH_UPDATE", HTTP_UPDATE); -+ HTTP_LONG_CONSTANT("HTTP_METH_LABEL", HTTP_LABEL); -+ HTTP_LONG_CONSTANT("HTTP_METH_MERGE", HTTP_MERGE); -+ HTTP_LONG_CONSTANT("HTTP_METH_BASELINE_CONTROL", HTTP_BASELINE_CONTROL); -+ HTTP_LONG_CONSTANT("HTTP_METH_MKACTIVITY", HTTP_MKACTIVITY); -+ /* WebDAV Access Control - RFC 3744 */ -+ HTTP_LONG_CONSTANT("HTTP_METH_ACL", HTTP_ACL); -+ -+ return SUCCESS; -+} -+ -+static void free_method(void *el) -+{ -+ efree(*(char **)el); -+} -+ -+static void unregister_method(const char *name TSRMLS_DC) -+{ -+ char *ptr, tmp[sizeof("HTTP_METH_") + HTTP_REQUEST_METHOD_MAXLEN] = "HTTP_METH_"; -+ -+ strlcpy(tmp + lenof("HTTP_METH_"), name, HTTP_REQUEST_METHOD_MAXLEN); -+ for (ptr = tmp + lenof("HTTP_METH_"); *ptr; ++ptr) { -+ if (*ptr == '-') { -+ *ptr = '_'; -+ } -+ } -+ -+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY) -+ if (SUCCESS != zend_hash_del(&http_request_object_ce->constants_table, tmp + lenof("HTTP_"), strlen(tmp + lenof("HTTP_")) + 1)) { -+ http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Could not unregister request method: HttpRequest::%s", tmp + lenof("HTTP_")); -+ } -+#endif -+ if (SUCCESS != zend_hash_del(EG(zend_constants), tmp, strlen(tmp) + 1)) { -+ http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Could not unregister request method: %s", tmp); -+ } -+} -+ -+PHP_RINIT_FUNCTION(http_request_method) -+{ -+ HashTable ht; -+ -+ zend_hash_init(&HTTP_G->request.methods.registered, 0, NULL, free_method, 0); -+#define HTTP_METH_REG(m) \ -+ { \ -+ char *_m=estrdup(m); \ -+ zend_hash_next_index_insert(&HTTP_G->request.methods.registered, (void *) &_m, sizeof(char *), NULL); \ -+ } -+ HTTP_METH_REG("UNKNOWN"); -+ /* HTTP/1.1 */ -+ HTTP_METH_REG("GET"); -+ HTTP_METH_REG("HEAD"); -+ HTTP_METH_REG("POST"); -+ HTTP_METH_REG("PUT"); -+ HTTP_METH_REG("DELETE"); -+ HTTP_METH_REG("OPTIONS"); -+ HTTP_METH_REG("TRACE"); -+ HTTP_METH_REG("CONNECT"); -+ /* WebDAV - RFC 2518 */ -+ HTTP_METH_REG("PROPFIND"); -+ HTTP_METH_REG("PROPPATCH"); -+ HTTP_METH_REG("MKCOL"); -+ HTTP_METH_REG("COPY"); -+ HTTP_METH_REG("MOVE"); -+ HTTP_METH_REG("LOCK"); -+ HTTP_METH_REG("UNLOCK"); -+ /* WebDAV Versioning - RFC 3253 */ -+ HTTP_METH_REG("VERSION-CONTROL"); -+ HTTP_METH_REG("REPORT"); -+ HTTP_METH_REG("CHECKOUT"); -+ HTTP_METH_REG("CHECKIN"); -+ HTTP_METH_REG("UNCHECKOUT"); -+ HTTP_METH_REG("MKWORKSPACE"); -+ HTTP_METH_REG("UPDATE"); -+ HTTP_METH_REG("LABEL"); -+ HTTP_METH_REG("MERGE"); -+ HTTP_METH_REG("BASELINE-CONTROL"); -+ HTTP_METH_REG("MKACTIVITY"); -+ /* WebDAV Access Control - RFC 3744 */ -+ HTTP_METH_REG("ACL"); -+ -+ zend_hash_init(&ht, 0, NULL, ZVAL_PTR_DTOR, 0); -+ if (*HTTP_G->request.methods.custom && SUCCESS == http_parse_params(HTTP_G->request.methods.custom, HTTP_PARAMS_DEFAULT, &ht)) { -+ HashPosition pos; -+ zval **val; -+ -+ FOREACH_HASH_VAL(pos, &ht, val) { -+ if (Z_TYPE_PP(val) == IS_STRING) { -+ http_request_method_register(Z_STRVAL_PP(val), Z_STRLEN_PP(val)); -+ } -+ } -+ } -+ zend_hash_destroy(&ht); -+ -+ return SUCCESS; -+} -+ -+PHP_RSHUTDOWN_FUNCTION(http_request_method) -+{ -+ char **name; -+ int i, c = zend_hash_next_free_element(&HTTP_G->request.methods.registered); -+ -+ for (i = HTTP_MAX_REQUEST_METHOD; i < c; ++i) { -+ if (SUCCESS == zend_hash_index_find(&HTTP_G->request.methods.registered, i, (void *) &name)) { -+ unregister_method(*name TSRMLS_CC); -+ } -+ } -+ -+ zend_hash_destroy(&HTTP_G->request.methods.registered); -+ return SUCCESS; -+} -+ -+#define http_request_method_cncl(m, c) _http_request_method_cncl_ex((m), strlen(m), (c) TSRMLS_CC) -+#define http_request_method_cncl_ex(m, l, c) _http_request_method_cncl_ex((m), (l), (c) TSRMLS_CC) -+static STATUS _http_request_method_cncl_ex(const char *method_name, int method_name_len, char **cnst TSRMLS_DC) -+{ -+ int i; -+ char *cncl; -+ -+ if (method_name_len >= HTTP_REQUEST_METHOD_MAXLEN) { -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Request method too long (%s)", method_name); -+ } -+ cncl = emalloc(method_name_len + 1); -+ -+ for (i = 0; i < method_name_len; ++i) { -+ switch (method_name[i]) { -+ case '-': -+ case '_': -+ cncl[i] = method_name[i]; -+ break; -+ -+ default: -+ if (!HTTP_IS_CTYPE(alnum, method_name[i])) { -+ efree(cncl); -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Request method contains illegal characters (%s)", method_name); -+ return FAILURE; -+ } -+ cncl[i] = HTTP_TO_CTYPE(upper, method_name[i]); -+ break; -+ } -+ } -+ cncl[method_name_len] = '\0'; -+ -+ *cnst = cncl; -+ return SUCCESS; -+} -+ -+PHP_HTTP_API const char *_http_request_method_name(http_request_method m TSRMLS_DC) -+{ -+ char **name; -+ -+ if (SUCCESS == zend_hash_index_find(&HTTP_G->request.methods.registered, m, (void *) &name)) { -+ return *name; -+ } -+ return "UNKNOWN"; -+} -+ -+PHP_HTTP_API int _http_request_method_exists(int by_name, http_request_method id_num, const char *id_str TSRMLS_DC) -+{ -+ char *id_dup; -+ -+ if (by_name && (SUCCESS == http_request_method_cncl(id_str, &id_dup))) { -+ char **name; -+ HashPosition pos; -+ HashKey key = initHashKey(0); -+ -+ FOREACH_HASH_KEYVAL(pos, &HTTP_G->request.methods.registered, key, name) { -+ if (key.type == HASH_KEY_IS_LONG && !strcmp(*name, id_dup)) { -+ efree(id_dup); -+ return key.num; -+ } -+ } -+ efree(id_dup); -+ } else if (zend_hash_index_exists(&HTTP_G->request.methods.registered, id_num)){ -+ return id_num; -+ } -+ return 0; -+} -+ -+PHP_HTTP_API int _http_request_method_register(const char *method_str, int method_len TSRMLS_DC) -+{ -+ char *method_dup, *ptr, tmp[sizeof("HTTP_METH_") + HTTP_REQUEST_METHOD_MAXLEN] = "HTTP_METH_"; -+ int method_num = http_request_method_exists(1, 0, method_str); -+ -+ if (!method_num && (SUCCESS == http_request_method_cncl_ex(method_str, method_len, &method_dup))) { -+ method_num = zend_hash_next_free_element(&HTTP_G->request.methods.registered); -+ zend_hash_index_update(&HTTP_G->request.methods.registered, method_num, (void *) &method_dup, sizeof(char *), NULL); -+ -+ strlcpy(tmp + lenof("HTTP_METH_"), method_dup, HTTP_REQUEST_METHOD_MAXLEN); -+ for (ptr = tmp + lenof("HTTP_METH_"); *ptr; ++ptr) { -+ if (*ptr == '-') { -+ *ptr = '_'; -+ } -+ } -+ -+ zend_register_long_constant(tmp, strlen(tmp) + 1, method_num, CONST_CS, http_module_number TSRMLS_CC); -+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY) -+ zend_declare_class_constant_long(http_request_object_ce, tmp + lenof("HTTP_"), strlen(tmp + lenof("HTTP_")), method_num TSRMLS_CC); -+#endif -+ } -+ -+ return method_num; -+} -+ -+PHP_HTTP_API STATUS _http_request_method_unregister(int method TSRMLS_DC) -+{ -+ char **name; -+ -+ if (HTTP_STD_REQUEST_METHOD(method)) { -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Standard request methods cannot be unregistered"); -+ return FAILURE; -+ } -+ -+ if (SUCCESS != zend_hash_index_find(&HTTP_G->request.methods.registered, method, (void *) &name)) { -+ http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Custom request method with id %d does not exist", method); -+ return FAILURE; -+ } -+ -+ unregister_method(*name TSRMLS_CC); -+ -+ zend_hash_index_del(&HTTP_G->request.methods.registered, method); -+ return SUCCESS; -+} -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_request_object.c -@@ -0,0 +1,1931 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_request_object.c 323304 2012-02-17 21:13:24Z mike $ */ -+ -+#define HTTP_WANT_CURL -+#include "php_http.h" -+ -+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) -+ -+#include "zend_interfaces.h" -+ -+#include "php_http_api.h" -+#include "php_http_cookie_api.h" -+#include "php_http_exception_object.h" -+#include "php_http_message_api.h" -+#include "php_http_message_object.h" -+#include "php_http_request_api.h" -+#include "php_http_request_object.h" -+#include "php_http_request_pool_api.h" -+#include "php_http_url_api.h" -+ -+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpRequest, method, 0, req_args) -+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpRequest, method, 0) -+#define HTTP_REQUEST_ME(method, visibility) PHP_ME(HttpRequest, method, HTTP_ARGS(HttpRequest, method), visibility) -+#define HTTP_REQUEST_ALIAS(method, func) HTTP_STATIC_ME_ALIAS(method, func, HTTP_ARGS(HttpRequest, method)) -+#define HTTP_REQUEST_MALIAS(me, al, vis) ZEND_FENTRY(me, ZEND_MN(HttpRequest_##al), HTTP_ARGS(HttpRequest, al), vis) -+ -+HTTP_BEGIN_ARGS(__construct, 0) -+ HTTP_ARG_VAL(url, 0) -+ HTTP_ARG_VAL(method, 0) -+ HTTP_ARG_VAL(options, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(factory, 0) -+ HTTP_ARG_VAL(url, 0) -+ HTTP_ARG_VAL(method, 0) -+ HTTP_ARG_VAL(options, 0) -+ HTTP_ARG_VAL(class_name, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getOptions); -+HTTP_BEGIN_ARGS(setOptions, 0) -+ HTTP_ARG_VAL(options, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getSslOptions); -+HTTP_BEGIN_ARGS(setSslOptions, 0) -+ HTTP_ARG_VAL(ssl_options, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(addSslOptions, 0) -+ HTTP_ARG_VAL(ssl_optins, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getHeaders); -+HTTP_BEGIN_ARGS(setHeaders, 0) -+ HTTP_ARG_VAL(headers, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(addHeaders, 1) -+ HTTP_ARG_VAL(headers, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getCookies); -+HTTP_BEGIN_ARGS(setCookies, 0) -+ HTTP_ARG_VAL(cookies, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(addCookies, 1) -+ HTTP_ARG_VAL(cookies, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(enableCookies); -+HTTP_BEGIN_ARGS(resetCookies, 0) -+ HTTP_ARG_VAL(session_only, 0) -+HTTP_END_ARGS; -+HTTP_EMPTY_ARGS(flushCookies); -+ -+HTTP_EMPTY_ARGS(getUrl); -+HTTP_BEGIN_ARGS(setUrl, 1) -+ HTTP_ARG_VAL(url, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getMethod); -+HTTP_BEGIN_ARGS(setMethod, 1) -+ HTTP_ARG_VAL(request_method, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getContentType); -+HTTP_BEGIN_ARGS(setContentType, 1) -+ HTTP_ARG_VAL(content_type, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getQueryData); -+HTTP_BEGIN_ARGS(setQueryData, 0) -+ HTTP_ARG_VAL(query_data, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(addQueryData, 1) -+ HTTP_ARG_VAL(query_data, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getPostFields); -+HTTP_BEGIN_ARGS(setPostFields, 0) -+ HTTP_ARG_VAL(post_fields, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(addPostFields, 1) -+ HTTP_ARG_VAL(post_fields, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getPostFiles); -+HTTP_BEGIN_ARGS(setPostFiles, 0) -+ HTTP_ARG_VAL(post_files, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(addPostFile, 2) -+ HTTP_ARG_VAL(formname, 0) -+ HTTP_ARG_VAL(filename, 0) -+ HTTP_ARG_VAL(content_type, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getBody); -+HTTP_BEGIN_ARGS(setBody, 0) -+ HTTP_ARG_VAL(request_body_data, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(addBody, 1) -+ HTTP_ARG_VAL(request_body_data, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getPutFile); -+HTTP_BEGIN_ARGS(setPutFile, 0) -+ HTTP_ARG_VAL(filename, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getPutData); -+HTTP_BEGIN_ARGS(setPutData, 0) -+ HTTP_ARG_VAL(put_data, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(addPutData, 1) -+ HTTP_ARG_VAL(put_data, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getResponseData); -+HTTP_BEGIN_ARGS(getResponseHeader, 0) -+ HTTP_ARG_VAL(name, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(getResponseCookies, 0) -+ HTTP_ARG_VAL(flags, 0) -+ HTTP_ARG_VAL(allowed_extras, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getResponseBody); -+HTTP_EMPTY_ARGS(getResponseCode); -+HTTP_EMPTY_ARGS(getResponseStatus); -+HTTP_BEGIN_ARGS(getResponseInfo, 0) -+ HTTP_ARG_VAL(name, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getMessageClass); -+HTTP_BEGIN_ARGS(setMessageClass, 1) -+ HTTP_ARG_VAL(message_class_name, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getResponseMessage); -+HTTP_EMPTY_ARGS(getRawResponseMessage); -+HTTP_EMPTY_ARGS(getRequestMessage); -+HTTP_EMPTY_ARGS(getRawRequestMessage); -+HTTP_EMPTY_ARGS(getHistory); -+HTTP_EMPTY_ARGS(clearHistory); -+HTTP_EMPTY_ARGS(send); -+ -+HTTP_BEGIN_ARGS(get, 1) -+ HTTP_ARG_VAL(url, 0) -+ HTTP_ARG_VAL(options, 0) -+ HTTP_ARG_VAL(info, 1) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(head, 1) -+ HTTP_ARG_VAL(url, 0) -+ HTTP_ARG_VAL(options, 0) -+ HTTP_ARG_VAL(info, 1) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(postData, 2) -+ HTTP_ARG_VAL(url, 0) -+ HTTP_ARG_VAL(data, 0) -+ HTTP_ARG_VAL(options, 0) -+ HTTP_ARG_VAL(info, 1) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(postFields, 2) -+ HTTP_ARG_VAL(url, 0) -+ HTTP_ARG_VAL(data, 0) -+ HTTP_ARG_VAL(options, 0) -+ HTTP_ARG_VAL(info, 1) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(putData, 2) -+ HTTP_ARG_VAL(url, 0) -+ HTTP_ARG_VAL(data, 0) -+ HTTP_ARG_VAL(options, 0) -+ HTTP_ARG_VAL(info, 1) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(putFile, 2) -+ HTTP_ARG_VAL(url, 0) -+ HTTP_ARG_VAL(file, 0) -+ HTTP_ARG_VAL(options, 0) -+ HTTP_ARG_VAL(info, 1) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(putStream, 2) -+ HTTP_ARG_VAL(url, 0) -+ HTTP_ARG_VAL(stream, 0) -+ HTTP_ARG_VAL(options, 0) -+ HTTP_ARG_VAL(info, 1) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(methodRegister, 1) -+ HTTP_ARG_VAL(method_name, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(methodUnregister, 1) -+ HTTP_ARG_VAL(method, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(methodName, 1) -+ HTTP_ARG_VAL(method_id, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(methodExists, 1) -+ HTTP_ARG_VAL(method, 0) -+HTTP_END_ARGS; -+ -+#ifdef HAVE_CURL_FORMGET -+HTTP_BEGIN_ARGS(encodeBody, 2) -+ HTTP_ARG_VAL(fields, 0) -+ HTTP_ARG_VAL(files, 0) -+HTTP_END_ARGS; -+#endif -+ -+#define THIS_CE http_request_object_ce -+zend_class_entry *http_request_object_ce; -+zend_function_entry http_request_object_fe[] = { -+ HTTP_REQUEST_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) -+ -+ HTTP_REQUEST_ME(setOptions, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getOptions, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(setSslOptions, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getSslOptions, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(addSslOptions, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQUEST_ME(addHeaders, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getHeaders, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(setHeaders, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQUEST_ME(addCookies, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getCookies, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(setCookies, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQUEST_ME(enableCookies, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(resetCookies, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(flushCookies, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQUEST_ME(setMethod, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getMethod, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQUEST_ME(setUrl, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getUrl, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQUEST_ME(setContentType, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getContentType, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQUEST_ME(setQueryData, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getQueryData, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(addQueryData, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQUEST_ME(setPostFields, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getPostFields, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(addPostFields, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQUEST_ME(setBody, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getBody, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(addBody, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_MALIAS(setRawPostData, setBody, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) -+ HTTP_REQUEST_MALIAS(getRawPostData, getBody, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) -+ HTTP_REQUEST_MALIAS(addRawPostData, addBody, ZEND_ACC_PUBLIC|ZEND_ACC_DEPRECATED) -+ -+ HTTP_REQUEST_ME(setPostFiles, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(addPostFile, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getPostFiles, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQUEST_ME(setPutFile, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getPutFile, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQUEST_ME(setPutData, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getPutData, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(addPutData, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQUEST_ME(send, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQUEST_ME(getResponseData, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getResponseHeader, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getResponseCookies, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getResponseCode, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getResponseStatus, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getResponseBody, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getResponseInfo, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getResponseMessage, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getRawResponseMessage, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getRequestMessage, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getRawRequestMessage, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(getHistory, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(clearHistory, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQUEST_ME(getMessageClass, ZEND_ACC_PUBLIC) -+ HTTP_REQUEST_ME(setMessageClass, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQUEST_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) -+ -+ HTTP_REQUEST_ALIAS(get, http_get) -+ HTTP_REQUEST_ALIAS(head, http_head) -+ HTTP_REQUEST_ALIAS(postData, http_post_data) -+ HTTP_REQUEST_ALIAS(postFields, http_post_fields) -+ HTTP_REQUEST_ALIAS(putData, http_put_data) -+ HTTP_REQUEST_ALIAS(putFile, http_put_file) -+ HTTP_REQUEST_ALIAS(putStream, http_put_stream) -+ -+ HTTP_REQUEST_ALIAS(methodRegister, http_request_method_register) -+ HTTP_REQUEST_ALIAS(methodUnregister, http_request_method_unregister) -+ HTTP_REQUEST_ALIAS(methodName, http_request_method_name) -+ HTTP_REQUEST_ALIAS(methodExists, http_request_method_exists) -+#ifdef HAVE_CURL_FORMGET -+ HTTP_REQUEST_ALIAS(encodeBody, http_request_body_encode) -+#endif -+ EMPTY_FUNCTION_ENTRY -+}; -+static zend_object_handlers http_request_object_handlers; -+ -+PHP_MINIT_FUNCTION(http_request_object) -+{ -+ HTTP_REGISTER_CLASS_EX(HttpRequest, http_request_object, NULL, 0); -+ http_request_object_handlers.clone_obj = _http_request_object_clone_obj; -+ -+ zend_declare_property_null(THIS_CE, ZEND_STRS("options")-1, ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_null(THIS_CE, ZEND_STRS("postFields")-1, ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_null(THIS_CE, ZEND_STRS("postFiles")-1, ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_null(THIS_CE, ZEND_STRS("responseInfo")-1, ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_null(THIS_CE, ZEND_STRS("responseMessage")-1, ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_long(THIS_CE, ZEND_STRS("responseCode")-1, 0, ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_string(THIS_CE, ZEND_STRS("responseStatus")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_long(THIS_CE, ZEND_STRS("method")-1, HTTP_GET, ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_string(THIS_CE, ZEND_STRS("url")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_string(THIS_CE, ZEND_STRS("contentType")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_string(THIS_CE, ZEND_STRS("requestBody")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_string(THIS_CE, ZEND_STRS("queryData")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_string(THIS_CE, ZEND_STRS("putFile")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_string(THIS_CE, ZEND_STRS("putData")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_null(THIS_CE, ZEND_STRS("history")-1, ZEND_ACC_PRIVATE TSRMLS_CC); -+ zend_declare_property_bool(THIS_CE, ZEND_STRS("recordHistory")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC); -+ zend_declare_property_string(THIS_CE, ZEND_STRS("messageClass")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC); -+ -+#ifndef WONKY -+ /* -+ * Request Method Constants -+ */ -+ /* HTTP/1.1 */ -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_GET")-1, HTTP_GET TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_HEAD")-1, HTTP_HEAD TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_POST")-1, HTTP_POST TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_PUT")-1, HTTP_PUT TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_DELETE")-1, HTTP_DELETE TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_OPTIONS")-1, HTTP_OPTIONS TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_TRACE")-1, HTTP_TRACE TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_CONNECT")-1, HTTP_CONNECT TSRMLS_CC); -+ /* WebDAV - RFC 2518 */ -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_PROPFIND")-1, HTTP_PROPFIND TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_PROPPATCH")-1, HTTP_PROPPATCH TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MKCOL")-1, HTTP_MKCOL TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_COPY")-1, HTTP_COPY TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MOVE")-1, HTTP_MOVE TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_LOCK")-1, HTTP_LOCK TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_UNLOCK")-1, HTTP_UNLOCK TSRMLS_CC); -+ /* WebDAV Versioning - RFC 3253 */ -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_VERSION_CONTROL")-1, HTTP_VERSION_CONTROL TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_REPORT")-1, HTTP_REPORT TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_CHECKOUT")-1, HTTP_CHECKOUT TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_CHECKIN")-1, HTTP_CHECKIN TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_UNCHECKOUT")-1, HTTP_UNCHECKOUT TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MKWORKSPACE")-1, HTTP_MKWORKSPACE TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_UPDATE")-1, HTTP_UPDATE TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_LABEL")-1, HTTP_LABEL TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MERGE")-1, HTTP_MERGE TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_BASELINE_CONTROL")-1, HTTP_BASELINE_CONTROL TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_MKACTIVITY")-1, HTTP_MKACTIVITY TSRMLS_CC); -+ /* WebDAV Access Control - RFC 3744 */ -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("METH_ACL")-1, HTTP_ACL TSRMLS_CC); -+ -+ /* -+ * HTTP Protocol Version Constants -+ */ -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_1_0")-1, CURL_HTTP_VERSION_1_0 TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_1_1")-1, CURL_HTTP_VERSION_1_1 TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_NONE")-1, CURL_HTTP_VERSION_NONE TSRMLS_CC); /* to be removed */ -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("VERSION_ANY")-1, CURL_HTTP_VERSION_NONE TSRMLS_CC); -+ -+ /* -+ * SSL Version Constants -+ */ -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_TLSv1")-1, CURL_SSLVERSION_TLSv1 TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_SSLv2")-1, CURL_SSLVERSION_SSLv2 TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_SSLv3")-1, CURL_SSLVERSION_SSLv3 TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("SSL_VERSION_ANY")-1, CURL_SSLVERSION_DEFAULT TSRMLS_CC); -+ -+ /* -+ * DNS IPvX resolving -+ */ -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("IPRESOLVE_V4")-1, CURL_IPRESOLVE_V4 TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("IPRESOLVE_V6")-1, CURL_IPRESOLVE_V6 TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("IPRESOLVE_ANY")-1, CURL_IPRESOLVE_WHATEVER TSRMLS_CC); -+ -+ /* -+ * Auth Constants -+ */ -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_BASIC")-1, CURLAUTH_BASIC TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_DIGEST")-1, CURLAUTH_DIGEST TSRMLS_CC); -+#if HTTP_CURL_VERSION(7,19,3) -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_DIGEST_IE")-1, CURLAUTH_DIGEST_IE TSRMLS_CC); -+#endif -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_NTLM")-1, CURLAUTH_NTLM TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_GSSNEG")-1, CURLAUTH_GSSNEGOTIATE TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("AUTH_ANY")-1, CURLAUTH_ANY TSRMLS_CC); -+ -+ /* -+ * Proxy Type Constants -+ */ -+# if HTTP_CURL_VERSION(7,15,2) -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS4")-1, CURLPROXY_SOCKS4 TSRMLS_CC); -+# endif -+#if HTTP_CURL_VERSION(7,18,0) -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS4A")-1, CURLPROXY_SOCKS5 TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS5_HOSTNAME")-1, CURLPROXY_SOCKS5 TSRMLS_CC); -+#endif -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_SOCKS5")-1, CURLPROXY_SOCKS5 TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_HTTP")-1, CURLPROXY_HTTP TSRMLS_CC); -+# if HTTP_CURL_VERSION(7,19,4) -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("PROXY_HTTP_1_0")-1, CURLPROXY_HTTP_1_0 TSRMLS_CC); -+# endif -+#endif /* WONKY */ -+ -+ /* -+ * Post Redirection Constants -+ */ -+#if HTTP_CURL_VERSION(7,19,1) -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("POSTREDIR_301")-1, CURL_REDIR_POST_301 TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("POSTREDIR_302")-1, CURL_REDIR_POST_302 TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("POSTREDIR_ALL")-1, CURL_REDIR_POST_ALL TSRMLS_CC); -+#endif -+ -+ return SUCCESS; -+} -+ -+zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC) -+{ -+ return http_request_object_new_ex(ce, NULL, NULL); -+} -+ -+zend_object_value _http_request_object_new_ex(zend_class_entry *ce, CURL *ch, http_request_object **ptr TSRMLS_DC) -+{ -+ zend_object_value ov; -+ http_request_object *o; -+ -+ o = ecalloc(1, sizeof(http_request_object)); -+ o->zo.ce = ce; -+ o->request = http_request_init_ex(NULL, ch, 0, NULL); -+ -+ if (ptr) { -+ *ptr = o; -+ } -+ -+#ifdef ZEND_ENGINE_2_4 -+ zend_object_std_init(o, ce TSRMLS_CC); -+ object_properties_init(o, ce); -+#else -+ ALLOC_HASHTABLE(OBJ_PROP(o)); -+ zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0); -+ zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+#endif -+ -+ ov.handle = putObject(http_request_object, o); -+ ov.handlers = &http_request_object_handlers; -+ -+ return ov; -+} -+ -+zend_object_value _http_request_object_clone_obj(zval *this_ptr TSRMLS_DC) -+{ -+ zend_object_value new_ov; -+ http_request_object *new_obj; -+ getObject(http_request_object, old_obj); -+ -+ new_ov = http_request_object_new_ex(old_obj->zo.ce, NULL, &new_obj); -+ if (old_obj->request->ch) { -+ http_curl_init_ex(http_curl_copy(old_obj->request->ch), new_obj->request); -+ } -+ -+ zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); -+ phpstr_append(&new_obj->request->conv.request, old_obj->request->conv.request.data, old_obj->request->conv.request.used); -+ phpstr_append(&new_obj->request->conv.response, old_obj->request->conv.response.data, old_obj->request->conv.response.used); -+ -+ return new_ov; -+} -+ -+void _http_request_object_free(zend_object *object TSRMLS_DC) -+{ -+ http_request_object *o = (http_request_object *) object; -+ -+ http_request_free(&o->request); -+ freeObject(o); -+} -+ -+#define http_request_object_check_request_content_type(t) _http_request_object_check_request_content_type((t) TSRMLS_CC) -+static inline void _http_request_object_check_request_content_type(zval *this_ptr TSRMLS_DC) -+{ -+ zval *ctype = zend_read_property(THIS_CE, getThis(), ZEND_STRS("contentType")-1, 0 TSRMLS_CC); -+ -+ if (Z_STRLEN_P(ctype)) { -+ zval **headers, *opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC); -+ -+ if ( (Z_TYPE_P(opts) == IS_ARRAY) && -+ (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), "headers", sizeof("headers"), (void *) &headers)) && -+ (Z_TYPE_PP(headers) == IS_ARRAY)) { -+ zval **ct_header; -+ -+ /* only override if not already set */ -+ if ((SUCCESS != zend_hash_find(Z_ARRVAL_PP(headers), "Content-Type", sizeof("Content-Type"), (void *) &ct_header))) { -+ add_assoc_stringl(*headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1); -+ } else -+ /* or not a string, zero length string or a string of spaces */ -+ if ((Z_TYPE_PP(ct_header) != IS_STRING) || !Z_STRLEN_PP(ct_header)) { -+ add_assoc_stringl(*headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1); -+ } else { -+ int i, only_space = 1; -+ -+ /* check for spaces only */ -+ for (i = 0; i < Z_STRLEN_PP(ct_header); ++i) { -+ if (!HTTP_IS_CTYPE(space, Z_STRVAL_PP(ct_header)[i])) { -+ only_space = 0; -+ break; -+ } -+ } -+ if (only_space) { -+ add_assoc_stringl(*headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1); -+ } -+ } -+ } else { -+ zval *headers; -+ -+ MAKE_STD_ZVAL(headers); -+ array_init(headers); -+ add_assoc_stringl(headers, "Content-Type", Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1); -+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addheaders", NULL, headers); -+ zval_ptr_dtor(&headers); -+ } -+ } -+} -+ -+#define http_request_object_message(zo, msg) _http_request_object_message((zo), (msg) TSRMLS_CC) -+static inline zend_object_value _http_request_object_message(zval *this_ptr, http_message *msg TSRMLS_DC) -+{ -+ zend_object_value ov; -+ zval *zcn = zend_read_property(THIS_CE, getThis(), ZEND_STRS("messageClass")-1, 0 TSRMLS_CC); -+ -+ if (Z_STRLEN_P(zcn) && (SUCCESS == http_object_new(&ov, Z_STRVAL_P(zcn), Z_STRLEN_P(zcn), _http_message_object_new_ex, http_message_object_ce, msg, NULL))) { -+ return ov; -+ } else { -+ return http_message_object_new_ex(http_message_object_ce, msg, NULL); -+ } -+} -+ -+STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_ptr TSRMLS_DC) -+{ -+ STATUS status = SUCCESS; -+ char *url = http_absolute_url(Z_STRVAL_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("url")-1, 0 TSRMLS_CC))); -+ -+ if (!url) { -+ return FAILURE; -+ } -+ -+ http_request_reset(obj->request); -+ obj->request->url = url; -+ HTTP_CHECK_CURL_INIT(obj->request->ch, http_curl_init(obj->request), return FAILURE); -+ -+ switch (obj->request->meth = Z_LVAL_P(zend_read_property(THIS_CE, getThis(), ZEND_STRS("method")-1, 0 TSRMLS_CC))) -+ { -+ case HTTP_GET: -+ case HTTP_HEAD: -+ break; -+ -+ case HTTP_PUT: -+ { -+ zval *put_file = zend_read_property(THIS_CE, getThis(), ZEND_STRS("putFile")-1, 0 TSRMLS_CC); -+ -+ http_request_object_check_request_content_type(getThis()); -+ -+ if (Z_STRLEN_P(put_file)) { -+ php_stream_statbuf ssb; -+ php_stream *stream = php_stream_open_wrapper_ex(Z_STRVAL_P(put_file), "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT); -+ -+ if (stream && SUCCESS == php_stream_stat(stream, &ssb)) { -+ obj->request->body = http_request_body_init_ex(obj->request->body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 1); -+ } else { -+ status = FAILURE; -+ } -+ } else { -+ zval *put_data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("putData")-1, 0 TSRMLS_CC); -+ obj->request->body = http_request_body_init_ex(obj->request->body, HTTP_REQUEST_BODY_CSTRING, -+ estrndup(Z_STRVAL_P(put_data), Z_STRLEN_P(put_data)), Z_STRLEN_P(put_data), 1); -+ } -+ break; -+ } -+ -+ case HTTP_POST: -+ default: -+ { -+ /* check for raw request body */ -+ zval *raw_data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, 0 TSRMLS_CC); -+ -+ if (Z_STRLEN_P(raw_data)) { -+ http_request_object_check_request_content_type(getThis()); -+ obj->request->body = http_request_body_init_ex(obj->request->body, HTTP_REQUEST_BODY_CSTRING, -+ estrndup(Z_STRVAL_P(raw_data), Z_STRLEN_P(raw_data)), Z_STRLEN_P(raw_data), 1); -+ } else { -+ zval *zfields = zend_read_property(THIS_CE, getThis(), ZEND_STRS("postFields")-1, 0 TSRMLS_CC), *zfiles = zend_read_property(THIS_CE, getThis(), ZEND_STRS("postFiles")-1, 0 TSRMLS_CC); -+ HashTable *fields; -+ HashTable *files; -+ -+ fields = (Z_TYPE_P(zfields) == IS_ARRAY) ? Z_ARRVAL_P(zfields) : NULL; -+ files = (Z_TYPE_P(zfiles) == IS_ARRAY) ? Z_ARRVAL_P(zfiles) : NULL; -+ -+ if ((fields && zend_hash_num_elements(fields)) || (files && zend_hash_num_elements(files))) { -+ if (!(obj->request->body = http_request_body_fill(obj->request->body, fields, files))) { -+ status = FAILURE; -+ } -+ } -+ } -+ break; -+ } -+ } -+ -+ if (status == SUCCESS) { -+ zval *qdata = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryData")-1, 0 TSRMLS_CC); -+ zval *options = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC); -+ -+ if (Z_STRLEN_P(qdata)) { -+ if (!strchr(obj->request->url, '?')) { -+ strlcat(obj->request->url, "?", HTTP_URL_MAXLEN); -+ } else { -+ strlcat(obj->request->url, "&", HTTP_URL_MAXLEN); -+ } -+ strlcat(obj->request->url, Z_STRVAL_P(qdata), HTTP_URL_MAXLEN); -+ } -+ -+ http_request_prepare(obj->request, Z_ARRVAL_P(options)); -+ -+ /* check if there's a onProgress method and add it as progress callback if one isn't already set */ -+ if (zend_hash_exists(&Z_OBJCE_P(getThis())->function_table, "onprogress", sizeof("onprogress"))) { -+ zval **entry, *pcb; -+ -+ if ( (Z_TYPE_P(options) != IS_ARRAY) -+ || (SUCCESS != zend_hash_find(Z_ARRVAL_P(options), "onprogress", sizeof("onprogress"), (void *) &entry) -+ || (!HTTP_IS_CALLABLE(*entry, 0, NULL)))) { -+ MAKE_STD_ZVAL(pcb); -+ array_init(pcb); -+ ZVAL_ADDREF(getThis()); -+ add_next_index_zval(pcb, getThis()); -+ add_next_index_stringl(pcb, "onprogress", lenof("onprogress"), 1); -+ http_request_set_progress_callback(obj->request, pcb); -+ zval_ptr_dtor(&pcb); -+ } -+ } -+ } -+ -+ return status; -+} -+ -+STATUS _http_request_object_responsehandler(http_request_object *obj, zval *this_ptr TSRMLS_DC) -+{ -+ STATUS ret; -+ zval *info; -+ http_message *msg; -+ -+ /* always fetch info */ -+ MAKE_STD_ZVAL(info); -+ array_init(info); -+ http_request_info(obj->request, Z_ARRVAL_P(info)); -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("responseInfo")-1, info TSRMLS_CC); -+ zval_ptr_dtor(&info); -+ -+ /* parse response message */ -+ phpstr_fix(&obj->request->conv.request); -+ phpstr_fix(&obj->request->conv.response); -+ -+ if ((msg = http_message_parse(PHPSTR_VAL(&obj->request->conv.response), PHPSTR_LEN(&obj->request->conv.response)))) { -+ zval *message; -+ -+ if (i_zend_is_true(zend_read_property(THIS_CE, getThis(), ZEND_STRS("recordHistory")-1, 0 TSRMLS_CC))) { -+ zval *hist, *history = zend_read_property(THIS_CE, getThis(), ZEND_STRS("history")-1, 0 TSRMLS_CC); -+ http_message *response = http_message_parse(PHPSTR_VAL(&obj->request->conv.response), PHPSTR_LEN(&obj->request->conv.response)); -+ http_message *request = http_message_parse(PHPSTR_VAL(&obj->request->conv.request), PHPSTR_LEN(&obj->request->conv.request)); -+ -+ MAKE_STD_ZVAL(hist); -+ ZVAL_OBJVAL(hist, http_request_object_message(getThis(), http_message_interconnect(response, request)), 0); -+ if (Z_TYPE_P(history) == IS_OBJECT) { -+ http_message_object_prepend(hist, history); -+ } -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("history")-1, hist TSRMLS_CC); -+ zval_ptr_dtor(&hist); -+ } -+ -+ zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("responseCode")-1, msg->http.info.response.code TSRMLS_CC); -+ zend_update_property_string(THIS_CE, getThis(), ZEND_STRS("responseStatus")-1, STR_PTR(msg->http.info.response.status) TSRMLS_CC); -+ -+ MAKE_STD_ZVAL(message); -+ ZVAL_OBJVAL(message, http_request_object_message(getThis(), msg), 0); -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, message TSRMLS_CC); -+ zval_ptr_dtor(&message); -+ -+ ret = SUCCESS; -+ } else { -+ /* update properties with empty values*/ -+ zval *znull; -+ -+ MAKE_STD_ZVAL(znull); -+ ZVAL_NULL(znull); -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, znull TSRMLS_CC); -+ zval_ptr_dtor(&znull); -+ -+ zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("responseCode")-1, 0 TSRMLS_CC); -+ zend_update_property_string(THIS_CE, getThis(), ZEND_STRS("responseStatus")-1, "" TSRMLS_CC); -+ -+ /* append request message to history */ -+ if (i_zend_is_true(zend_read_property(THIS_CE, getThis(), ZEND_STRS("recordHistory")-1, 0 TSRMLS_CC))) { -+ http_message *request; -+ -+ if ((request = http_message_parse(PHPSTR_VAL(&obj->request->conv.request), PHPSTR_LEN(&obj->request->conv.request)))) { -+ zval *hist, *history = zend_read_property(THIS_CE, getThis(), ZEND_STRS("history")-1, 0 TSRMLS_CC); -+ -+ MAKE_STD_ZVAL(hist); -+ ZVAL_OBJVAL(hist, http_request_object_message(getThis(), request), 0); -+ if (Z_TYPE_P(history) == IS_OBJECT) { -+ http_message_object_prepend(hist, history); -+ } -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("history")-1, hist TSRMLS_CC); -+ zval_ptr_dtor(&hist); -+ } -+ } -+ -+ ret = FAILURE; -+ } -+ -+ http_request_set_progress_callback(obj->request, NULL); -+ -+ if (!EG(exception) && zend_hash_exists(&Z_OBJCE_P(getThis())->function_table, "onfinish", sizeof("onfinish"))) { -+ zval *param; -+ -+ MAKE_STD_ZVAL(param); -+ ZVAL_BOOL(param, ret == SUCCESS); -+ with_error_handling(EH_NORMAL, NULL) { -+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "onfinish", NULL, param); -+ } end_error_handling(); -+ zval_ptr_dtor(¶m); -+ } -+ -+ return ret; -+} -+#ifdef ZEND_ENGINE_2_4 -+# define APK_DC TSRMLS_DC -+#else -+# define APK_DC -+#endif -+static int apply_pretty_key(void *pDest APK_DC, int num_args, va_list args, zend_hash_key *hash_key) -+{ -+ if (hash_key->arKey && hash_key->nKeyLength > 1) { -+ hash_key->h = zend_hash_func(pretty_key(hash_key->arKey, hash_key->nKeyLength - 1, 1, 0), hash_key->nKeyLength); -+ } -+ return ZEND_HASH_APPLY_KEEP; -+} -+ -+#define http_request_object_set_options_subr(key, ow, pk) \ -+ _http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU, (key), sizeof(key), (ow), (pk)) -+static inline void _http_request_object_set_options_subr(INTERNAL_FUNCTION_PARAMETERS, char *key, size_t len, int overwrite, int prettify_keys) -+{ -+ zval *old_opts, *new_opts, *opts = NULL, **entry = NULL; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a/!", &opts)) { -+ RETURN_FALSE; -+ } -+ -+ MAKE_STD_ZVAL(new_opts); -+ array_init(new_opts); -+ old_opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC); -+ if (Z_TYPE_P(old_opts) == IS_ARRAY) { -+ array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL_P(new_opts)); -+ } -+ -+ if (SUCCESS == zend_hash_find(Z_ARRVAL_P(new_opts), key, len, (void *) &entry)) { -+ if (overwrite) { -+ zend_hash_clean(Z_ARRVAL_PP(entry)); -+ } -+ if (opts && zend_hash_num_elements(Z_ARRVAL_P(opts))) { -+ if (overwrite) { -+ array_copy(Z_ARRVAL_P(opts), Z_ARRVAL_PP(entry)); -+ } else { -+ array_join(Z_ARRVAL_P(opts), Z_ARRVAL_PP(entry), 0, prettify_keys ? ARRAY_JOIN_PRETTIFY : 0); -+ } -+ } -+ } else if (opts) { -+ if (prettify_keys) { -+ zend_hash_apply_with_arguments(Z_ARRVAL_P(opts) HTTP_ZAPI_HASH_TSRMLS_CC, apply_pretty_key, 0, NULL); -+ } -+ ZVAL_ADDREF(opts); -+ add_assoc_zval_ex(new_opts, key, len, opts); -+ } -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("options")-1, new_opts TSRMLS_CC); -+ zval_ptr_dtor(&new_opts); -+ -+ RETURN_TRUE; -+} -+ -+#define http_request_object_get_options_subr(key) \ -+ _http_request_get_options_subr(INTERNAL_FUNCTION_PARAM_PASSTHRU, (key), sizeof(key)) -+static inline void _http_request_get_options_subr(INTERNAL_FUNCTION_PARAMETERS, char *key, size_t len) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ zval *opts, **options; -+ -+ opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC); -+ array_init(return_value); -+ -+ if ( (Z_TYPE_P(opts) == IS_ARRAY) && -+ (SUCCESS == zend_hash_find(Z_ARRVAL_P(opts), key, len, (void *) &options))) { -+ convert_to_array(*options); -+ array_copy(Z_ARRVAL_PP(options), Z_ARRVAL_P(return_value)); -+ } -+ } -+} -+ -+ -+/* ### USERLAND ### */ -+ -+/* {{{ proto void HttpRequest::__construct([string url[, int request_method = HTTP_METH_GET[, array options]]]) -+ Create a new HttpRequest object instance. */ -+PHP_METHOD(HttpRequest, __construct) -+{ -+ char *URL = NULL; -+ int URL_len; -+ long meth = -1; -+ zval *options = NULL; -+ -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sla!", &URL, &URL_len, &meth, &options)) { -+ if (URL) { -+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("url")-1, URL, URL_len TSRMLS_CC); -+ } -+ if (meth > -1) { -+ zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("method")-1, meth TSRMLS_CC); -+ } -+ if (options) { -+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setoptions", NULL, options); -+ } -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+/* {{{ proto HttpRequest HttpRequest::factory([string url[, int request_method HTTP_METH_GET[, array options[, string class_name = "HttpRequest"]]]]) -+ Create a new HttpRequest object instance. */ -+PHP_METHOD(HttpRequest, factory) -+{ -+ char *cn = NULL, *URL = NULL; -+ int cl = 0, URL_len = 0; -+ long meth = -1; -+ zval *options = NULL; -+ zend_object_value ov; -+ -+ SET_EH_THROW_HTTP(); -+ if ( SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sla!s", &URL, &URL_len, &meth, &options, &cn, &cl) && -+ SUCCESS == http_object_new(&ov, cn, cl, _http_request_object_new_ex, http_request_object_ce, NULL, NULL)) { -+ RETVAL_OBJVAL(ov, 0); -+ getThis() = return_value; -+ if (URL) { -+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("url")-1, URL, URL_len TSRMLS_CC); -+ } -+ if (meth > -1) { -+ zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("method")-1, meth TSRMLS_CC); -+ } -+ if (options) { -+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setoptions", NULL, options); -+ } -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::setOptions([array options]) -+ Set the request options to use. See http_get() for a full list of available options. */ -+PHP_METHOD(HttpRequest, setOptions) -+{ -+ HashKey key = initHashKey(0); -+ HashPosition pos; -+ zval *opts = NULL, *old_opts, *new_opts, *add_opts, **opt; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!/", &opts)) { -+ RETURN_FALSE; -+ } -+ -+ MAKE_STD_ZVAL(new_opts); -+ array_init(new_opts); -+ -+ if (!opts || !zend_hash_num_elements(Z_ARRVAL_P(opts))) { -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("options")-1, new_opts TSRMLS_CC); -+ zval_ptr_dtor(&new_opts); -+ RETURN_TRUE; -+ } -+ -+ MAKE_STD_ZVAL(add_opts); -+ array_init(add_opts); -+ /* some options need extra attention -- thus cannot use array_merge() directly */ -+ FOREACH_KEYVAL(pos, opts, key, opt) { -+ if (key.type == HASH_KEY_IS_STRING) { -+#define KEYMATCH(k, s) ((sizeof(s)==k.len) && !strcasecmp(k.str, s)) -+ if (KEYMATCH(key, "headers")) { -+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addheaders", NULL, *opt); -+ } else if (KEYMATCH(key, "cookies")) { -+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addcookies", NULL, *opt); -+ } else if (KEYMATCH(key, "ssl")) { -+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "addssloptions", NULL, *opt); -+ } else if (KEYMATCH(key, "url") || KEYMATCH(key, "uri")) { -+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "seturl", NULL, *opt); -+ } else if (KEYMATCH(key, "method")) { -+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setmethod", NULL, *opt); -+ } else if (KEYMATCH(key, "flushcookies")) { -+ getObject(http_request_object, obj); -+ if (i_zend_is_true(*opt)) { -+ http_request_flush_cookies(obj->request); -+ } -+ } else if (KEYMATCH(key, "resetcookies")) { -+ getObject(http_request_object, obj); -+ http_request_reset_cookies(obj->request, (zend_bool) i_zend_is_true(*opt)); -+ } else if (KEYMATCH(key, "enablecookies")) { -+ getObject(http_request_object, obj); -+ http_request_enable_cookies(obj->request); -+ } else if (KEYMATCH(key, "recordHistory")) { -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("recordHistory")-1, *opt TSRMLS_CC); -+ } else if (KEYMATCH(key, "messageClass")) { -+ zend_call_method_with_1_params(&getThis(), Z_OBJCE_P(getThis()), NULL, "setmessageclass", NULL, *opt); -+ } else if (Z_TYPE_PP(opt) == IS_NULL) { -+ old_opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC); -+ if (Z_TYPE_P(old_opts) == IS_ARRAY) { -+ zend_hash_del(Z_ARRVAL_P(old_opts), key.str, key.len); -+ } -+ } else { -+ ZVAL_ADDREF(*opt); -+ add_assoc_zval_ex(add_opts, key.str, key.len, *opt); -+ } -+ } -+ } -+ -+ old_opts = zend_read_property(THIS_CE, getThis(), ZEND_STRS("options")-1, 0 TSRMLS_CC); -+ if (Z_TYPE_P(old_opts) == IS_ARRAY) { -+ array_copy(Z_ARRVAL_P(old_opts), Z_ARRVAL_P(new_opts)); -+ } -+ array_join(Z_ARRVAL_P(add_opts), Z_ARRVAL_P(new_opts), 0, 0); -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("options")-1, new_opts TSRMLS_CC); -+ zval_ptr_dtor(&new_opts); -+ zval_ptr_dtor(&add_opts); -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto array HttpRequest::getOptions() -+ Get currently set options. */ -+PHP_METHOD(HttpRequest, getOptions) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ RETURN_PROP(options); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::setSslOptions([array options]) -+ Set SSL options. */ -+PHP_METHOD(HttpRequest, setSslOptions) -+{ -+ http_request_object_set_options_subr("ssl", 1, 0); -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::addSslOptions(array options) -+ Set additional SSL options. */ -+PHP_METHOD(HttpRequest, addSslOptions) -+{ -+ http_request_object_set_options_subr("ssl", 0, 0); -+} -+/* }}} */ -+ -+/* {{{ proto array HttpRequest::getSslOtpions() -+ Get previously set SSL options. */ -+PHP_METHOD(HttpRequest, getSslOptions) -+{ -+ http_request_object_get_options_subr("ssl"); -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::addHeaders(array headers) -+ Add request header name/value pairs. */ -+PHP_METHOD(HttpRequest, addHeaders) -+{ -+ http_request_object_set_options_subr("headers", 0, 1); -+} -+ -+/* {{{ proto bool HttpRequest::setHeaders([array headers]) -+ Set request header name/value pairs. */ -+PHP_METHOD(HttpRequest, setHeaders) -+{ -+ http_request_object_set_options_subr("headers", 1, 1); -+} -+/* }}} */ -+ -+/* {{{ proto array HttpRequest::getHeaders() -+ Get previously set request headers. */ -+PHP_METHOD(HttpRequest, getHeaders) -+{ -+ http_request_object_get_options_subr("headers"); -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::setCookies([array cookies]) -+ Set cookies. */ -+PHP_METHOD(HttpRequest, setCookies) -+{ -+ http_request_object_set_options_subr("cookies", 1, 0); -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::addCookies(array cookies) -+ Add cookies. */ -+PHP_METHOD(HttpRequest, addCookies) -+{ -+ http_request_object_set_options_subr("cookies", 0, 0); -+} -+/* }}} */ -+ -+/* {{{ proto array HttpRequest::getCookies() -+ Get previously set cookies. */ -+PHP_METHOD(HttpRequest, getCookies) -+{ -+ http_request_object_get_options_subr("cookies"); -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::enableCookies() -+ Enable automatic sending of received cookies. Note that customly set cookies will be sent anyway. */ -+PHP_METHOD(HttpRequest, enableCookies) -+{ -+ NO_ARGS { -+ getObject(http_request_object, obj); -+ RETURN_SUCCESS(http_request_enable_cookies(obj->request)); -+ } -+ -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::resetCookies([bool session_only = FALSE]) -+ Reset all automatically received/sent cookies. Note that customly set cookies are not affected. */ -+PHP_METHOD(HttpRequest, resetCookies) -+{ -+ zend_bool session_only = 0; -+ getObject(http_request_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &session_only)) { -+ RETURN_FALSE; -+ } -+ RETURN_SUCCESS(http_request_reset_cookies(obj->request, session_only)); -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::flushCookies() -+ Flush internal cookies to the cookiestore file */ -+PHP_METHOD(HttpRequest, flushCookies) -+{ -+ NO_ARGS { -+ getObject(http_request_object, obj); -+ RETURN_SUCCESS(http_request_flush_cookies(obj->request)); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::setUrl(string url) -+ Set the request URL. */ -+PHP_METHOD(HttpRequest, setUrl) -+{ -+ char *URL = NULL; -+ int URL_len; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URL, &URL_len)) { -+ RETURN_FALSE; -+ } -+ -+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("url")-1, URL, URL_len TSRMLS_CC); -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto string HttpRequest::getUrl() -+ Get the previously set request URL. */ -+PHP_METHOD(HttpRequest, getUrl) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ RETURN_PROP(url); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::setMethod(int request_method) -+ Set the request method. */ -+PHP_METHOD(HttpRequest, setMethod) -+{ -+ long meth; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &meth)) { -+ RETURN_FALSE; -+ } -+ -+ zend_update_property_long(THIS_CE, getThis(), ZEND_STRS("method")-1, meth TSRMLS_CC); -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto int HttpRequest::getMethod() -+ Get the previously set request method. */ -+PHP_METHOD(HttpRequest, getMethod) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ RETURN_PROP(method); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::setContentType(string content_type) -+ Set the content type the post request should have. */ -+PHP_METHOD(HttpRequest, setContentType) -+{ -+ char *ctype; -+ int ct_len; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ct_len)) { -+ RETURN_FALSE; -+ } -+ -+ if (ct_len) { -+ HTTP_CHECK_CONTENT_TYPE(ctype, RETURN_FALSE); -+ } -+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("contentType")-1, ctype, ct_len TSRMLS_CC); -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto string HttpRequest::getContentType() -+ Get the previously content type. */ -+PHP_METHOD(HttpRequest, getContentType) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ RETURN_PROP(contentType); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::setQueryData([mixed query_data]) -+ Set the URL query parameters to use, overwriting previously set query parameters. */ -+PHP_METHOD(HttpRequest, setQueryData) -+{ -+ zval *qdata = NULL; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!", &qdata)) { -+ RETURN_FALSE; -+ } -+ -+ if ((!qdata) || Z_TYPE_P(qdata) == IS_NULL) { -+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryData")-1, "", 0 TSRMLS_CC); -+ } else if ((Z_TYPE_P(qdata) == IS_ARRAY) || (Z_TYPE_P(qdata) == IS_OBJECT)) { -+ char *query_data = NULL; -+ -+ if (SUCCESS != http_urlencode_hash(HASH_OF(qdata), &query_data)) { -+ RETURN_FALSE; -+ } -+ -+ zend_update_property_string(THIS_CE, getThis(), ZEND_STRS("queryData")-1, query_data TSRMLS_CC); -+ efree(query_data); -+ } else { -+ zval *data = http_zsep(IS_STRING, qdata); -+ -+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryData")-1, Z_STRVAL_P(data), Z_STRLEN_P(data) TSRMLS_CC); -+ zval_ptr_dtor(&data); -+ } -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto string HttpRequest::getQueryData() -+ Get the current query data in form of an urlencoded query string. */ -+PHP_METHOD(HttpRequest, getQueryData) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ RETURN_PROP(queryData); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::addQueryData(array query_params) -+ Add parameters to the query parameter list, leaving previously set unchanged. */ -+PHP_METHOD(HttpRequest, addQueryData) -+{ -+ zval *qdata, *old_qdata; -+ char *query_data = NULL; -+ size_t query_data_len = 0; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &qdata)) { -+ RETURN_FALSE; -+ } -+ -+ old_qdata = zend_read_property(THIS_CE, getThis(), ZEND_STRS("queryData")-1, 0 TSRMLS_CC); -+ -+ if (SUCCESS != http_urlencode_hash_ex(HASH_OF(qdata), 1, Z_STRVAL_P(old_qdata), Z_STRLEN_P(old_qdata), &query_data, &query_data_len)) { -+ RETURN_FALSE; -+ } -+ -+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("queryData")-1, query_data, query_data_len TSRMLS_CC); -+ efree(query_data); -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::addPostFields(array post_data) -+ Adds POST data entries, leaving previously set unchanged, unless a post entry with the same name already exists. */ -+PHP_METHOD(HttpRequest, addPostFields) -+{ -+ zval *post_data, *old_post, *new_post; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &post_data)) { -+ RETURN_FALSE; -+ } -+ -+ if (zend_hash_num_elements(Z_ARRVAL_P(post_data))) { -+ MAKE_STD_ZVAL(new_post); -+ array_init(new_post); -+ old_post = zend_read_property(THIS_CE, getThis(), ZEND_STRS("postFields")-1, 0 TSRMLS_CC); -+ if (Z_TYPE_P(old_post) == IS_ARRAY) { -+ array_copy(Z_ARRVAL_P(old_post), Z_ARRVAL_P(new_post)); -+ } -+ array_join(Z_ARRVAL_P(post_data), Z_ARRVAL_P(new_post), 0, 0); -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFields")-1, new_post TSRMLS_CC); -+ zval_ptr_dtor(&new_post); -+ } -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::setPostFields([array post_data]) -+ Set the POST data entries, overwriting previously set POST data. */ -+PHP_METHOD(HttpRequest, setPostFields) -+{ -+ zval *post, *post_data = NULL; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!", &post_data)) { -+ RETURN_FALSE; -+ } -+ -+ MAKE_STD_ZVAL(post); -+ array_init(post); -+ if (post_data && zend_hash_num_elements(Z_ARRVAL_P(post_data))) { -+ array_copy(Z_ARRVAL_P(post_data), Z_ARRVAL_P(post)); -+ } -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFields")-1, post TSRMLS_CC); -+ zval_ptr_dtor(&post); -+ -+ RETURN_TRUE; -+} -+/* }}}*/ -+ -+/* {{{ proto array HttpRequest::getPostFields() -+ Get previously set POST data. */ -+PHP_METHOD(HttpRequest, getPostFields) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ RETURN_PROP(postFields); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::setBody([string request_body_data]) -+ Set request body to send, overwriting previously set request body. Don't forget to specify a content type. */ -+PHP_METHOD(HttpRequest, setBody) -+{ -+ char *raw_data = NULL; -+ int data_len = 0; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &raw_data, &data_len)) { -+ RETURN_FALSE; -+ } -+ -+ if (!raw_data) { -+ raw_data = ""; -+ } -+ -+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, raw_data, data_len TSRMLS_CC); -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::addBody(string request_body_data) -+ Add request body data, leaving previously set request body data unchanged. */ -+PHP_METHOD(HttpRequest, addBody) -+{ -+ char *raw_data; -+ int data_len; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &raw_data, &data_len)) { -+ RETURN_FALSE; -+ } -+ -+ if (data_len) { -+ zval *data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, 0 TSRMLS_CC); -+ -+ if (Z_STRLEN_P(data)) { -+ Z_STRVAL_P(data) = erealloc(Z_STRVAL_P(data), (Z_STRLEN_P(data) += data_len) + 1); -+ Z_STRVAL_P(data)[Z_STRLEN_P(data)] = '\0'; -+ memcpy(Z_STRVAL_P(data) + Z_STRLEN_P(data) - data_len, raw_data, data_len); -+ } else { -+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("requestBody")-1, raw_data, data_len TSRMLS_CC); -+ } -+ } -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto string HttpRequest::getBody() -+ Get previously set request body data. */ -+PHP_METHOD(HttpRequest, getBody) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ RETURN_PROP(requestBody); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::addPostFile(string name, string file[, string content_type = "application/x-octetstream"]) -+ Add a file to the POST request, leaving previously set files unchanged. */ -+PHP_METHOD(HttpRequest, addPostFile) -+{ -+ zval *entry, *old_post, *new_post; -+ char *name, *file, *type = NULL; -+ int name_len, file_len, type_len = 0; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", &name, &name_len, &file, &file_len, &type, &type_len)) { -+ RETURN_FALSE; -+ } -+ -+ if (type_len) { -+ HTTP_CHECK_CONTENT_TYPE(type, RETURN_FALSE); -+ } else { -+ type = "application/x-octetstream"; -+ type_len = sizeof("application/x-octetstream") - 1; -+ } -+ -+ MAKE_STD_ZVAL(entry); -+ array_init(entry); -+ -+ add_assoc_stringl(entry, "name", name, name_len, 1); -+ add_assoc_stringl(entry, "type", type, type_len, 1); -+ add_assoc_stringl(entry, "file", file, file_len, 1); -+ -+ MAKE_STD_ZVAL(new_post); -+ array_init(new_post); -+ old_post = zend_read_property(THIS_CE, getThis(), ZEND_STRS("postFiles")-1, 0 TSRMLS_CC); -+ if (Z_TYPE_P(old_post) == IS_ARRAY) { -+ array_copy(Z_ARRVAL_P(old_post), Z_ARRVAL_P(new_post)); -+ } -+ add_next_index_zval(new_post, entry); -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFiles")-1, new_post TSRMLS_CC); -+ zval_ptr_dtor(&new_post); -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::setPostFiles([array post_files]) -+ Set files to post, overwriting previously set post files. */ -+PHP_METHOD(HttpRequest, setPostFiles) -+{ -+ zval *files = NULL, *post; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!/", &files)) { -+ RETURN_FALSE; -+ } -+ -+ MAKE_STD_ZVAL(post); -+ array_init(post); -+ if (files && (Z_TYPE_P(files) == IS_ARRAY)) { -+ array_copy(Z_ARRVAL_P(files), Z_ARRVAL_P(post)); -+ } -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("postFiles")-1, post TSRMLS_CC); -+ zval_ptr_dtor(&post); -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto array HttpRequest::getPostFiles() -+ Get all previously added POST files. */ -+PHP_METHOD(HttpRequest, getPostFiles) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ RETURN_PROP(postFiles); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::setPutFile([string file]) -+ Set file to put. Affects only PUT requests. */ -+PHP_METHOD(HttpRequest, setPutFile) -+{ -+ char *file = ""; -+ int file_len = 0; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &file, &file_len)) { -+ RETURN_FALSE; -+ } -+ -+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("putFile")-1, file, file_len TSRMLS_CC); -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto string HttpRequest::getPutFile() -+ Get previously set put file. */ -+PHP_METHOD(HttpRequest, getPutFile) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ RETURN_PROP(putFile); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::setPutData([string put_data]) -+ Set PUT data to send, overwriting previously set PUT data. */ -+PHP_METHOD(HttpRequest, setPutData) -+{ -+ char *put_data = NULL; -+ int data_len = 0; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &put_data, &data_len)) { -+ RETURN_FALSE; -+ } -+ -+ if (!put_data) { -+ put_data = ""; -+ } -+ -+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("putData")-1, put_data, data_len TSRMLS_CC); -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequest::addPutData(string put_data) -+ Add PUT data, leaving previously set PUT data unchanged. */ -+PHP_METHOD(HttpRequest, addPutData) -+{ -+ char *put_data; -+ int data_len; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &put_data, &data_len)) { -+ RETURN_FALSE; -+ } -+ -+ if (data_len) { -+ zval *data = zend_read_property(THIS_CE, getThis(), ZEND_STRS("putData")-1, 0 TSRMLS_CC); -+ -+ if (Z_STRLEN_P(data)) { -+ Z_STRVAL_P(data) = erealloc(Z_STRVAL_P(data), (Z_STRLEN_P(data) += data_len) + 1); -+ Z_STRVAL_P(data)[Z_STRLEN_P(data)] = '\0'; -+ memcpy(Z_STRVAL_P(data) + Z_STRLEN_P(data) - data_len, put_data, data_len); -+ } else { -+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("putData")-1, put_data, data_len TSRMLS_CC); -+ } -+ } -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto string HttpRequest::getPutData() -+ Get previously set PUT data. */ -+PHP_METHOD(HttpRequest, getPutData) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ RETURN_PROP(putData); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto array HttpRequest::getResponseData() -+ Get all response data after the request has been sent. */ -+PHP_METHOD(HttpRequest, getResponseData) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ char *body; -+ size_t body_len; -+ zval *headers, *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC); -+ -+ if (Z_TYPE_P(message) == IS_OBJECT) { -+ getObjectEx(http_message_object, msg, message); -+ -+ array_init(return_value); -+ -+ MAKE_STD_ZVAL(headers); -+ array_init(headers); -+ zend_hash_copy(Z_ARRVAL_P(headers), &msg->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+ add_assoc_zval(return_value, "headers", headers); -+ -+ phpstr_data(PHPSTR(msg->message), &body, &body_len); -+ add_assoc_stringl(return_value, "body", body, body_len, 0); -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ proto mixed HttpRequest::getResponseHeader([string name]) -+ Get response header(s) after the request has been sent. */ -+PHP_METHOD(HttpRequest, getResponseHeader) -+{ -+ if (return_value_used) { -+ zval *header; -+ char *header_name = NULL; -+ int header_len = 0; -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &header_name, &header_len)) { -+ zval *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC); -+ -+ if (Z_TYPE_P(message) == IS_OBJECT) { -+ getObjectEx(http_message_object, msg, message); -+ -+ if (header_len) { -+ if ((header = http_message_header_ex(msg->message, pretty_key(header_name, header_len, 1, 1), header_len + 1, 0))) { -+ RETURN_ZVAL(header, 1, 1); -+ } -+ } else { -+ array_init(return_value); -+ zend_hash_copy(Z_ARRVAL_P(return_value), &msg->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+ return; -+ } -+ } -+ } -+ RETURN_FALSE; -+ } -+} -+/* }}} */ -+ -+/* {{{ proto array HttpRequest::getResponseCookies([int flags[, array allowed_extras]]) -+ Get response cookie(s) after the request has been sent. */ -+PHP_METHOD(HttpRequest, getResponseCookies) -+{ -+ if (return_value_used) { -+ long flags = 0; -+ zval *allowed_extras_array = NULL; -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|la!", &flags, &allowed_extras_array)) { -+ int i = 0; -+ HashKey key = initHashKey(0); -+ char **allowed_extras = NULL; -+ zval **header = NULL, **entry = NULL, *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC); -+ HashPosition pos, pos1, pos2; -+ -+ if (Z_TYPE_P(message) == IS_OBJECT) { -+ getObjectEx(http_message_object, msg, message); -+ -+ array_init(return_value); -+ -+ if (allowed_extras_array) { -+ allowed_extras = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(allowed_extras_array)) + 1, sizeof(char *)); -+ FOREACH_VAL(pos, allowed_extras_array, entry) { -+ zval *data = http_zsep(IS_STRING, *entry); -+ allowed_extras[i++] = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data)); -+ zval_ptr_dtor(&data); -+ } -+ } -+ -+ FOREACH_HASH_KEYVAL(pos1, &msg->message->hdrs, key, header) { -+ if (key.type == HASH_KEY_IS_STRING && !strcasecmp(key.str, "Set-Cookie")) { -+ http_cookie_list list; -+ -+ if (Z_TYPE_PP(header) == IS_ARRAY) { -+ zval **single_header; -+ -+ FOREACH_VAL(pos2, *header, single_header) { -+ zval *data = http_zsep(IS_STRING, *single_header); -+ -+ if (http_parse_cookie_ex(&list, Z_STRVAL_P(data), flags, allowed_extras)) { -+ zval *cookie; -+ -+ MAKE_STD_ZVAL(cookie); -+ object_init(cookie); -+ http_cookie_list_tostruct(&list, cookie); -+ add_next_index_zval(return_value, cookie); -+ http_cookie_list_dtor(&list); -+ } -+ zval_ptr_dtor(&data); -+ } -+ } else { -+ zval *data = http_zsep(IS_STRING, *header); -+ if (http_parse_cookie_ex(&list, Z_STRVAL_P(data), flags, allowed_extras)) { -+ zval *cookie; -+ -+ MAKE_STD_ZVAL(cookie); -+ object_init(cookie); -+ http_cookie_list_tostruct(&list, cookie); -+ add_next_index_zval(return_value, cookie); -+ http_cookie_list_dtor(&list); -+ } -+ zval_ptr_dtor(&data); -+ } -+ } -+ } -+ -+ if (allowed_extras) { -+ for (i = 0; allowed_extras[i]; ++i) { -+ efree(allowed_extras[i]); -+ } -+ efree(allowed_extras); -+ } -+ -+ return; -+ } -+ } -+ RETURN_FALSE; -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string HttpRequest::getResponseBody() -+ Get the response body after the request has been sent. */ -+PHP_METHOD(HttpRequest, getResponseBody) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ zval *message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC); -+ -+ if (Z_TYPE_P(message) == IS_OBJECT) { -+ getObjectEx(http_message_object, msg, message); -+ RETURN_PHPSTR_DUP(&msg->message->body); -+ } else { -+ RETURN_FALSE; -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ proto int HttpRequest::getResponseCode() -+ Get the response code after the request has been sent. */ -+PHP_METHOD(HttpRequest, getResponseCode) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ RETURN_PROP(responseCode); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string HttpRequest::getResponseStatus() -+ Get the response status (i.e. the string after the response code) after the message has been sent. */ -+PHP_METHOD(HttpRequest, getResponseStatus) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ RETURN_PROP(responseStatus); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto mixed HttpRequest::getResponseInfo([string name]) -+ Get response info after the request has been sent. */ -+PHP_METHOD(HttpRequest, getResponseInfo) -+{ -+ if (return_value_used) { -+ zval *info, **infop; -+ char *info_name = NULL; -+ int info_len = 0; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &info_name, &info_len)) { -+ RETURN_FALSE; -+ } -+ -+ info = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseInfo")-1, 0 TSRMLS_CC); -+ -+ if (Z_TYPE_P(info) != IS_ARRAY) { -+ RETURN_FALSE; -+ } -+ -+ if (info_len && info_name) { -+ if (SUCCESS == zend_hash_find(Z_ARRVAL_P(info), pretty_key(info_name, info_len, 0, 0), info_len + 1, (void *) &infop)) { -+ RETURN_ZVAL(*infop, 1, 0); -+ } else { -+ http_error_ex(HE_NOTICE, HTTP_E_INVALID_PARAM, "Could not find response info named %s", info_name); -+ RETURN_FALSE; -+ } -+ } else { -+ RETURN_ZVAL(info, 1, 0); -+ } -+ } -+} -+/* }}}*/ -+ -+/* {{{ proto HttpMessage HttpRequest::getResponseMessage() -+ Get the full response as HttpMessage object after the request has been sent. */ -+PHP_METHOD(HttpRequest, getResponseMessage) -+{ -+ NO_ARGS { -+ zval *message; -+ -+ SET_EH_THROW_HTTP(); -+ message = zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC); -+ if (Z_TYPE_P(message) == IS_OBJECT) { -+ RETVAL_OBJECT(message, 1); -+ } else { -+ http_error(HE_WARNING, HTTP_E_RUNTIME, "HttpRequest does not contain a response message"); -+ } -+ SET_EH_NORMAL(); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto HttpMessage HttpRequest::getRequestMessage() -+ Get sent HTTP message. */ -+PHP_METHOD(HttpRequest, getRequestMessage) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ http_message *msg; -+ getObject(http_request_object, obj); -+ -+ SET_EH_THROW_HTTP(); -+ if ((msg = http_message_parse(PHPSTR_VAL(&obj->request->conv.request), PHPSTR_LEN(&obj->request->conv.request)))) { -+ RETVAL_OBJVAL(http_request_object_message(getThis(), msg), 0); -+ } -+ SET_EH_NORMAL(); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string HttpRequest::getRawRequestMessage() -+ Get sent HTTP message. */ -+PHP_METHOD(HttpRequest, getRawRequestMessage) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ getObject(http_request_object, obj); -+ -+ RETURN_PHPSTR_DUP(&obj->request->conv.request); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string HttpRequest::getRawResponseMessage() -+ Get the entire HTTP response. */ -+PHP_METHOD(HttpRequest, getRawResponseMessage) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ getObject(http_request_object, obj); -+ -+ RETURN_PHPSTR_DUP(&obj->request->conv.response); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto HttpMessage HttpRequest::getHistory() -+ Get all sent requests and received responses as an HttpMessage object. */ -+PHP_METHOD(HttpRequest, getHistory) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ zval *hist; -+ -+ SET_EH_THROW_HTTP(); -+ hist = zend_read_property(THIS_CE, getThis(), ZEND_STRS("history")-1, 0 TSRMLS_CC); -+ if (Z_TYPE_P(hist) == IS_OBJECT) { -+ RETVAL_OBJECT(hist, 1); -+ } else { -+ http_error(HE_WARNING, HTTP_E_RUNTIME, "The history is empty"); -+ } -+ SET_EH_NORMAL(); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto void HttpRequest::clearHistory() -+ Clear the history. */ -+PHP_METHOD(HttpRequest, clearHistory) -+{ -+ NO_ARGS { -+ zval *hist; -+ -+ MAKE_STD_ZVAL(hist); -+ ZVAL_NULL(hist); -+ zend_update_property(THIS_CE, getThis(), ZEND_STRS("history")-1, hist TSRMLS_CC); -+ zval_ptr_dtor(&hist); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto string HttpRequest::getMessageClass() -+ Get the message class name. */ -+PHP_METHOD(HttpRequest, getMessageClass) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ RETURN_PROP("messageClass"); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto void setMessageClass(string class_name) -+ Set the message class name. */ -+PHP_METHOD(HttpRequest, setMessageClass) -+{ -+ char *cn; -+ int cl; -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &cn, &cl)) { -+ zend_update_property_stringl(THIS_CE, getThis(), ZEND_STRS("messageClass")-1, cn, cl TSRMLS_CC); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto HttpMessage HttpRequest::send() -+ Send the HTTP request. */ -+PHP_METHOD(HttpRequest, send) -+{ -+ getObject(http_request_object, obj); -+ -+ NO_ARGS; -+ -+ SET_EH_THROW_HTTP(); -+ -+ RETVAL_FALSE; -+ -+ if (obj->pool) { -+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot perform HttpRequest::send() while attached to an HttpRequestPool"); -+ } else if (SUCCESS == http_request_object_requesthandler(obj, getThis())) { -+ http_request_exec(obj->request); -+ if (SUCCESS == http_request_object_responsehandler(obj, getThis())) { -+ RETVAL_OBJECT(zend_read_property(THIS_CE, getThis(), ZEND_STRS("responseMessage")-1, 0 TSRMLS_CC), 1); -+ } -+ } -+ -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_request_pool_api.c -@@ -0,0 +1,660 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_request_pool_api.c 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#define HTTP_WANT_CURL -+#define HTTP_WANT_EVENT -+#include "php_http.h" -+ -+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) -+ -+#include "php_http_api.h" -+#include "php_http_exception_object.h" -+#include "php_http_persistent_handle_api.h" -+#include "php_http_request_api.h" -+#include "php_http_request_object.h" -+#include "php_http_request_pool_api.h" -+#include "php_http_requestpool_object.h" -+ -+#ifndef HTTP_DEBUG_REQPOOLS -+# define HTTP_DEBUG_REQPOOLS 0 -+#endif -+ -+#ifdef HTTP_HAVE_EVENT -+typedef struct _http_request_pool_event_t { -+ struct event evnt; -+ http_request_pool *pool; -+} http_request_pool_event; -+ -+static void http_request_pool_timeout_callback(int socket, short action, void *event_data); -+static void http_request_pool_event_callback(int socket, short action, void *event_data); -+static int http_request_pool_socket_callback(CURL *easy, curl_socket_t s, int action, void *, void *); -+static void http_request_pool_timer_callback(CURLM *multi, long timeout_ms, void *timer_data); -+#endif -+ -+static int http_request_pool_compare_handles(void *h1, void *h2); -+ -+PHP_MINIT_FUNCTION(http_request_pool) -+{ -+ if (SUCCESS != http_persistent_handle_provide("http_request_pool", curl_multi_init, (http_persistent_handle_dtor) curl_multi_cleanup, NULL)) { -+ return FAILURE; -+ } -+ return SUCCESS; -+} -+ -+#ifdef HTTP_HAVE_EVENT -+PHP_RINIT_FUNCTION(http_request_pool) -+{ -+ if (!HTTP_G->request.pool.event.base && !(HTTP_G->request.pool.event.base = event_init())) { -+ return FAILURE; -+ } -+ -+ return SUCCESS; -+} -+#endif -+ -+/* {{{ http_request_pool *http_request_pool_init(http_request_pool *) */ -+PHP_HTTP_API http_request_pool *_http_request_pool_init(http_request_pool *pool TSRMLS_DC) -+{ -+ zend_bool free_pool; -+ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "Initializing request pool %p\n", pool); -+#endif -+ -+ if ((free_pool = (!pool))) { -+ pool = emalloc(sizeof(http_request_pool)); -+ pool->ch = NULL; -+ } -+ -+ if (SUCCESS != http_persistent_handle_acquire("http_request_pool", &pool->ch)) { -+ if (free_pool) { -+ efree(pool); -+ } -+ return NULL; -+ } -+ -+ TSRMLS_SET_CTX(pool->tsrm_ls); -+ -+#ifdef HTTP_HAVE_EVENT -+ pool->timeout = ecalloc(1, sizeof(struct event)); -+ curl_multi_setopt(pool->ch, CURLMOPT_SOCKETDATA, pool); -+ curl_multi_setopt(pool->ch, CURLMOPT_SOCKETFUNCTION, http_request_pool_socket_callback); -+ curl_multi_setopt(pool->ch, CURLMOPT_TIMERDATA, pool); -+ curl_multi_setopt(pool->ch, CURLMOPT_TIMERFUNCTION, http_request_pool_timer_callback); -+#endif -+ -+ pool->unfinished = 0; -+ zend_llist_init(&pool->finished, sizeof(zval *), (llist_dtor_func_t) ZVAL_PTR_DTOR, 0); -+ zend_llist_init(&pool->handles, sizeof(zval *), (llist_dtor_func_t) ZVAL_PTR_DTOR, 0); -+ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "Initialized request pool %p\n", pool); -+#endif -+ -+ return pool; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_request_pool_attach(http_request_pool *, zval *) */ -+PHP_HTTP_API STATUS _http_request_pool_attach(http_request_pool *pool, zval *request) -+{ -+#ifdef ZTS -+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls); -+#endif -+ getObjectEx(http_request_object, req, request); -+ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "Attaching HttpRequest(#%d) %p to pool %p\n", Z_OBJ_HANDLE_P(request), req, pool); -+#endif -+ -+ if (req->pool) { -+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "HttpRequest object(#%d) is already member of %s HttpRequestPool", Z_OBJ_HANDLE_P(request), req->pool == pool ? "this" : "another"); -+ } else if (SUCCESS != http_request_object_requesthandler(req, request)) { -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "Could not initialize HttpRequest object(#%d) for attaching to the HttpRequestPool", Z_OBJ_HANDLE_P(request)); -+ } else { -+ CURLMcode code = curl_multi_add_handle(pool->ch, req->request->ch); -+ -+ if (CURLM_OK != code) { -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_POOL, "Could not attach HttpRequest object(#%d) to the HttpRequestPool: %s", Z_OBJ_HANDLE_P(request), curl_multi_strerror(code)); -+ } else { -+ req->pool = pool; -+ -+ ZVAL_ADDREF(request); -+ zend_llist_add_element(&pool->handles, &request); -+ ++pool->unfinished; -+ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "> %d HttpRequests attached to pool %p\n", zend_llist_count(&pool->handles), pool); -+#endif -+ return SUCCESS; -+ } -+ } -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_request_pool_detach(http_request_pool *, zval *) */ -+PHP_HTTP_API STATUS _http_request_pool_detach(http_request_pool *pool, zval *request) -+{ -+ CURLMcode code; -+#ifdef ZTS -+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls); -+#endif -+ getObjectEx(http_request_object, req, request); -+ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "Detaching HttpRequest(#%d) %p from pool %p\n", Z_OBJ_HANDLE_P(request), req, pool); -+#endif -+ -+ if (!req->pool) { -+ /* not attached to any pool */ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "HttpRequest object(#%d) %p is not attached to any HttpRequestPool\n", Z_OBJ_HANDLE_P(request), req); -+#endif -+ } else if (req->pool != pool) { -+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "HttpRequest object(#%d) is not attached to this HttpRequestPool", Z_OBJ_HANDLE_P(request)); -+ } else if (req->request->_in_progress_cb) { -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_POOL, "HttpRequest object(#%d) cannot be detached from the HttpRequestPool while executing the progress callback", Z_OBJ_HANDLE_P(request)); -+ } else if (CURLM_OK != (code = curl_multi_remove_handle(pool->ch, req->request->ch))) { -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST_POOL, "Could not detach HttpRequest object(#%d) from the HttpRequestPool: %s", Z_OBJ_HANDLE_P(request), curl_multi_strerror(code)); -+ } else { -+ req->pool = NULL; -+ zend_llist_del_element(&pool->finished, request, http_request_pool_compare_handles); -+ zend_llist_del_element(&pool->handles, request, http_request_pool_compare_handles); -+ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "> %d HttpRequests remaining in pool %p\n", zend_llist_count(&pool->handles), pool); -+#endif -+ -+ return SUCCESS; -+ } -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ void http_request_pool_apply(http_request_pool *, http_request_pool_apply_func) */ -+PHP_HTTP_API void _http_request_pool_apply(http_request_pool *pool, http_request_pool_apply_func cb) -+{ -+ int count = zend_llist_count(&pool->handles); -+ -+ if (count) { -+ int i = 0; -+ zend_llist_position pos; -+ zval **handle, **handles = emalloc(count * sizeof(zval *)); -+ -+ for (handle = zend_llist_get_first_ex(&pool->handles, &pos); handle; handle = zend_llist_get_next_ex(&pool->handles, &pos)) { -+ handles[i++] = *handle; -+ } -+ -+ /* should never happen */ -+ if (i != count) { -+ zend_error(E_ERROR, "number of fetched request handles do not match overall count"); -+ count = i; -+ } -+ -+ for (i = 0; i < count; ++i) { -+ if (cb(pool, handles[i])) { -+ break; -+ } -+ } -+ efree(handles); -+ } -+} -+/* }}} */ -+ -+/* {{{ void http_request_pool_apply_with_arg(http_request_pool *, http_request_pool_apply_with_arg_func, void *) */ -+PHP_HTTP_API void _http_request_pool_apply_with_arg(http_request_pool *pool, http_request_pool_apply_with_arg_func cb, void *arg) -+{ -+ int count = zend_llist_count(&pool->handles); -+ -+ if (count) { -+ int i = 0; -+ zend_llist_position pos; -+ zval **handle, **handles = emalloc(count * sizeof(zval *)); -+ -+ for (handle = zend_llist_get_first_ex(&pool->handles, &pos); handle; handle = zend_llist_get_next_ex(&pool->handles, &pos)) { -+ handles[i++] = *handle; -+ } -+ -+ /* should never happen */ -+ if (i != count) { -+ zend_error(E_ERROR, "number of fetched request handles do not match overall count"); -+ count = i; -+ } -+ -+ for (i = 0; i < count; ++i) { -+ if (cb(pool, handles[i], arg)) { -+ break; -+ } -+ } -+ efree(handles); -+ } -+} -+/* }}} */ -+ -+/* {{{ void http_request_pool_detach_all(http_request_pool *) */ -+PHP_HTTP_API void _http_request_pool_detach_all(http_request_pool *pool) -+{ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "Detaching %d requests from pool %p\n", zend_llist_count(&pool->handles), pool); -+#endif -+ http_request_pool_apply(pool, _http_request_pool_detach); -+} -+/* }}} */ -+ -+/* {{{ STATUS http_request_pool_send(http_request_pool *) */ -+PHP_HTTP_API STATUS _http_request_pool_send(http_request_pool *pool) -+{ -+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls); -+ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "Attempt to send %d requests of pool %p\n", zend_llist_count(&pool->handles), pool); -+#endif -+ -+#ifdef HTTP_HAVE_EVENT -+ if (pool->useevents) { -+ do { -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "& Starting event dispatcher of pool %p\n", pool); -+#endif -+ event_base_dispatch(HTTP_G->request.pool.event.base); -+ } while (pool->unfinished); -+ } else -+#endif -+ { -+ while (http_request_pool_perform(pool)) { -+ if (SUCCESS != http_request_pool_select(pool)) { -+#ifdef PHP_WIN32 -+ /* see http://msdn.microsoft.com/library/en-us/winsock/winsock/windows_sockets_error_codes_2.asp */ -+ http_error_ex(HE_WARNING, HTTP_E_SOCKET, "WinSock error: %d", WSAGetLastError()); -+#else -+ http_error(HE_WARNING, HTTP_E_SOCKET, strerror(errno)); -+#endif -+ return FAILURE; -+ } -+ } -+ } -+ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "Finished sending %d HttpRequests of pool %p (still unfinished: %d)\n", zend_llist_count(&pool->handles), pool, pool->unfinished); -+#endif -+ -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ void http_request_pool_dtor(http_request_pool *) */ -+PHP_HTTP_API void _http_request_pool_dtor(http_request_pool *pool) -+{ -+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls); -+ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "Destructing request pool %p\n", pool); -+#endif -+ -+#ifdef HTTP_HAVE_EVENT -+ efree(pool->timeout); -+#endif -+ -+ http_request_pool_detach_all(pool); -+ -+ pool->unfinished = 0; -+ zend_llist_clean(&pool->finished); -+ zend_llist_clean(&pool->handles); -+ http_persistent_handle_release("http_request_pool", &pool->ch); -+} -+/* }}} */ -+ -+#ifdef PHP_WIN32 -+# define SELECT_ERROR SOCKET_ERROR -+#else -+# define SELECT_ERROR -1 -+#endif -+ -+/* {{{ STATUS http_request_pool_select(http_request_pool *) */ -+PHP_HTTP_API STATUS _http_request_pool_select(http_request_pool *pool) -+{ -+ return http_request_pool_select_ex(pool, NULL); -+} -+/* }}} */ -+ -+/* {{{ STATUS http_request_pool_select_ex(http_request_pool *, struct timeval *) */ -+PHP_HTTP_API STATUS _http_request_pool_select_ex(http_request_pool *pool, struct timeval *custom_timeout) -+{ -+ int MAX; -+ fd_set R, W, E; -+ struct timeval timeout; -+ -+#ifdef HTTP_HAVE_EVENT -+ if (pool->useevents) { -+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls); -+ http_error(HE_WARNING, HTTP_E_RUNTIME, "not implemented; use HttpRequest callbacks"); -+ return FAILURE; -+ } -+#endif -+ -+ if (custom_timeout && timerisset(custom_timeout)) { -+ timeout = *custom_timeout; -+ } else { -+ http_request_pool_timeout(pool, &timeout); -+ } -+ -+ FD_ZERO(&R); -+ FD_ZERO(&W); -+ FD_ZERO(&E); -+ -+ if (CURLM_OK == curl_multi_fdset(pool->ch, &R, &W, &E, &MAX)) { -+ if (MAX == -1) { -+ http_sleep((double) timeout.tv_sec + (double) (timeout.tv_usec / HTTP_MCROSEC)); -+ return SUCCESS; -+ } else if (SELECT_ERROR != select(MAX + 1, &R, &W, &E, &timeout)) { -+ return SUCCESS; -+ } -+ } -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ int http_request_pool_perform(http_request_pool *) */ -+PHP_HTTP_API int _http_request_pool_perform(http_request_pool *pool) -+{ -+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls); -+ -+#ifdef HTTP_HAVE_EVENT -+ if (pool->useevents) { -+ http_error(HE_WARNING, HTTP_E_RUNTIME, "not implemented; use HttpRequest callbacks"); -+ return FAILURE; -+ } -+#endif -+ -+ while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(pool->ch, &pool->unfinished)); -+ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "%u unfinished requests of pool %p remaining\n", pool->unfinished, pool); -+#endif -+ -+ http_request_pool_responsehandler(pool); -+ -+ return pool->unfinished; -+} -+/* }}} */ -+ -+/* {{{ void http_request_pool_responsehandler(http_request_pool *) */ -+void _http_request_pool_responsehandler(http_request_pool *pool) -+{ -+ CURLMsg *msg; -+ int remaining = 0; -+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls); -+ -+ do { -+ msg = curl_multi_info_read(pool->ch, &remaining); -+ if (msg && CURLMSG_DONE == msg->msg) { -+ if (CURLE_OK != msg->data.result) { -+ http_request_storage *st = http_request_storage_get(msg->easy_handle); -+ http_error_ex(HE_WARNING, HTTP_E_REQUEST, "%s; %s (%s)", curl_easy_strerror(msg->data.result), st?st->errorbuffer:"", st?st->url:""); -+ } -+ http_request_pool_apply_with_arg(pool, _http_request_pool_apply_responsehandler, msg->easy_handle); -+ } -+ } while (remaining); -+} -+/* }}} */ -+ -+/* {{{ int http_request_pool_apply_responsehandler(http_request_pool *, zval *, void *) */ -+int _http_request_pool_apply_responsehandler(http_request_pool *pool, zval *req, void *ch) -+{ -+#ifdef ZTS -+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls); -+#endif -+ getObjectEx(http_request_object, obj, req); -+ -+ if ((!ch) || obj->request->ch == (CURL *) ch) { -+ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "Fetching data from HttpRequest(#%d) %p of pool %p\n", Z_OBJ_HANDLE_P(req), obj, obj->pool); -+#endif -+ -+ ZVAL_ADDREF(req); -+ zend_llist_add_element(&obj->pool->finished, &req); -+ http_request_object_responsehandler(obj, req); -+ return 1; -+ } -+ return 0; -+} -+/* }}} */ -+ -+/* {{{ struct timeval *_http_request_pool_timeout(http_request_pool *, struct timeval *) */ -+struct timeval *_http_request_pool_timeout(http_request_pool *pool, struct timeval *timeout) -+{ -+#ifdef HAVE_CURL_MULTI_TIMEOUT -+ long max_tout = 1000; -+ -+ if ((CURLM_OK == curl_multi_timeout(pool->ch, &max_tout)) && (max_tout > 0)) { -+ timeout->tv_sec = max_tout / 1000; -+ timeout->tv_usec = (max_tout % 1000) * 1000; -+ } else { -+#endif -+ timeout->tv_sec = 0; -+ timeout->tv_usec = 1000; -+#ifdef HAVE_CURL_MULTI_TIMEOUT -+ } -+#endif -+ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "Calculating timeout (%lu, %lu) of pool %p\n", (ulong) timeout->tv_sec, (ulong) timeout->tv_usec, pool); -+#endif -+ -+ return timeout; -+} -+/* }}} */ -+ -+/*#*/ -+ -+/* {{{ static int http_request_pool_compare_handles(void *, void *) */ -+static int http_request_pool_compare_handles(void *h1, void *h2) -+{ -+ return (Z_OBJ_HANDLE_PP((zval **) h1) == Z_OBJ_HANDLE_P((zval *) h2)); -+} -+/* }}} */ -+ -+#ifdef HTTP_HAVE_EVENT -+/* {{{ static void http_request_pool_timeout_callback(int, short, void *) */ -+static void http_request_pool_timeout_callback(int socket, short action, void *event_data) -+{ -+ http_request_pool *pool = event_data; -+ -+ if (pool->useevents) { -+ CURLMcode rc; -+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls); -+ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "Timeout occurred of pool %p\n", pool); -+#endif -+ -+ while (CURLM_CALL_MULTI_PERFORM == (rc = curl_multi_socket(pool->ch, CURL_SOCKET_TIMEOUT, &pool->unfinished))); -+ -+ if (CURLM_OK != rc) { -+ http_error(HE_WARNING, HTTP_E_SOCKET, curl_multi_strerror(rc)); -+ } -+ -+ http_request_pool_responsehandler(pool); -+ } -+} -+/* }}} */ -+ -+/* {{{ static void http_request_pool_event_callback(int, short, void *) */ -+static void http_request_pool_event_callback(int socket, short action, void *event_data) -+{ -+ http_request_pool_event *ev = event_data; -+ http_request_pool *pool = ev->pool; -+ -+ if (pool->useevents) { -+ CURLMcode rc = CURLE_OK; -+ TSRMLS_FETCH_FROM_CTX(ev->pool->tsrm_ls); -+ -+#if HTTP_DEBUG_REQPOOLS -+ { -+ static const char event_strings[][20] = {"NONE","TIMEOUT","READ","TIMEOUT|READ","WRITE","TIMEOUT|WRITE","READ|WRITE","TIMEOUT|READ|WRITE","SIGNAL"}; -+ fprintf(stderr, "Event on socket %d (%s) event %p of pool %p\n", socket, event_strings[action], ev, pool); -+ } -+#endif -+ -+ /* don't use 'ev' below this loop as it might 've been freed in the socket callback */ -+ do { -+#ifdef HAVE_CURL_MULTI_SOCKET_ACTION -+ switch (action & (EV_READ|EV_WRITE)) { -+ case EV_READ: -+ rc = curl_multi_socket_action(pool->ch, socket, CURL_CSELECT_IN, &pool->unfinished); -+ break; -+ case EV_WRITE: -+ rc = curl_multi_socket_action(pool->ch, socket, CURL_CSELECT_OUT, &pool->unfinished); -+ break; -+ case EV_READ|EV_WRITE: -+ rc = curl_multi_socket_action(pool->ch, socket, CURL_CSELECT_IN|CURL_CSELECT_OUT, &pool->unfinished); -+ break; -+ default: -+ http_error_ex(HE_WARNING, HTTP_E_SOCKET, "Unknown event %d", (int) action); -+ return; -+ } -+#else -+ rc = curl_multi_socket(pool->ch, socket, &pool->unfinished); -+#endif -+ } while (CURLM_CALL_MULTI_PERFORM == rc); -+ -+ switch (rc) { -+ case CURLM_BAD_SOCKET: -+#if 0 -+ fprintf(stderr, "!!! Bad socket: %d (%d)\n", socket, (int) action); -+#endif -+ case CURLM_OK: -+ break; -+ default: -+ http_error(HE_WARNING, HTTP_E_SOCKET, curl_multi_strerror(rc)); -+ break; -+ } -+ -+ http_request_pool_responsehandler(pool); -+ -+ /* remove timeout if there are no transfers left */ -+ if (!pool->unfinished && event_initialized(pool->timeout) && event_pending(pool->timeout, EV_TIMEOUT, NULL)) { -+ event_del(pool->timeout); -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "Removed timeout of pool %p\n", pool); -+#endif -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ static int http_request_pool_socket_callback(CURL *, curl_socket_t, int, void *, void *) */ -+static int http_request_pool_socket_callback(CURL *easy, curl_socket_t sock, int action, void *socket_data, void *assign_data) -+{ -+ http_request_pool *pool = socket_data; -+ -+ if (pool->useevents) { -+ int events = EV_PERSIST; -+ http_request_pool_event *ev = assign_data; -+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls); -+ -+ if (!ev) { -+ ev = ecalloc(1, sizeof(http_request_pool_event)); -+ ev->pool = pool; -+ curl_multi_assign(pool->ch, sock, ev); -+ event_base_set(HTTP_G->request.pool.event.base, &ev->evnt); -+ } else { -+ event_del(&ev->evnt); -+ } -+ -+#if HTTP_DEBUG_REQPOOLS -+ { -+ static const char action_strings[][8] = {"NONE", "IN", "OUT", "INOUT", "REMOVE"}; -+ http_request *r; -+ curl_easy_getinfo(easy, CURLINFO_PRIVATE, &r); -+ fprintf(stderr, "Callback on socket %2d (%8s) event %p of pool %p (%d)\n", (int) sock, action_strings[action], ev, pool, pool->unfinished); -+ } -+#endif -+ -+ switch (action) { -+ case CURL_POLL_IN: -+ events |= EV_READ; -+ break; -+ case CURL_POLL_OUT: -+ events |= EV_WRITE; -+ break; -+ case CURL_POLL_INOUT: -+ events |= EV_READ|EV_WRITE; -+ break; -+ -+ case CURL_POLL_REMOVE: -+ efree(ev); -+ case CURL_POLL_NONE: -+ return 0; -+ -+ default: -+ http_error_ex(HE_WARNING, HTTP_E_SOCKET, "Unknown socket action %d", action); -+ return -1; -+ } -+ -+ event_set(&ev->evnt, sock, events, http_request_pool_event_callback, ev); -+ event_add(&ev->evnt, NULL); -+ } -+ -+ return 0; -+} -+/* }}} */ -+ -+/* {{{ static void http_request_pool_timer_callback(CURLM *, long, void*) */ -+static void http_request_pool_timer_callback(CURLM *multi, long timeout_ms, void *timer_data) -+{ -+ http_request_pool *pool = timer_data; -+ -+ if (pool->useevents) { -+ TSRMLS_FETCH_FROM_CTX(pool->tsrm_ls); -+ struct timeval timeout; -+ -+ if (!event_initialized(pool->timeout)) { -+ event_set(pool->timeout, -1, 0, http_request_pool_timeout_callback, pool); -+ event_base_set(HTTP_G->request.pool.event.base, pool->timeout); -+ } else if (event_pending(pool->timeout, EV_TIMEOUT, NULL)) { -+ event_del(pool->timeout); -+ } -+ -+ if (timeout_ms > 0) { -+ timeout.tv_sec = timeout_ms / 1000; -+ timeout.tv_usec = (timeout_ms % 1000) * 1000; -+ } else { -+ http_request_pool_timeout(pool, &timeout); -+ } -+ -+ event_add(pool->timeout, &timeout); -+ -+#if HTTP_DEBUG_REQPOOLS -+ fprintf(stderr, "Updating timeout %lu (%lu, %lu) of pool %p\n", (ulong) timeout_ms, (ulong) timeout.tv_sec, (ulong) timeout.tv_usec, pool); -+#endif -+ } -+} -+/* }}} */ -+#endif /* HTTP_HAVE_EVENT */ -+ -+#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */ -+ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_requestdatashare_object.c -@@ -0,0 +1,332 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_requestdatashare_object.c 323304 2012-02-17 21:13:24Z mike $ */ -+ -+#define HTTP_WANT_CURL -+#include "php_http.h" -+ -+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) -+ -+#include "zend_interfaces.h" -+ -+#include "php_http_api.h" -+#include "php_http_exception_object.h" -+#include "php_http_request_api.h" -+#include "php_http_request_object.h" -+#include "php_http_request_datashare_api.h" -+#include "php_http_requestdatashare_object.h" -+ -+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpRequestDataShare, method, 0, req_args) -+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpRequestDataShare, method, 0) -+#define HTTP_RSHARE_ME(method, visibility) PHP_ME(HttpRequestDataShare, method, HTTP_ARGS(HttpRequestDataShare, method), visibility) -+ -+#if defined(HAVE_SPL) && !defined(WONKY) -+/* SPL doesn't install its headers */ -+extern PHPAPI zend_class_entry *spl_ce_Countable; -+#endif -+ -+HTTP_EMPTY_ARGS(__destruct); -+HTTP_EMPTY_ARGS(count); -+ -+HTTP_BEGIN_ARGS(attach, 1) -+ HTTP_ARG_OBJ(HttpRequest, request, 0) -+HTTP_END_ARGS; -+HTTP_BEGIN_ARGS(detach, 1) -+ HTTP_ARG_OBJ(HttpRequest, request, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(reset); -+ -+HTTP_BEGIN_ARGS(factory, 0) -+ HTTP_ARG_VAL(global, 0) -+ HTTP_ARG_VAL(class_name, 0) -+HTTP_END_ARGS; -+ -+#ifndef WONKY -+HTTP_BEGIN_ARGS(singleton, 0) -+ HTTP_ARG_VAL(global, 0) -+HTTP_END_ARGS; -+#endif -+ -+ -+#define http_requestdatashare_object_read_prop _http_requestdatashare_object_read_prop -+static zval *_http_requestdatashare_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC); -+#define http_requestdatashare_object_write_prop _http_requestdatashare_object_write_prop -+static void _http_requestdatashare_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC); -+#define http_requestdatashare_instantiate(t, g) _http_requestdatashare_instantiate((t), (g) TSRMLS_CC) -+static inline zval *_http_requestdatashare_instantiate(zval *this_ptr, zend_bool global TSRMLS_DC); -+ -+#define THIS_CE http_requestdatashare_object_ce -+zend_class_entry *http_requestdatashare_object_ce; -+zend_function_entry http_requestdatashare_object_fe[] = { -+ HTTP_RSHARE_ME(__destruct, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR) -+ HTTP_RSHARE_ME(count, ZEND_ACC_PUBLIC) -+ HTTP_RSHARE_ME(attach, ZEND_ACC_PUBLIC) -+ HTTP_RSHARE_ME(detach, ZEND_ACC_PUBLIC) -+ HTTP_RSHARE_ME(reset, ZEND_ACC_PUBLIC) -+ HTTP_RSHARE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) -+#ifndef WONKY -+ HTTP_RSHARE_ME(singleton, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) -+#endif -+ EMPTY_FUNCTION_ENTRY -+}; -+static zend_object_handlers http_requestdatashare_object_handlers; -+ -+PHP_MINIT_FUNCTION(http_requestdatashare_object) -+{ -+ HTTP_REGISTER_CLASS_EX(HttpRequestDataShare, http_requestdatashare_object, NULL, 0); -+ http_requestdatashare_object_handlers.clone_obj = NULL; -+ http_requestdatashare_object_handlers.read_property = http_requestdatashare_object_read_prop; -+ http_requestdatashare_object_handlers.write_property = http_requestdatashare_object_write_prop; -+ -+#if defined(HAVE_SPL) && !defined(WONKY) -+ zend_class_implements(http_requestdatashare_object_ce TSRMLS_CC, 1, spl_ce_Countable); -+#endif -+ -+ zend_declare_property_null(THIS_CE, ZEND_STRS("instance")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC); -+ zend_declare_property_bool(THIS_CE, ZEND_STRS("cookie")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC); -+ zend_declare_property_bool(THIS_CE, ZEND_STRS("dns")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC); -+ zend_declare_property_bool(THIS_CE, ZEND_STRS("ssl")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC); -+ zend_declare_property_bool(THIS_CE, ZEND_STRS("connect")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC); -+ -+ return SUCCESS; -+} -+ -+zend_object_value _http_requestdatashare_object_new(zend_class_entry *ce TSRMLS_DC) -+{ -+ return http_requestdatashare_object_new_ex(ce, NULL, NULL); -+} -+ -+zend_object_value _http_requestdatashare_object_new_ex(zend_class_entry *ce, http_request_datashare *share, http_requestdatashare_object **ptr TSRMLS_DC) -+{ -+ zend_object_value ov; -+ http_requestdatashare_object *o; -+ -+ o = ecalloc(1, sizeof(http_requestdatashare_object)); -+ o->zo.ce = ce; -+ -+ if (share) { -+ o->share = share; -+ } else { -+ o->share = http_request_datashare_new(); -+ } -+ -+ if (ptr) { -+ *ptr = o; -+ } -+ -+#ifdef ZEND_ENGINE_2_4 -+ zend_object_std_init(o, ce TSRMLS_CC); -+ object_properties_init(o, ce); -+#else -+ ALLOC_HASHTABLE(OBJ_PROP(o)); -+ zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0); -+ zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+#endif -+ -+ ov.handle = putObject(http_requestdatashare_object, o); -+ ov.handlers = &http_requestdatashare_object_handlers; -+ -+ return ov; -+} -+ -+void _http_requestdatashare_object_free(zend_object *object TSRMLS_DC) -+{ -+ http_requestdatashare_object *o = (http_requestdatashare_object *) object; -+ -+ if (!o->share->persistent) { -+ http_request_datashare_free(&o->share); -+ } -+ freeObject(o); -+} -+ -+static zval *_http_requestdatashare_object_read_prop(zval *object, zval *member, int type ZEND_LITERAL_KEY_DC TSRMLS_DC) -+{ -+ if (type == BP_VAR_W && -+#ifdef ZEND_ENGINE_2_4 -+ zend_hash_exists(&THIS_CE->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1) -+#else -+ zend_hash_exists(&THIS_CE->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1) -+#endif -+ ) { -+ zend_error(E_ERROR, "Cannot access HttpRequestDataShare default properties by reference or array key/index"); -+ return NULL; -+ } -+ -+ return zend_get_std_object_handlers()->read_property(object, member, type ZEND_LITERAL_KEY_CC TSRMLS_CC); -+} -+ -+static void _http_requestdatashare_object_write_prop(zval *object, zval *member, zval *value ZEND_LITERAL_KEY_DC TSRMLS_DC) -+{ -+ if ( -+#ifdef ZEND_ENGINE_2_4 -+ zend_hash_exists(&THIS_CE->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1) -+#else -+ zend_hash_exists(&THIS_CE->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1) -+#endif -+ ) { -+ int status; -+ getObjectEx(http_requestdatashare_object, obj, object); -+ -+ status = http_request_datashare_set(obj->share, Z_STRVAL_P(member), Z_STRLEN_P(member), (zend_bool) i_zend_is_true(value)); -+ if (SUCCESS != status) { -+ return; -+ } -+ } -+ -+ zend_get_std_object_handlers()->write_property(object, member, value ZEND_LITERAL_KEY_CC TSRMLS_CC); -+} -+ -+/* {{{ proto void HttpRequestDataShare::__destruct() -+ Clean up HttpRequestDataShare object. */ -+PHP_METHOD(HttpRequestDataShare, __destruct) -+{ -+ NO_ARGS { -+ getObject(http_requestdatashare_object, obj); -+ http_request_datashare_detach_all(obj->share); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto int HttpRequestDataShare::count() -+ Implements Countable::count(). */ -+PHP_METHOD(HttpRequestDataShare, count) -+{ -+ getObject(http_requestdatashare_object, obj); -+ -+ NO_ARGS; -+ -+ RETURN_LONG(zend_llist_count(HTTP_RSHARE_HANDLES(obj->share))); -+} -+/* }}} */ -+ -+PHP_METHOD(HttpRequestDataShare, attach) -+{ -+ zval *request; -+ getObject(http_requestdatashare_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) { -+ RETURN_FALSE; -+ } -+ -+ RETURN_SUCCESS(http_request_datashare_attach(obj->share, request)); -+} -+ -+PHP_METHOD(HttpRequestDataShare, detach) -+{ -+ zval *request; -+ getObject(http_requestdatashare_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) { -+ RETURN_FALSE; -+ } -+ -+ RETURN_SUCCESS(http_request_datashare_detach(obj->share, request)); -+} -+ -+PHP_METHOD(HttpRequestDataShare, reset) -+{ -+ NO_ARGS { -+ getObject(http_requestdatashare_object, obj); -+ http_request_datashare_detach_all(obj->share); -+ } -+} -+ -+PHP_METHOD(HttpRequestDataShare, factory) -+{ -+ zend_bool global = 0; -+ char *cn = NULL; -+ int cl = 0; -+ zend_object_value ov; -+ -+ SET_EH_THROW_HTTP(); -+ if ( SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bs", &global, &cn, &cl) && -+ SUCCESS == http_object_new(&ov, cn, cl, _http_requestdatashare_object_new_ex, http_requestdatashare_object_ce, NULL, NULL)) { -+ RETVAL_OBJVAL(ov, 0); -+ http_requestdatashare_instantiate(return_value, global); -+ } -+ SET_EH_NORMAL(); -+} -+ -+#ifndef WONKY -+/* {{{ proto static HttpRequestDataShare HttpRequestDataShare::singleton([bool global = false]) -+ Get a single instance (differentiates between the global setting). */ -+PHP_METHOD(HttpRequestDataShare, singleton) -+{ -+ zend_bool global = 0; -+ zval *instance = *zend_std_get_static_property(THIS_CE, ZEND_STRS("instance")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC); -+ -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &global)) { -+ zval **zobj_ptr = NULL, *zobj = NULL; -+ -+ if (Z_TYPE_P(instance) == IS_ARRAY) { -+ if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(instance), global, (void *) &zobj_ptr)) { -+ RETVAL_ZVAL(*zobj_ptr, 1, 0); -+ } else { -+ zobj = http_requestdatashare_instantiate(NULL, global); -+ add_index_zval(instance, global, zobj); -+ RETVAL_OBJECT(zobj, 1); -+ } -+ } else { -+ MAKE_STD_ZVAL(instance); -+ array_init(instance); -+ -+ zobj = http_requestdatashare_instantiate(NULL, global); -+ add_index_zval(instance, global, zobj); -+ RETVAL_OBJECT(zobj, 1); -+ -+ zend_update_static_property(THIS_CE, ZEND_STRS("instance")-1, instance TSRMLS_CC); -+ zval_ptr_dtor(&instance); -+ } -+ } -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+#endif /* !WONKY */ -+ -+static inline zval *_http_requestdatashare_instantiate(zval *this_ptr, zend_bool global TSRMLS_DC) -+{ -+ if (!this_ptr) { -+ MAKE_STD_ZVAL(this_ptr); -+ Z_TYPE_P(this_ptr) = IS_OBJECT; -+ this_ptr->value.obj = http_requestdatashare_object_new_ex(http_requestdatashare_object_ce, global ? http_request_datashare_global_get() : NULL, NULL); -+ } -+ if (global) { -+ if (HTTP_G->request.datashare.cookie) { -+ zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("cookie")-1, HTTP_G->request.datashare.cookie TSRMLS_CC); -+ } -+ if (HTTP_G->request.datashare.dns) { -+ zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("dns")-1, HTTP_G->request.datashare.dns TSRMLS_CC); -+ } -+ if (HTTP_G->request.datashare.ssl) { -+ zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("ssl")-1, HTTP_G->request.datashare.ssl TSRMLS_CC); -+ } -+ if (HTTP_G->request.datashare.connect) { -+ zend_update_property_bool(THIS_CE, getThis(), ZEND_STRS("connect")-1, HTTP_G->request.datashare.connect TSRMLS_CC); -+ } -+ } -+ return this_ptr; -+} -+ -+#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_requestpool_object.c -@@ -0,0 +1,471 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_requestpool_object.c 323304 2012-02-17 21:13:24Z mike $ */ -+ -+#define HTTP_WANT_CURL -+#include "php_http.h" -+ -+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) -+ -+#include "zend_interfaces.h" -+ -+#include "php_http_api.h" -+#include "php_http_exception_object.h" -+#include "php_http_request_api.h" -+#include "php_http_request_object.h" -+#include "php_http_request_pool_api.h" -+#include "php_http_requestpool_object.h" -+ -+#if defined(HAVE_SPL) && !defined(WONKY) -+/* SPL doesn't install its headers */ -+extern PHPAPI zend_class_entry *spl_ce_Countable; -+#endif -+ -+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpRequestPool, method, 0, req_args) -+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpRequestPool, method, 0) -+#define HTTP_REQPOOL_ME(method, visibility) PHP_ME(HttpRequestPool, method, HTTP_ARGS(HttpRequestPool, method), visibility) -+ -+HTTP_EMPTY_ARGS(__construct); -+ -+HTTP_EMPTY_ARGS(__destruct); -+HTTP_EMPTY_ARGS(reset); -+ -+HTTP_BEGIN_ARGS(attach, 1) -+ HTTP_ARG_OBJ(HttpRequest, request, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(detach, 1) -+ HTTP_ARG_OBJ(HttpRequest, request, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(send); -+HTTP_EMPTY_ARGS(socketPerform); -+HTTP_BEGIN_ARGS(socketSelect, 0) -+ HTTP_ARG_VAL(timeout, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(valid); -+HTTP_EMPTY_ARGS(current); -+HTTP_EMPTY_ARGS(key); -+HTTP_EMPTY_ARGS(next); -+HTTP_EMPTY_ARGS(rewind); -+ -+HTTP_EMPTY_ARGS(count); -+ -+HTTP_EMPTY_ARGS(getAttachedRequests); -+HTTP_EMPTY_ARGS(getFinishedRequests); -+ -+HTTP_BEGIN_ARGS(enablePipelining, 0) -+ HTTP_ARG_VAL(enable, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(enableEvents, 0) -+ HTTP_ARG_VAL(enable, 0) -+HTTP_END_ARGS; -+ -+zend_class_entry *http_requestpool_object_ce; -+zend_function_entry http_requestpool_object_fe[] = { -+ HTTP_REQPOOL_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) -+ HTTP_REQPOOL_ME(__destruct, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR) -+ HTTP_REQPOOL_ME(attach, ZEND_ACC_PUBLIC) -+ HTTP_REQPOOL_ME(detach, ZEND_ACC_PUBLIC) -+ HTTP_REQPOOL_ME(send, ZEND_ACC_PUBLIC) -+ HTTP_REQPOOL_ME(reset, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQPOOL_ME(socketPerform, ZEND_ACC_PROTECTED) -+ HTTP_REQPOOL_ME(socketSelect, ZEND_ACC_PROTECTED) -+ -+ /* implements Iterator */ -+ HTTP_REQPOOL_ME(valid, ZEND_ACC_PUBLIC) -+ HTTP_REQPOOL_ME(current, ZEND_ACC_PUBLIC) -+ HTTP_REQPOOL_ME(key, ZEND_ACC_PUBLIC) -+ HTTP_REQPOOL_ME(next, ZEND_ACC_PUBLIC) -+ HTTP_REQPOOL_ME(rewind, ZEND_ACC_PUBLIC) -+ -+ /* implmenents Countable */ -+ HTTP_REQPOOL_ME(count, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQPOOL_ME(getAttachedRequests, ZEND_ACC_PUBLIC) -+ HTTP_REQPOOL_ME(getFinishedRequests, ZEND_ACC_PUBLIC) -+ -+ HTTP_REQPOOL_ME(enablePipelining, ZEND_ACC_PUBLIC) -+ HTTP_REQPOOL_ME(enableEvents, ZEND_ACC_PUBLIC) -+ -+ EMPTY_FUNCTION_ENTRY -+}; -+static zend_object_handlers http_requestpool_object_handlers; -+ -+PHP_MINIT_FUNCTION(http_requestpool_object) -+{ -+ HTTP_REGISTER_CLASS_EX(HttpRequestPool, http_requestpool_object, NULL, 0); -+ http_requestpool_object_handlers.clone_obj = NULL; -+ -+#if defined(HAVE_SPL) && !defined(WONKY) -+ zend_class_implements(http_requestpool_object_ce TSRMLS_CC, 2, spl_ce_Countable, zend_ce_iterator); -+#else -+ zend_class_implements(http_requestpool_object_ce TSRMLS_CC, 1, zend_ce_iterator); -+#endif -+ -+ return SUCCESS; -+} -+ -+zend_object_value _http_requestpool_object_new(zend_class_entry *ce TSRMLS_DC) -+{ -+ zend_object_value ov; -+ http_requestpool_object *o; -+ -+ o = ecalloc(1, sizeof(http_requestpool_object)); -+ o->zo.ce = ce; -+ -+ http_request_pool_init(&o->pool); -+ -+#ifdef ZEND_ENGINE_2_4 -+ zend_object_std_init(o, ce TSRMLS_CC); -+ object_properties_init(o, ce); -+#else -+ ALLOC_HASHTABLE(OBJ_PROP(o)); -+ zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0); -+ zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); -+#endif -+ -+ ov.handle = putObject(http_requestpool_object, o); -+ ov.handlers = &http_requestpool_object_handlers; -+ -+ return ov; -+} -+ -+void _http_requestpool_object_free(zend_object *object TSRMLS_DC) -+{ -+ http_requestpool_object *o = (http_requestpool_object *) object; -+ -+ http_request_pool_dtor(&o->pool); -+ freeObject(o); -+} -+ -+#define http_requestpool_object_llist2array _http_requestpool_object_llist2array -+static void _http_requestpool_object_llist2array(zval **req, zval *array TSRMLS_DC) -+{ -+ ZVAL_ADDREF(*req); -+ add_next_index_zval(array, *req); -+} -+ -+/* ### USERLAND ### */ -+ -+/* {{{ proto void HttpRequestPool::__construct([HttpRequest request[, ...]]) -+ Creates a new HttpRequestPool object instance. */ -+PHP_METHOD(HttpRequestPool, __construct) -+{ -+ int argc = ZEND_NUM_ARGS(); -+ zval ***argv = safe_emalloc(argc, sizeof(zval *), 0); -+ getObject(http_requestpool_object, obj); -+ -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_get_parameters_array_ex(argc, argv)) { -+ int i; -+ -+ for (i = 0; i < argc; ++i) { -+ if (Z_TYPE_PP(argv[i]) == IS_OBJECT && instanceof_function(Z_OBJCE_PP(argv[i]), http_request_object_ce TSRMLS_CC)) { -+ http_request_pool_attach(&obj->pool, *(argv[i])); -+ } -+ } -+ } -+ efree(argv); -+ http_final(HTTP_EX_CE(request_pool)); -+ SET_EH_NORMAL(); -+} -+/* }}} */ -+ -+/* {{{ proto void HttpRequestPool::__destruct() -+ Clean up HttpRequestPool object. */ -+PHP_METHOD(HttpRequestPool, __destruct) -+{ -+ getObject(http_requestpool_object, obj); -+ -+ NO_ARGS; -+ -+ http_request_pool_detach_all(&obj->pool); -+} -+/* }}} */ -+ -+/* {{{ proto void HttpRequestPool::reset() -+ Detach all attached HttpRequest objects. */ -+PHP_METHOD(HttpRequestPool, reset) -+{ -+ getObject(http_requestpool_object, obj); -+ -+ NO_ARGS; -+ -+ obj->iterator.pos = 0; -+ http_request_pool_detach_all(&obj->pool); -+} -+ -+/* {{{ proto bool HttpRequestPool::attach(HttpRequest request) -+ Attach an HttpRequest object to this HttpRequestPool. WARNING: set all options prior attaching! */ -+PHP_METHOD(HttpRequestPool, attach) -+{ -+ zval *request; -+ STATUS status = FAILURE; -+ getObject(http_requestpool_object, obj); -+ -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) { -+ if (obj->iterator.pos > 0 && obj->iterator.pos < zend_llist_count(&obj->pool.handles)) { -+ http_error(HE_THROW, HTTP_E_REQUEST_POOL, "Cannot attach to the HttpRequestPool while the iterator is active"); -+ } else { -+ status = http_request_pool_attach(&obj->pool, request); -+ } -+ } -+ SET_EH_NORMAL(); -+ RETURN_SUCCESS(status); -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequestPool::detach(HttpRequest request) -+ Detach an HttpRequest object from this HttpRequestPool. */ -+PHP_METHOD(HttpRequestPool, detach) -+{ -+ zval *request; -+ STATUS status = FAILURE; -+ getObject(http_requestpool_object, obj); -+ -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &request, http_request_object_ce)) { -+ obj->iterator.pos = -1; -+ status = http_request_pool_detach(&obj->pool, request); -+ } -+ SET_EH_NORMAL(); -+ RETURN_SUCCESS(status); -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequestPool::send() -+ Send all attached HttpRequest objects in parallel. */ -+PHP_METHOD(HttpRequestPool, send) -+{ -+ STATUS status; -+ getObject(http_requestpool_object, obj); -+ -+ NO_ARGS; -+ -+ SET_EH_THROW_HTTP(); -+ status = http_request_pool_send(&obj->pool); -+ SET_EH_NORMAL(); -+ -+ /* rethrow as HttpRequestPoolException */ -+ http_final(HTTP_EX_CE(request_pool)); -+ -+ RETURN_SUCCESS(status); -+} -+/* }}} */ -+ -+/* {{{ proto protected bool HttpRequestPool::socketPerform() -+ Returns TRUE until each request has finished its transaction. */ -+PHP_METHOD(HttpRequestPool, socketPerform) -+{ -+ getObject(http_requestpool_object, obj); -+ -+ NO_ARGS; -+ -+ if (0 < http_request_pool_perform(&obj->pool)) { -+ RETURN_TRUE; -+ } else { -+ RETURN_FALSE; -+ } -+} -+/* }}} */ -+ -+/* {{{ proto protected bool HttpRequestPool::socketSelect([double timeout]) */ -+PHP_METHOD(HttpRequestPool, socketSelect) -+{ -+ double timeout = 0; -+ struct timeval custom_timeout, *custom_timeout_ptr = NULL; -+ getObject(http_requestpool_object, obj); -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|d", &timeout)) { -+ RETURN_FALSE; -+ } -+ if (ZEND_NUM_ARGS() && timeout > 0) { -+ custom_timeout.tv_sec = (time_t) timeout; -+ custom_timeout.tv_usec = HTTP_USEC(timeout) % HTTP_MCROSEC; -+ custom_timeout_ptr = &custom_timeout; -+ } -+ -+ RETURN_SUCCESS(http_request_pool_select_ex(&obj->pool, custom_timeout_ptr)); -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequestPool::valid() -+ Implements Iterator::valid(). */ -+PHP_METHOD(HttpRequestPool, valid) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ getObject(http_requestpool_object, obj); -+ RETURN_BOOL(obj->iterator.pos >= 0 && obj->iterator.pos < zend_llist_count(&obj->pool.handles)); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto HttpRequest HttpRequestPool::current() -+ Implements Iterator::current(). */ -+PHP_METHOD(HttpRequestPool, current) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ long pos = 0; -+ zval **current = NULL; -+ zend_llist_position lpos; -+ getObject(http_requestpool_object, obj); -+ -+ if (obj->iterator.pos < zend_llist_count(&obj->pool.handles)) { -+ for ( current = zend_llist_get_first_ex(&obj->pool.handles, &lpos); -+ current && obj->iterator.pos != pos++; -+ current = zend_llist_get_next_ex(&obj->pool.handles, &lpos)); -+ if (current) { -+ RETURN_OBJECT(*current, 1); -+ } -+ } -+ RETURN_NULL(); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto int HttpRequestPool::key() -+ Implements Iterator::key(). */ -+PHP_METHOD(HttpRequestPool, key) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ getObject(http_requestpool_object, obj); -+ RETURN_LONG(obj->iterator.pos); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto void HttpRequestPool::next() -+ Implements Iterator::next(). */ -+PHP_METHOD(HttpRequestPool, next) -+{ -+ NO_ARGS { -+ getObject(http_requestpool_object, obj); -+ ++(obj->iterator.pos); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto void HttpRequestPool::rewind() -+ Implements Iterator::rewind(). */ -+PHP_METHOD(HttpRequestPool, rewind) -+{ -+ NO_ARGS { -+ getObject(http_requestpool_object, obj); -+ obj->iterator.pos = 0; -+ } -+} -+/* }}} */ -+ -+/* {{{ proto int HttpRequestPool::count() -+ Implements Countable::count(). */ -+PHP_METHOD(HttpRequestPool, count) -+{ -+ NO_ARGS { -+ getObject(http_requestpool_object, obj); -+ RETURN_LONG((long) zend_llist_count(&obj->pool.handles)); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto array HttpRequestPool::getAttachedRequests() -+ Get attached HttpRequest objects. */ -+PHP_METHOD(HttpRequestPool, getAttachedRequests) -+{ -+ getObject(http_requestpool_object, obj); -+ -+ NO_ARGS; -+ -+ array_init(return_value); -+ zend_llist_apply_with_argument(&obj->pool.handles, -+ (llist_apply_with_arg_func_t) http_requestpool_object_llist2array, -+ return_value TSRMLS_CC); -+} -+/* }}} */ -+ -+/* {{{ proto array HttpRequestPool::getFinishedRequests() -+ Get attached HttpRequest objects that already have finished their work. */ -+PHP_METHOD(HttpRequestPool, getFinishedRequests) -+{ -+ getObject(http_requestpool_object, obj); -+ -+ NO_ARGS; -+ -+ array_init(return_value); -+ zend_llist_apply_with_argument(&obj->pool.finished, -+ (llist_apply_with_arg_func_t) http_requestpool_object_llist2array, -+ return_value TSRMLS_CC); -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequestPool::enablePipelining([bool enable = true]) -+ Enables pipelining support for all attached requests if support in libcurl is given. */ -+PHP_METHOD(HttpRequestPool, enablePipelining) -+{ -+ zend_bool enable = 1; -+#if defined(HAVE_CURL_MULTI_SETOPT) && HTTP_CURL_VERSION(7,16,0) -+ getObject(http_requestpool_object, obj); -+#endif -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &enable)) { -+ RETURN_FALSE; -+ } -+#if defined(HAVE_CURL_MULTI_SETOPT) && HTTP_CURL_VERSION(7,16,0) -+ if (CURLM_OK == curl_multi_setopt(obj->pool.ch, CURLMOPT_PIPELINING, (long) enable)) { -+ RETURN_TRUE; -+ } -+#endif -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+/* {{{ proto bool HttpRequestPool::enableEvents([bool enable = true]) -+ Enables event-driven I/O if support in libcurl is given. */ -+PHP_METHOD(HttpRequestPool, enableEvents) -+{ -+ zend_bool enable = 1; -+#if defined(HTTP_HAVE_EVENT) -+ getObject(http_requestpool_object, obj); -+#endif -+ -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &enable)) { -+#if defined(HTTP_HAVE_EVENT) -+ obj->pool.useevents = enable; -+ RETURN_TRUE; -+#endif -+ } -+ RETURN_FALSE; -+} -+/* }}} */ -+ -+#endif /* ZEND_ENGINE_2 && HTTP_HAVE_CURL */ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_response_object.c -@@ -0,0 +1,927 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_response_object.c 323304 2012-02-17 21:13:24Z mike $ */ -+ -+#define HTTP_WANT_SAPI -+#define HTTP_WANT_MAGIC -+#include "php_http.h" -+ -+/* broken static properties in PHP 5.0 */ -+#if defined(ZEND_ENGINE_2) && !defined(WONKY) -+ -+#include "php_ini.h" -+ -+#include "php_http_api.h" -+#include "php_http_cache_api.h" -+#include "php_http_exception_object.h" -+#include "php_http_headers_api.h" -+#include "php_http_response_object.h" -+#include "php_http_send_api.h" -+ -+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpResponse, method, 0, req_args) -+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpResponse, method, 0) -+#define HTTP_RESPONSE_ME(method, visibility) PHP_ME(HttpResponse, method, HTTP_ARGS(HttpResponse, method), visibility|ZEND_ACC_STATIC) -+#define HTTP_RESPONSE_ALIAS(method, func) HTTP_STATIC_ME_ALIAS(method, func, HTTP_ARGS(HttpResponse, method)) -+ -+HTTP_BEGIN_ARGS(setHeader, 1) -+ HTTP_ARG_VAL(name, 0) -+ HTTP_ARG_VAL(value, 0) -+ HTTP_ARG_VAL(replace, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(getHeader, 0) -+ HTTP_ARG_VAL(name, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getETag); -+HTTP_BEGIN_ARGS(setETag, 1) -+ HTTP_ARG_VAL(etag, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getLastModified); -+HTTP_BEGIN_ARGS(setLastModified, 1) -+ HTTP_ARG_VAL(timestamp, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getCache); -+HTTP_BEGIN_ARGS(setCache, 1) -+ HTTP_ARG_VAL(cache, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getGzip); -+HTTP_BEGIN_ARGS(setGzip, 1) -+ HTTP_ARG_VAL(gzip, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getCacheControl); -+HTTP_BEGIN_ARGS(setCacheControl, 1) -+ HTTP_ARG_VAL(cache_control, 0) -+ HTTP_ARG_VAL(max_age, 0) -+ HTTP_ARG_VAL(must_revalidate, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getContentType); -+HTTP_BEGIN_ARGS(setContentType, 1) -+ HTTP_ARG_VAL(content_type, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(guessContentType, 1) -+ HTTP_ARG_VAL(magic_file, 0) -+ HTTP_ARG_VAL(magic_mode, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getContentDisposition); -+HTTP_BEGIN_ARGS(setContentDisposition, 1) -+ HTTP_ARG_VAL(filename, 0) -+ HTTP_ARG_VAL(send_inline, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getThrottleDelay); -+HTTP_BEGIN_ARGS(setThrottleDelay, 1) -+ HTTP_ARG_VAL(seconds, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getBufferSize); -+HTTP_BEGIN_ARGS(setBufferSize, 1) -+ HTTP_ARG_VAL(bytes, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getData); -+HTTP_BEGIN_ARGS(setData, 1) -+ HTTP_ARG_VAL(data, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getStream); -+HTTP_BEGIN_ARGS(setStream, 1) -+ HTTP_ARG_VAL(stream, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getFile); -+HTTP_BEGIN_ARGS(setFile, 1) -+ HTTP_ARG_VAL(filepath, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(send, 0) -+ HTTP_ARG_VAL(clean_ob, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(capture); -+ -+HTTP_BEGIN_ARGS(redirect, 0) -+ HTTP_ARG_VAL(url, 0) -+ HTTP_ARG_VAL(params, 0) -+ HTTP_ARG_VAL(session, 0) -+ HTTP_ARG_VAL(permanent, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(status, 1) -+ HTTP_ARG_VAL(code, 0) -+HTTP_END_ARGS; -+ -+HTTP_EMPTY_ARGS(getRequestHeaders); -+HTTP_EMPTY_ARGS(getRequestBody); -+HTTP_EMPTY_ARGS(getRequestBodyStream); -+ -+#define THIS_CE http_response_object_ce -+zend_class_entry *http_response_object_ce; -+zend_function_entry http_response_object_fe[] = { -+ -+ HTTP_RESPONSE_ME(setHeader, ZEND_ACC_PUBLIC) -+ HTTP_RESPONSE_ME(getHeader, ZEND_ACC_PUBLIC) -+ -+ HTTP_RESPONSE_ME(setETag, ZEND_ACC_PUBLIC) -+ HTTP_RESPONSE_ME(getETag, ZEND_ACC_PUBLIC) -+ -+ HTTP_RESPONSE_ME(setLastModified, ZEND_ACC_PUBLIC) -+ HTTP_RESPONSE_ME(getLastModified, ZEND_ACC_PUBLIC) -+ -+ HTTP_RESPONSE_ME(setContentDisposition, ZEND_ACC_PUBLIC) -+ HTTP_RESPONSE_ME(getContentDisposition, ZEND_ACC_PUBLIC) -+ -+ HTTP_RESPONSE_ME(setContentType, ZEND_ACC_PUBLIC) -+ HTTP_RESPONSE_ME(getContentType, ZEND_ACC_PUBLIC) -+ -+ HTTP_RESPONSE_ME(guessContentType, ZEND_ACC_PUBLIC) -+ -+ HTTP_RESPONSE_ME(setCache, ZEND_ACC_PUBLIC) -+ HTTP_RESPONSE_ME(getCache, ZEND_ACC_PUBLIC) -+ -+ HTTP_RESPONSE_ME(setCacheControl, ZEND_ACC_PUBLIC) -+ HTTP_RESPONSE_ME(getCacheControl, ZEND_ACC_PUBLIC) -+ -+ HTTP_RESPONSE_ME(setGzip, ZEND_ACC_PUBLIC) -+ HTTP_RESPONSE_ME(getGzip, ZEND_ACC_PUBLIC) -+ -+ HTTP_RESPONSE_ME(setThrottleDelay, ZEND_ACC_PUBLIC) -+ HTTP_RESPONSE_ME(getThrottleDelay, ZEND_ACC_PUBLIC) -+ -+ HTTP_RESPONSE_ME(setBufferSize, ZEND_ACC_PUBLIC) -+ HTTP_RESPONSE_ME(getBufferSize, ZEND_ACC_PUBLIC) -+ -+ HTTP_RESPONSE_ME(setData, ZEND_ACC_PUBLIC) -+ HTTP_RESPONSE_ME(getData, ZEND_ACC_PUBLIC) -+ -+ HTTP_RESPONSE_ME(setFile, ZEND_ACC_PUBLIC) -+ HTTP_RESPONSE_ME(getFile, ZEND_ACC_PUBLIC) -+ -+ HTTP_RESPONSE_ME(setStream, ZEND_ACC_PUBLIC) -+ HTTP_RESPONSE_ME(getStream, ZEND_ACC_PUBLIC) -+ -+ HTTP_RESPONSE_ME(send, ZEND_ACC_PUBLIC) -+ HTTP_RESPONSE_ME(capture, ZEND_ACC_PUBLIC) -+ -+ HTTP_RESPONSE_ALIAS(redirect, http_redirect) -+ HTTP_RESPONSE_ALIAS(status, http_send_status) -+ HTTP_RESPONSE_ALIAS(getRequestHeaders, http_get_request_headers) -+ HTTP_RESPONSE_ALIAS(getRequestBody, http_get_request_body) -+ HTTP_RESPONSE_ALIAS(getRequestBodyStream, http_get_request_body_stream) -+ -+ EMPTY_FUNCTION_ENTRY -+}; -+ -+PHP_MINIT_FUNCTION(http_response_object) -+{ -+ HTTP_REGISTER_CLASS(HttpResponse, http_response_object, NULL, 0); -+ -+ zend_declare_property_bool(THIS_CE, ZEND_STRS("sent")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC); -+ zend_declare_property_bool(THIS_CE, ZEND_STRS("catch")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC); -+ zend_declare_property_long(THIS_CE, ZEND_STRS("mode")-1, -1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC); -+ zend_declare_property_long(THIS_CE, ZEND_STRS("stream")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC); -+ zend_declare_property_null(THIS_CE, ZEND_STRS("file")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC); -+ zend_declare_property_null(THIS_CE, ZEND_STRS("data")-1, (ZEND_ACC_STATIC|ZEND_ACC_PRIVATE) TSRMLS_CC); -+ zend_declare_property_bool(THIS_CE, ZEND_STRS("cache")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC); -+ zend_declare_property_bool(THIS_CE, ZEND_STRS("gzip")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC); -+ zend_declare_property_null(THIS_CE, ZEND_STRS("eTag")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC); -+ zend_declare_property_long(THIS_CE, ZEND_STRS("lastModified")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC); -+ zend_declare_property_null(THIS_CE, ZEND_STRS("cacheControl")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC); -+ zend_declare_property_null(THIS_CE, ZEND_STRS("contentType")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC); -+ zend_declare_property_null(THIS_CE, ZEND_STRS("contentDisposition")-1, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC); -+ zend_declare_property_long(THIS_CE, ZEND_STRS("bufferSize")-1, 0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC); -+ zend_declare_property_double(THIS_CE, ZEND_STRS("throttleDelay")-1, 0.0, (ZEND_ACC_STATIC|ZEND_ACC_PROTECTED) TSRMLS_CC); -+ -+#ifndef WONKY -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT")-1, HTTP_REDIRECT TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_PERM")-1, HTTP_REDIRECT_PERM TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_FOUND")-1, HTTP_REDIRECT_FOUND TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_POST")-1, HTTP_REDIRECT_POST TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_PROXY")-1, HTTP_REDIRECT_PROXY TSRMLS_CC); -+ zend_declare_class_constant_long(THIS_CE, ZEND_STRS("REDIRECT_TEMP")-1, HTTP_REDIRECT_TEMP TSRMLS_CC); -+#endif /* WONKY */ -+ -+ return SUCCESS; -+} -+ -+/* ### USERLAND ### */ -+ -+/* {{{ proto static bool HttpResponse::setHeader(string name[, mixed value[, bool replace = true]]) -+ Send an HTTP header. */ -+PHP_METHOD(HttpResponse, setHeader) -+{ -+ zend_bool replace = 1; -+ char *name; -+ int name_len = 0; -+ zval *value = NULL; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/!b", &name, &name_len, &value, &replace)) { -+ RETURN_FALSE; -+ } -+ if (SG(headers_sent)) { -+ http_error(HE_WARNING, HTTP_E_HEADER, "Cannot add another header when headers have already been sent"); -+ RETURN_FALSE; -+ } -+ if (!name_len) { -+ http_error(HE_WARNING, HTTP_E_HEADER, "Cannot send anonymous headers"); -+ RETURN_FALSE; -+ } -+ http_send_header_zval_ex(name, name_len, &value, replace); -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto static mixed HttpResponse::getHeader([string name]) -+ Get header(s) about to be sent. */ -+PHP_METHOD(HttpResponse, getHeader) -+{ -+ char *name = NULL; -+ int name_len = 0; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len)) { -+ RETURN_FALSE; -+ } -+ -+ if (name && name_len) { -+ zval **header; -+ HashTable headers_ht; -+ -+ zend_hash_init(&headers_ht, sizeof(zval *), NULL, ZVAL_PTR_DTOR, 0); -+ if ( (SUCCESS == http_get_response_headers(&headers_ht)) && -+ (SUCCESS == zend_hash_find(&headers_ht, name, name_len + 1, (void *) &header))) { -+ RETVAL_ZVAL(*header, 1, 0); -+ } else { -+ RETVAL_NULL(); -+ } -+ zend_hash_destroy(&headers_ht); -+ } else { -+ array_init(return_value); -+ http_get_response_headers(Z_ARRVAL_P(return_value)); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto static bool HttpResponse::setCache(bool cache) -+ Whether it should be attempted to cache the entity. */ -+PHP_METHOD(HttpResponse, setCache) -+{ -+ zend_bool do_cache = 0; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_cache)) { -+ RETURN_FALSE; -+ } -+ -+ RETURN_SUCCESS(zend_update_static_property_bool(THIS_CE, ZEND_STRS("cache")-1, do_cache TSRMLS_CC)); -+} -+/* }}} */ -+ -+/* {{{ proto static bool HttpResponse::getCache() -+ Get current caching setting. */ -+PHP_METHOD(HttpResponse, getCache) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ zval *cache = http_zsep(IS_BOOL, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("cache")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ RETVAL_ZVAL(cache, 1, 1); -+ } -+} -+/* }}}*/ -+ -+/* {{{ proto static bool HttpResponse::setGzip(bool gzip) -+ Enable on-thy-fly gzipping of the sent entity. */ -+PHP_METHOD(HttpResponse, setGzip) -+{ -+ zend_bool do_gzip = 0; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_gzip)) { -+ RETURN_FALSE; -+ } -+ -+ RETURN_SUCCESS(zend_update_static_property_bool(THIS_CE, ZEND_STRS("gzip")-1, do_gzip TSRMLS_CC)); -+} -+/* }}} */ -+ -+/* {{{ proto static bool HttpResponse::getGzip() -+ Get current gzipping setting. */ -+PHP_METHOD(HttpResponse, getGzip) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ zval *gzip = http_zsep(IS_BOOL, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("gzip")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ RETVAL_ZVAL(gzip, 1, 1); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto static bool HttpResponse::setCacheControl(string control[, int max_age = 0[, bool must_revalidate = true]]) -+ Set a custom cache-control header, usually being "private" or "public"; The max_age parameter controls how long the cache entry is valid on the client side. */ -+PHP_METHOD(HttpResponse, setCacheControl) -+{ -+ char *ccontrol, *cctl; -+ int cc_len; -+ long max_age = 0; -+ zend_bool must_revalidate = 1; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &ccontrol, &cc_len, &max_age, &must_revalidate)) { -+ RETURN_FALSE; -+ } -+ -+ if (strcmp(ccontrol, "public") && strcmp(ccontrol, "private") && strcmp(ccontrol, "no-cache")) { -+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol); -+ RETURN_FALSE; -+ } else { -+ size_t cctl_len = spprintf(&cctl, 0, "%s,%s max-age=%ld", ccontrol, must_revalidate?" must-revalidate,":"", max_age); -+ RETVAL_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("cacheControl")-1, cctl, cctl_len TSRMLS_CC)); -+ efree(cctl); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto static string HttpResponse::getCacheControl() -+ Get current Cache-Control header setting. */ -+PHP_METHOD(HttpResponse, getCacheControl) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ zval *cctl = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("cacheControl")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ RETVAL_ZVAL(cctl, 1, 1); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto static bool HttpResponse::setContentType(string content_type) -+ Set the content-type of the sent entity. */ -+PHP_METHOD(HttpResponse, setContentType) -+{ -+ char *ctype; -+ int ctype_len; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ctype_len)) { -+ RETURN_FALSE; -+ } -+ -+ HTTP_CHECK_CONTENT_TYPE(ctype, RETURN_FALSE); -+ RETURN_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("contentType")-1, ctype, ctype_len TSRMLS_CC)); -+} -+/* }}} */ -+ -+/* {{{ proto static string HttpResponse::getContentType() -+ Get current Content-Type header setting. */ -+PHP_METHOD(HttpResponse, getContentType) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ zval *ctype = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentType")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ RETVAL_ZVAL(ctype, 1, 1); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto static string HttpResponse::guessContentType(string magic_file[, int magic_mode = MAGIC_MIME]) -+ Attempts to guess the content type of supplied payload through libmagic. */ -+PHP_METHOD(HttpResponse, guessContentType) -+{ -+#ifdef HTTP_HAVE_MAGIC -+ char *magic_file, *ct = NULL; -+ int magic_file_len; -+ long magic_mode = MAGIC_MIME; -+ -+ RETVAL_FALSE; -+ SET_EH_THROW_HTTP(); -+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &magic_file, &magic_file_len, &magic_mode)) { -+ switch (Z_LVAL_P(*zend_std_get_static_property(THIS_CE, ZEND_STRS("mode")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) { -+ case SEND_DATA: -+ { -+ zval *data = *zend_std_get_static_property(THIS_CE, ZEND_STRS("data")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC); -+ ct = http_guess_content_type(magic_file, magic_mode, Z_STRVAL_P(data), Z_STRLEN_P(data), SEND_DATA); -+ break; -+ } -+ -+ case SEND_RSRC: -+ { -+ php_stream *s; -+ zval *z = *zend_std_get_static_property(THIS_CE, ZEND_STRS("stream")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC); -+ z->type = IS_RESOURCE; -+ php_stream_from_zval(s, &z); -+ ct = http_guess_content_type(magic_file, magic_mode, s, 0, SEND_RSRC); -+ break; -+ } -+ -+ default: -+ ct = http_guess_content_type(magic_file, magic_mode, Z_STRVAL_P(*zend_std_get_static_property(THIS_CE, ZEND_STRS("file")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)), 0, -1); -+ break; -+ } -+ if (ct) { -+ zend_update_static_property_string(THIS_CE, ZEND_STRS("contentType")-1, ct TSRMLS_CC); -+ RETVAL_STRING(ct, 0); -+ } -+ } -+ SET_EH_NORMAL(); -+#else -+ http_error(HE_THROW, HTTP_E_RUNTIME, "Cannot guess Content-Type; libmagic not available"); -+ RETURN_FALSE; -+#endif -+} -+/* }}} */ -+ -+/* {{{ proto static bool HttpResponse::setContentDisposition(string filename[, bool inline = false]) -+ Set the Content-Disposition. */ -+PHP_METHOD(HttpResponse, setContentDisposition) -+{ -+ char *file, *cd; -+ int file_len; -+ size_t cd_len; -+ zend_bool send_inline = 0; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &file, &file_len, &send_inline)) { -+ RETURN_FALSE; -+ } -+ -+ cd_len = spprintf(&cd, 0, "%s; filename=\"%s\"", send_inline ? "inline" : "attachment", file); -+ RETVAL_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("contentDisposition")-1, cd, cd_len TSRMLS_CC)); -+ efree(cd); -+} -+/* }}} */ -+ -+/* {{{ proto static string HttpResponse::getContentDisposition() -+ Get current Content-Disposition setting. */ -+PHP_METHOD(HttpResponse, getContentDisposition) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ zval *cdisp = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentDisposition")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ RETVAL_ZVAL(cdisp, 1, 1); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto static bool HttpResponse::setETag(string etag) -+ Set a custom ETag. Use this only if you know what you're doing. */ -+PHP_METHOD(HttpResponse, setETag) -+{ -+ char *etag; -+ int etag_len; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &etag, &etag_len)) { -+ RETURN_FALSE; -+ } -+ -+ RETURN_SUCCESS(zend_update_static_property_stringl(THIS_CE, ZEND_STRS("eTag")-1, etag, etag_len TSRMLS_CC)); -+} -+/* }}} */ -+ -+/* {{{ proto static string HttpResponse::getETag() -+ Get calculated or previously set custom ETag. */ -+PHP_METHOD(HttpResponse, getETag) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ zval *etag = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("eTag")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ RETVAL_ZVAL(etag, 1, 1); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto static bool HttpResponse::setLastModified(int timestamp) -+ Set a custom Last-Modified date. */ -+PHP_METHOD(HttpResponse, setLastModified) -+{ -+ long lm; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &lm)) { -+ RETURN_FALSE; -+ } -+ -+ RETURN_SUCCESS(zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, lm TSRMLS_CC)); -+} -+/* }}} */ -+ -+/* {{{ proto static int HttpResponse::getLastModified() -+ Get calculated or previously set custom Last-Modified date. */ -+PHP_METHOD(HttpResponse, getLastModified) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ zval *lmod = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("lastModified")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ RETVAL_ZVAL(lmod, 1, 1); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto static bool HttpResponse::setThrottleDelay(double seconds) -+ Sets the throttle delay for use with HttpResponse::setBufferSize(). */ -+PHP_METHOD(HttpResponse, setThrottleDelay) -+{ -+ double seconds; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &seconds)) { -+ RETURN_FALSE; -+ } -+ RETURN_SUCCESS(zend_update_static_property_double(THIS_CE, ZEND_STRS("throttleDelay")-1, seconds TSRMLS_CC)); -+} -+/* }}} */ -+ -+/* {{{ proto static double HttpResponse::getThrottleDelay() -+ Get the current throttle delay. */ -+PHP_METHOD(HttpResponse, getThrottleDelay) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ zval *tdel = http_zsep(IS_DOUBLE, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("throttleDelay")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ RETVAL_ZVAL(tdel, 1, 1); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto static bool HttpResponse::setBufferSize(int bytes) -+ Sets the send buffer size for use with HttpResponse::setThrottleDelay(). */ -+PHP_METHOD(HttpResponse, setBufferSize) -+{ -+ long bytes; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &bytes)) { -+ RETURN_FALSE; -+ } -+ RETURN_SUCCESS(zend_update_static_property_long(THIS_CE, ZEND_STRS("bufferSize")-1, bytes TSRMLS_CC)); -+} -+/* }}} */ -+ -+/* {{{ proto static int HttpResponse::getBufferSize() -+ Get current buffer size. */ -+PHP_METHOD(HttpResponse, getBufferSize) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ zval *bsize = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("bufferSize")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ RETVAL_ZVAL(bsize, 1, 1); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto static bool HttpResponse::setData(mixed data) -+ Set the data to be sent. */ -+PHP_METHOD(HttpResponse, setData) -+{ -+ char *etag; -+ zval *the_data; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &the_data)) { -+ RETURN_FALSE; -+ } -+ if (Z_TYPE_P(the_data) != IS_STRING) { -+ convert_to_string(the_data); -+ } -+ -+ if ( (SUCCESS != zend_update_static_property(THIS_CE, ZEND_STRS("data")-1, the_data TSRMLS_CC)) || -+ (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("mode")-1, SEND_DATA TSRMLS_CC))) { -+ RETURN_FALSE; -+ } -+ -+ zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, http_last_modified(the_data, SEND_DATA) TSRMLS_CC); -+ if ((etag = http_etag(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), SEND_DATA))) { -+ zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC); -+ efree(etag); -+ } -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto static string HttpResponse::getData() -+ Get the previously set data to be sent. */ -+PHP_METHOD(HttpResponse, getData) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ zval *the_data = *zend_std_get_static_property(THIS_CE, ZEND_STRS("data")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC); -+ -+ RETURN_ZVAL(the_data, 1, 0); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto static bool HttpResponse::setStream(resource stream) -+ Set the resource to be sent. */ -+PHP_METHOD(HttpResponse, setStream) -+{ -+ char *etag; -+ zval *the_stream; -+ php_stream *the_real_stream; -+ php_stream_statbuf ssb; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &the_stream)) { -+ RETURN_FALSE; -+ } -+ -+ php_stream_from_zval(the_real_stream, &the_stream); -+ if (php_stream_stat(the_real_stream, &ssb)) { -+ RETURN_FALSE; -+ } -+ -+ if ( (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("stream")-1, Z_LVAL_P(the_stream) TSRMLS_CC)) || -+ (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("mode")-1, SEND_RSRC TSRMLS_CC))) { -+ RETURN_FALSE; -+ } -+ zend_list_addref(Z_LVAL_P(the_stream)); -+ -+ zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, http_last_modified(the_real_stream, SEND_RSRC) TSRMLS_CC); -+ if ((etag = http_etag(the_real_stream, 0, SEND_RSRC))) { -+ zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC); -+ efree(etag); -+ } -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto static resource HttpResponse::getStream() -+ Get the previously set resource to be sent. */ -+PHP_METHOD(HttpResponse, getStream) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ zval *stream = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("stream")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ RETVAL_RESOURCE(Z_LVAL_P(stream)); -+ zval_ptr_dtor(&stream); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto static bool HttpResponse::setFile(string file) -+ Set the file to be sent. */ -+PHP_METHOD(HttpResponse, setFile) -+{ -+ char *the_file, *etag; -+ int file_len; -+ php_stream_statbuf ssb; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &the_file, &file_len)) { -+ RETURN_FALSE; -+ } -+ -+ if (php_stream_stat_path(the_file, &ssb)) { -+ RETURN_FALSE; -+ } -+ -+ if ( (SUCCESS != zend_update_static_property_stringl(THIS_CE, ZEND_STRS("file")-1, the_file, file_len TSRMLS_CC)) || -+ (SUCCESS != zend_update_static_property_long(THIS_CE, ZEND_STRS("mode")-1, -1 TSRMLS_CC))) { -+ RETURN_FALSE; -+ } -+ -+ zend_update_static_property_long(THIS_CE, ZEND_STRS("lastModified")-1, http_last_modified(the_file, -1) TSRMLS_CC); -+ if ((etag = http_etag(the_file, 0, -1))) { -+ zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC); -+ efree(etag); -+ } -+ -+ RETURN_TRUE; -+} -+/* }}} */ -+ -+/* {{{ proto static string HttpResponse::getFile() -+ Get the previously set file to be sent. */ -+PHP_METHOD(HttpResponse, getFile) -+{ -+ NO_ARGS; -+ -+ if (return_value_used) { -+ zval *file = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("file")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ RETVAL_ZVAL(file, 1, 1); -+ } -+} -+/* }}} */ -+ -+/* {{{ proto static bool HttpResponse::send([bool clean_ob = true]) -+ Finally send the entity. */ -+PHP_METHOD(HttpResponse, send) -+{ -+ zval *sent; -+ zend_bool clean_ob = 1; -+ -+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clean_ob)) { -+ RETURN_FALSE; -+ } -+ -+ HTTP_CHECK_HEADERS_SENT(RETURN_FALSE); -+ -+ sent = *zend_std_get_static_property(THIS_CE, ZEND_STRS("sent")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC); -+ if (Z_LVAL_P(sent)) { -+ http_error(HE_WARNING, HTTP_E_RESPONSE, "Cannot send HttpResponse, response has already been sent"); -+ RETURN_FALSE; -+ } else { -+ Z_LVAL_P(sent) = 1; -+ } -+ -+ /* capture mode */ -+ if (i_zend_is_true(*zend_std_get_static_property(THIS_CE, ZEND_STRS("catch")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) { -+ zval *zetag, *the_data; -+ -+ MAKE_STD_ZVAL(the_data); -+#ifdef PHP_OUTPUT_NEWAPI -+ php_output_get_contents(the_data TSRMLS_CC); -+#else -+ php_ob_get_buffer(the_data TSRMLS_CC); -+#endif -+ zend_update_static_property(THIS_CE, ZEND_STRS("data")-1, the_data TSRMLS_CC); -+ ZVAL_LONG(*zend_std_get_static_property(THIS_CE, ZEND_STRS("mode")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC), SEND_DATA); -+ -+ zetag = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("eTag")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ if (!Z_STRLEN_P(zetag)) { -+ char *etag = http_etag(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), SEND_DATA); -+ if (etag) { -+ zend_update_static_property_string(THIS_CE, ZEND_STRS("eTag")-1, etag TSRMLS_CC); -+ efree(etag); -+ } -+ } -+ zval_ptr_dtor(&the_data); -+ zval_ptr_dtor(&zetag); -+ -+ clean_ob = 1; -+ } -+ -+ if (clean_ob) { -+ /* interrupt on-the-fly etag generation */ -+ HTTP_G->etag.started = 0; -+ /* discard previous output buffers */ -+#ifdef PHP_OUTPUT_NEWAPI -+ php_output_discard_all(TSRMLS_C); -+#else -+ php_end_ob_buffers(0 TSRMLS_CC); -+#endif -+ } -+ -+ /* caching */ -+ if (i_zend_is_true(*zend_std_get_static_property(THIS_CE, ZEND_STRS("cache")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) { -+ zval *cctl, *etag, *lmod; -+ -+ lmod = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("lastModified")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ etag = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("eTag")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ cctl = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("cacheControl")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ -+ if (Z_LVAL_P(lmod) || Z_STRLEN_P(etag)) { -+ if (Z_STRLEN_P(cctl)) { -+ http_send_cache_control(Z_STRVAL_P(cctl), Z_STRLEN_P(cctl)); -+ } else { -+ http_send_cache_control(HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL)); -+ } -+ if (Z_STRLEN_P(etag)) { -+ http_send_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag)); -+ } -+ if (Z_LVAL_P(lmod)) { -+ http_send_last_modified(Z_LVAL_P(lmod)); -+ } -+ } -+ -+ zval_ptr_dtor(&etag); -+ zval_ptr_dtor(&lmod); -+ zval_ptr_dtor(&cctl); -+ } -+ -+ /* content type */ -+ { -+ zval *ctype = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentType")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ if (Z_STRLEN_P(ctype)) { -+ http_send_content_type(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype)); -+ } else { -+ char *ctypes = INI_STR("default_mimetype"); -+ size_t ctlen = ctypes ? strlen(ctypes) : 0; -+ -+ if (ctlen) { -+ http_send_content_type(ctypes, ctlen); -+ } else { -+ http_send_content_type("application/x-octetstream", lenof("application/x-octetstream")); -+ } -+ } -+ zval_ptr_dtor(&ctype); -+ } -+ -+ /* content disposition */ -+ { -+ zval *cd = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("contentDisposition")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ if (Z_STRLEN_P(cd)) { -+ http_send_header_ex("Content-Disposition", lenof("Content-Disposition"), Z_STRVAL_P(cd), Z_STRLEN_P(cd), 1, NULL); -+ } -+ zval_ptr_dtor(&cd); -+ } -+ -+ /* throttling */ -+ { -+ zval *bsize = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("bufferSize")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ zval *delay = http_zsep(IS_DOUBLE, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("throttleDelay")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ HTTP_G->send.buffer_size = Z_LVAL_P(bsize); -+ HTTP_G->send.throttle_delay = Z_DVAL_P(delay); -+ zval_ptr_dtor(&bsize); -+ zval_ptr_dtor(&delay); -+ } -+ -+ /* gzip */ -+ HTTP_G->send.deflate.response = i_zend_is_true(*zend_std_get_static_property(THIS_CE, ZEND_STRS("gzip")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC)); -+ -+ /* send */ -+ switch (Z_LVAL_P(*zend_std_get_static_property(THIS_CE, ZEND_STRS("mode")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))) { -+ case SEND_DATA: -+ { -+ zval *zdata = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("data")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ RETVAL_SUCCESS(http_send_data(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata))); -+ zval_ptr_dtor(&zdata); -+ return; -+ } -+ -+ case SEND_RSRC: -+ { -+ php_stream *the_real_stream; -+ zval *the_stream = http_zsep(IS_LONG, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("stream")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ the_stream->type = IS_RESOURCE; -+ php_stream_from_zval(the_real_stream, &the_stream); -+ RETVAL_SUCCESS(http_send_stream(the_real_stream)); -+ zval_ptr_dtor(&the_stream); -+ return; -+ } -+ -+ default: -+ { -+ zval *file = http_zsep(IS_STRING, *(zend_std_get_static_property(THIS_CE, ZEND_STRS("file")-1, 0 ZEND_LITERAL_NIL_CC TSRMLS_CC))); -+ RETVAL_SUCCESS(http_send_file(Z_STRVAL_P(file))); -+ zval_ptr_dtor(&file); -+ return; -+ } -+ } -+} -+/* }}} */ -+ -+/* {{{ proto static void HttpResponse::capture() -+ Capture script output. -+ */ -+PHP_METHOD(HttpResponse, capture) -+{ -+ NO_ARGS; -+ -+ HTTP_CHECK_HEADERS_SENT(RETURN_FALSE); -+ -+ zend_update_static_property_long(THIS_CE, ZEND_STRS("catch")-1, 1 TSRMLS_CC); -+#ifdef PHP_OUTPUT_NEWAPI -+ php_output_discard_all(TSRMLS_C); -+ php_output_start_default(TSRMLS_C); -+#else -+ php_end_ob_buffers(0 TSRMLS_CC); -+ php_start_ob_buffer(NULL, 0, 0 TSRMLS_CC); -+#endif -+ -+ /* register shutdown function */ -+ { -+ zval func, retval, arg, *argp[1]; -+ -+ INIT_PZVAL(&arg); -+ INIT_PZVAL(&func); -+ INIT_PZVAL(&retval); -+ ZVAL_STRINGL(&func, "register_shutdown_function", lenof("register_shutdown_function"), 0); -+ -+ array_init(&arg); -+ add_next_index_stringl(&arg, "HttpResponse", lenof("HttpResponse"), 1); -+ add_next_index_stringl(&arg, "send", lenof("send"), 1); -+ argp[0] = &arg; -+ call_user_function(EG(function_table), NULL, &func, &retval, 1, argp TSRMLS_CC); -+ zval_dtor(&arg); -+ } -+} -+/* }}} */ -+ -+#endif /* ZEND_ENGINE_2 && !WONKY */ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_send_api.c -@@ -0,0 +1,611 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_send_api.c 312028 2011-06-10 22:03:12Z felipe $ */ -+ -+#define HTTP_WANT_SAPI -+#define HTTP_WANT_ZLIB -+#define HTTP_WANT_MAGIC -+#include "php_http.h" -+ -+#include "php_streams.h" -+ -+#include "php_http_api.h" -+#include "php_http_cache_api.h" -+#include "php_http_date_api.h" -+#include "php_http_encoding_api.h" -+#include "php_http_headers_api.h" -+#include "php_http_send_api.h" -+ -+/* {{{ http_flush() */ -+#define http_flush(d, l) _http_flush(NULL, (d), (l) TSRMLS_CC) -+static inline void _http_flush(void *nothing, const char *data, size_t data_len TSRMLS_DC) -+{ -+ PHPWRITE(data, data_len); -+ /* we really only need to flush when throttling is enabled, -+ because we push the data as fast as possible anyway if not */ -+ if (HTTP_G->send.throttle_delay >= HTTP_DIFFSEC) { -+#if defined(PHP_VERSION_ID) && (PHP_VERSION_ID >= 50399) -+ php_output_end_all(TSRMLS_C); -+#else -+ if (OG(ob_nesting_level)) { -+ php_end_ob_buffer(1, 1 TSRMLS_CC); -+ } -+ if (!OG(implicit_flush)) { -+ sapi_flush(TSRMLS_C); -+ } -+#endif -+ http_sleep(HTTP_G->send.throttle_delay); -+ } -+} -+/* }}} */ -+ -+/* {{{ http_send_response_start */ -+#define http_send_response_start(b, cl) _http_send_response_start((b), (cl) TSRMLS_CC) -+static inline void _http_send_response_start(void **buffer, size_t content_length TSRMLS_DC) -+{ -+ int encoding; -+ -+ if ((encoding = http_encoding_response_start(content_length, 0))) { -+#ifdef HTTP_HAVE_ZLIB -+ *((http_encoding_stream **) buffer) = http_encoding_deflate_stream_init(NULL, -+ (encoding == HTTP_ENCODING_GZIP) ? -+ HTTP_DEFLATE_TYPE_GZIP : HTTP_DEFLATE_TYPE_ZLIB); -+#endif -+ } -+ /* flush headers */ -+ sapi_flush(TSRMLS_C); -+} -+/* }}} */ -+ -+/* {{{ http_send_response_data_plain */ -+#define http_send_response_data_plain(b, d, dl) _http_send_response_data_plain((b), (d), (dl) TSRMLS_CC) -+static inline void _http_send_response_data_plain(void **buffer, const char *data, size_t data_len TSRMLS_DC) -+{ -+ if (HTTP_G->send.deflate.response && HTTP_G->send.deflate.encoding) { -+#ifdef HTTP_HAVE_ZLIB -+ char *encoded; -+ size_t encoded_len; -+ http_encoding_stream *s = *((http_encoding_stream **) buffer); -+ -+ http_encoding_deflate_stream_update(s, data, data_len, &encoded, &encoded_len); -+ if (HTTP_G->send.buffer_size) { -+ phpstr_chunked_output((phpstr **) &s->storage, encoded, encoded_len, HTTP_G->send.buffer_size, _http_flush, NULL TSRMLS_CC); -+ } else { -+ http_flush(encoded, encoded_len); -+ } -+ efree(encoded); -+#else -+ http_error(HE_ERROR, HTTP_E_RESPONSE, "Attempt to send GZIP response despite being able to do so; please report this bug"); -+#endif -+ } else if (HTTP_G->send.buffer_size) { -+ phpstr_chunked_output((phpstr **) buffer, data, data_len, HTTP_G->send.buffer_size, _http_flush, NULL TSRMLS_CC); -+ } else { -+ http_flush(data, data_len); -+ } -+} -+/* }}} */ -+ -+/* {{{ http_send_response_data_fetch */ -+#define http_send_response_data_fetch(b, d, l, m, s, e) _http_send_response_data_fetch((b), (d), (l), (m), (s), (e) TSRMLS_CC) -+static inline void _http_send_response_data_fetch(void **buffer, const void *data, size_t data_len, http_send_mode mode, size_t begin, size_t end TSRMLS_DC) -+{ -+ long bsz, got, len = end - begin; -+ -+ if (!(bsz = HTTP_G->send.buffer_size)) { -+ bsz = HTTP_SENDBUF_SIZE; -+ } -+ -+ switch (mode) { -+ case SEND_RSRC: { -+ php_stream *s = (php_stream *) data; -+ if (SUCCESS == php_stream_seek(s, begin, SEEK_SET)) { -+ char *buf = emalloc(bsz); -+ -+ while (len > 0) { -+ got = php_stream_read(s, buf, MIN(len, bsz)); -+ http_send_response_data_plain(buffer, buf, got); -+ len -= got; -+ } -+ -+ efree(buf); -+ } -+ break; -+ } -+ case SEND_DATA: { -+ const char *buf = ((const char *) data) + begin; -+ while (len > 0) { -+ got = MIN(len, bsz); -+ http_send_response_data_plain(buffer, buf, got); -+ len -= got; -+ buf += got; -+ } -+ break; -+ } -+ EMPTY_SWITCH_DEFAULT_CASE(); -+ } -+} -+/* }}} */ -+ -+/* {{{ http_send_response_finish */ -+#define http_send_response_finish(b) _http_send_response_finish((b) TSRMLS_CC) -+static inline void _http_send_response_finish(void **buffer TSRMLS_DC) -+{ -+ if (HTTP_G->send.deflate.response && HTTP_G->send.deflate.encoding) { -+#ifdef HTTP_HAVE_ZLIB -+ char *encoded = NULL; -+ size_t encoded_len = 0; -+ http_encoding_stream *s = *((http_encoding_stream **) buffer); -+ -+ http_encoding_deflate_stream_finish(s, &encoded, &encoded_len); -+ if (HTTP_G->send.buffer_size) { -+ phpstr_chunked_output((phpstr **) &s->storage, encoded, encoded_len, 0, _http_flush, NULL TSRMLS_CC); -+ } else { -+ http_flush(encoded, encoded_len); -+ } -+ http_encoding_deflate_stream_free(&s); -+ STR_FREE(encoded); -+#else -+ http_error(HE_ERROR, HTTP_E_RESPONSE, "Attempt to send GZIP response despite being able to do so; please report this bug"); -+#endif -+ } else if (HTTP_G->send.buffer_size) { -+ phpstr_chunked_output((phpstr **) buffer, NULL, 0, 0, _http_flush, NULL TSRMLS_CC); -+ } -+} -+/* }}} */ -+ -+/* {{{ */ -+PHP_MINIT_FUNCTION(http_send) -+{ -+ HTTP_LONG_CONSTANT("HTTP_REDIRECT", HTTP_REDIRECT); -+ HTTP_LONG_CONSTANT("HTTP_REDIRECT_PERM", HTTP_REDIRECT_PERM); -+ HTTP_LONG_CONSTANT("HTTP_REDIRECT_FOUND", HTTP_REDIRECT_FOUND); -+ HTTP_LONG_CONSTANT("HTTP_REDIRECT_POST", HTTP_REDIRECT_POST); -+ HTTP_LONG_CONSTANT("HTTP_REDIRECT_PROXY", HTTP_REDIRECT_PROXY); -+ HTTP_LONG_CONSTANT("HTTP_REDIRECT_TEMP", HTTP_REDIRECT_TEMP); -+ -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ http_find_header */ -+typedef struct { -+ const char *h; -+ size_t l; -+} http_response_header_t; -+ -+static int http_find_header(void *data, void *arg) -+{ -+ http_response_header_t *h = arg; -+ sapi_header_struct *s = data; -+ -+ return (!strncasecmp(s->header, h->h, h->l)) && s->header[h->l] == ':'; -+} -+/* }}} */ -+ -+/* {{{ void http_hide_header(char *) */ -+PHP_HTTP_API void _http_hide_header_ex(const char *name, size_t name_len TSRMLS_DC) -+{ -+ http_response_header_t h = {name, name_len}; -+ zend_llist_del_element(&SG(sapi_headers).headers, (void *) &h, http_find_header); -+} -+/* }}} */ -+ -+/* {{{ void http_send_header_zval(char*, zval **, zend_bool) */ -+PHP_HTTP_API void _http_send_header_zval_ex(const char *name, size_t name_len, zval **val, zend_bool replace TSRMLS_DC) -+{ -+ if (!val || !*val || Z_TYPE_PP(val) == IS_NULL || (Z_TYPE_PP(val) == IS_STRING && !Z_STRLEN_PP(val))) { -+ http_hide_header_ex(name, name_len); -+ } else if (Z_TYPE_PP(val) == IS_ARRAY || Z_TYPE_PP(val) == IS_OBJECT) { -+ zend_bool first = replace; -+ zval **data_ptr; -+ HashPosition pos; -+ -+ FOREACH_HASH_VAL(pos, HASH_OF(*val), data_ptr) { -+ zval *data = http_zsep(IS_STRING, *data_ptr); -+ -+ http_send_header_ex(name, name_len, Z_STRVAL_P(data), Z_STRLEN_P(data), first, NULL); -+ zval_ptr_dtor(&data); -+ first = 0; -+ } -+ } else { -+ zval *data = http_zsep(IS_STRING, *val); -+ -+ http_send_header_ex(name, name_len, Z_STRVAL_P(data), Z_STRLEN_P(data), replace, NULL); -+ zval_ptr_dtor(&data); -+ } -+} -+/* }}} */ -+ -+/* {{{ STATUS http_send_header(char *, char *, zend_bool) */ -+PHP_HTTP_API STATUS _http_send_header_ex(const char *name, size_t name_len, const char *value, size_t value_len, zend_bool replace, char **sent_header TSRMLS_DC) -+{ -+ STATUS ret; -+ -+ if (value && value_len) { -+ size_t header_len = sizeof(": ") + name_len + value_len + 1; -+ char *header = emalloc(header_len + 1); -+ -+ header[header_len] = '\0'; -+ header_len = snprintf(header, header_len, "%s: %s", name, value); -+ ret = http_send_header_string_ex(header, header_len, replace); -+ if (sent_header) { -+ *sent_header = header; -+ } else { -+ efree(header); -+ } -+ } else { -+ http_hide_header_ex(name, name_len); -+ ret = SUCCESS; -+ } -+ return ret; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_send_status_header(int, char *) */ -+PHP_HTTP_API STATUS _http_send_status_header_ex(int status, const char *header, size_t header_len, zend_bool replace TSRMLS_DC) -+{ -+ STATUS ret; -+ sapi_header_line h = {(char *) header, header_len, status}; -+ if (SUCCESS != (ret = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD, &h TSRMLS_CC))) { -+ http_error_ex(HE_WARNING, HTTP_E_HEADER, "Could not send header: %s (%d)", header, status); -+ } -+ return ret; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_send_last_modified(int) */ -+PHP_HTTP_API STATUS _http_send_last_modified_ex(time_t t, char **sent_header TSRMLS_DC) -+{ -+ STATUS ret; -+ char *date = http_date(t); -+ -+ if (!date) { -+ return FAILURE; -+ } -+ -+ ret = http_send_header_ex("Last-Modified", lenof("Last-Modified"), date, strlen(date), 1, sent_header); -+ efree(date); -+ -+ /* remember */ -+ HTTP_G->send.last_modified = t; -+ -+ return ret; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_send_etag(char *, size_t) */ -+PHP_HTTP_API STATUS _http_send_etag_ex(const char *etag, size_t etag_len, char **sent_header TSRMLS_DC) -+{ -+ STATUS status; -+ char *etag_header; -+ size_t etag_header_len; -+ -+ if (!etag_len){ -+ http_error_ex(HE_WARNING, HTTP_E_HEADER, "Attempt to send empty ETag (previous: %s)\n", HTTP_G->send.unquoted_etag); -+ return FAILURE; -+ } -+ -+ etag_header_len = spprintf(&etag_header, 0, "ETag: \"%s\"", etag); -+ status = http_send_header_string_ex(etag_header, etag_header_len, 1); -+ -+ /* remember */ -+ STR_SET(HTTP_G->send.unquoted_etag, estrndup(etag, etag_len)); -+ -+ if (sent_header) { -+ *sent_header = etag_header; -+ } else { -+ efree(etag_header); -+ } -+ -+ return status; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_send_content_type(char *, size_t) */ -+PHP_HTTP_API STATUS _http_send_content_type(const char *content_type, size_t ct_len TSRMLS_DC) -+{ -+ HTTP_CHECK_CONTENT_TYPE(content_type, return FAILURE); -+ -+ /* remember for multiple ranges */ -+ STR_FREE(HTTP_G->send.content_type); -+ HTTP_G->send.content_type = estrndup(content_type, ct_len); -+ -+ return http_send_header_ex("Content-Type", lenof("Content-Type"), content_type, ct_len, 1, NULL); -+} -+/* }}} */ -+ -+/* {{{ STATUS http_send_content_disposition(char *, size_t, zend_bool) */ -+PHP_HTTP_API STATUS _http_send_content_disposition(const char *filename, size_t f_len, zend_bool send_inline TSRMLS_DC) -+{ -+ STATUS status; -+ char *cd_header; -+ -+ if (send_inline) { -+ cd_header = ecalloc(1, sizeof("Content-Disposition: inline; filename=\"\"") + f_len); -+ sprintf(cd_header, "Content-Disposition: inline; filename=\"%s\"", filename); -+ } else { -+ cd_header = ecalloc(1, sizeof("Content-Disposition: attachment; filename=\"\"") + f_len); -+ sprintf(cd_header, "Content-Disposition: attachment; filename=\"%s\"", filename); -+ } -+ -+ status = http_send_header_string(cd_header); -+ efree(cd_header); -+ return status; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_send(void *, size_t, http_send_mode) */ -+PHP_HTTP_API STATUS _http_send_ex(const void *data_ptr, size_t data_size, http_send_mode data_mode, zend_bool no_cache TSRMLS_DC) -+{ -+ void *s = NULL; -+ HashTable ranges; -+ http_range_status range_status; -+ -+ if (!data_ptr) { -+ return FAILURE; -+ } -+ if (!data_size) { -+ return SUCCESS; -+ } -+ -+ /* enable partial dl and resume */ -+ http_send_header_string("Accept-Ranges: bytes"); -+ -+ zend_hash_init(&ranges, 0, NULL, ZVAL_PTR_DTOR, 0); -+ range_status = http_get_request_ranges(&ranges, data_size); -+ -+ switch (range_status) { -+ case RANGE_ERR: -+ { -+ zend_hash_destroy(&ranges); -+ http_send_status(416); -+ return FAILURE; -+ } -+ case RANGE_OK: -+ { -+ /* Range Request - only send ranges if entity hasn't changed */ -+ if ( http_got_server_var("HTTP_IF_RANGE") && -+ !http_match_etag("HTTP_IF_RANGE", HTTP_G->send.unquoted_etag) && -+ !http_match_last_modified("HTTP_IF_RANGE", HTTP_G->send.last_modified)) { -+ /* fallthrough to send full entity with 200 Ok */ -+ no_cache = 1; -+ } else if ( !http_match_etag_ex("HTTP_IF_MATCH", HTTP_G->send.unquoted_etag, 0) || -+ !http_match_last_modified_ex("HTTP_IF_UNMODIFIED_SINCE", HTTP_G->send.last_modified, 0) || -+ !http_match_last_modified_ex("HTTP_UNLESS_MODIFIED_SINCE", HTTP_G->send.last_modified, 0)) { -+ /* 412 Precondition failed */ -+ zend_hash_destroy(&ranges); -+ http_send_status(412); -+ return FAILURE; -+ } else if (zend_hash_num_elements(&ranges) == 1) { -+ /* single range */ -+ zval **range, **begin, **end; -+ -+ if ( SUCCESS != zend_hash_index_find(&ranges, 0, (void *) &range) || -+ SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(range), 0, (void *) &begin) || -+ SUCCESS != zend_hash_index_find(Z_ARRVAL_PP(range), 1, (void *) &end)) { -+ /* this should never happen */ -+ zend_hash_destroy(&ranges); -+ http_send_status(500); -+ return FAILURE; -+ } else { -+ phpstr header; -+ -+ phpstr_init(&header); -+ phpstr_appendf(&header, "Content-Range: bytes %ld-%ld/%zu", Z_LVAL_PP(begin), Z_LVAL_PP(end), data_size); -+ phpstr_fix(&header); -+ http_send_status_header_ex(206, PHPSTR_VAL(&header), PHPSTR_LEN(&header), 1); -+ phpstr_dtor(&header); -+ http_send_response_start(&s, Z_LVAL_PP(end)-Z_LVAL_PP(begin)+1); -+ http_send_response_data_fetch(&s, data_ptr, data_size, data_mode, Z_LVAL_PP(begin), Z_LVAL_PP(end) + 1); -+ http_send_response_finish(&s); -+ zend_hash_destroy(&ranges); -+ return SUCCESS; -+ } -+ } else { -+ /* multi range */ -+ HashPosition pos; -+ zval **range, **begin, **end; -+ const char *content_type = HTTP_G->send.content_type; -+ char boundary_str[32]; -+ size_t boundary_len; -+ phpstr header, preface; -+ -+ boundary_len = http_boundary(boundary_str, sizeof(boundary_str)); -+ phpstr_init(&header); -+ phpstr_appendf(&header, "Content-Type: multipart/byteranges; boundary=%s", boundary_str); -+ phpstr_fix(&header); -+ http_send_status_header_ex(206, PHPSTR_VAL(&header), PHPSTR_LEN(&header), 1); -+ phpstr_dtor(&header); -+ http_send_response_start(&s, 0); -+ -+ if (!content_type) { -+ content_type = "application/x-octetstream"; -+ } -+ -+ phpstr_init(&preface); -+ FOREACH_HASH_VAL(pos, &ranges, range) { -+ if ( SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(range), 0, (void *) &begin) && -+ SUCCESS == zend_hash_index_find(Z_ARRVAL_PP(range), 1, (void *) &end)) { -+ -+#define HTTP_RANGE_PREFACE \ -+ HTTP_CRLF "--%s" \ -+ HTTP_CRLF "Content-Type: %s" \ -+ HTTP_CRLF "Content-Range: bytes %ld-%ld/%zu" \ -+ HTTP_CRLF HTTP_CRLF -+ -+ phpstr_appendf(&preface, HTTP_RANGE_PREFACE, boundary_str, content_type, Z_LVAL_PP(begin), Z_LVAL_PP(end), data_size); -+ phpstr_fix(&preface); -+ http_send_response_data_plain(&s, PHPSTR_VAL(&preface), PHPSTR_LEN(&preface)); -+ phpstr_reset(&preface); -+ http_send_response_data_fetch(&s, data_ptr, data_size, data_mode, Z_LVAL_PP(begin), Z_LVAL_PP(end) + 1); -+ } -+ } -+ phpstr_dtor(&preface); -+ -+ http_send_response_data_plain(&s, HTTP_CRLF "--", lenof(HTTP_CRLF "--")); -+ http_send_response_data_plain(&s, boundary_str, boundary_len); -+ http_send_response_data_plain(&s, "--", lenof("--")); -+ -+ http_send_response_finish(&s); -+ zend_hash_destroy(&ranges); -+ return SUCCESS; -+ } -+ } -+ case RANGE_NO: -+ { -+ zend_hash_destroy(&ranges); -+ -+ /* send 304 Not Modified if etag matches - DON'T return on ETag generation failure */ -+ if (!no_cache && (http_interrupt_ob_etaghandler() || (HTTP_G->send.unquoted_etag != NULL))) { -+ char *etag = NULL; -+ -+ if (HTTP_G->send.unquoted_etag) { -+ etag = estrdup(HTTP_G->send.unquoted_etag); -+ } -+ -+ if (etag || (etag = http_etag(data_ptr, data_size, data_mode))) { -+ char *sent_header = NULL; -+ -+ http_send_etag_ex(etag, strlen(etag), &sent_header); -+ if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) { -+ return http_exit_ex(304, sent_header, NULL, 0); -+ } else { -+ STR_FREE(sent_header); -+ /* no caching for Last-Modified if ETags really don't match */ -+ no_cache = http_got_server_var("HTTP_IF_NONE_MATCH"); -+ } -+ efree(etag); -+ } -+ } -+ -+ /* send 304 Not Modified if last modified matches */ -+ if (!no_cache && HTTP_G->send.last_modified && http_match_last_modified("HTTP_IF_MODIFIED_SINCE", HTTP_G->send.last_modified)) { -+ char *sent_header = NULL; -+ http_send_last_modified_ex(HTTP_G->send.last_modified, &sent_header); -+ return http_exit_ex(304, sent_header, NULL, 0); -+ } -+ -+ /* send full response */ -+ http_send_response_start(&s, data_size); -+ http_send_response_data_fetch(&s, data_ptr, data_size, data_mode, 0, data_size); -+ http_send_response_finish(&s); -+ return SUCCESS; -+ } -+ } -+ return FAILURE; -+} -+/* }}} */ -+ -+/* {{{ STATUS http_send_stream(php_stream *) */ -+PHP_HTTP_API STATUS _http_send_stream_ex(php_stream *file, zend_bool close_stream, zend_bool no_cache TSRMLS_DC) -+{ -+ STATUS status; -+ php_stream_statbuf ssb; -+ int orig_flags; -+ -+ if ((!file) || php_stream_stat(file, &ssb)) { -+ char *defct = sapi_get_default_content_type(TSRMLS_C); -+ -+ http_hide_header("Content-Disposition"); -+ http_send_content_type(defct, strlen(defct)); -+ http_error(HE_WARNING, HTTP_E_RESPONSE, "File not found; stat failed"); -+ STR_FREE(defct); -+ -+ if (HTTP_G->send.not_found_404) { -+ http_exit_ex(404, NULL, estrdup("File not found\n"), 0); -+ } -+ return FAILURE; -+ } -+ -+ orig_flags = file->flags; -+ file->flags |= PHP_STREAM_FLAG_NO_BUFFER; -+ status = http_send_ex(file, ssb.sb.st_size, SEND_RSRC, no_cache); -+ file->flags = orig_flags; -+ -+ if (close_stream) { -+ php_stream_close(file); -+ } -+ -+ return status; -+} -+/* }}} */ -+ -+/* {{{ char *http_guess_content_type(char *magic_file, long magic_mode, void *data, size_t size, http_send_mode mode) */ -+PHP_HTTP_API char *_http_guess_content_type(const char *magicfile, long magicmode, void *data_ptr, size_t data_len, http_send_mode data_mode TSRMLS_DC) -+{ -+ char *ct = NULL; -+ -+#ifdef HTTP_HAVE_MAGIC -+ struct magic_set *magic = NULL; -+ -+ HTTP_CHECK_OPEN_BASEDIR(magicfile, return NULL); -+ -+ if (!data_ptr) { -+ http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Supplied payload is empty"); -+ } else if (!(magic = magic_open(magicmode &~ MAGIC_MIME))) { -+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid magic mode: %ld", magicmode); -+ } else if (-1 == magic_load(magic, magicfile)) { -+ http_error_ex(HE_WARNING, HTTP_E_RUNTIME, "Failed to load magic database '%s' (%s)", magicfile, magic_error(magic)); -+ } else { -+ const char *ctype = NULL; -+ -+ magic_setflags(magic, magicmode); -+ -+ switch (data_mode) { -+ case SEND_RSRC: -+ { -+ char *buffer; -+ size_t b_len; -+ -+ b_len = php_stream_copy_to_mem(data_ptr, &buffer, 65536, 0); -+ ctype = magic_buffer(magic, buffer, b_len); -+ efree(buffer); -+ break; -+ } -+ -+ case SEND_DATA: -+ ctype = magic_buffer(magic, data_ptr, data_len); -+ break; -+ -+ default: -+ HTTP_CHECK_OPEN_BASEDIR(data_ptr, magic_close(magic); return NULL); -+ ctype = magic_file(magic, data_ptr); -+ break; -+ } -+ -+ if (ctype) { -+ ct = estrdup(ctype); -+ } else { -+ http_error_ex(HE_WARNING, HTTP_E_RUNTIME, "Failed to guess Content-Type: %s", magic_error(magic)); -+ } -+ } -+ if (magic) { -+ magic_close(magic); -+ } -+#else -+ http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot guess Content-Type; libmagic not available"); -+#endif -+ -+ return ct; -+} -+/* }}} */ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim600: sw=4 ts=4 fdm=marker -+ * vim<600: sw=4 ts=4 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_url_api.c -@@ -0,0 +1,482 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_url_api.c 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#define HTTP_WANT_SAPI -+#define HTTP_WANT_NETDB -+#include "php_http.h" -+ -+#include "zend_ini.h" -+#include "php_output.h" -+#include "ext/standard/php_string.h" -+ -+#include "php_http_api.h" -+#include "php_http_querystring_api.h" -+#include "php_http_url_api.h" -+ -+static inline char *localhostname(void) -+{ -+ char hostname[1024] = {0}; -+ -+#ifdef PHP_WIN32 -+ if (SUCCESS == gethostname(hostname, lenof(hostname))) { -+ return estrdup(hostname); -+ } -+#elif defined(HAVE_GETHOSTNAME) -+ if (SUCCESS == gethostname(hostname, lenof(hostname))) { -+# if defined(HAVE_GETDOMAINNAME) -+ size_t hlen = strlen(hostname); -+ if (hlen <= lenof(hostname) - lenof("(none)")) { -+ hostname[hlen++] = '.'; -+ if (SUCCESS == getdomainname(&hostname[hlen], lenof(hostname) - hlen)) { -+ if (!strcmp(&hostname[hlen], "(none)")) { -+ hostname[hlen - 1] = '\0'; -+ } -+ return estrdup(hostname); -+ } -+ } -+# endif -+ if (strcmp(hostname, "(none)")) { -+ return estrdup(hostname); -+ } -+ } -+#endif -+ return estrndup("localhost", lenof("localhost")); -+} -+ -+PHP_MINIT_FUNCTION(http_url) -+{ -+ HTTP_LONG_CONSTANT("HTTP_URL_REPLACE", HTTP_URL_REPLACE); -+ HTTP_LONG_CONSTANT("HTTP_URL_JOIN_PATH", HTTP_URL_JOIN_PATH); -+ HTTP_LONG_CONSTANT("HTTP_URL_JOIN_QUERY", HTTP_URL_JOIN_QUERY); -+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_USER", HTTP_URL_STRIP_USER); -+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PASS", HTTP_URL_STRIP_PASS); -+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_AUTH", HTTP_URL_STRIP_AUTH); -+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PORT", HTTP_URL_STRIP_PORT); -+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PATH", HTTP_URL_STRIP_PATH); -+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_QUERY", HTTP_URL_STRIP_QUERY); -+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_FRAGMENT", HTTP_URL_STRIP_FRAGMENT); -+ HTTP_LONG_CONSTANT("HTTP_URL_STRIP_ALL", HTTP_URL_STRIP_ALL); -+ HTTP_LONG_CONSTANT("HTTP_URL_FROM_ENV", HTTP_URL_FROM_ENV); -+ return SUCCESS; -+} -+ -+PHP_HTTP_API char *_http_absolute_url_ex(const char *url, int flags TSRMLS_DC) -+{ -+ char *abs = NULL; -+ php_url *purl = NULL; -+ -+ if (url) { -+ purl = php_url_parse(abs = estrdup(url)); -+ STR_SET(abs, NULL); -+ if (!purl) { -+ http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", url); -+ return NULL; -+ } -+ } -+ -+ http_build_url(flags, purl, NULL, NULL, &abs, NULL); -+ -+ if (purl) { -+ php_url_free(purl); -+ } -+ -+ return abs; -+} -+ -+/* {{{ void http_build_url(int flags, const php_url *, const php_url *, php_url **, char **, size_t *) */ -+PHP_HTTP_API void _http_build_url(int flags, const php_url *old_url, const php_url *new_url, php_url **url_ptr, char **url_str, size_t *url_len TSRMLS_DC) -+{ -+#if defined(HAVE_GETSERVBYPORT) || defined(HAVE_GETSERVBYNAME) -+ struct servent *se; -+#endif -+ php_url *url = ecalloc(1, sizeof(php_url)); -+ -+#define __URLSET(u,n) \ -+ ((u)&&(u)->n) -+#define __URLCPY(n) \ -+ url->n = __URLSET(new_url,n) ? estrdup(new_url->n) : (__URLSET(old_url,n) ? estrdup(old_url->n) : NULL) -+ -+ if (!(flags & HTTP_URL_STRIP_PORT)) { -+ url->port = __URLSET(new_url, port) ? new_url->port : ((old_url) ? old_url->port : 0); -+ } -+ if (!(flags & HTTP_URL_STRIP_USER)) { -+ __URLCPY(user); -+ } -+ if (!(flags & HTTP_URL_STRIP_PASS)) { -+ __URLCPY(pass); -+ } -+ -+ __URLCPY(scheme); -+ __URLCPY(host); -+ -+ if (!(flags & HTTP_URL_STRIP_PATH)) { -+ if ((flags & HTTP_URL_JOIN_PATH) && __URLSET(old_url, path) && __URLSET(new_url, path) && *new_url->path != '/') { -+ size_t old_path_len = strlen(old_url->path), new_path_len = strlen(new_url->path); -+ -+ url->path = ecalloc(1, old_path_len + new_path_len + 1 + 1); -+ -+ strcat(url->path, old_url->path); -+ if (url->path[old_path_len - 1] != '/') { -+ php_dirname(url->path, old_path_len); -+ strcat(url->path, "/"); -+ } -+ strcat(url->path, new_url->path); -+ } else { -+ __URLCPY(path); -+ } -+ } -+ if (!(flags & HTTP_URL_STRIP_QUERY)) { -+ if ((flags & HTTP_URL_JOIN_QUERY) && __URLSET(new_url, query) && __URLSET(old_url, query)) { -+ zval qarr, qstr; -+ -+ INIT_PZVAL(&qstr); -+ INIT_PZVAL(&qarr); -+ array_init(&qarr); -+ -+ ZVAL_STRING(&qstr, old_url->query, 0); -+ http_querystring_modify(&qarr, &qstr); -+ ZVAL_STRING(&qstr, new_url->query, 0); -+ http_querystring_modify(&qarr, &qstr); -+ -+ ZVAL_NULL(&qstr); -+ http_querystring_update(&qarr, &qstr); -+ url->query = Z_STRVAL(qstr); -+ zval_dtor(&qarr); -+ } else { -+ __URLCPY(query); -+ } -+ } -+ if (!(flags & HTTP_URL_STRIP_FRAGMENT)) { -+ __URLCPY(fragment); -+ } -+ -+ if (!url->scheme) { -+ if (flags & HTTP_URL_FROM_ENV) { -+ zval *https = http_get_server_var("HTTPS", 1); -+ if (https && !strcasecmp(Z_STRVAL_P(https), "ON")) { -+ url->scheme = estrndup("https", lenof("https")); -+ } else switch (url->port) { -+ case 443: -+ url->scheme = estrndup("https", lenof("https")); -+ break; -+ -+#ifndef HAVE_GETSERVBYPORT -+ default: -+#endif -+ case 80: -+ case 0: -+ url->scheme = estrndup("http", lenof("http")); -+ break; -+ -+#ifdef HAVE_GETSERVBYPORT -+ default: -+ if ((se = getservbyport(htons(url->port), "tcp")) && se->s_name) { -+ url->scheme = estrdup(se->s_name); -+ } else { -+ url->scheme = estrndup("http", lenof("http")); -+ } -+ break; -+#endif -+ } -+ } else { -+ url->scheme = estrndup("http", lenof("http")); -+ } -+ } -+ -+ if (!url->host) { -+ if (flags & HTTP_URL_FROM_ENV) { -+ zval *zhost; -+ -+ if ((((zhost = http_get_server_var("HTTP_HOST", 1)) || -+ (zhost = http_get_server_var("SERVER_NAME", 1)))) && Z_STRLEN_P(zhost)) { -+ url->host = estrndup(Z_STRVAL_P(zhost), Z_STRLEN_P(zhost)); -+ } else { -+ url->host = localhostname(); -+ } -+ } else { -+ url->host = estrndup("localhost", lenof("localhost")); -+ } -+ } -+ -+ if (!url->path) { -+ if ((flags & HTTP_URL_FROM_ENV) && SG(request_info).request_uri && SG(request_info).request_uri[0]) { -+ const char *q = strchr(SG(request_info).request_uri, '?'); -+ -+ if (q) { -+ url->path = estrndup(SG(request_info).request_uri, q - SG(request_info).request_uri); -+ } else { -+ url->path = estrdup(SG(request_info).request_uri); -+ } -+ } else { -+ url->path = estrndup("/", 1); -+ } -+ } else if (url->path[0] != '/') { -+ if ((flags & HTTP_URL_FROM_ENV) && SG(request_info).request_uri && SG(request_info).request_uri[0]) { -+ size_t ulen = strlen(SG(request_info).request_uri); -+ size_t plen = strlen(url->path); -+ char *path; -+ -+ if (SG(request_info).request_uri[ulen-1] != '/') { -+ for (--ulen; ulen && SG(request_info).request_uri[ulen - 1] != '/'; --ulen); -+ } -+ -+ path = emalloc(ulen + plen + 1); -+ memcpy(path, SG(request_info).request_uri, ulen); -+ memcpy(path + ulen, url->path, plen); -+ path[ulen + plen] = '\0'; -+ STR_SET(url->path, path); -+ } else { -+ size_t plen = strlen(url->path); -+ char *path = emalloc(plen + 1 + 1); -+ -+ path[0] = '/'; -+ memcpy(&path[1], url->path, plen + 1); -+ STR_SET(url->path, path); -+ } -+ } -+ /* replace directory references if path is not a single slash */ -+ if (url->path[0] && (url->path[0] != '/' || url->path[1])) { -+ char *ptr, *end = url->path + strlen(url->path) + 1; -+ -+ for (ptr = strstr(url->path, "/."); ptr; ptr = strstr(ptr, "/.")) { -+ switch (ptr[2]) { -+ case '\0': -+ ptr[1] = '\0'; -+ break; -+ -+ case '/': -+ memmove(&ptr[1], &ptr[3], end - &ptr[3]); -+ break; -+ -+ case '.': -+ if (ptr[3] == '/') { -+ char *pos = &ptr[4]; -+ while (ptr != url->path) { -+ if (*--ptr == '/') { -+ break; -+ } -+ } -+ memmove(&ptr[1], pos, end - pos); -+ break; -+ } else if (!ptr[3]) { -+ /* .. at the end */ -+ ptr[1] = '\0'; -+ } -+ /* fallthrough */ -+ -+ default: -+ /* something else */ -+ ++ptr; -+ break; -+ } -+ } -+ } -+ -+ if (url->port) { -+ if ( ((url->port == 80) && !strcmp(url->scheme, "http")) -+ || ((url->port ==443) && !strcmp(url->scheme, "https")) -+#ifdef HAVE_GETSERVBYNAME -+ || ((se = getservbyname(url->scheme, "tcp")) && se->s_port && -+ (url->port == ntohs(se->s_port))) -+#endif -+ ) { -+ url->port = 0; -+ } -+ } -+ -+ if (url_str) { -+ size_t len; -+ -+ *url_str = emalloc(HTTP_URL_MAXLEN + 1); -+ -+ **url_str = '\0'; -+ strlcat(*url_str, url->scheme, HTTP_URL_MAXLEN); -+ strlcat(*url_str, "://", HTTP_URL_MAXLEN); -+ -+ if (url->user && *url->user) { -+ strlcat(*url_str, url->user, HTTP_URL_MAXLEN); -+ if (url->pass && *url->pass) { -+ strlcat(*url_str, ":", HTTP_URL_MAXLEN); -+ strlcat(*url_str, url->pass, HTTP_URL_MAXLEN); -+ } -+ strlcat(*url_str, "@", HTTP_URL_MAXLEN); -+ } -+ -+ strlcat(*url_str, url->host, HTTP_URL_MAXLEN); -+ -+ if (url->port) { -+ char port_str[8]; -+ -+ snprintf(port_str, sizeof(port_str), "%d", (int) url->port); -+ strlcat(*url_str, ":", HTTP_URL_MAXLEN); -+ strlcat(*url_str, port_str, HTTP_URL_MAXLEN); -+ } -+ -+ strlcat(*url_str, url->path, HTTP_URL_MAXLEN); -+ -+ if (url->query && *url->query) { -+ strlcat(*url_str, "?", HTTP_URL_MAXLEN); -+ strlcat(*url_str, url->query, HTTP_URL_MAXLEN); -+ } -+ -+ if (url->fragment && *url->fragment) { -+ strlcat(*url_str, "#", HTTP_URL_MAXLEN); -+ strlcat(*url_str, url->fragment, HTTP_URL_MAXLEN); -+ } -+ -+ if (HTTP_URL_MAXLEN == (len = strlen(*url_str))) { -+ http_error(HE_NOTICE, HTTP_E_URL, "Length of URL exceeds HTTP_URL_MAXLEN"); -+ } -+ if (url_len) { -+ *url_len = len; -+ } -+ } -+ -+ if (url_ptr) { -+ *url_ptr = url; -+ } else { -+ php_url_free(url); -+ } -+} -+/* }}} */ -+ -+/* {{{ STATUS http_urlencode_hash_ex(HashTable *, zend_bool, char *, size_t, char **, size_t *) */ -+PHP_HTTP_API STATUS _http_urlencode_hash_ex(HashTable *hash, zend_bool override_argsep, -+ char *pre_encoded_data, size_t pre_encoded_len, -+ char **encoded_data, size_t *encoded_len TSRMLS_DC) -+{ -+ char *arg_sep; -+ size_t arg_sep_len; -+ phpstr *qstr = phpstr_new(); -+ -+ if (override_argsep || !(arg_sep_len = strlen(arg_sep = INI_STR("arg_separator.output")))) { -+ arg_sep = HTTP_URL_ARGSEP; -+ arg_sep_len = lenof(HTTP_URL_ARGSEP); -+ } -+ -+ if (pre_encoded_len && pre_encoded_data) { -+ phpstr_append(qstr, pre_encoded_data, pre_encoded_len); -+ } -+ -+ if (SUCCESS != http_urlencode_hash_recursive(hash, qstr, arg_sep, arg_sep_len, NULL, 0)) { -+ phpstr_free(&qstr); -+ return FAILURE; -+ } -+ -+ phpstr_data(qstr, encoded_data, encoded_len); -+ phpstr_free(&qstr); -+ -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* {{{ http_urlencode_hash_recursive */ -+PHP_HTTP_API STATUS _http_urlencode_hash_recursive(HashTable *ht, phpstr *str, const char *arg_sep, size_t arg_sep_len, const char *prefix, size_t prefix_len TSRMLS_DC) -+{ -+ HashKey key = initHashKey(0); -+ zval **data = NULL; -+ HashPosition pos; -+ -+ if (!ht || !str) { -+ http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid parameters"); -+ return FAILURE; -+ } -+ if (ht->nApplyCount > 0) { -+ return SUCCESS; -+ } -+ -+ FOREACH_HASH_KEYVAL(pos, ht, key, data) { -+ char *encoded_key; -+ int encoded_len; -+ phpstr new_prefix; -+ -+ if (!data || !*data) { -+ phpstr_dtor(str); -+ return FAILURE; -+ } -+ -+ if (key.type == HASH_KEY_IS_STRING) { -+ if (!*key.str) { -+ /* only public properties */ -+ continue; -+ } -+ if (key.len && key.str[key.len - 1] == '\0') { -+ --key.len; -+ } -+ encoded_key = php_url_encode(key.str, key.len, &encoded_len); -+ } else { -+ encoded_len = spprintf(&encoded_key, 0, "%ld", key.num); -+ } -+ -+ { -+ phpstr_init(&new_prefix); -+ if (prefix && prefix_len) { -+ phpstr_append(&new_prefix, prefix, prefix_len); -+ phpstr_appends(&new_prefix, "%5B"); -+ } -+ -+ phpstr_append(&new_prefix, encoded_key, encoded_len); -+ efree(encoded_key); -+ -+ if (prefix && prefix_len) { -+ phpstr_appends(&new_prefix, "%5D"); -+ } -+ phpstr_fix(&new_prefix); -+ } -+ -+ if (Z_TYPE_PP(data) == IS_ARRAY || Z_TYPE_PP(data) == IS_OBJECT) { -+ STATUS status; -+ ++ht->nApplyCount; -+ status = http_urlencode_hash_recursive(HASH_OF(*data), str, arg_sep, arg_sep_len, PHPSTR_VAL(&new_prefix), PHPSTR_LEN(&new_prefix)); -+ --ht->nApplyCount; -+ if (SUCCESS != status) { -+ phpstr_dtor(&new_prefix); -+ phpstr_dtor(str); -+ return FAILURE; -+ } -+ } else { -+ zval *val = http_zsep(IS_STRING, *data); -+ -+ if (PHPSTR_LEN(str)) { -+ phpstr_append(str, arg_sep, arg_sep_len); -+ } -+ phpstr_append(str, PHPSTR_VAL(&new_prefix), PHPSTR_LEN(&new_prefix)); -+ phpstr_appends(str, "="); -+ -+ if (Z_STRLEN_P(val) && Z_STRVAL_P(val)) { -+ char *encoded_val; -+ int encoded_len; -+ -+ encoded_val = php_url_encode(Z_STRVAL_P(val), Z_STRLEN_P(val), &encoded_len); -+ phpstr_append(str, encoded_val, encoded_len); -+ efree(encoded_val); -+ } -+ -+ zval_ptr_dtor(&val); -+ } -+ phpstr_dtor(&new_prefix); -+ } -+ return SUCCESS; -+} -+/* }}} */ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/http_util_object.c -@@ -0,0 +1,158 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: http_util_object.c 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#include "php_http.h" -+ -+#ifdef ZEND_ENGINE_2 -+ -+#include "ext/standard/php_http.h" -+ -+#include "php_http_util_object.h" -+ -+#define HTTP_BEGIN_ARGS(method, req_args) HTTP_BEGIN_ARGS_EX(HttpUtil, method, 0, req_args) -+#define HTTP_EMPTY_ARGS(method) HTTP_EMPTY_ARGS_EX(HttpUtil, method, 0) -+ -+#define HTTP_UTIL_ALIAS(method, func) HTTP_STATIC_ME_ALIAS(method, func, HTTP_ARGS(HttpUtil, method)) -+ -+HTTP_BEGIN_ARGS(date, 0) -+ HTTP_ARG_VAL(timestamp, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(buildStr, 1) -+ HTTP_ARG_VAL(query, 0) -+ HTTP_ARG_VAL(prefix, 0) -+ HTTP_ARG_VAL(arg_sep, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(buildUrl, 1) -+ HTTP_ARG_VAL(url, 0) -+ HTTP_ARG_VAL(parts, 0) -+ HTTP_ARG_VAL(flags, 0) -+ HTTP_ARG_VAL(composed, 1) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(negotiateLanguage, 1) -+ HTTP_ARG_VAL(supported, 0) -+ HTTP_ARG_VAL(result, 1) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(negotiateCharset, 1) -+ HTTP_ARG_VAL(supported, 0) -+ HTTP_ARG_VAL(result, 1) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(negotiateContentType, 1) -+ HTTP_ARG_VAL(supported, 0) -+ HTTP_ARG_VAL(result, 1) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(matchModified, 1) -+ HTTP_ARG_VAL(last_modified, 0) -+ HTTP_ARG_VAL(for_range, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(matchEtag, 1) -+ HTTP_ARG_VAL(plain_etag, 0) -+ HTTP_ARG_VAL(for_range, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(matchRequestHeader, 2) -+ HTTP_ARG_VAL(header_name, 0) -+ HTTP_ARG_VAL(header_value, 0) -+ HTTP_ARG_VAL(case_sensitive, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(parseMessage, 1) -+ HTTP_ARG_VAL(message_string, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(parseHeaders, 1) -+ HTTP_ARG_VAL(headers_string, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(parseCookie, 1) -+ HTTP_ARG_VAL(cookie_string, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(buildCookie, 1) -+ HTTP_ARG_VAL(cookie_array, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(parseParams, 1) -+ HTTP_ARG_VAL(param_string, 0) -+ HTTP_ARG_VAL(flags, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(chunkedDecode, 1) -+ HTTP_ARG_VAL(encoded_string, 0) -+HTTP_END_ARGS; -+ -+#ifdef HTTP_HAVE_ZLIB -+HTTP_BEGIN_ARGS(deflate, 1) -+ HTTP_ARG_VAL(plain, 0) -+ HTTP_ARG_VAL(flags, 0) -+HTTP_END_ARGS; -+ -+HTTP_BEGIN_ARGS(inflate, 1) -+ HTTP_ARG_VAL(encoded, 0) -+HTTP_END_ARGS; -+#endif -+ -+HTTP_BEGIN_ARGS(support, 0) -+ HTTP_ARG_VAL(feature, 0) -+HTTP_END_ARGS; -+ -+zend_class_entry *http_util_object_ce; -+zend_function_entry http_util_object_fe[] = { -+ HTTP_UTIL_ALIAS(date, http_date) -+ HTTP_UTIL_ALIAS(buildUrl, http_build_url) -+ HTTP_UTIL_ALIAS(buildStr, http_build_str) -+ HTTP_UTIL_ALIAS(negotiateLanguage, http_negotiate_language) -+ HTTP_UTIL_ALIAS(negotiateCharset, http_negotiate_charset) -+ HTTP_UTIL_ALIAS(negotiateContentType, http_negotiate_content_type) -+ HTTP_UTIL_ALIAS(matchModified, http_match_modified) -+ HTTP_UTIL_ALIAS(matchEtag, http_match_etag) -+ HTTP_UTIL_ALIAS(matchRequestHeader, http_match_request_header) -+ HTTP_UTIL_ALIAS(parseMessage, http_parse_message) -+ HTTP_UTIL_ALIAS(parseHeaders, http_parse_headers) -+ HTTP_UTIL_ALIAS(parseCookie, http_parse_cookie) -+ HTTP_UTIL_ALIAS(buildCookie, http_build_cookie) -+ HTTP_UTIL_ALIAS(parseParams, http_parse_params) -+ HTTP_UTIL_ALIAS(chunkedDecode, http_chunked_decode) -+#ifdef HTTP_HAVE_ZLIB -+ HTTP_UTIL_ALIAS(deflate, http_deflate) -+ HTTP_UTIL_ALIAS(inflate, http_inflate) -+#endif /* HTTP_HAVE_ZLIB */ -+ HTTP_UTIL_ALIAS(support, http_support) -+ -+ EMPTY_FUNCTION_ENTRY -+}; -+ -+PHP_MINIT_FUNCTION(http_util_object) -+{ -+ HTTP_REGISTER_CLASS(HttpUtil, http_util_object, NULL, 0); -+ return SUCCESS; -+} -+ -+#endif /* ZEND_ENGINE_2 */ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/lib/BigGet.php -@@ -0,0 +1,213 @@ -+ -+ * @license BSD, revised -+ * @version $Revision: 220502 $ -+ */ -+class BigGet extends HttpRequestPool -+{ -+ /** -+ * File split size -+ */ -+ const SIZE = 1048576; -+ -+ /** -+ * Parallel Request count -+ */ -+ const RMAX = 5; -+ -+ /** -+ * Whether to output debug messages -+ * -+ * @var bool -+ */ -+ public $dbg = false; -+ -+ /** -+ * URL -+ * -+ * @var string -+ */ -+ private $url; -+ -+ /** -+ * Temp file prefix -+ * -+ * @var string -+ */ -+ private $tmp; -+ -+ /** -+ * Size of requested resource -+ * -+ * @var int -+ */ -+ private $size; -+ -+ /** -+ * Whether the requests have been sent -+ * -+ * @var bool -+ */ -+ private $sent = false; -+ -+ /** -+ * Request counter -+ * -+ * @var int -+ */ -+ private $count = 0; -+ -+ /** -+ * Static constructor -+ * -+ * @param string $url -+ * @param string $tmp -+ * @return BigGet -+ * @throws Exception -+ */ -+ public static function url($url, $tmp = '/tmp') -+ { -+ $head = new HttpRequest($url, HttpRequest::METH_HEAD); -+ $headers = $head->send()->getHeaders(); -+ -+ if (200 != $head->getResponseCode()) { -+ throw new HttpException("Did not receive '200 Ok' from HEAD $url"); -+ } -+ if (!isset($headers['Accept-Ranges'])) { -+ throw new HttpException("Did not receive an Accept-Ranges header from HEAD $url"); -+ } -+ if (!isset($headers['Content-Length'])) { -+ throw new HttpException("Did not receive a Content-Length header from HEAD $url"); -+ } -+ -+ $bigget = new BigGet; -+ $bigget->url = $url; -+ $bigget->tmp = tempnam($tmp, 'BigGet.'); -+ $bigget->size = $headers['Content-Length']; -+ return $bigget; -+ } -+ -+ /** -+ * Save the resource to a file -+ * -+ * @param string $file -+ * @return bool -+ * @throws Exception -+ */ -+ public function saveTo($file) -+ { -+ $this->sent or $this->send(); -+ -+ if ($w = fopen($this->tmp, 'wb')) { -+ -+ $this->dbg && print "\nCopying temp files to $file ...\n"; -+ -+ foreach (glob($this->tmp .".????") as $tmp) { -+ -+ $this->dbg && print "\t$tmp\n"; -+ -+ if ($r = fopen($tmp, 'rb')) { -+ stream_copy_to_stream($r, $w); -+ fclose($r); -+ } -+ unlink($tmp); -+ } -+ fclose($w); -+ rename($this->tmp, $file); -+ -+ $this->dbg && print "\nDone.\n"; -+ -+ return true; -+ } -+ return false; -+ } -+ -+ /** -+ * Overrides HttpRequestPool::send() -+ * -+ * @return void -+ * @throws Exception -+ */ -+ public function send() -+ { -+ $this->sent = true; -+ -+ // use max RMAX simultanous requests with a req size of SIZE -+ while ($this->count < self::RMAX && -1 != $offset = $this->getRangeOffset()) { -+ $this->attachNew($offset); -+ } -+ -+ while ($this->socketPerform()) { -+ if (!$this->socketSelect()) { -+ throw new HttpSocketException; -+ } -+ } -+ } -+ -+ /** -+ * Overrides HttpRequestPool::socketPerform() -+ * -+ * @return bool -+ */ -+ protected function socketPerform() -+ { -+ $rs = parent::socketPerform(); -+ -+ foreach ($this->getFinishedRequests() as $r) { -+ $this->detach($r); -+ -+ if (206 != $rc = $r->getResponseCode()) { -+ throw new HttpException("Unexpected response code: $rc"); -+ } -+ -+ file_put_contents(sprintf("%s.%04d", $this->tmp, $r->id), $r->getResponseBody()); -+ -+ if (-1 != $offset = $this->getRangeOffset()) { -+ $this->attachNew($offset); -+ } -+ } -+ -+ return $rs; -+ } -+ -+ private function attachNew($offset) -+ { -+ $stop = min($this->count * self::SIZE + self::SIZE, $this->size) - 1; -+ -+ $this->dbg && print "Attaching new request to get range: $offset-$stop\n"; -+ -+ $req = new BigGetRequest( -+ $this->url, -+ HttpRequest::METH_GET, -+ array( -+ 'headers' => array( -+ 'Range' => "bytes=$offset-$stop" -+ ) -+ ) -+ ); -+ $this->attach($req); -+ $req->id = $this->count++; -+ } -+ -+ private function getRangeOffset() -+ { -+ return ($this->size >= $start = $this->count * self::SIZE) ? $start : -1; -+ } -+} -+ -+ -+/** -+ * BigGet request -+ * @ignore -+ */ -+class BigGetRequest extends HttpRequest -+{ -+ public $id; -+} -+ -+?> ---- /dev/null -+++ b/ext/http/lib/FeedAggregator.php -@@ -0,0 +1,187 @@ -+ -+ * @license BSD, revised -+ * @package pecl/http -+ * @version $Revision: 208774 $ -+ */ -+class FeedAggregator -+{ -+ /** -+ * Cache directory -+ * -+ * @var string -+ */ -+ public $directory; -+ -+ /** -+ * Feeds -+ * -+ * @var array -+ */ -+ protected $feeds = array(); -+ -+ /** -+ * Constructor -+ * -+ * @param string $directory -+ */ -+ public function __construct($directory = 'feeds') -+ { -+ $this->setDirectory($directory); -+ } -+ -+ /** -+ * Set cache directory -+ * -+ * @param string $directory -+ */ -+ public function setDirectory($directory) -+ { -+ $this->directory = $directory; -+ foreach (glob($this->directory .'/*.xml') as $feed) { -+ $this->feeds[basename($feed, '.xml')] = filemtime($feed); -+ } -+ } -+ -+ /** -+ * Strips all special chars -+ * -+ * @param string $url -+ * @return string -+ */ -+ public function url2name($url) -+ { -+ return preg_replace('/[^\w\.-]+/', '_', $url); -+ } -+ -+ /** -+ * Checks if $url is a known feed -+ * -+ * @param string $url -+ * @return bool -+ */ -+ public function hasFeed($url) -+ { -+ return isset($this->feeds[$this->url2name($url)]); -+ } -+ -+ /** -+ * Add an URL as feed -+ * -+ * @param string $url -+ * @return void -+ * @throws Exception -+ */ -+ public function addFeed($url) -+ { -+ $r = $this->setupRequest($url); -+ $r->send(); -+ $this->handleResponse($r); -+ } -+ -+ /** -+ * Add several URLs as feeds -+ * -+ * @param array $urls -+ * @return void -+ * @throws Exception -+ */ -+ public function addFeeds(array $urls) -+ { -+ $pool = new HttpRequestPool; -+ foreach ($urls as $url) { -+ $pool->attach($r = $this->setupRequest($url)); -+ } -+ $pool->send(); -+ -+ foreach ($pool as $request) { -+ $this->handleResponse($request); -+ } -+ } -+ -+ /** -+ * Load a feed (from cache) -+ * -+ * @param string $url -+ * @return string -+ * @throws Exception -+ */ -+ public function getFeed($url) -+ { -+ $this->addFeed($url); -+ return $this->loadFeed($this->url2name($url)); -+ } -+ -+ /** -+ * Load several feeds (from cache) -+ * -+ * @param array $urls -+ * @return array -+ * @throws Exception -+ */ -+ public function getFeeds(array $urls) -+ { -+ $feeds = array(); -+ $this->addFeeds($urls); -+ foreach ($urls as $url) { -+ $feeds[] = $this->loadFeed($this->url2name($url)); -+ } -+ return $feeds; -+ } -+ -+ protected function saveFeed($file, $contents) -+ { -+ if (file_put_contents($this->directory .'/'. $file .'.xml', $contents)) { -+ $this->feeds[$file] = time(); -+ } else { -+ throw new Exception("Could not save feed contents to $file.xml"); -+ } -+ } -+ -+ protected function loadFeed($file) -+ { -+ if (isset($this->feeds[$file])) { -+ if ($data = file_get_contents($this->directory .'/'. $file .'.xml')) { -+ return $data; -+ } else { -+ throw new Exception("Could not load feed contents from $file.xml"); -+ } -+ } else { -+ throw new Exception("Unknown feed/file $file.xml"); -+ } -+ } -+ -+ protected function setupRequest($url, $escape = true) -+ { -+ $r = new HttpRequest($url); -+ $r->setOptions(array('redirect' => true)); -+ -+ $file = $escape ? $this->url2name($url) : $url; -+ -+ if (isset($this->feeds[$file])) { -+ $r->setOptions(array('lastmodified' => $this->feeds[$file])); -+ } -+ -+ return $r; -+ } -+ -+ protected function handleResponse(HttpRequest $r) -+ { -+ if ($r->getResponseCode() != 304) { -+ if ($r->getResponseCode() != 200) { -+ throw new Exception("Unexpected response code ". $r->getResponseCode()); -+ } -+ if (!strlen($body = $r->getResponseBody())) { -+ throw new Exception("Received empty feed from ". $r->getUrl()); -+ } -+ $this->saveFeed($this->url2name($r->getUrl()), $body); -+ } -+ } -+} -+ -+?> ---- /dev/null -+++ b/ext/http/lib/PgLobStream.php -@@ -0,0 +1,100 @@ -+ -+ * // GET /image.php?image=1234 -+ * if (PgLobStream::$loId = (int) $_GET['image']) { -+ * if ($lob = fopen('pglob://dbname=database user=mike', 'r')) { -+ * HttpResponse::setContentType('image/jpeg'); -+ * HttpResponse::setStream($lob); -+ * HttpResponse::send(); -+ * } -+ * } -+ * -+ * -+ * @copyright Michael Wallner, -+ * @license BSD, revised -+ * @package pecl/http -+ * @version $Revision: 210232 $ -+ */ -+class PgLobStream -+{ -+ private $dbh; -+ private $loh; -+ private $lon; -+ private $size = 0; -+ -+ public static $loId; -+ -+ function stream_open($path, $mode) -+ { -+ $path = trim(parse_url($path, PHP_URL_HOST)); -+ -+ if ($path) { -+ if ($this->dbh = pg_connect($path)) { -+ if (pg_query($this->dbh, 'BEGIN')) { -+ if (is_resource($this->loh = pg_lo_open($this->dbh, $this->lon = self::$loId, $mode))) { -+ pg_lo_seek($this->loh, 0, PGSQL_SEEK_END); -+ $this->size = (int) pg_lo_tell($this->loh); -+ pg_lo_seek($this->loh, 0, PGSQL_SEEK_SET); -+ return true; -+ } -+ } -+ } -+ } -+ return false; -+ } -+ -+ function stream_read($length) -+ { -+ return pg_lo_read($this->loh, $length); -+ } -+ -+ function stream_seek($offset, $whence = PGSQL_SEEK_SET) -+ { -+ return pg_lo_seek($this->loh, $offset, $whence); -+ } -+ -+ function stream_tell() -+ { -+ return pg_lo_tell($this->loh); -+ } -+ -+ function stream_eof() -+ { -+ return pg_lo_tell($this->loh) >= $this->size; -+ } -+ -+ function stream_flush() -+ { -+ return true; -+ } -+ -+ function stream_stat() -+ { -+ return array('size' => $this->size, 'ino' => $this->lon); -+ } -+ -+ function stream_write($data) -+ { -+ return pg_lo_write($this->loh, $data); -+ } -+ -+ function stream_close() -+ { -+ if (pg_lo_close($this->loh)) { -+ return pg_query($this->dbh, 'COMMIT'); -+ } else { -+ pg_query($this->dbh, 'ROLLBACK'); -+ return false; -+ } -+ } -+} -+ -+stream_register_wrapper('pglob', 'PgLobStream'); -+ -+?> ---- /dev/null -+++ b/ext/http/lib/XmlRpcClient.php -@@ -0,0 +1,119 @@ -+ -+ * __request->setOptions(array('compress' => true)); -+ * try { -+ * print_r($rpc->vpop->listdomain(array('domain' => 'example.com'))); -+ * } catch (Exception $ex) { -+ * echo $ex; -+ * } -+ * ?> -+ * -+ * -+ * @copyright Michael Wallner, -+ * @license BSD, revised -+ * @package pecl/http -+ * @version $Revision: 227268 $ -+ */ -+class XmlRpcClient -+{ -+ /** -+ * RPC namespace -+ * -+ * @var string -+ */ -+ public $__namespace; -+ -+ /** -+ * HttpRequest instance -+ * -+ * @var HttpRequest -+ */ -+ public $__request; -+ -+ /** -+ * Client charset -+ * -+ * @var string -+ */ -+ public $__encoding = "iso-8859-1"; -+ -+ /** -+ * RPC options -+ * -+ * @var array -+ */ -+ public $__options; -+ -+ /** -+ * Constructor -+ * -+ * @param string $url RPC endpoint -+ * @param string $namespace RPC namespace -+ * @param array $options HttpRequest options -+ */ -+ public function __construct($url, $namespace = '', array $options = null) -+ { -+ $this->__request = new HttpRequest($url, HttpRequest::METH_POST, (array) $options); -+ $this->__namespace = $namespace; -+ } -+ -+ /** -+ * RPC method proxy -+ * -+ * @param string $method RPC method name -+ * @param array $params RPC method arguments -+ * @return mixed decoded RPC response -+ * @throws Exception -+ */ -+ public function __call($method, array $params) -+ { -+ if (strlen($this->__namespace)) { -+ $method = $this->__namespace .'.'. $method; -+ } -+ $this->__request->setContentType("text/xml"); -+ $this->__request->setRawPostData( -+ xmlrpc_encode_request($method, $params, -+ array("encoding" => $this->__encoding) + (array) $this->__options)); -+ $response = $this->__request->send(); -+ if ($response->getResponseCode() != 200) { -+ throw new Exception( -+ $response->getResponseStatus(), -+ $response->getResponseCode() -+ ); -+ } -+ -+ $data = xmlrpc_decode($response->getBody(), $this->__encoding); -+ if (xmlrpc_is_fault($data)) { -+ throw new Exception( -+ (string) $data['faultString'], -+ (int) $data['faultCode'] -+ ); -+ } -+ -+ return $data; -+ } -+ -+ /** -+ * Returns self, where namespace is set to variable name -+ * -+ * @param string $ns -+ * @return XmlRpcRequest -+ */ -+ public function __get($ns) -+ { -+ $this->__namespace = $ns; -+ return $this; -+ } -+} -+ -+?> ---- /dev/null -+++ b/ext/http/lib/XmlRpcServer.php -@@ -0,0 +1,254 @@ -+ -+ * registerHandler(new Handler); -+ * XmlRpcServer::run(); -+ * } catch (Exception $ex) { -+ * XmlRpcServer::error($ex->getCode(), $ex->getMessage()); -+ * } -+ * -+ * -+ * @copyright Michael Wallner, -+ * @license BSD, revised -+ * @package pecl/http -+ * @version $Revision: 227268 $ -+ */ -+ -+class XmlRpcServer extends HttpResponse -+{ -+ /** -+ * Server charset -+ * -+ * @var string -+ */ -+ public static $encoding = "iso-8859-1"; -+ -+ /** -+ * RPC namespace -+ * -+ * @var string -+ */ -+ public $namespace; -+ -+ /** -+ * RPC handler attached to this server instance -+ * -+ * @var XmlRpcRequestHandler -+ */ -+ protected $handler; -+ -+ private static $xmlreq; -+ private static $xmlrpc; -+ private static $refcnt = 0; -+ private static $handle = array(); -+ -+ /** -+ * Create a new XmlRpcServer instance -+ * -+ * @param string $namespace -+ * @param string $encoding -+ */ -+ public function __construct($namespace) -+ { -+ $this->namespace = $namespace; -+ self::initialize(); -+ } -+ -+ /** -+ * Destructor -+ */ -+ public function __destruct() -+ { -+ if (self::$refcnt && !--self::$refcnt) { -+ xmlrpc_server_destroy(self::$xmlrpc); -+ } -+ } -+ -+ /** -+ * Static factory -+ * -+ * @param string $namespace -+ * @return XmlRpcServer -+ */ -+ public static function factory($namespace) -+ { -+ return new XmlRpcServer($namespace); -+ } -+ -+ /** -+ * Run all servers and send response -+ * -+ * @param array $options -+ */ -+ public static function run(array $options = null) -+ { -+ self::initialize(false, true); -+ self::setContentType("text/xml; charset=". self::$encoding); -+ echo xmlrpc_server_call_method(self::$xmlrpc, self::$xmlreq, null, -+ array("encoding" => self::$encoding) + (array) $options); -+ } -+ -+ /** -+ * Test hook; call instead of XmlRpcServer::run() -+ * -+ * @param string $method -+ * @param array $params -+ * @param array $request_options -+ * @param array $response_options -+ */ -+ public static function test($method, array $params, array $request_options = null, array $response_options = null) -+ { -+ self::$xmlreq = xmlrpc_encode_request($method, $params, $request_options); -+ self::run($response_options); -+ } -+ -+ /** -+ * Optional XMLRPC error handler -+ * -+ * @param int $code -+ * @param string $msg -+ */ -+ public static function error($code, $msg, array $options = null) -+ { -+ echo xmlrpc_encode(array("faultCode" => $code, "faultString" => $msg), -+ array("encoding" => self::$encoding) + (array) $options); -+ } -+ -+ /** -+ * Register a single method -+ * -+ * @param string $name -+ * @param mixed $callback -+ * @param mixed $dispatch -+ * @param array $spec -+ */ -+ public function registerMethod($name, $callback, $dispatch = null, array $spec = null) -+ { -+ if (!is_callable($callback, false, $cb_name)) { -+ throw new Exception("$cb_name is not a valid callback"); -+ } -+ if (isset($dispatch)) { -+ if (!is_callable($dispatch, false, $cb_name)) { -+ throw new Exception("$cb_name is not a valid callback"); -+ } -+ xmlrpc_server_register_method(self::$xmlrpc, $name, $dispatch); -+ self::$handle[$name] = $callback; -+ } else { -+ xmlrpc_server_register_method(self::$xmlrpc, $name, $callback); -+ } -+ -+ if (isset($spec)) { -+ xmlrpc_server_add_introspection_data(self::$xmlrpc, $spec); -+ } -+ } -+ -+ /** -+ * Register an XmlRpcRequestHandler for this server instance -+ * -+ * @param XmlRpcRequestHandler $handler -+ */ -+ public function registerHandler(XmlRpcRequestHandler $handler) -+ { -+ $this->handler = $handler; -+ -+ foreach (get_class_methods($handler) as $method) { -+ if (!strncmp($method, "xmlrpc", 6)) { -+ $this->registerMethod( -+ $this->method($method, $handler->getNamespace()), -+ array($handler, $method), array($this, "dispatch")); -+ } -+ } -+ -+ $handler->getIntrospectionData($spec); -+ if (is_array($spec)) { -+ xmlrpc_server_add_introspection_data(self::$xmlrpc, $spec); -+ } -+ } -+ -+ private function method($method, $namespace = null) -+ { -+ if (!strlen($namespace)) { -+ $namespace = strlen($this->namespace) ? $this->namespace : "xmlrpc"; -+ } -+ return $namespace .".". strtolower($method[6]) . substr($method, 7); -+ } -+ -+ private function dispatch($method, array $params = null) -+ { -+ if (array_key_exists($method, self::$handle)) { -+ return call_user_func(self::$handle[$method], $params); -+ } -+ throw new Exception("Unknown XMLRPC method: $method"); -+ } -+ -+ private static function initialize($server = true, $data = false) -+ { -+ if ($data) { -+ if (!self::$xmlreq && !(self::$xmlreq = http_get_request_body())) { -+ throw new Exception("Failed to fetch XMLRPC request body"); -+ } -+ } -+ if ($server) { -+ if (!self::$xmlrpc && !(self::$xmlrpc = xmlrpc_server_create())) { -+ throw new Exception("Failed to initialize XMLRPC server"); -+ } -+ ++self::$refcnt; -+ } -+ } -+} -+ -+/** -+ * XmlRpcRequestHandler -+ * -+ * Define XMLRPC methods with an "xmlrpc" prefix, eg: -+ * -+ * class IntOp implements XmlRpcRequestHandler { -+ * public function getNamespace() { -+ * return "int"; -+ * } -+ * public function getInstrospectionData(array &$spec = null) { -+ * } -+ * // XMLRPC method name: int.sumValues -+ * public function xmlrpcSumValues(array $values) { -+ * return array_sum($values); -+ * } -+ * } -+ * -+ */ -+interface XmlRpcRequestHandler -+{ -+ public function getNamespace(); -+ public function getIntrospectionData(array &$spec = null); -+} -+ -+/** -+ * XmlRpcRequestHandlerStub -+ */ -+abstract class XmlRpcRequestHandlerStub implements XmlRpcRequestHandler -+{ -+ public function getNamespace() -+ { -+ } -+ public function getIntrospectionData(array &$spec = null) -+ { -+ } -+} -+ -+?> ---- /dev/null -+++ b/ext/http/missing.c -@@ -0,0 +1,74 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: missing.c 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifdef HAVE_CONFIG_H -+# include "config.h" -+#endif -+ -+#include "php.h" -+#include "missing.h" -+ -+#ifdef WONKY -+int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC) -+{ -+ zval *property = pemalloc(sizeof(zval), ce->type & ZEND_INTERNAL_CLASS); -+ INIT_PZVAL(property); -+ ZVAL_DOUBLE(property, value); -+ return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC); -+} -+ -+void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC) -+{ -+ zval *tmp = ecalloc(1, sizeof(zval)); -+ ZVAL_DOUBLE(tmp, value); -+ zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC); -+} -+ -+int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC) -+{ -+ zval *property = pemalloc(sizeof(zval), ce->type & ZEND_INTERNAL_CLASS); -+ INIT_PZVAL(property); -+ ZVAL_BOOL(property, value); -+ return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC); -+} -+ -+void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC) -+{ -+ zval *tmp = ecalloc(1, sizeof(zval)); -+ ZVAL_BOOL(tmp, value); -+ zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC); -+} -+ -+void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, char *value, int value_len TSRMLS_DC) -+{ -+ zval *tmp; -+ -+ ALLOC_ZVAL(tmp); -+ tmp->is_ref = 0; -+ tmp->refcount = 0; -+ ZVAL_STRINGL(tmp, value, value_len, 1); -+ zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC); -+} -+ -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/missing.h -@@ -0,0 +1,184 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: missing.h 323304 2012-02-17 21:13:24Z mike $ */ -+ -+#ifndef PHP_HTTP_MISSING -+#define PHP_HTTP_MISSING -+ -+#include "php_version.h" -+ -+#if ZEND_MODULE_API_NO >= 20100409 -+#define ZEND_ENGINE_2_4 -+#endif -+ -+#if defined(PHP_VERSION_ID) && (PHP_VERSION_ID >= 50399) -+# define ZEND_LITERAL_KEY_DC , const zend_literal *_zend_literal_key -+# define ZEND_LITERAL_KEY_CC , _zend_literal_key -+# define ZEND_LITERAL_NIL_CC , NULL -+# define HTTP_CHECK_OPEN_BASEDIR(file, act) \ -+ if ((PG(open_basedir) && *PG(open_basedir))) \ -+ { \ -+ const char *tmp = file; \ -+ \ -+ if (!strncasecmp(tmp, "file:", lenof("file:"))) { \ -+ tmp += lenof("file:"); \ -+ while ((tmp - (const char *)file < 7) && (*tmp == '/' || *tmp == '\\')) ++tmp; \ -+ } \ -+ \ -+ if ( (tmp != file || !strstr(file, "://")) && \ -+ (!*tmp || php_check_open_basedir(tmp TSRMLS_CC))) { \ -+ act; \ -+ } \ -+ } -+ -+#else -+# define ZEND_LITERAL_KEY_DC -+# define ZEND_LITERAL_KEY_CC -+# define ZEND_LITERAL_NIL_CC -+# define HTTP_CHECK_OPEN_BASEDIR(file, act) \ -+ if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) \ -+ { \ -+ const char *tmp = file; \ -+ \ -+ if (!strncasecmp(tmp, "file:", lenof("file:"))) { \ -+ tmp += lenof("file:"); \ -+ while ((tmp - (const char *)file < 7) && (*tmp == '/' || *tmp == '\\')) ++tmp; \ -+ } \ -+ \ -+ if ( (tmp != file || !strstr(file, "://")) && \ -+ (!*tmp || php_check_open_basedir(tmp TSRMLS_CC) || \ -+ (PG(safe_mode) && !php_checkuid(tmp, "rb+", CHECKUID_CHECK_MODE_PARAM)))) { \ -+ act; \ -+ } \ -+ } -+ -+#endif -+ -+#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION >= 3) -+# define HTTP_ZAPI_HASH_TSRMLS_CC TSRMLS_CC -+# define HTTP_ZAPI_HASH_TSRMLS_DC TSRMLS_DC -+# define HTTP_ZAPI_CONST_CAST(t) (const t) -+# define GLOBAL_ERROR_HANDLING EG(error_handling) -+# define GLOBAL_EXCEPTION_CLASS EG(exception_class) -+# define HTTP_IS_CALLABLE(cb_zv, flags, cb_sp) zend_is_callable((cb_zv), (flags), (cb_sp) TSRMLS_CC) -+# define HTTP_STATIC_ARG_INFO -+#else -+# define HTTP_ZAPI_HASH_TSRMLS_CC -+# define HTTP_ZAPI_HASH_TSRMLS_DC -+# define HTTP_ZAPI_CONST_CAST(t) (t) -+# define GLOBAL_ERROR_HANDLING PG(error_handling) -+# define GLOBAL_EXCEPTION_CLASS PG(exception_class) -+# define HTTP_IS_CALLABLE(cb_zv, flags, cb_sp) zend_is_callable((cb_zv), (flags), (cb_sp)) -+# define HTTP_STATIC_ARG_INFO static -+#endif -+ -+#if (PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION == 0) -+# define WONKY -+#endif -+ -+#ifndef pemalloc_rel -+# define pemalloc_rel(size, persistent) ((persistent)?malloc(size):emalloc_rel(size)) -+#endif -+ -+#ifndef ZEND_ACC_DEPRECATED -+# define ZEND_ACC_DEPRECATED 0 -+#endif -+ -+#if PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION < 10 -+# define php_url_parse_ex(u, l) php_url_parse(u) -+#endif -+ -+#ifndef TSRMLS_FETCH_FROM_CTX -+# ifdef ZTS -+# define TSRMLS_FETCH_FROM_CTX(ctx) void ***tsrm_ls = (void ***) ctx -+# else -+# define TSRMLS_FETCH_FROM_CTX(ctx) -+# endif -+#endif -+ -+#ifndef TSRMLS_SET_CTX -+# ifdef ZTS -+# define TSRMLS_SET_CTX(ctx) ctx = (void ***) tsrm_ls -+# else -+# define TSRMLS_SET_CTX(ctx) -+# endif -+#endif -+ -+#ifndef ZVAL_ADDREF -+# define ZVAL_ADDREF Z_ADDREF_P -+#endif -+ -+#ifndef SEPARATE_ARG_IF_REF -+#define SEPARATE_ARG_IF_REF(zv) \ -+ if (PZVAL_IS_REF(zv)) { \ -+ zval *ov = zv; \ -+ ALLOC_INIT_ZVAL(zv); \ -+ Z_TYPE_P(zv) = Z_TYPE_P(ov); \ -+ zv->value = ov->value; \ -+ zval_copy_ctor(zv); \ -+ } else { \ -+ ZVAL_ADDREF(zv); \ -+ } -+#endif -+ -+#ifndef ZVAL_ZVAL -+#define ZVAL_ZVAL(z, zv, copy, dtor) { \ -+ int is_ref, refcount; \ -+ is_ref = (z)->is_ref; \ -+ refcount = (z)->refcount; \ -+ *(z) = *(zv); \ -+ if (copy) { \ -+ zval_copy_ctor(z); \ -+ } \ -+ if (dtor) { \ -+ if (!copy) { \ -+ ZVAL_NULL(zv); \ -+ } \ -+ zval_ptr_dtor(&zv); \ -+ } \ -+ (z)->is_ref = is_ref; \ -+ (z)->refcount = refcount; \ -+ } -+#endif -+#ifndef RETVAL_ZVAL -+# define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor) -+#endif -+#ifndef RETURN_ZVAL -+# define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; } -+#endif -+ -+#ifndef ZEND_MN -+# define ZEND_MN(name) ZEND_FN(name) -+#endif -+ -+#ifdef WONKY -+extern int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC); -+extern void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC); -+ -+extern int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC); -+extern void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC); -+ -+extern void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, char *value, int value_len TSRMLS_DC); -+#endif -+ -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http.h -@@ -0,0 +1,262 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http.h 324012 2012-03-08 08:44:32Z mike $ */ -+ -+#ifndef PHP_EXT_HTTP_H -+#define PHP_EXT_HTTP_H -+ -+#define PHP_HTTP_VERSION "1.7.4" -+ -+#ifdef HAVE_CONFIG_H -+# include "config.h" -+#else -+# ifndef PHP_WIN32 -+# include "php_config.h" -+# endif -+#endif -+ -+#include "php.h" -+#include "missing.h" -+#include "php_http_std_defs.h" -+#include "phpstr/phpstr.h" -+ -+#ifdef HTTP_WANT_SAPI -+# if PHP_API_VERSION > 20041225 -+# define HTTP_HAVE_SAPI_RTIME -+# endif -+# include "SAPI.h" -+#endif -+ -+#ifdef HTTP_WANT_NETDB -+# ifdef PHP_WIN32 -+# define HTTP_HAVE_NETDB -+# include -+# elif defined(HAVE_NETDB_H) -+# define HTTP_HAVE_NETDB -+# include -+# ifdef HAVE_UNISTD_H -+# include -+# endif -+# endif -+#endif -+ -+#if defined(HTTP_WANT_CURL) && defined(HTTP_HAVE_CURL) -+# ifdef PHP_WIN32 -+# include -+# define CURL_STATICLIB -+# endif -+# include -+# define HTTP_CURL_VERSION(x, y, z) (LIBCURL_VERSION_NUM >= (((x)<<16) + ((y)<<8) + (z))) -+# -+# if defined(HTTP_WANT_EVENT) && defined(HTTP_HAVE_EVENT) -+# include -+# endif -+#endif -+ -+#if defined(HTTP_WANT_MAGIC) && defined(HTTP_HAVE_MAGIC) -+# if defined(PHP_WIN32) && !defined(USE_MAGIC_DLL) && !defined(USE_MAGIC_STATIC) -+# define USE_MAGIC_STATIC -+# endif -+# include -+#endif -+ -+#if defined(HTTP_WANT_ZLIB) && defined(HTTP_HAVE_ZLIB) -+# include -+#endif -+ -+#include -+#define HTTP_IS_CTYPE(type, c) is##type((int) (unsigned char) (c)) -+#define HTTP_TO_CTYPE(type, c) to##type((int) (unsigned char) (c)) -+ -+extern zend_module_entry http_module_entry; -+#define phpext_http_ptr &http_module_entry -+ -+extern int http_module_number; -+ -+ZEND_BEGIN_MODULE_GLOBALS(http) -+ -+ struct _http_globals_etag { -+ char *mode; -+ void *ctx; -+ zend_bool started; -+ } etag; -+ -+ struct _http_globals_log { -+ char *cache; -+ char *redirect; -+ char *not_found; -+ char *allowed_methods; -+ char *composite; -+ } log; -+ -+ struct _http_globals_send { -+ double throttle_delay; -+ size_t buffer_size; -+ char *content_type; -+ char *unquoted_etag; -+ time_t last_modified; -+ struct _http_globals_send_deflate { -+ zend_bool response; -+ zend_bool start_auto; -+ long start_flags; -+ int encoding; -+ void *stream; -+ } deflate; -+ struct _http_globals_send_inflate { -+ zend_bool start_auto; -+ long start_flags; -+ void *stream; -+ } inflate; -+ zend_bool not_found_404; -+ } send; -+ -+ struct _http_globals_request { -+ time_t time; -+ HashTable *headers; -+ struct _http_globals_request_methods { -+ HashTable registered; -+ char *allowed; -+ char *custom; -+ } methods; -+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) -+ struct _http_globals_request_datashare { -+ zend_llist handles; -+ zend_bool cookie; -+ zend_bool dns; -+ zend_bool ssl; -+ zend_bool connect; -+ } datashare; -+#endif -+#if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_EVENT) -+ struct _http_globals_request_pool { -+ struct _http_globals_request_pool_event { -+ void *base; -+ } event; -+ } pool; -+#endif -+ } request; -+ -+ struct _http_globals_persistent { -+ struct _http_globals_persistent_handles { -+ ulong limit; -+ struct _http_globals_persistent_handles_ident { -+ ulong h; -+ char *s; -+ size_t l; -+ } ident; -+ } handles; -+ } persistent; -+ -+#ifdef ZEND_ENGINE_2 -+ zend_bool only_exceptions; -+#endif -+ -+ zend_bool force_exit; -+ zend_bool read_post_data; -+ zval *server_var; -+ -+ZEND_END_MODULE_GLOBALS(http) -+ -+ZEND_EXTERN_MODULE_GLOBALS(http); -+ -+#ifdef ZTS -+# include "TSRM.h" -+# define HTTP_G ((zend_http_globals *) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(http_globals_id)]) -+#else -+# define HTTP_G (&http_globals) -+#endif -+ -+#if defined(HAVE_ICONV) && (HTTP_SHARED_DEPS || !defined(COMPILE_DL_ICONV)) -+# define HTTP_HAVE_ICONV -+#endif -+ -+#if defined(HAVE_PHP_SESSION) && (HTTP_SHARED_DEPS || !defined(COMPILE_DL_SESSION)) -+# define HTTP_HAVE_SESSION -+#endif -+ -+#if defined(HAVE_HASH_EXT) && (HTTP_SHARED_DEPS || !defined(COMPILE_DL_HASH)) && defined(HTTP_HAVE_PHP_HASH_H) -+# define HTTP_HAVE_HASH -+#endif -+ -+#if defined(HAVE_SPL) -+# define HTTP_HAVE_SPL -+#endif -+ -+PHP_FUNCTION(http_date); -+PHP_FUNCTION(http_build_url); -+PHP_FUNCTION(http_build_str); -+PHP_FUNCTION(http_negotiate_language); -+PHP_FUNCTION(http_negotiate_charset); -+PHP_FUNCTION(http_negotiate_content_type); -+PHP_FUNCTION(http_negotiate); -+PHP_FUNCTION(http_redirect); -+PHP_FUNCTION(http_throttle); -+PHP_FUNCTION(http_send_status); -+PHP_FUNCTION(http_send_last_modified); -+PHP_FUNCTION(http_send_content_type); -+PHP_FUNCTION(http_send_content_disposition); -+PHP_FUNCTION(http_match_modified); -+PHP_FUNCTION(http_match_etag); -+PHP_FUNCTION(http_cache_last_modified); -+PHP_FUNCTION(http_cache_etag); -+PHP_FUNCTION(http_send_data); -+PHP_FUNCTION(http_send_file); -+PHP_FUNCTION(http_send_stream); -+PHP_FUNCTION(http_chunked_decode); -+PHP_FUNCTION(http_parse_message); -+PHP_FUNCTION(http_parse_headers); -+PHP_FUNCTION(http_parse_cookie); -+PHP_FUNCTION(http_build_cookie); -+PHP_FUNCTION(http_parse_params); -+PHP_FUNCTION(http_get_request_headers); -+PHP_FUNCTION(http_get_request_body); -+PHP_FUNCTION(http_get_request_body_stream); -+PHP_FUNCTION(http_match_request_header); -+PHP_FUNCTION(http_persistent_handles_count); -+PHP_FUNCTION(http_persistent_handles_clean); -+PHP_FUNCTION(http_persistent_handles_ident); -+#ifdef HTTP_HAVE_CURL -+PHP_FUNCTION(http_get); -+PHP_FUNCTION(http_head); -+PHP_FUNCTION(http_post_data); -+PHP_FUNCTION(http_post_fields); -+PHP_FUNCTION(http_put_data); -+PHP_FUNCTION(http_put_file); -+PHP_FUNCTION(http_put_stream); -+PHP_FUNCTION(http_request); -+PHP_FUNCTION(http_request_body_encode); -+#endif /* HTTP_HAVE_CURL */ -+PHP_FUNCTION(http_request_method_register); -+PHP_FUNCTION(http_request_method_unregister); -+PHP_FUNCTION(http_request_method_exists); -+PHP_FUNCTION(http_request_method_name); -+PHP_FUNCTION(ob_etaghandler); -+#ifdef HTTP_HAVE_ZLIB -+PHP_FUNCTION(http_deflate); -+PHP_FUNCTION(http_inflate); -+PHP_FUNCTION(ob_deflatehandler); -+PHP_FUNCTION(ob_inflatehandler); -+#endif -+PHP_FUNCTION(http_support); -+ -+#endif /* PHP_HTTP_H */ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_api.h -@@ -0,0 +1,326 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_api.h 323304 2012-02-17 21:13:24Z mike $ */ -+ -+#ifndef PHP_HTTP_API_H -+#define PHP_HTTP_API_H -+ -+#define HTTP_SUPPORT 0x01L -+#define HTTP_SUPPORT_REQUESTS 0x02L -+#define HTTP_SUPPORT_MAGICMIME 0x04L -+#define HTTP_SUPPORT_ENCODINGS 0x08L -+#define HTTP_SUPPORT_SSLREQUESTS 0x20L -+#define HTTP_SUPPORT_PERSISTENCE 0x40L -+#define HTTP_SUPPORT_EVENTS 0x80L -+ -+#define HTTP_PARAMS_ALLOW_COMMA 0x01 -+#define HTTP_PARAMS_ALLOW_FAILURE 0x02 -+#define HTTP_PARAMS_RAISE_ERROR 0x04 -+#define HTTP_PARAMS_DEFAULT (HTTP_PARAMS_ALLOW_COMMA|HTTP_PARAMS_ALLOW_FAILURE|HTTP_PARAMS_RAISE_ERROR) -+#define HTTP_PARAMS_COLON_SEPARATOR 0x10 -+ -+extern PHP_MINIT_FUNCTION(http_support); -+ -+#define http_support(f) _http_support(f) -+PHP_HTTP_API long _http_support(long feature); -+ -+#define pretty_key(key, key_len, uctitle, xhyphen) _http_pretty_key(key, key_len, uctitle, xhyphen) -+extern char *_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen); -+ -+#define http_boundary(b, l) _http_boundary((b), (l) TSRMLS_CC) -+extern size_t _http_boundary(char *buf, size_t len TSRMLS_DC); -+ -+#define http_error(type, code, string) _http_error_ex(type, code, "%s", string) -+#define http_error_ex _http_error_ex -+extern void _http_error_ex(long type TSRMLS_DC, long code, const char *format, ...); -+ -+ -+#ifdef ZEND_ENGINE_2 -+#define http_exception_wrap(o, n, ce) _http_exception_wrap((o), (n), (ce) TSRMLS_CC) -+extern zval *_http_exception_wrap(zval *old_exception, zval *new_exception, zend_class_entry *ce TSRMLS_DC); -+ -+#define http_try \ -+{ \ -+ zval *old_exception = EG(exception); \ -+ EG(exception) = NULL; -+#define http_catch(ex_ce) \ -+ if (EG(exception) && old_exception) { \ -+ EG(exception) = http_exception_wrap(old_exception, EG(exception), ex_ce); \ -+ } \ -+} -+#define http_final(ex_ce) \ -+ if (EG(exception)) { \ -+ EG(exception) = http_exception_wrap(EG(exception), NULL, ex_ce); \ -+ } -+ -+typedef zend_object_value (*http_object_new_t)(zend_class_entry *ce, void *, void ** TSRMLS_DC); -+ -+#define http_object_new(ov, cn, cl, co, ce, i, pp) _http_object_new((ov), (cn), (cl), (http_object_new_t) (co), (ce), (i), (void *) (pp) TSRMLS_CC) -+extern STATUS _http_object_new(zend_object_value *ov, const char *cname_str, uint cname_len, http_object_new_t create, zend_class_entry *parent_ce, void *intern_ptr, void **obj_ptr TSRMLS_DC); -+#endif /* ZEND_ENGINE_2 */ -+ -+ -+#define HTTP_CHECK_CURL_INIT(ch, init, action) \ -+ if ((!(ch)) && (!((ch) = init))) { \ -+ http_error(HE_WARNING, HTTP_E_REQUEST, "Could not initialize curl"); \ -+ action; \ -+ } -+#define HTTP_CHECK_CONTENT_TYPE(ct, action) \ -+ if (!strchr((ct), '/')) { \ -+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, \ -+ "Content type \"%s\" does not seem to contain a primary and a secondary part", (ct)); \ -+ action; \ -+ } -+#define HTTP_CHECK_MESSAGE_TYPE_RESPONSE(msg, action) \ -+ if (!HTTP_MSG_TYPE(RESPONSE, (msg))) { \ -+ http_error(HE_NOTICE, HTTP_E_MESSAGE_TYPE, "HttpMessage is not of type HTTP_MSG_RESPONSE"); \ -+ action; \ -+ } -+#define HTTP_CHECK_MESSAGE_TYPE_REQUEST(msg, action) \ -+ if (!HTTP_MSG_TYPE(REQUEST, (msg))) { \ -+ http_error(HE_NOTICE, HTTP_E_MESSAGE_TYPE, "HttpMessage is not of type HTTP_MSG_REQUEST"); \ -+ action; \ -+ } -+#define HTTP_CHECK_GZIP_LEVEL(level, action) \ -+ if (level < -1 || level > 9) { \ -+ http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid compression level (-1 to 9): %d", level); \ -+ action; \ -+ } -+#ifndef PHP_OUTPUT_NEWAPI -+# define HTTP_GET_OUTPUT_START() \ -+ char *output_start_filename = php_get_output_start_filename(TSRMLS_C); \ -+ int output_start_lineno = php_get_output_start_lineno(TSRMLS_C) -+#else -+# define HTTP_GET_OUTPUT_START() \ -+ char *output_start_filename = php_output_get_start_filename(TSRMLS_C); \ -+ int output_start_lineno = php_output_get_start_lineno(TSRMLS_C) -+#endif -+#define HTTP_CHECK_HEADERS_SENT(action) \ -+ if (SG(headers_sent) && !SG(request_info).no_headers) { \ -+ HTTP_GET_OUTPUT_START(); \ -+ if (output_start_filename) { \ -+ http_error_ex(HE_WARNING, HTTP_E_HEADER, "Cannot modify header information - headers already sent by (output started at %s:%d)", \ -+ output_start_filename, output_start_lineno); \ -+ } else { \ -+ http_error(HE_WARNING, HTTP_E_HEADER, "Cannot modify header information - headers already sent"); \ -+ } \ -+ action; \ -+ } -+ -+#define http_log(f, i, m) _http_log_ex((f), (i), (m) TSRMLS_CC) -+extern void _http_log_ex(char *file, const char *ident, const char *message TSRMLS_DC); -+ -+#define http_exit(s, h) http_exit_ex((s), (h), NULL, 1) -+#define http_exit_ex(s, h, b, e) _http_exit_ex((s), (h), (b), (e) TSRMLS_CC) -+extern STATUS _http_exit_ex(int status, char *header, char *body, zend_bool send_header TSRMLS_DC); -+ -+#define http_check_method(m) http_check_method_ex((m), HTTP_KNOWN_METHODS) -+#define http_check_method_ex(m, a) _http_check_method_ex((m), (a)) -+extern STATUS _http_check_method_ex(const char *method, const char *methods); -+ -+#define http_got_server_var(v) (NULL != http_get_server_var_ex((v), strlen(v), 1)) -+#define http_get_server_var(v, c) http_get_server_var_ex((v), strlen(v), (c)) -+#define http_get_server_var_ex(v, l, c) _http_get_server_var_ex((v), (l), (c) TSRMLS_CC) -+PHP_HTTP_API zval *_http_get_server_var_ex(const char *key, size_t key_len, zend_bool check TSRMLS_DC); -+ -+#define http_get_request_body(b, l) _http_get_request_body_ex((b), (l), 1 TSRMLS_CC) -+#define http_get_request_body_ex(b, l, d) _http_get_request_body_ex((b), (l), (d) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_get_request_body_ex(char **body, size_t *length, zend_bool dup TSRMLS_DC); -+ -+#define http_get_request_body_stream() _http_get_request_body_stream(TSRMLS_C) -+PHP_HTTP_API php_stream *_http_get_request_body_stream(TSRMLS_D); -+ -+ -+typedef void (*http_parse_params_callback)(void *cb_arg, const char *key, int keylen, const char *val, int vallen TSRMLS_DC); -+ -+#define http_parse_params_default_callback _http_parse_params_default_callback -+PHP_HTTP_API void _http_parse_params_default_callback(void *ht, const char *key, int keylen, const char *val, int vallen TSRMLS_DC); -+ -+#define http_parse_params(s, f, ht) _http_parse_params_ex((s), (f), _http_parse_params_default_callback, (ht) TSRMLS_CC) -+#define http_parse_params_ex(s, f, cb, a) _http_parse_params_ex((s), (f), (cb), (a) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_parse_params_ex(const char *params, int flags, http_parse_params_callback cb, void *cb_arg TSRMLS_DC); -+ -+ -+#define http_sleep(s) _http_sleep(s) -+static inline void _http_sleep(double s) -+{ -+#define HTTP_DIFFSEC (0.001) -+#define HTTP_MLLISEC (1000) -+#define HTTP_MCROSEC (1000 * 1000) -+#define HTTP_NANOSEC (1000 * 1000 * 1000) -+#define HTTP_MSEC(s) ((long)(s * HTTP_MLLISEC)) -+#define HTTP_USEC(s) ((long)(s * HTTP_MCROSEC)) -+#define HTTP_NSEC(s) ((long)(s * HTTP_NANOSEC)) -+ -+#if defined(PHP_WIN32) -+ Sleep((DWORD) HTTP_MSEC(s)); -+#elif defined(HAVE_USLEEP) -+ usleep(HTTP_USEC(s)); -+#elif defined(HAVE_NANOSLEEP) -+ struct timespec req, rem; -+ -+ req.tv_sec = (time_t) s; -+ req.tv_nsec = HTTP_NSEC(s) % HTTP_NANOSEC; -+ -+ while (nanosleep(&req, &rem) && (errno == EINTR) && (HTTP_NSEC(rem.tv_sec) + rem.tv_nsec) > HTTP_NSEC(HTTP_DIFFSEC))) { -+ req.tv_sec = rem.tv_sec; -+ req.tv_nsec = rem.tv_nsec; -+ } -+#else -+ struct timeval timeout; -+ -+ timeout.tv.sec = (time_t) s; -+ timeout.tv_usec = HTTP_USEC(s) % HTTP_MCROSEC; -+ -+ select(0, NULL, NULL, NULL, &timeout); -+#endif -+} -+ -+#define http_locate_str _http_locate_str -+static inline const char *_http_locate_str(const char *h, size_t h_len, const char *n, size_t n_len) -+{ -+ const char *p, *e; -+ -+ if (n_len && h_len) { -+ e = h + h_len; -+ do { -+ if (*h == *n) { -+ for (p = n; *p == h[p-n]; ++p) { -+ if (p == n+n_len-1) { -+ return h; -+ } -+ } -+ } -+ } while (h++ != e); -+ } -+ -+ return NULL; -+} -+ -+#define http_locate_body _http_locate_body -+static inline const char *_http_locate_body(const char *message) -+{ -+ const char *body = NULL, *msg = message; -+ -+ while (*msg) { -+ if (*msg == '\n') { -+ if (*(msg+1) == '\n') { -+ body = msg + 2; -+ break; -+ } else if (*(msg+1) == '\r' && *(msg+2) == '\n') { -+ body = msg + 3; -+ break; -+ } -+ } -+ ++msg; -+ } -+ return body; -+} -+ -+#define http_locate_eol _http_locate_eol -+static inline const char *_http_locate_eol(const char *line, int *eol_len) -+{ -+ const char *eol = strpbrk(line, "\r\n"); -+ -+ if (eol_len) { -+ *eol_len = eol ? ((eol[0] == '\r' && eol[1] == '\n') ? 2 : 1) : 0; -+ } -+ return eol; -+} -+ -+#define http_zset(t, z) _http_zset((t), (z)) -+static inline zval *_http_zset(int type, zval *z) -+{ -+ if (Z_TYPE_P(z) != type) { -+ switch (type) { -+ case IS_NULL: convert_to_null(z); break; -+ case IS_BOOL: convert_to_boolean(z); break; -+ case IS_LONG: convert_to_long(z); break; -+ case IS_DOUBLE: convert_to_double(z); break; -+ case IS_STRING: convert_to_string(z); break; -+ case IS_ARRAY: convert_to_array(z); break; -+ case IS_OBJECT: convert_to_object(z); break; -+ } -+ } -+ return z; -+} -+#define http_zsep(t, z) _http_zsep_ex((t), (z), NULL) -+#define http_zsep_ex(t, z, p) _http_zsep_ex((t), (z), (p)) -+static inline zval *_http_zsep_ex(int type, zval *z, zval **p) { -+ ZVAL_ADDREF(z); -+ if (Z_TYPE_P(z) != type) { -+ switch (type) { -+ case IS_NULL: convert_to_null_ex(&z); break; -+ case IS_BOOL: convert_to_boolean_ex(&z); break; -+ case IS_LONG: convert_to_long_ex(&z); break; -+ case IS_DOUBLE: convert_to_double_ex(&z); break; -+ case IS_STRING: convert_to_string_ex(&z); break; -+ case IS_ARRAY: convert_to_array_ex(&z); break; -+ case IS_OBJECT: convert_to_object_ex(&z); break; -+ } -+ } else { -+ SEPARATE_ZVAL_IF_NOT_REF(&z); -+ } -+ if (p) { -+ *p = z; -+ } -+ return z; -+} -+ -+typedef struct _HashKey { -+ char *str; -+ uint len; -+ ulong num; -+ uint dup:1; -+ uint type:31; -+} HashKey; -+#define initHashKey(dup) {NULL, 0, 0, (dup), 0} -+ -+#define FOREACH_VAL(pos, array, val) FOREACH_HASH_VAL(pos, Z_ARRVAL_P(array), val) -+#define FOREACH_HASH_VAL(pos, hash, val) \ -+ for ( zend_hash_internal_pointer_reset_ex(hash, &pos); \ -+ zend_hash_get_current_data_ex(hash, (void *) &val, &pos) == SUCCESS; \ -+ zend_hash_move_forward_ex(hash, &pos)) -+ -+#define FOREACH_KEY(pos, array, key) FOREACH_HASH_KEY(pos, Z_ARRVAL_P(array), key) -+#define FOREACH_HASH_KEY(pos, hash, _key) \ -+ for ( zend_hash_internal_pointer_reset_ex(hash, &pos); \ -+ ((_key).type = zend_hash_get_current_key_ex(hash, &(_key).str, &(_key).len, &(_key).num, (zend_bool) (_key).dup, &pos)) != HASH_KEY_NON_EXISTANT; \ -+ zend_hash_move_forward_ex(hash, &pos)) \ -+ -+#define FOREACH_KEYVAL(pos, array, key, val) FOREACH_HASH_KEYVAL(pos, Z_ARRVAL_P(array), key, val) -+#define FOREACH_HASH_KEYVAL(pos, hash, _key, val) \ -+ for ( zend_hash_internal_pointer_reset_ex(hash, &pos); \ -+ ((_key).type = zend_hash_get_current_key_ex(hash, &(_key).str, &(_key).len, &(_key).num, (zend_bool) (_key).dup, &pos)) != HASH_KEY_NON_EXISTANT && \ -+ zend_hash_get_current_data_ex(hash, (void *) &val, &pos) == SUCCESS; \ -+ zend_hash_move_forward_ex(hash, &pos)) -+ -+#define array_copy(src, dst) zend_hash_copy(dst, src, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)) -+#define ARRAY_JOIN_STRONLY 1 -+#define ARRAY_JOIN_PRETTIFY 2 -+#define array_join(src, dst, append, flags) zend_hash_apply_with_arguments(src HTTP_ZAPI_HASH_TSRMLS_CC, (append)?apply_array_append_func:apply_array_merge_func, 2, dst, (int)flags) -+ -+extern int apply_array_append_func(void *pDest HTTP_ZAPI_HASH_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key); -+extern int apply_array_merge_func(void *pDest HTTP_ZAPI_HASH_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key); -+ -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_cache_api.h -@@ -0,0 +1,162 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_cache_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_CACHE_API_H -+#define PHP_HTTP_CACHE_API_H -+ -+#include "php_http_send_api.h" -+ -+#include "ext/standard/crc32.h" -+#include "ext/standard/sha1.h" -+#include "ext/standard/md5.h" -+ -+#ifdef HTTP_HAVE_HASH -+# include "php_hash.h" -+#endif -+ -+#define http_etag_digest(d, l) _http_etag_digest((d), (l)) -+static inline char *_http_etag_digest(const unsigned char *digest, int len) -+{ -+ static const char hexdigits[17] = "0123456789abcdef"; -+ int i; -+ char *hex = emalloc(len * 2 + 1); -+ char *ptr = hex; -+ -+ for (i = 0; i < len; ++i) { -+ *ptr++ = hexdigits[digest[i] >> 4]; -+ *ptr++ = hexdigits[digest[i] & 0xF]; -+ } -+ *ptr = '\0'; -+ -+ return hex; -+} -+ -+#define http_etag_init() _http_etag_init(TSRMLS_C) -+static inline void *_http_etag_init(TSRMLS_D) -+{ -+ void *ctx = NULL; -+ char *mode = HTTP_G->etag.mode; -+ -+#ifdef HTTP_HAVE_HASH -+ const php_hash_ops *eho = NULL; -+ -+ if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) { -+ ctx = emalloc(eho->context_size); -+ eho->hash_init(ctx); -+ } else -+#endif -+ if (mode && ((!strcasecmp(mode, "crc32")) || (!strcasecmp(mode, "crc32b")))) { -+ ctx = emalloc(sizeof(uint)); -+ *((uint *) ctx) = ~0; -+ } else if (mode && !strcasecmp(mode, "sha1")) { -+ PHP_SHA1Init(ctx = emalloc(sizeof(PHP_SHA1_CTX))); -+ } else { -+ PHP_MD5Init(ctx = emalloc(sizeof(PHP_MD5_CTX))); -+ } -+ -+ return ctx; -+} -+ -+#define http_etag_finish(c) _http_etag_finish((c) TSRMLS_CC) -+static inline char *_http_etag_finish(void *ctx TSRMLS_DC) -+{ -+ unsigned char digest[128] = {0}; -+ char *etag = NULL, *mode = HTTP_G->etag.mode; -+ -+#ifdef HTTP_HAVE_HASH -+ const php_hash_ops *eho = NULL; -+ -+ if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) { -+ eho->hash_final(digest, ctx); -+ etag = http_etag_digest(digest, eho->digest_size); -+ } else -+#endif -+ if (mode && ((!strcasecmp(mode, "crc32")) || (!strcasecmp(mode, "crc32b")))) { -+ *((uint *) ctx) = ~*((uint *) ctx); -+ etag = http_etag_digest((const unsigned char *) ctx, sizeof(uint)); -+ } else if (mode && (!strcasecmp(mode, "sha1"))) { -+ PHP_SHA1Final(digest, ctx); -+ etag = http_etag_digest(digest, 20); -+ } else { -+ PHP_MD5Final(digest, ctx); -+ etag = http_etag_digest(digest, 16); -+ } -+ efree(ctx); -+ -+ return etag; -+} -+ -+#define http_etag_update(c, d, l) _http_etag_update((c), (d), (l) TSRMLS_CC) -+static inline void _http_etag_update(void *ctx, const char *data_ptr, size_t data_len TSRMLS_DC) -+{ -+ char *mode = HTTP_G->etag.mode; -+#ifdef HTTP_HAVE_HASH -+ const php_hash_ops *eho = NULL; -+ -+ if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) { -+ eho->hash_update(ctx, (const unsigned char *) data_ptr, data_len); -+ } else -+#endif -+ if (mode && ((!strcasecmp(mode, "crc32")) || (!strcasecmp(mode, "crc32b")))) { -+ uint i, c = *((uint *) ctx); -+ for (i = 0; i < data_len; ++i) { -+ CRC32(c, data_ptr[i]); -+ } -+ *((uint *)ctx) = c; -+ } else if (mode && (!strcasecmp(mode, "sha1"))) { -+ PHP_SHA1Update(ctx, (const unsigned char *) data_ptr, data_len); -+ } else { -+ PHP_MD5Update(ctx, (const unsigned char *) data_ptr, data_len); -+ } -+} -+ -+#define http_ob_etaghandler(o, l, ho, hl, m) _http_ob_etaghandler((o), (l), (ho), (hl), (m) TSRMLS_CC) -+extern void _http_ob_etaghandler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC); -+ -+#define http_etag(p, l, m) _http_etag((p), (l), (m) TSRMLS_CC) -+PHP_HTTP_API char *_http_etag(const void *data_ptr, size_t data_len, http_send_mode data_mode TSRMLS_DC); -+ -+#define http_last_modified(p, m) _http_last_modified((p), (m) TSRMLS_CC) -+PHP_HTTP_API time_t _http_last_modified(const void *data_ptr, http_send_mode data_mode TSRMLS_DC); -+ -+#define http_match_last_modified(entry, modified) _http_match_last_modified_ex((entry), (modified), 1 TSRMLS_CC) -+#define http_match_last_modified_ex(entry, modified, ep) _http_match_last_modified_ex((entry), (modified), (ep) TSRMLS_CC) -+PHP_HTTP_API zend_bool _http_match_last_modified_ex(const char *entry, time_t t, zend_bool enforce_presence TSRMLS_DC); -+ -+#define http_match_etag(entry, etag) _http_match_etag_ex((entry), (etag), 1 TSRMLS_CC) -+#define http_match_etag_ex(entry, etag, ep) _http_match_etag_ex((entry), (etag), (ep) TSRMLS_CC) -+PHP_HTTP_API zend_bool _http_match_etag_ex(const char *entry, const char *etag, zend_bool enforce_presence TSRMLS_DC); -+ -+#define http_cache_last_modified(l, s, cc, ccl) _http_cache_last_modified((l), (s), (cc), (ccl) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_cache_last_modified(time_t last_modified, time_t send_modified, const char *cache_control, size_t cc_len TSRMLS_DC); -+ -+#define http_cache_etag(e, el, cc, ccl) _http_cache_etag((e), (el), (cc), (ccl) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_cache_etag(const char *etag, size_t etag_len, const char *cache_control, size_t cc_len TSRMLS_DC); -+ -+#define http_start_ob_etaghandler() _http_start_ob_etaghandler(TSRMLS_C) -+PHP_HTTP_API STATUS _http_start_ob_etaghandler(TSRMLS_D); -+#define http_interrupt_ob_etaghandler() _http_interrupt_ob_etaghandler(TSRMLS_C) -+PHP_HTTP_API zend_bool _http_interrupt_ob_etaghandler(TSRMLS_D); -+ -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_cookie_api.h -@@ -0,0 +1,86 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_cookie_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_COOKIE_API_H -+#define PHP_HTTP_COOKIE_API_H -+ -+#define HTTP_COOKIE_SECURE 0x10L -+#define HTTP_COOKIE_HTTPONLY 0x20L -+ -+#define HTTP_COOKIE_PARSE_RAW 0x01L -+ -+extern PHP_MINIT_FUNCTION(http_cookie); -+ -+/* -+ generally a netscape cookie compliant struct, recognizing httpOnly attribute, too; -+ cookie params like those from rfc2109 and rfc2965 are just put into extras, if -+ one specifies them in allowed extras, else they're treated like cookies themself -+*/ -+typedef struct _http_cookie_list_t { -+ HashTable cookies; -+ HashTable extras; -+ long flags; -+ char *path; -+ char *domain; -+ time_t expires; -+} http_cookie_list; -+ -+#define http_cookie_list_new() _http_cookie_list_init(NULL ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+#define http_cookie_list_init(l) _http_cookie_list_init((l) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+PHP_HTTP_API http_cookie_list *_http_cookie_list_init(http_cookie_list *list ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC); -+ -+#define http_cookie_list_dtor(l) _http_cookie_list_dtor((l) TSRMLS_CC) -+PHP_HTTP_API void _http_cookie_list_dtor(http_cookie_list *list TSRMLS_DC); -+ -+#define http_cookie_list_free(l) _http_cookie_list_free((l) TSRMLS_CC) -+PHP_HTTP_API void _http_cookie_list_free(http_cookie_list **list TSRMLS_DC); -+ -+#define http_cookie_list_has_cookie(list, name, name_len) zend_hash_exists(&(list)->cookies, (name), (name_len)+1) -+#define http_cookie_list_has_extra(list, name, name_len) zend_hash_exists(&(list)->extras, (name), (name_len)+1) -+ -+#define http_cookie_list_add_cookie(l, n, nl, v, vl) _http_cookie_list_add_cookie((l), (n), (nl), (v), (vl) TSRMLS_CC) -+PHP_HTTP_API void _http_cookie_list_add_cookie(http_cookie_list *list, const char *name, size_t name_len, const char *value, size_t value_len TSRMLS_DC); -+ -+#define http_cookie_list_add_extra(l, n , nl, v, vl) _http_cookie_list_add_extra((l), (n), (nl), (v), (vl) TSRMLS_CC) -+PHP_HTTP_API void _http_cookie_list_add_extra(http_cookie_list *list, const char *name, size_t name_len, const char *value, size_t value_len TSRMLS_DC); -+ -+#define http_cookie_list_get_cookie(l, n, nl) _http_cookie_list_get_cookie((l), (n), (nl) TSRMLS_CC) -+PHP_HTTP_API const char *_http_cookie_list_get_cookie(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC); -+ -+#define http_cookie_list_get_extra(l, n, nl) _http_cookie_list_get_extra((l), (n), (nl) TSRMLS_CC) -+PHP_HTTP_API const char *_http_cookie_list_get_extra(http_cookie_list *list, const char *name, size_t name_len TSRMLS_DC); -+ -+#define http_parse_cookie(s) _http_parse_cookie_ex(NULL, (s), 0, NULL TSRMLS_CC) -+#define http_parse_cookie_ex(l, s, f, a) _http_parse_cookie_ex((l), (s), (f), (a) TSRMLS_CC) -+PHP_HTTP_API http_cookie_list *_http_parse_cookie_ex(http_cookie_list * list, const char *string, long flags, char **allowed_extras TSRMLS_DC); -+ -+#define http_cookie_list_tostruct(l, s) _http_cookie_list_tostruct((l), (s) TSRMLS_CC) -+PHP_HTTP_API void _http_cookie_list_tostruct(http_cookie_list *list, zval *strct TSRMLS_DC); -+ -+#define http_cookie_list_fromstruct(l, s) _http_cookie_list_fromstruct((l), (s) TSRMLS_CC) -+PHP_HTTP_API http_cookie_list *_http_cookie_list_fromstruct(http_cookie_list *list, zval *strct TSRMLS_DC); -+ -+#define http_cookie_list_tostring(l, str, len) _http_cookie_list_tostring((l), (str), (len) TSRMLS_CC) -+PHP_HTTP_API void _http_cookie_list_tostring(http_cookie_list *list, char **str, size_t *len TSRMLS_DC); -+ -+#endif -+ -+/* -+ * 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 -+ */ ---- /dev/null -+++ b/ext/http/php_http_date_api.h -@@ -0,0 +1,35 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_date_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_DATE_API_H -+#define PHP_HTTP_DATE_API_H -+ -+#define http_date(t) _http_date((t) TSRMLS_CC) -+PHP_HTTP_API char *_http_date(time_t t TSRMLS_DC); -+ -+#define http_parse_date(d) _http_parse_date_ex((d), 0 TSRMLS_CC) -+#define http_parse_date_ex(d, s) _http_parse_date_ex((d), (s) TSRMLS_CC) -+PHP_HTTP_API time_t _http_parse_date_ex(const char *date, zend_bool silent TSRMLS_DC); -+ -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_deflatestream_object.h -@@ -0,0 +1,57 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_deflatestream_object.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_DEFLATESTREAM_OBJECT_H -+#define PHP_HTTP_DEFLATESTREAM_OBJECT_H -+#ifdef HTTP_HAVE_ZLIB -+#ifdef ZEND_ENGINE_2 -+ -+typedef struct _http_deflatestream_object_t { -+ zend_object zo; -+ http_encoding_stream *stream; -+} http_deflatestream_object; -+ -+extern zend_class_entry *http_deflatestream_object_ce; -+extern zend_function_entry http_deflatestream_object_fe[]; -+ -+extern PHP_MINIT_FUNCTION(http_deflatestream_object); -+ -+#define http_deflatestream_object_new(ce) _http_deflatestream_object_new((ce) TSRMLS_CC) -+extern zend_object_value _http_deflatestream_object_new(zend_class_entry *ce TSRMLS_DC); -+#define http_deflatestream_object_new_ex(ce, s, ptr) _http_deflatestream_object_new_ex((ce), (s), (ptr) TSRMLS_CC) -+extern zend_object_value _http_deflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_deflatestream_object **ptr TSRMLS_DC); -+#define http_deflatestream_object_clone(zobj) _http_deflatestream_object_clone_obj(zobj TSRMLS_CC) -+extern zend_object_value _http_deflatestream_object_clone_obj(zval *object TSRMLS_DC); -+#define http_deflatestream_object_free(o) _http_deflatestream_object_free((o) TSRMLS_CC) -+extern void _http_deflatestream_object_free(zend_object *object TSRMLS_DC); -+ -+PHP_METHOD(HttpDeflateStream, __construct); -+PHP_METHOD(HttpDeflateStream, factory); -+PHP_METHOD(HttpDeflateStream, update); -+PHP_METHOD(HttpDeflateStream, flush); -+PHP_METHOD(HttpDeflateStream, finish); -+ -+#endif -+#endif -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_encoding_api.h -@@ -0,0 +1,192 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_encoding_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_ENCODING_API_H -+#define PHP_HTTP_ENCODING_API_H -+ -+#define http_encoding_dechunk(e, el, d, dl) _http_encoding_dechunk((e), (el), (d), (dl) TSRMLS_CC) -+PHP_HTTP_API const char *_http_encoding_dechunk(const char *encoded, size_t encoded_len, char **decoded, size_t *decoded_len TSRMLS_DC); -+ -+#define http_encoding_response_start(cl, i) _http_encoding_response_start((cl), (i) TSRMLS_CC) -+PHP_HTTP_API int _http_encoding_response_start(size_t content_length, zend_bool ignore_http_ohandler TSRMLS_DC); -+ -+#ifdef HTTP_HAVE_ZLIB -+ -+extern PHP_MINIT_FUNCTION(http_encoding); -+extern PHP_RINIT_FUNCTION(http_encoding); -+extern PHP_RSHUTDOWN_FUNCTION(http_encoding); -+ -+typedef enum _http_encoding_type_t { -+ HTTP_ENCODING_NONE, -+ HTTP_ENCODING_GZIP, -+ HTTP_ENCODING_DEFLATE, -+} http_encoding_type; -+ -+#define HTTP_INFLATE_ROUNDS 100 -+ -+#define HTTP_DEFLATE_BUFFER_SIZE_GUESS(S) \ -+ (((size_t) ((double) S * (double) 1.015)) + 10 + 8 + 4 + 1) -+#define HTTP_INFLATE_BUFFER_SIZE_GUESS(S) \ -+ (((S) + 1) << 3) -+#define HTTP_INFLATE_BUFFER_SIZE_ALIGN(S) \ -+ ((S) += (S) >> (3)) -+ -+#define HTTP_DEFLATE_BUFFER_SIZE 0x8000 -+#define HTTP_INFLATE_BUFFER_SIZE 0x1000 -+ -+#define HTTP_DEFLATE_LEVEL_DEF 0x00000000 -+#define HTTP_DEFLATE_LEVEL_MIN 0x00000001 -+#define HTTP_DEFLATE_LEVEL_MAX 0x00000009 -+#define HTTP_DEFLATE_TYPE_ZLIB 0x00000000 -+#define HTTP_DEFLATE_TYPE_GZIP 0x00000010 -+#define HTTP_DEFLATE_TYPE_RAW 0x00000020 -+#define HTTP_DEFLATE_STRATEGY_DEF 0x00000000 -+#define HTTP_DEFLATE_STRATEGY_FILT 0x00000100 -+#define HTTP_DEFLATE_STRATEGY_HUFF 0x00000200 -+#define HTTP_DEFLATE_STRATEGY_RLE 0x00000300 -+#define HTTP_DEFLATE_STRATEGY_FIXED 0x00000400 -+ -+#define HTTP_DEFLATE_LEVEL_SET(flags, level) \ -+ switch (flags & 0xf) \ -+ { \ -+ default: \ -+ if ((flags & 0xf) < 10) { \ -+ level = flags & 0xf; \ -+ break; \ -+ } \ -+ case HTTP_DEFLATE_LEVEL_DEF: \ -+ level = Z_DEFAULT_COMPRESSION; \ -+ break; \ -+ } -+ -+#define HTTP_DEFLATE_WBITS_SET(flags, wbits) \ -+ switch (flags & 0xf0) \ -+ { \ -+ case HTTP_DEFLATE_TYPE_GZIP: \ -+ wbits = HTTP_WINDOW_BITS_GZIP; \ -+ break; \ -+ case HTTP_DEFLATE_TYPE_RAW: \ -+ wbits = HTTP_WINDOW_BITS_RAW; \ -+ break; \ -+ default: \ -+ wbits = HTTP_WINDOW_BITS_ZLIB; \ -+ break; \ -+ } -+ -+#define HTTP_INFLATE_WBITS_SET(flags, wbits) \ -+ if (flags & HTTP_INFLATE_TYPE_RAW) { \ -+ wbits = HTTP_WINDOW_BITS_RAW; \ -+} else { \ -+ wbits = HTTP_WINDOW_BITS_ANY; \ -+} -+ -+#define HTTP_DEFLATE_STRATEGY_SET(flags, strategy) \ -+ switch (flags & 0xf00) \ -+ { \ -+ case HTTP_DEFLATE_STRATEGY_FILT: \ -+ strategy = Z_FILTERED; \ -+ break; \ -+ case HTTP_DEFLATE_STRATEGY_HUFF: \ -+ strategy = Z_HUFFMAN_ONLY; \ -+ break; \ -+ case HTTP_DEFLATE_STRATEGY_RLE: \ -+ strategy = Z_RLE; \ -+ break; \ -+ case HTTP_DEFLATE_STRATEGY_FIXED: \ -+ strategy = Z_FIXED; \ -+ break; \ -+ default: \ -+ strategy = Z_DEFAULT_STRATEGY; \ -+ break; \ -+ } -+ -+#define HTTP_WINDOW_BITS_ZLIB 0x0000000f -+#define HTTP_WINDOW_BITS_GZIP 0x0000001f -+#define HTTP_WINDOW_BITS_ANY 0x0000002f -+#define HTTP_WINDOW_BITS_RAW -0x000000f -+ -+#ifndef Z_FIXED -+/* Z_FIXED does not exist prior 1.2.2.2 */ -+# define Z_FIXED 0 -+#endif -+ -+#define HTTP_INFLATE_TYPE_ZLIB 0x00000000 -+#define HTTP_INFLATE_TYPE_GZIP 0x00000000 -+#define HTTP_INFLATE_TYPE_RAW 0x00000001 -+ -+#define HTTP_ENCODING_STREAM_FLUSH_NONE 0x00000000 -+#define HTTP_ENCODING_STREAM_FLUSH_SYNC 0x00100000 -+#define HTTP_ENCODING_STREAM_FLUSH_FULL 0x00200000 -+ -+#define HTTP_ENCODING_STREAM_FLUSH_FLAG(f) \ -+ (((f) & HTTP_ENCODING_STREAM_FLUSH_FULL) ? Z_FULL_FLUSH : \ -+ (((f) & HTTP_ENCODING_STREAM_FLUSH_SYNC) ? Z_SYNC_FLUSH : Z_NO_FLUSH)) -+ -+#define HTTP_ENCODING_STREAM_PERSISTENT 0x01000000 -+ -+typedef struct _http_encoding_stream_t { -+ z_stream stream; -+ int flags; -+ void *storage; -+} http_encoding_stream; -+ -+#define http_encoding_deflate(f, d, dl, r, rl) _http_encoding_deflate((f), (d), (dl), (r), (rl) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+PHP_HTTP_API STATUS _http_encoding_deflate(int flags, const char *data, size_t data_len, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC); -+#define http_encoding_inflate(d, dl, r, rl) _http_encoding_inflate((d), (dl), (r), (rl) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+PHP_HTTP_API STATUS _http_encoding_inflate(const char *data, size_t data_len, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC); -+ -+#define http_encoding_deflate_stream_init(s, f) _http_encoding_deflate_stream_init((s), (f) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+PHP_HTTP_API http_encoding_stream *_http_encoding_deflate_stream_init(http_encoding_stream *s, int flags ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC); -+#define http_encoding_deflate_stream_update(s, d, dl, e, el) _http_encoding_deflate_stream_update((s), (d), (dl), (e), (el) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+PHP_HTTP_API STATUS _http_encoding_deflate_stream_update(http_encoding_stream *s, const char *data, size_t data_len, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC); -+#define http_encoding_deflate_stream_flush(s, e, el) _http_encoding_deflate_stream_flush((s), (e), (el) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+PHP_HTTP_API STATUS _http_encoding_deflate_stream_flush(http_encoding_stream *s, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC); -+#define http_encoding_deflate_stream_finish(s, e, el) _http_encoding_deflate_stream_finish((s), (e), (el) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+PHP_HTTP_API STATUS _http_encoding_deflate_stream_finish(http_encoding_stream *s, char **encoded, size_t *encoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC); -+#define http_encoding_deflate_stream_dtor(s) _http_encoding_deflate_stream_dtor((s) TSRMLS_CC) -+PHP_HTTP_API void _http_encoding_deflate_stream_dtor(http_encoding_stream *s TSRMLS_DC); -+#define http_encoding_deflate_stream_free(s) _http_encoding_deflate_stream_free((s) TSRMLS_CC) -+PHP_HTTP_API void _http_encoding_deflate_stream_free(http_encoding_stream **s TSRMLS_DC); -+ -+#define http_encoding_inflate_stream_init(s, f) _http_encoding_inflate_stream_init((s), (f) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+PHP_HTTP_API http_encoding_stream *_http_encoding_inflate_stream_init(http_encoding_stream *s, int flags ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC); -+#define http_encoding_inflate_stream_update(s, d, dl, e, el) _http_encoding_inflate_stream_update((s), (d), (dl), (e), (el) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+PHP_HTTP_API STATUS _http_encoding_inflate_stream_update(http_encoding_stream *s, const char *data, size_t data_len, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC); -+#define http_encoding_inflate_stream_flush(s, d, dl) _http_encoding_inflate_stream_flush((s), (d), (dl) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+PHP_HTTP_API STATUS _http_encoding_inflate_stream_flush(http_encoding_stream *s, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC); -+#define http_encoding_inflate_stream_finish(s, e, el) _http_encoding_inflate_stream_finish((s), (e), (el) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+PHP_HTTP_API STATUS _http_encoding_inflate_stream_finish(http_encoding_stream *s, char **decoded, size_t *decoded_len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC); -+#define http_encoding_inflate_stream_dtor(s) _http_encoding_inflate_stream_dtor((s) TSRMLS_CC) -+PHP_HTTP_API void _http_encoding_inflate_stream_dtor(http_encoding_stream *s TSRMLS_DC); -+#define http_encoding_inflate_stream_free(s) _http_encoding_inflate_stream_free((s) TSRMLS_CC) -+PHP_HTTP_API void _http_encoding_inflate_stream_free(http_encoding_stream **s TSRMLS_DC); -+ -+#define http_ob_deflatehandler(o, ol, h, hl, m) _http_ob_deflatehandler((o), (ol), (h), (hl), (m) TSRMLS_CC) -+extern void _http_ob_deflatehandler(char *, uint, char **, uint *, int TSRMLS_DC); -+ -+#define http_ob_inflatehandler(o, ol, h, hl, m) _http_ob_inflatehandler((o), (ol), (h), (hl), (m) TSRMLS_CC) -+extern void _http_ob_inflatehandler(char *, uint, char **, uint *, int TSRMLS_DC); -+ -+#endif /* HTTP_HAVE_ZLIB */ -+ -+#endif -+ -+/* -+ * 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 -+ */ ---- /dev/null -+++ b/ext/http/php_http_exception_object.h -@@ -0,0 +1,60 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_exception_object.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_EXCEPTION_OBJECT_H -+#define PHP_HTTP_EXCEPTION_OBJECT_H -+#ifdef ZEND_ENGINE_2 -+ -+#include "zend_exceptions.h" -+ -+PHP_MINIT_FUNCTION(http_exception_object); -+ -+#define HTTP_EX_DEF_CE http_exception_object_ce -+#define HTTP_EX_CE(name) http_ ##name## _exception_object_ce -+ -+extern zend_class_entry *http_exception_object_ce; -+extern zend_class_entry *HTTP_EX_CE(runtime); -+extern zend_class_entry *HTTP_EX_CE(header); -+extern zend_class_entry *HTTP_EX_CE(malformed_headers); -+extern zend_class_entry *HTTP_EX_CE(request_method); -+extern zend_class_entry *HTTP_EX_CE(message_type); -+extern zend_class_entry *HTTP_EX_CE(invalid_param); -+extern zend_class_entry *HTTP_EX_CE(encoding); -+extern zend_class_entry *HTTP_EX_CE(request); -+extern zend_class_entry *HTTP_EX_CE(request_pool); -+extern zend_class_entry *HTTP_EX_CE(socket); -+extern zend_class_entry *HTTP_EX_CE(response); -+extern zend_class_entry *HTTP_EX_CE(url); -+extern zend_function_entry http_exception_object_fe[]; -+ -+#define http_exception_get_default _http_exception_get_default -+extern zend_class_entry *_http_exception_get_default(); -+ -+#define http_exception_get_for_code(c) _http_exception_get_for_code(c) -+extern zend_class_entry *_http_exception_get_for_code(long code); -+ -+PHP_METHOD(HttpException, __toString); -+ -+#endif -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_filter_api.h -@@ -0,0 +1,33 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_filter_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_FILTER_API_H -+#define PHP_HTTP_FILTER_API_H -+#ifdef ZEND_ENGINE_2 -+ -+extern php_stream_filter_factory http_filter_factory; -+PHP_MINIT_FUNCTION(http_filter); -+ -+#endif -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_headers_api.h -@@ -0,0 +1,77 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_headers_api.h 300300 2010-06-09 07:29:35Z mike $ */ -+ -+#ifndef PHP_HTTP_HEADERS_API_H -+#define PHP_HTTP_HEADERS_API_H -+ -+#include "php_http_info_api.h" -+ -+typedef enum http_range_status_t { -+ RANGE_OK, -+ RANGE_NO, -+ RANGE_ERR -+} http_range_status; -+ -+#define http_parse_headers(h, a) _http_parse_headers_ex((h), Z_ARRVAL_P(a), 1, http_info_default_callback, NULL TSRMLS_CC) -+#define http_parse_headers_ex(h, ht, p) _http_parse_headers_ex((h), (ht), (p), http_info_default_callback, NULL TSRMLS_CC) -+#define http_parse_headers_cb(h, ht, p, f, d) _http_parse_headers_ex((h), (ht), (p), (f), (d) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_parse_headers_ex(const char *header, HashTable *headers, zend_bool prettify, http_info_callback callback_func, void **callback_data TSRMLS_DC); -+ -+typedef char *(*negotiate_func_t)(const char *test, double *quality, HashTable *supported TSRMLS_DC); -+ -+#define http_negotiate_language_func _http_negotiate_language_func -+extern char *_http_negotiate_language_func(const char *test, double *quality, HashTable *supported TSRMLS_DC); -+#define http_negotiate_content_type_func _http_negotiate_default_func -+#define http_negotiate_encoding_func _http_negotiate_default_func -+#define http_negotiate_charset_func _http_negotiate_default_func -+#define http_negotiate_default_func _http_negotiate_default_func -+extern char *_http_negotiate_default_func(const char *test, double *quality, HashTable *supported TSRMLS_DC); -+ -+#define http_negotiate_language(zsupported) http_negotiate_language_ex(Z_ARRVAL_P(zsupported)) -+#define http_negotiate_language_ex(supported) http_negotiate_q("HTTP_ACCEPT_LANGUAGE", (supported), http_negotiate_language_func) -+#define http_negotiate_charset(zsupported) http_negotiate_charset_ex(Z_ARRVAL_P(zsupported)) -+#define http_negotiate_charset_ex(supported) http_negotiate_q("HTTP_ACCEPT_CHARSET", (supported), http_negotiate_charset_func) -+#define http_negotiate_encoding(zsupported) http_negotiate_encoding_ex(Z_ARRVAL_P(zsupported)) -+#define http_negotiate_encoding_ex(supported) http_negotiate_q("HTTP_ACCEPT_ENCODING", (supported), http_negotiate_encoding_func) -+#define http_negotiate_content_type(zsupported) http_negotiate_content_type_ex(Z_ARRVAL_P(zsupported)) -+#define http_negotiate_content_type_ex(supported) http_negotiate_q("HTTP_ACCEPT", (supported), http_negotiate_content_type_func) -+#define http_negotiate_q(e, s, n) _http_negotiate_q((e), (s), (n) TSRMLS_CC) -+PHP_HTTP_API HashTable *_http_negotiate_q(const char *header, HashTable *supported, negotiate_func_t neg TSRMLS_DC); -+#define http_negotiate_z(z, s, n) _http_negotiate_z((z), (s), (n) TSRMLS_CC) -+PHP_HTTP_API HashTable *_http_negotiate_z(zval *value, HashTable *supported, negotiate_func_t neg TSRMLS_DC); -+ -+#define http_get_request_ranges(r, l) _http_get_request_ranges((r), (l) TSRMLS_CC) -+PHP_HTTP_API http_range_status _http_get_request_ranges(HashTable *ranges, size_t length TSRMLS_DC); -+ -+#define http_get_request_headers(h) _http_get_request_headers((h) TSRMLS_CC) -+PHP_HTTP_API void _http_get_request_headers(HashTable *headers TSRMLS_DC); -+ -+#define http_get_response_headers(h) _http_get_response_headers((h) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_get_response_headers(HashTable *headers_ht TSRMLS_DC); -+ -+#define http_match_request_header(h, v) http_match_request_header_ex((h), (v), 0) -+#define http_match_request_header_ex(h, v, c) _http_match_request_header_ex((h), (v), (c) TSRMLS_CC) -+PHP_HTTP_API zend_bool _http_match_request_header_ex(const char *header, const char *value, zend_bool match_case TSRMLS_DC); -+ -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_inflatestream_object.h -@@ -0,0 +1,57 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_inflatestream_object.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_INFLATESTREAM_OBJECT_H -+#define PHP_HTTP_INFLATESTREAM_OBJECT_H -+#ifdef HTTP_HAVE_ZLIB -+#ifdef ZEND_ENGINE_2 -+ -+typedef struct _http_inflatestream_object_t { -+ zend_object zo; -+ http_encoding_stream *stream; -+} http_inflatestream_object; -+ -+extern zend_class_entry *http_inflatestream_object_ce; -+extern zend_function_entry http_inflatestream_object_fe[]; -+ -+extern PHP_MINIT_FUNCTION(http_inflatestream_object); -+ -+#define http_inflatestream_object_new(ce) _http_inflatestream_object_new((ce) TSRMLS_CC) -+extern zend_object_value _http_inflatestream_object_new(zend_class_entry *ce TSRMLS_DC); -+#define http_inflatestream_object_new_ex(ce, s, ptr) _http_inflatestream_object_new_ex((ce), (s), (ptr) TSRMLS_CC) -+extern zend_object_value _http_inflatestream_object_new_ex(zend_class_entry *ce, http_encoding_stream *s, http_inflatestream_object **ptr TSRMLS_DC); -+#define http_inflatestream_object_clone(zobj) _http_inflatestream_object_clone_obj(zobj TSRMLS_CC) -+extern zend_object_value _http_inflatestream_object_clone_obj(zval *object TSRMLS_DC); -+#define http_inflatestream_object_free(o) _http_inflatestream_object_free((o) TSRMLS_CC) -+extern void _http_inflatestream_object_free(zend_object *object TSRMLS_DC); -+ -+PHP_METHOD(HttpInflateStream, __construct); -+PHP_METHOD(HttpInflateStream, factory); -+PHP_METHOD(HttpInflateStream, update); -+PHP_METHOD(HttpInflateStream, flush); -+PHP_METHOD(HttpInflateStream, finish); -+ -+#endif -+#endif -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_info_api.h -@@ -0,0 +1,79 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_info_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_INFO_API_H -+#define PHP_HTTP_INFO_API_H -+ -+#define IS_HTTP_REQUEST 1 -+#define IS_HTTP_RESPONSE 2 -+ -+#define HTTP_INFO(ptr) (ptr)->http.info -+ -+#define HTTP_INFO_REQUEST_FMT_ARGS(_http_ptr, _EOL) "%s %s HTTP/%1.1f" _EOL, \ -+ (_http_ptr)->info.request.method?(_http_ptr)->info.request.method:"UNKNOWN", \ -+ (_http_ptr)->info.request.url?(_http_ptr)->info.request.url:"/", \ -+ (_http_ptr)->version>0.0?(_http_ptr)->version:1.1 -+ -+#define HTTP_INFO_RESPONSE_FMT_ARGS(_http_ptr, _EOL) "HTTP/%1.1f %d%s%s" _EOL, \ -+ (_http_ptr)->version>0.0?(_http_ptr)->version:1.1, \ -+ (_http_ptr)->info.response.code?(_http_ptr)->info.response.code:200, \ -+ (_http_ptr)->info.response.status&&*(_http_ptr)->info.response.status ? " ":"", \ -+ STR_PTR((_http_ptr)->info.response.status) -+ -+typedef struct _http_request_info_t { -+ char *method; -+ char *url; -+} http_request_info; -+ -+typedef struct _http_response_info_t { -+ int code; -+ char *status; -+} http_response_info; -+ -+typedef union _http_info_union_t { -+ http_request_info request; -+ http_response_info response; -+} http_info_union; -+ -+struct http_info { -+ http_info_union info; -+ double version; -+}; -+ -+typedef struct _http_info_t { -+ struct http_info http; -+ int type; -+} http_info; -+ -+typedef void (*http_info_callback)(void **callback_data, HashTable **headers, http_info *info TSRMLS_DC); -+ -+#define http_info_default_callback _http_info_default_callback -+PHP_HTTP_API void _http_info_default_callback(void **nothing, HashTable **headers, http_info *info TSRMLS_DC); -+#define http_info_dtor _http_info_dtor -+PHP_HTTP_API void _http_info_dtor(http_info *info); -+#define http_info_parse(p, i) _http_info_parse_ex((p), (i), 1 TSRMLS_CC) -+#define http_info_parse_ex(p, i, s) _http_info_parse_ex((p), (i), (s) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_info_parse_ex(const char *pre_header, http_info *info , zend_bool silent TSRMLS_DC); -+ -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_message_api.h -@@ -0,0 +1,131 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_message_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_MESSAGE_API_H -+#define PHP_HTTP_MESSAGE_API_H -+ -+#include "php_http_info_api.h" -+ -+typedef enum _http_message_type_t { -+ HTTP_MSG_NONE = 0, -+ HTTP_MSG_REQUEST = IS_HTTP_REQUEST, -+ HTTP_MSG_RESPONSE = IS_HTTP_RESPONSE, -+} http_message_type; -+ -+typedef struct _http_message_t http_message; -+ -+struct _http_message_t { -+ phpstr body; -+ HashTable hdrs; -+ http_message_type type; -+ struct http_info http; -+ http_message *parent; -+}; -+ -+/* required minimum length of an HTTP message "HTTP/1.1" */ -+#define HTTP_MSG_MIN_SIZE 8 -+ -+/* shorthand for type checks */ -+#define HTTP_MSG_TYPE(TYPE, msg) ((msg) && ((msg)->type == HTTP_MSG_ ##TYPE)) -+ -+#define http_message_new() http_message_init_ex(NULL, 0) -+#define http_message_init(m) http_message_init_ex((m), 0) -+#define http_message_init_ex(m, t) _http_message_init_ex((m), (t) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) -+#define http_message_init_rel(m, t) _http_message_init_ex((m), (t) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC) -+PHP_HTTP_API http_message *_http_message_init_ex(http_message *m, http_message_type t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); -+#define http_message_init_env(m, t) _http_message_init_env((m), (t) TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) -+PHP_HTTP_API http_message *_http_message_init_env(http_message *m, http_message_type t TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); -+ -+#define http_message_set_type(m, t) _http_message_set_type((m), (t)) -+PHP_HTTP_API void _http_message_set_type(http_message *m, http_message_type t); -+ -+#define http_message_set_info(m, i) _http_message_set_info((m), (i)) -+PHP_HTTP_API void _http_message_set_info(http_message *message, http_info *info); -+ -+#define http_message_header(m, h) _http_message_header_ex((m), (h), sizeof(h), 1) -+#define http_message_header_ex _http_message_header_ex -+static inline zval *_http_message_header_ex(http_message *msg, char *key_str, size_t key_len, int join) -+{ -+ zval **header; -+ if (SUCCESS == zend_hash_find(&msg->hdrs, key_str, key_len, (void *) &header)) { -+ if (join && Z_TYPE_PP(header) == IS_ARRAY) { -+ zval *header_str, **val; -+ HashPosition pos; -+ phpstr str; -+ -+ phpstr_init(&str); -+ MAKE_STD_ZVAL(header_str); -+ FOREACH_VAL(pos, *header, val) { -+ phpstr_appendf(&str, PHPSTR_LEN(&str) ? ", %s":"%s", Z_STRVAL_PP(val)); -+ } -+ phpstr_fix(&str); -+ ZVAL_STRINGL(header_str, PHPSTR_VAL(&str), PHPSTR_LEN(&str), 0); -+ return header_str; -+ } else { -+ ZVAL_ADDREF(*header); -+ return *header; -+ } -+ } -+ return NULL; -+} -+ -+#define http_message_count(c, m) \ -+{ \ -+ http_message *__tmp_msg = (m); \ -+ for (c = 0; __tmp_msg; __tmp_msg = __tmp_msg->parent, ++(c)); \ -+} -+ -+#define http_message_parse(m, l) http_message_parse_ex(NULL, (m), (l)) -+#define http_message_parse_ex(h, m, l) _http_message_parse_ex((h), (m), (l) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+#define http_message_parse_rel(h, m, l) _http_message_parse_ex((h), (m), (l) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC TSRMLS_CC) -+PHP_HTTP_API http_message *_http_message_parse_ex(http_message *msg, const char *message, size_t length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC); -+ -+#define http_message_tostring(m, s, l) _http_message_tostring((m), (s), (l)) -+PHP_HTTP_API void _http_message_tostring(http_message *msg, char **string, size_t *length); -+ -+#define http_message_serialize(m, s, l) _http_message_serialize((m), (s), (l)) -+PHP_HTTP_API void _http_message_serialize(http_message *message, char **string, size_t *length); -+ -+#define http_message_reverse(m) _http_message_reverse(m) -+PHP_HTTP_API http_message *_http_message_reverse(http_message *msg); -+ -+#define http_message_interconnect(m1, m2) _http_message_interconnect((m1), (m2)) -+PHP_HTTP_API http_message *_http_message_interconnect(http_message *m1, http_message *m2); -+ -+#define http_message_tostruct_recursive(m, s) _http_message_tostruct_recursive((m), (s) TSRMLS_CC) -+PHP_HTTP_API void _http_message_tostruct_recursive(http_message *msg, zval *strct TSRMLS_DC); -+ -+#define http_message_send(m) _http_message_send((m) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_message_send(http_message *message TSRMLS_DC); -+ -+#define http_message_dup(m) _http_message_dup((m) TSRMLS_CC) -+PHP_HTTP_API http_message *_http_message_dup(http_message *msg TSRMLS_DC); -+ -+#define http_message_dtor(m) _http_message_dtor((m)) -+PHP_HTTP_API void _http_message_dtor(http_message *message); -+ -+#define http_message_free(m) _http_message_free((m)) -+PHP_HTTP_API void _http_message_free(http_message **message); -+ -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_message_object.h -@@ -0,0 +1,115 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_message_object.h 298590 2010-04-26 11:46:35Z mike $ */ -+ -+#ifndef PHP_HTTP_MESSAGE_OBJECT_H -+#define PHP_HTTP_MESSAGE_OBJECT_H -+#ifdef ZEND_ENGINE_2 -+ -+typedef struct _http_message_object_t { -+ zend_object zo; -+ http_message *message; -+ zend_object_value parent; -+ zval *iterator; -+} http_message_object; -+ -+extern zend_class_entry *http_message_object_ce; -+extern zend_function_entry http_message_object_fe[]; -+ -+extern PHP_MINIT_FUNCTION(http_message_object); -+extern PHP_MSHUTDOWN_FUNCTION(http_message_object); -+ -+#define http_message_object_prepend(o, p) http_message_object_prepend_ex((o), (p), 1) -+#define http_message_object_prepend_ex(o, p, t) _http_message_object_prepend_ex((o), (p), (t) TSRMLS_CC) -+extern void _http_message_object_prepend_ex(zval *this_ptr, zval *prepend, zend_bool top TSRMLS_DC); -+ -+#define http_message_object_reverse(t, r) _http_message_object_reverse((t), (r) TSRMLS_CC) -+extern void _http_message_object_reverse(zval *this_ptr, zval *return_value TSRMLS_DC); -+ -+#define http_message_object_new(ce) _http_message_object_new((ce) TSRMLS_CC) -+extern zend_object_value _http_message_object_new(zend_class_entry *ce TSRMLS_DC); -+#define http_message_object_new_ex(ce, msg, ptr) _http_message_object_new_ex((ce), (msg), (ptr) TSRMLS_CC) -+extern zend_object_value _http_message_object_new_ex(zend_class_entry *ce, http_message *msg, http_message_object **ptr TSRMLS_DC); -+#define http_message_object_clone(zobj) _http_message_object_clone_obj(zobj TSRMLS_CC) -+extern zend_object_value _http_message_object_clone_obj(zval *object TSRMLS_DC); -+#define http_message_object_free(o) _http_message_object_free((o) TSRMLS_CC) -+extern void _http_message_object_free(zend_object *object TSRMLS_DC); -+ -+#define HTTP_MSG_CHECK_OBJ(obj, dofail) \ -+ if (!(obj)->message) { \ -+ http_error(E_WARNING, HTTP_E_MSG, "HttpMessage is empty"); \ -+ dofail; \ -+ } -+#define HTTP_MSG_CHECK_STD() HTTP_MSG_CHECK_OBJ(obj, RETURN_FALSE) -+ -+#define HTTP_MSG_INIT_OBJ(obj) \ -+ if (!(obj)->message) { \ -+ (obj)->message = http_message_new(); \ -+ } -+#define HTTP_MSG_INIT_STD() HTTP_MSG_INIT_OBJ(obj) -+ -+PHP_METHOD(HttpMessage, __construct); -+PHP_METHOD(HttpMessage, getBody); -+PHP_METHOD(HttpMessage, setBody); -+PHP_METHOD(HttpMessage, getHeader); -+PHP_METHOD(HttpMessage, getHeaders); -+PHP_METHOD(HttpMessage, setHeaders); -+PHP_METHOD(HttpMessage, addHeaders); -+PHP_METHOD(HttpMessage, getType); -+PHP_METHOD(HttpMessage, setType); -+PHP_METHOD(HttpMessage, getInfo); -+PHP_METHOD(HttpMessage, setInfo); -+PHP_METHOD(HttpMessage, getResponseCode); -+PHP_METHOD(HttpMessage, setResponseCode); -+PHP_METHOD(HttpMessage, getResponseStatus); -+PHP_METHOD(HttpMessage, setResponseStatus); -+PHP_METHOD(HttpMessage, getRequestMethod); -+PHP_METHOD(HttpMessage, setRequestMethod); -+PHP_METHOD(HttpMessage, getRequestUrl); -+PHP_METHOD(HttpMessage, setRequestUrl); -+PHP_METHOD(HttpMessage, getHttpVersion); -+PHP_METHOD(HttpMessage, setHttpVersion); -+PHP_METHOD(HttpMessage, guessContentType); -+PHP_METHOD(HttpMessage, getParentMessage); -+PHP_METHOD(HttpMessage, send); -+PHP_METHOD(HttpMessage, toString); -+PHP_METHOD(HttpMessage, toMessageTypeObject); -+ -+PHP_METHOD(HttpMessage, count); -+PHP_METHOD(HttpMessage, serialize); -+PHP_METHOD(HttpMessage, unserialize); -+PHP_METHOD(HttpMessage, rewind); -+PHP_METHOD(HttpMessage, valid); -+PHP_METHOD(HttpMessage, current); -+PHP_METHOD(HttpMessage, key); -+PHP_METHOD(HttpMessage, next); -+ -+PHP_METHOD(HttpMessage, factory); -+PHP_METHOD(HttpMessage, fromEnv); -+ -+PHP_METHOD(HttpMessage, detach); -+PHP_METHOD(HttpMessage, prepend); -+PHP_METHOD(HttpMessage, reverse); -+ -+#endif -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_persistent_handle_api.h -@@ -0,0 +1,58 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_persistent_handle_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef HTTP_PERSISTENT_HANDLE_H -+#define HTTP_PERSISTENT_HANDLE_H -+ -+typedef void *(*http_persistent_handle_ctor)(void); -+typedef void (*http_persistent_handle_dtor)(void *handle); -+typedef void *(*http_persistent_handle_copy)(void *handle); -+ -+PHP_MINIT_FUNCTION(http_persistent_handle); -+PHP_MSHUTDOWN_FUNCTION(http_persistent_handle); -+ -+#define http_persistent_handle_provide(n, c, d, cc) _http_persistent_handle_provide_ex((n), strlen(n), (c), (d), (cc)) -+#define http_persistent_handle_provide_ex(n, l, c, d, cc) _http_persistent_handle_provide_ex((n), (l), (c), (d), (cc)) -+PHP_HTTP_API STATUS _http_persistent_handle_provide_ex(const char *name_str, size_t name_len, http_persistent_handle_ctor ctor, http_persistent_handle_dtor dtor, http_persistent_handle_copy copy); -+ -+#define http_persistent_handle_cleanup(n, c) _http_persistent_handle_cleanup_ex((n), strlen(n), (c) TSRMLS_CC) -+#define http_persistent_handle_cleanup_ex(n, l,c ) _http_persistent_handle_cleanup_ex((n), (l), (c) TSRMLS_CC) -+PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len, int current_ident_only TSRMLS_DC); -+ -+#define http_persistent_handle_statall() _http_persistent_handle_statall_ex(NULL TSRMLS_CC) -+#define http_persistent_handle_statall_ex(ht) _http_persistent_handle_statall_ex((ht) TSRMLS_CC) -+PHP_HTTP_API HashTable *_http_persistent_handle_statall_ex(HashTable *ht TSRMLS_DC); -+ -+#define http_persistent_handle_acquire(n, h) _http_persistent_handle_acquire_ex((n), strlen(n), (h) TSRMLS_CC) -+#define http_persistent_handle_acquire_ex(n, l, h) _http_persistent_handle_acquire_ex((n), (l), (h) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC); -+ -+#define http_persistent_handle_release(n, h) _http_persistent_handle_release_ex((n), strlen(n), (h) TSRMLS_CC) -+#define http_persistent_handle_release_ex(n, l, h) _http_persistent_handle_release_ex((n), (l), (h) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle TSRMLS_DC); -+ -+#define http_persistent_handle_accrete(n, oh, nh) _http_persistent_handle_accrete_ex((n), strlen(n), (oh), (nh) TSRMLS_CC) -+#define http_persistent_handle_accrete_ex(n, l, oh, nh) _http_persistent_handle_accrete_ex((n), (l), (oh), (nh) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_persistent_handle_accrete_ex(const char *name_str, size_t name_len, void *old_handle, void **new_handle TSRMLS_DC); -+ -+#endif /* HTTP_PERSISTENT_HANDLE_H */ -+ -+/* -+ * 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 -+ */ ---- /dev/null -+++ b/ext/http/php_http_querystring_api.h -@@ -0,0 +1,38 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_querystring_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_QUERYSTRING_API_H -+#define PHP_HTTP_QUERYSTRING_API_H -+ -+#ifdef HTTP_HAVE_ICONV -+#define http_querystring_xlate(a, p, ie, oe) _http_querystring_xlate((a), (p), (ie), (oe) TSRMLS_CC) -+PHP_HTTP_API int _http_querystring_xlate(zval *array, zval *param, const char *ie, const char *oe TSRMLS_DC); -+#endif -+ -+#define http_querystring_update(qa, qs) _http_querystring_update((qa), (qs) TSRMLS_CC) -+PHP_HTTP_API void _http_querystring_update(zval *qarray, zval *qstring TSRMLS_DC); -+ -+#define http_querystring_modify(q, p) _http_querystring_modify((q), (p) TSRMLS_CC) -+PHP_HTTP_API int _http_querystring_modify(zval *qarray, zval *params TSRMLS_DC); -+ -+#endif -+ -+/* -+ * 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 -+ */ ---- /dev/null -+++ b/ext/http/php_http_querystring_object.h -@@ -0,0 +1,78 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_querystring_object.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_QUERYSTRING_OBJECT_H -+#define PHP_HTTP_QUERYSTRING_OBJECT_H -+#ifdef ZEND_ENGINE_2 -+ -+typedef struct _http_querystring_object_t { -+ zend_object zo; -+} http_querystring_object; -+ -+#define HTTP_QUERYSTRING_TYPE_BOOL IS_BOOL -+#define HTTP_QUERYSTRING_TYPE_INT IS_LONG -+#define HTTP_QUERYSTRING_TYPE_FLOAT IS_DOUBLE -+#define HTTP_QUERYSTRING_TYPE_STRING IS_STRING -+#define HTTP_QUERYSTRING_TYPE_ARRAY IS_ARRAY -+#define HTTP_QUERYSTRING_TYPE_OBJECT IS_OBJECT -+ -+extern zend_class_entry *http_querystring_object_ce; -+extern zend_function_entry http_querystring_object_fe[]; -+ -+extern PHP_MINIT_FUNCTION(http_querystring_object); -+ -+#define http_querystring_object_new(ce) _http_querystring_object_new((ce) TSRMLS_CC) -+extern zend_object_value _http_querystring_object_new(zend_class_entry *ce TSRMLS_DC); -+#define http_querystring_object_new_ex(ce, n, ptr) _http_querystring_object_new_ex((ce), (n), (ptr) TSRMLS_CC) -+extern zend_object_value _http_querystring_object_new_ex(zend_class_entry *ce, void *nothing, http_querystring_object **ptr TSRMLS_DC); -+#define http_querystring_object_free(o) _http_querystring_object_free((o) TSRMLS_CC) -+extern void _http_querystring_object_free(zend_object *object TSRMLS_DC); -+ -+PHP_METHOD(HttpQueryString, __construct); -+PHP_METHOD(HttpQueryString, toString); -+PHP_METHOD(HttpQueryString, toArray); -+PHP_METHOD(HttpQueryString, get); -+PHP_METHOD(HttpQueryString, set); -+PHP_METHOD(HttpQueryString, mod); -+PHP_METHOD(HttpQueryString, getBool); -+PHP_METHOD(HttpQueryString, getInt); -+PHP_METHOD(HttpQueryString, getFloat); -+PHP_METHOD(HttpQueryString, getString); -+PHP_METHOD(HttpQueryString, getArray); -+PHP_METHOD(HttpQueryString, getObject); -+#ifdef HTTP_HAVE_ICONV -+PHP_METHOD(HttpQueryString, xlate); -+#endif -+PHP_METHOD(HttpQueryString, factory); -+#ifndef WONKY -+PHP_METHOD(HttpQueryString, singleton); -+#endif -+PHP_METHOD(HttpQueryString, serialize); -+PHP_METHOD(HttpQueryString, unserialize); -+PHP_METHOD(HttpQueryString, offsetGet); -+PHP_METHOD(HttpQueryString, offsetSet); -+PHP_METHOD(HttpQueryString, offsetExists); -+PHP_METHOD(HttpQueryString, offsetUnset); -+#endif -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_request_api.h -@@ -0,0 +1,144 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_request_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_REQUEST_API_H -+#define PHP_HTTP_REQUEST_API_H -+ -+#ifdef HTTP_HAVE_CURL -+ -+#include "php_http_request_body_api.h" -+#include "php_http_request_method_api.h" -+ -+extern PHP_MINIT_FUNCTION(http_request); -+extern PHP_MSHUTDOWN_FUNCTION(http_request); -+ -+typedef struct _http_request_t { -+ CURL *ch; -+ char *url; -+ http_request_method meth; -+ http_request_body *body; -+ -+ struct { -+ curl_infotype last_type; -+ phpstr request; -+ phpstr response; -+ } conv; -+ -+ struct { -+ phpstr cookies; -+ HashTable options; -+ struct curl_slist *headers; -+ } _cache; -+ -+ struct { -+ uint count; -+ double delay; -+ } _retry; -+ -+ char _error[CURL_ERROR_SIZE+1]; -+ zval *_progress_callback; -+ -+#ifdef ZTS -+ void ***tsrm_ls; -+#endif -+ -+ uint _in_progress_cb:1; -+ -+} http_request; -+ -+#ifndef pestrndup -+# define pestrndup(s,l,p) _pestrndup((s),(l),(p)) -+static inline void *_pestrndup(const void *s, size_t l, int p) -+{ -+ void *d = pemalloc(l+1, p); -+ memcpy(d, s, l); -+ ((char *) d)[l] = '\0'; -+ return d; -+} -+#endif -+ -+/* CURLOPT_PRIVATE storage living as long as a CURL handle */ -+typedef struct _http_request_storage_t { -+ char *url; -+ char *cookiestore; -+ char errorbuffer[CURL_ERROR_SIZE]; -+} http_request_storage; -+ -+static inline http_request_storage *http_request_storage_get(CURL *ch) -+{ -+ http_request_storage *st = NULL; -+ curl_easy_getinfo(ch, CURLINFO_PRIVATE, &st); -+ return st; -+} -+ -+#define http_curl_init(r) http_curl_init_ex(NULL, (r)) -+#define http_curl_init_ex(c, r) _http_curl_init_ex((c), (r) TSRMLS_CC) -+PHP_HTTP_API CURL *_http_curl_init_ex(CURL *ch, http_request *request TSRMLS_DC); -+ -+#define http_curl_free(c) _http_curl_free((c) TSRMLS_CC) -+PHP_HTTP_API void _http_curl_free(CURL **ch TSRMLS_DC); -+ -+#define http_curl_copy(c) _http_curl_copy((c) TSRMLS_CC) -+PHP_HTTP_API CURL *_http_curl_copy(CURL *ch TSRMLS_DC); -+ -+#define http_request_new() _http_request_init_ex(NULL, NULL, 0, NULL ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+#define http_request_init(r) _http_request_init_ex((r), NULL, 0, NULL ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+#define http_request_init_ex(r, c, m, u) _http_request_init_ex((r), (c), (m), (u) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+PHP_HTTP_API http_request *_http_request_init_ex(http_request *request, CURL *ch, http_request_method meth, const char *url ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC); -+ -+#define http_request_dtor(r) _http_request_dtor((r)) -+PHP_HTTP_API void _http_request_dtor(http_request *request); -+ -+#define http_request_free(r) _http_request_free((r)) -+PHP_HTTP_API void _http_request_free(http_request **request); -+ -+#define http_request_reset(r) _http_request_reset(r) -+PHP_HTTP_API void _http_request_reset(http_request *r); -+ -+#define http_request_enable_cookies(r) _http_request_enable_cookies(r) -+PHP_HTTP_API STATUS _http_request_enable_cookies(http_request *request); -+ -+#define http_request_reset_cookies(r, s) _http_request_reset_cookies((r), (s)) -+PHP_HTTP_API STATUS _http_request_reset_cookies(http_request *request, int session_only); -+ -+#define http_request_flush_cookies(r) _http_request_flush_cookies(r) -+PHP_HTTP_API STATUS _http_request_flush_cookies(http_request *request); -+ -+#define http_request_defaults(r) _http_request_defaults(r) -+PHP_HTTP_API void _http_request_defaults(http_request *request); -+ -+#define http_request_prepare(r, o) _http_request_prepare((r), (o)) -+PHP_HTTP_API STATUS _http_request_prepare(http_request *request, HashTable *options); -+ -+#define http_request_exec(r) _http_request_exec((r)) -+PHP_HTTP_API void _http_request_exec(http_request *request); -+ -+#define http_request_info(r, i) _http_request_info((r), (i)) -+PHP_HTTP_API void _http_request_info(http_request *request, HashTable *info); -+ -+#define http_request_set_progress_callback(r, cb) _http_request_set_progress_callback((r), (cb)) -+PHP_HTTP_API void _http_request_set_progress_callback(http_request *request, zval *cb); -+ -+#endif -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_request_body_api.h -@@ -0,0 +1,62 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_request_body_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_REQUEST_BODY_API_H -+#define PHP_HTTP_REQUEST_BODY_API_H -+ -+#ifdef HTTP_HAVE_CURL -+ -+#define HTTP_REQUEST_BODY_EMPTY 0 -+#define HTTP_REQUEST_BODY_CSTRING 1 -+#define HTTP_REQUEST_BODY_CURLPOST 2 -+#define HTTP_REQUEST_BODY_UPLOADFILE 3 -+typedef struct _http_request_body_t { -+ void *data; -+ size_t size; -+ uint type:3; -+ uint free:1; -+ uint priv:28; -+} http_request_body; -+ -+ -+#define http_request_body_new() http_request_body_init(NULL) -+#define http_request_body_init(b) http_request_body_init_ex((b), 0, NULL, 0, 0) -+#define http_request_body_init_ex(b, t, d, l, f) _http_request_body_init_ex((b), (t), (d), (l), (f) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+#define http_request_body_init_rel(b, t, d, l, f) _http_request_body_init_ex((b), (t), (d), (l), (f) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC TSRMLS_CC) -+PHP_HTTP_API http_request_body *_http_request_body_init_ex(http_request_body *body, int type, void *data, size_t len, zend_bool free ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC); -+ -+#define http_request_body_fill(b, fields, files) _http_request_body_fill((b), (fields), (files) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC TSRMLS_CC) -+PHP_HTTP_API http_request_body *_http_request_body_fill(http_request_body *body, HashTable *fields, HashTable *files ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC); -+ -+#define http_request_body_encode(b, s, l) _http_request_body_encode((b), (s), (l) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_request_body_encode(http_request_body *body, char **buf, size_t *len TSRMLS_DC); -+ -+#define http_request_body_dtor(b) _http_request_body_dtor((b) TSRMLS_CC) -+PHP_HTTP_API void _http_request_body_dtor(http_request_body *body TSRMLS_DC); -+ -+#define http_request_body_free(b) _http_request_body_free((b) TSRMLS_CC) -+PHP_HTTP_API void _http_request_body_free(http_request_body **body TSRMLS_DC); -+ -+#endif -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_request_datashare_api.h -@@ -0,0 +1,88 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_request_datashare_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_REQUEST_DATASHARE_API_H -+#define PHP_HTTP_REQUEST_DATASHARE_API_H -+#ifdef HTTP_HAVE_CURL -+#ifdef ZEND_ENGINE_2 -+ -+#ifdef ZTS -+typedef struct _http_request_datashare_lock_t { -+ CURL *ch; -+ MUTEX_T mx; -+} http_request_datashare_lock; -+ -+typedef union _http_request_datashare_handle_t { -+ zend_llist *list; -+ http_request_datashare_lock *locks; -+} http_request_datashare_handle; -+#else -+typedef struct _http_request_datashare_handle_t { -+ zend_llist *list; -+} http_request_datashare_handle; -+#endif -+ -+typedef struct _http_request_datashare_t { -+ CURLSH *ch; -+ zend_bool persistent; -+ http_request_datashare_handle handle; -+} http_request_datashare; -+ -+#define HTTP_RSHARE_HANDLES(s) ((s)->persistent ? &HTTP_G->request.datashare.handles : (s)->handle.list) -+ -+#define http_request_datashare_global_get _http_request_datashare_global_get -+extern http_request_datashare *_http_request_datashare_global_get(void); -+ -+extern PHP_MINIT_FUNCTION(http_request_datashare); -+extern PHP_MSHUTDOWN_FUNCTION(http_request_datashare); -+extern PHP_RINIT_FUNCTION(http_request_datashare); -+extern PHP_RSHUTDOWN_FUNCTION(http_request_datashare); -+ -+#define http_request_datashare_new() _http_request_datashare_init_ex(NULL, 0 TSRMLS_CC) -+#define http_request_datashare_init(s) _http_request_datashare_init_ex((s), 0 TSRMLS_CC) -+#define http_request_datashare_init_ex(s, p) _http_request_datashare_init_ex((s), (p) TSRMLS_CC) -+PHP_HTTP_API http_request_datashare *_http_request_datashare_init_ex(http_request_datashare *share, zend_bool persistent TSRMLS_DC); -+ -+#define http_request_datashare_attach(s, r) _http_request_datashare_attach((s), (r) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_request_datashare_attach(http_request_datashare *share, zval *request TSRMLS_DC); -+ -+#define http_request_datashare_detach(s, r) _http_request_datashare_detach((s), (r) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_request_datashare_detach(http_request_datashare *share, zval *request TSRMLS_DC); -+ -+#define http_request_datashare_detach_all(s) _http_request_datashare_detach_all((s) TSRMLS_CC) -+PHP_HTTP_API void _http_request_datashare_detach_all(http_request_datashare *share TSRMLS_DC); -+ -+#define http_request_datashare_dtor(s) _http_request_datashare_dtor((s) TSRMLS_CC) -+PHP_HTTP_API void _http_request_datashare_dtor(http_request_datashare *share TSRMLS_DC); -+ -+#define http_request_datashare_free(s) _http_request_datashare_free((s) TSRMLS_CC) -+PHP_HTTP_API void _http_request_datashare_free(http_request_datashare **share TSRMLS_DC); -+ -+#define http_request_datashare_set(s, o, l, e) _http_request_datashare_set((s), (o), (l), (e) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_request_datashare_set(http_request_datashare *share, const char *option, size_t option_len, zend_bool enable TSRMLS_DC); -+ -+ -+#endif -+#endif -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_request_int.h -@@ -0,0 +1,72 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_request_int.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#if defined(ZTS) && defined(HTTP_HAVE_SSL) -+# ifdef PHP_WIN32 -+# define HTTP_NEED_OPENSSL_TSL -+# include -+# else /* !PHP_WIN32 */ -+# if defined(HTTP_HAVE_OPENSSL) -+# define HTTP_NEED_OPENSSL_TSL -+# include -+# elif defined(HTTP_HAVE_GNUTLS) -+# define HTTP_NEED_GNUTLS_TSL -+# include -+# else -+# warning \ -+ "libcurl was compiled with SSL support, but configure could not determine which" \ -+ "library was used; thus no SSL crypto locking callbacks will be set, which may " \ -+ "cause random crashes on SSL requests" -+# endif /* HTTP_HAVE_OPENSSL || HTTP_HAVE_GNUTLS */ -+# endif /* PHP_WIN32 */ -+#endif /* ZTS && HTTP_HAVE_SSL */ -+ -+#define HTTP_CURL_OPT(OPTION, p) curl_easy_setopt((request->ch), OPTION, (p)) -+ -+#define HTTP_CURL_OPT_STRING(OPTION, ldiff, obdc) \ -+ { \ -+ char *K = #OPTION; \ -+ HTTP_CURL_OPT_STRING_EX(K+lenof("CURLOPT_KEY")+ldiff, OPTION, obdc); \ -+ } -+#define HTTP_CURL_OPT_STRING_EX(keyname, optname, obdc) \ -+ if (!strcasecmp(key.str, keyname)) { \ -+ zval *copy = http_request_option_cache_ex(request, keyname, strlen(keyname)+1, 0, http_zsep(IS_STRING, *param)); \ -+ if (obdc) { \ -+ HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(copy), return FAILURE); \ -+ } \ -+ HTTP_CURL_OPT(optname, Z_STRVAL_P(copy)); \ -+ zval_ptr_dtor(©); \ -+ continue; \ -+ } -+#define HTTP_CURL_OPT_LONG(OPTION, ldiff) \ -+ { \ -+ char *K = #OPTION; \ -+ HTTP_CURL_OPT_LONG_EX(K+lenof("CURLOPT_KEY")+ldiff, OPTION); \ -+ } -+#define HTTP_CURL_OPT_LONG_EX(keyname, optname) \ -+ if (!strcasecmp(key.str, keyname)) { \ -+ zval *copy = http_zsep(IS_LONG, *param); \ -+ HTTP_CURL_OPT(optname, Z_LVAL_P(copy)); \ -+ zval_ptr_dtor(©); \ -+ continue; \ -+ } -+ -+/* -+ * 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 -+ */ ---- /dev/null -+++ b/ext/http/php_http_request_method_api.h -@@ -0,0 +1,85 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_request_method_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_REQUEST_METHOD_API_H -+#define PHP_HTTP_REQUEST_METHOD_API_H -+ -+typedef enum _http_request_method_t { -+ /* force the enum to be signed */ -+ HTTP_NEG_REQUEST_METHOD =-1, -+ HTTP_NO_REQUEST_METHOD = 0, -+ /* HTTP/1.1 */ -+ HTTP_GET = 1, -+ HTTP_HEAD = 2, -+ HTTP_POST = 3, -+ HTTP_PUT = 4, -+ HTTP_DELETE = 5, -+ HTTP_OPTIONS = 6, -+ HTTP_TRACE = 7, -+ HTTP_CONNECT = 8, -+ /* WebDAV - RFC 2518 */ -+ HTTP_PROPFIND = 9, -+ HTTP_PROPPATCH = 10, -+ HTTP_MKCOL = 11, -+ HTTP_COPY = 12, -+ HTTP_MOVE = 13, -+ HTTP_LOCK = 14, -+ HTTP_UNLOCK = 15, -+ /* WebDAV Versioning - RFC 3253 */ -+ HTTP_VERSION_CONTROL = 16, -+ HTTP_REPORT = 17, -+ HTTP_CHECKOUT = 18, -+ HTTP_CHECKIN = 19, -+ HTTP_UNCHECKOUT = 20, -+ HTTP_MKWORKSPACE = 21, -+ HTTP_UPDATE = 22, -+ HTTP_LABEL = 23, -+ HTTP_MERGE = 24, -+ HTTP_BASELINE_CONTROL = 25, -+ HTTP_MKACTIVITY = 26, -+ /* WebDAV Access Control - RFC 3744 */ -+ HTTP_ACL = 27, -+ HTTP_MAX_REQUEST_METHOD = 28 -+} http_request_method; -+ -+#define HTTP_MIN_REQUEST_METHOD (HTTP_NO_REQUEST_METHOD + 1) -+#define HTTP_STD_REQUEST_METHOD(m) ((m > HTTP_NO_REQUEST_METHOD) && (m < HTTP_MAX_REQUEST_METHOD)) -+ -+extern PHP_MINIT_FUNCTION(http_request_method); -+extern PHP_RINIT_FUNCTION(http_request_method); -+extern PHP_RSHUTDOWN_FUNCTION(http_request_method); -+ -+#define http_request_method_name(m) _http_request_method_name((m) TSRMLS_CC) -+PHP_HTTP_API const char *_http_request_method_name(http_request_method m TSRMLS_DC); -+ -+#define http_request_method_exists(u, l, c) _http_request_method_exists((u), (l), (c) TSRMLS_CC) -+PHP_HTTP_API int _http_request_method_exists(int by_name, http_request_method id, const char *name TSRMLS_DC); -+ -+#define http_request_method_register(m, l) _http_request_method_register((m), (l) TSRMLS_CC) -+PHP_HTTP_API int _http_request_method_register(const char *method, int method_name_len TSRMLS_DC); -+ -+#define http_request_method_unregister(mn) _http_request_method_unregister((mn) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_request_method_unregister(int method TSRMLS_DC); -+ -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_request_object.h -@@ -0,0 +1,118 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_request_object.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_REQUEST_OBJECT_H -+#define PHP_HTTP_REQUEST_OBJECT_H -+#ifdef HTTP_HAVE_CURL -+#ifdef ZEND_ENGINE_2 -+ -+#include "php_http_request_api.h" -+#include "php_http_request_pool_api.h" -+#include "php_http_request_datashare_api.h" -+ -+typedef struct _http_request_object_t { -+ zend_object zo; -+ http_request *request; -+ http_request_pool *pool; -+ http_request_datashare *share; -+} http_request_object; -+ -+extern zend_class_entry *http_request_object_ce; -+extern zend_function_entry http_request_object_fe[]; -+ -+extern PHP_MINIT_FUNCTION(http_request_object); -+ -+#define http_request_object_new(ce) _http_request_object_new((ce) TSRMLS_CC) -+extern zend_object_value _http_request_object_new(zend_class_entry *ce TSRMLS_DC); -+#define http_request_object_new_ex(ce, ch, ptr) _http_request_object_new_ex((ce), (ch), (ptr) TSRMLS_CC) -+extern zend_object_value _http_request_object_new_ex(zend_class_entry *ce, CURL *ch, http_request_object **ptr TSRMLS_DC); -+#define http_request_object_clone(zv) _http_request_object_clone_obj((zv) TSRMLS_CC) -+extern zend_object_value _http_request_object_clone_obj(zval *zobject TSRMLS_DC); -+#define http_request_object_free(o) _http_request_object_free((o) TSRMLS_CC) -+extern void _http_request_object_free(zend_object *object TSRMLS_DC); -+ -+#define http_request_object_requesthandler(req, this) _http_request_object_requesthandler((req), (this) TSRMLS_CC) -+extern STATUS _http_request_object_requesthandler(http_request_object *obj, zval *this_ptr TSRMLS_DC); -+#define http_request_object_responsehandler(req, this) _http_request_object_responsehandler((req), (this) TSRMLS_CC) -+extern STATUS _http_request_object_responsehandler(http_request_object *obj, zval *this_ptr TSRMLS_DC); -+ -+PHP_METHOD(HttpRequest, __construct); -+PHP_METHOD(HttpRequest, setOptions); -+PHP_METHOD(HttpRequest, getOptions); -+PHP_METHOD(HttpRequest, addSslOptions); -+PHP_METHOD(HttpRequest, setSslOptions); -+PHP_METHOD(HttpRequest, getSslOptions); -+PHP_METHOD(HttpRequest, addHeaders); -+PHP_METHOD(HttpRequest, getHeaders); -+PHP_METHOD(HttpRequest, setHeaders); -+PHP_METHOD(HttpRequest, addCookies); -+PHP_METHOD(HttpRequest, getCookies); -+PHP_METHOD(HttpRequest, setCookies); -+PHP_METHOD(HttpRequest, enableCookies); -+PHP_METHOD(HttpRequest, resetCookies); -+PHP_METHOD(HttpRequest, flushCookies); -+PHP_METHOD(HttpRequest, setMethod); -+PHP_METHOD(HttpRequest, getMethod); -+PHP_METHOD(HttpRequest, setUrl); -+PHP_METHOD(HttpRequest, getUrl); -+PHP_METHOD(HttpRequest, setContentType); -+PHP_METHOD(HttpRequest, getContentType); -+PHP_METHOD(HttpRequest, setQueryData); -+PHP_METHOD(HttpRequest, getQueryData); -+PHP_METHOD(HttpRequest, addQueryData); -+PHP_METHOD(HttpRequest, setPostFields); -+PHP_METHOD(HttpRequest, getPostFields); -+PHP_METHOD(HttpRequest, addPostFields); -+PHP_METHOD(HttpRequest, getBody); -+PHP_METHOD(HttpRequest, setBody); -+PHP_METHOD(HttpRequest, addBody); -+PHP_METHOD(HttpRequest, addPostFile); -+PHP_METHOD(HttpRequest, setPostFiles); -+PHP_METHOD(HttpRequest, getPostFiles); -+PHP_METHOD(HttpRequest, setPutFile); -+PHP_METHOD(HttpRequest, getPutFile); -+PHP_METHOD(HttpRequest, getPutData); -+PHP_METHOD(HttpRequest, setPutData); -+PHP_METHOD(HttpRequest, addPutData); -+PHP_METHOD(HttpRequest, send); -+PHP_METHOD(HttpRequest, getResponseData); -+PHP_METHOD(HttpRequest, getResponseHeader); -+PHP_METHOD(HttpRequest, getResponseCookies); -+PHP_METHOD(HttpRequest, getResponseCode); -+PHP_METHOD(HttpRequest, getResponseStatus); -+PHP_METHOD(HttpRequest, getResponseBody); -+PHP_METHOD(HttpRequest, getResponseInfo); -+PHP_METHOD(HttpRequest, getResponseMessage); -+PHP_METHOD(HttpRequest, getRawResponseMessage); -+PHP_METHOD(HttpRequest, getRequestMessage); -+PHP_METHOD(HttpRequest, getRawRequestMessage); -+PHP_METHOD(HttpRequest, getHistory); -+PHP_METHOD(HttpRequest, clearHistory); -+PHP_METHOD(HttpRequest, getMessageClass); -+PHP_METHOD(HttpRequest, setMessageClass); -+PHP_METHOD(HttpRequest, factory); -+ -+#endif -+#endif -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_request_pool_api.h -@@ -0,0 +1,97 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_request_pool_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_REQUEST_POOL_API_H -+#define PHP_HTTP_REQUEST_POOL_API_H -+#ifdef HTTP_HAVE_CURL -+#ifdef ZEND_ENGINE_2 -+ -+typedef struct _http_request_pool_t { -+ CURLM *ch; -+ zend_llist finished; -+ zend_llist handles; -+ int unfinished; -+#ifdef ZTS -+ void ***tsrm_ls; -+#endif -+#ifdef HTTP_HAVE_EVENT -+ struct event *timeout; -+ unsigned useevents:1; -+ unsigned runsocket:1; -+#endif -+} http_request_pool; -+ -+typedef int (*http_request_pool_apply_func)(http_request_pool *pool, zval *request); -+typedef int (*http_request_pool_apply_with_arg_func)(http_request_pool *pool, zval *request, void *arg); -+ -+PHP_MINIT_FUNCTION(http_request_pool); -+#ifdef HTTP_HAVE_EVENT -+PHP_RINIT_FUNCTION(http_request_pool); -+#endif -+ -+#define http_request_pool_timeout _http_request_pool_timeout -+extern struct timeval *_http_request_pool_timeout(http_request_pool *pool, struct timeval *timeout); -+ -+#define http_request_pool_responsehandler _http_request_pool_responsehandler -+extern void _http_request_pool_responsehandler(http_request_pool *pool); -+ -+#define http_request_pool_apply_responsehandler _http_request_pool_responsehandler -+extern int _http_request_pool_apply_responsehandler(http_request_pool *pool, zval *req, void *ch); -+ -+#define http_request_pool_init(p) _http_request_pool_init((p) TSRMLS_CC) -+PHP_HTTP_API http_request_pool *_http_request_pool_init(http_request_pool *pool TSRMLS_DC); -+ -+#define http_request_pool_attach(p, r) _http_request_pool_attach((p), (r)) -+PHP_HTTP_API STATUS _http_request_pool_attach(http_request_pool *pool, zval *request); -+ -+#define http_request_pool_detach(p, r) _http_request_pool_detach((p), (r)) -+PHP_HTTP_API STATUS _http_request_pool_detach(http_request_pool *pool, zval *request); -+ -+#define http_request_pool_apply(p, f) _http_request_pool_apply((p), (f)) -+PHP_HTTP_API void _http_request_pool_apply(http_request_pool *pool, http_request_pool_apply_func cb); -+ -+#define http_request_pool_apply_with_arg(p, f, a) _http_request_pool_apply_with_arg((p), (f), (a)) -+PHP_HTTP_API void _http_request_pool_apply_with_arg(http_request_pool *pool, http_request_pool_apply_with_arg_func cb, void *arg); -+ -+#define http_request_pool_detach_all(p) _http_request_pool_detach_all((p)) -+PHP_HTTP_API void _http_request_pool_detach_all(http_request_pool *pool); -+ -+#define http_request_pool_send(p) _http_request_pool_send((p)) -+PHP_HTTP_API STATUS _http_request_pool_send(http_request_pool *pool); -+ -+#define http_request_pool_select _http_request_pool_select -+PHP_HTTP_API STATUS _http_request_pool_select(http_request_pool *pool); -+ -+#define http_request_pool_select_ex _http_request_pool_select_ex -+PHP_HTTP_API STATUS _http_request_pool_select_ex(http_request_pool *pool, struct timeval *custom_timeout); -+ -+#define http_request_pool_perform(p) _http_request_pool_perform((p)) -+PHP_HTTP_API int _http_request_pool_perform(http_request_pool *pool); -+ -+#define http_request_pool_dtor(p) _http_request_pool_dtor((p)) -+PHP_HTTP_API void _http_request_pool_dtor(http_request_pool *pool); -+ -+#endif -+#endif -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_requestdatashare_object.h -@@ -0,0 +1,59 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_requestdatashare_object.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_REQUEST_DATASHARE_OBJECT_H -+#define PHP_HTTP_REQUEST_DATASHARE_OBJECT_H -+#ifdef HTTP_HAVE_CURL -+#ifdef ZEND_ENGINE_2 -+ -+typedef struct _http_requestdatashare_object_t { -+ zend_object zo; -+ http_request_datashare *share; -+} http_requestdatashare_object; -+ -+extern zend_class_entry *http_requestdatashare_object_ce; -+extern zend_function_entry http_requestdatashare_object_fe[]; -+ -+extern PHP_MINIT_FUNCTION(http_requestdatashare_object); -+ -+#define http_requestdatashare_object_new(ce) _http_requestdatashare_object_new((ce) TSRMLS_CC) -+extern zend_object_value _http_requestdatashare_object_new(zend_class_entry *ce TSRMLS_DC); -+#define http_requestdatashare_object_new_ex(ce, s, ptr) _http_requestdatashare_object_new_ex((ce), (s), (ptr) TSRMLS_CC) -+extern zend_object_value _http_requestdatashare_object_new_ex(zend_class_entry *ce, http_request_datashare *share, http_requestdatashare_object **ptr TSRMLS_DC); -+#define http_requestdatashare_object_free(o) _http_requestdatashare_object_free((o) TSRMLS_CC) -+extern void _http_requestdatashare_object_free(zend_object *object TSRMLS_DC); -+ -+PHP_METHOD(HttpRequestDataShare, __destruct); -+PHP_METHOD(HttpRequestDataShare, count); -+PHP_METHOD(HttpRequestDataShare, attach); -+PHP_METHOD(HttpRequestDataShare, detach); -+PHP_METHOD(HttpRequestDataShare, reset); -+PHP_METHOD(HttpRequestDataShare, factory); -+#ifndef WONKY -+PHP_METHOD(HttpRequestDataShare, singleton); -+#endif -+ -+#endif -+#endif -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_requestpool_object.h -@@ -0,0 +1,69 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_requestpool_object.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_REQUESTPOOL_OBJECT_H -+#define PHP_HTTP_REQUESTPOOL_OBJECT_H -+#ifdef HTTP_HAVE_CURL -+#ifdef ZEND_ENGINE_2 -+ -+typedef struct _http_requestpool_object_t { -+ zend_object zo; -+ http_request_pool pool; -+ struct { -+ long pos; -+ } iterator; -+} http_requestpool_object; -+ -+extern zend_class_entry *http_requestpool_object_ce; -+extern zend_function_entry http_requestpool_object_fe[]; -+ -+extern PHP_MINIT_FUNCTION(http_requestpool_object); -+ -+#define http_requestpool_object_new(ce) _http_requestpool_object_new(ce TSRMLS_CC) -+extern zend_object_value _http_requestpool_object_new(zend_class_entry *ce TSRMLS_DC); -+#define http_requestpool_object_free(o) _http_requestpool_object_free(o TSRMLS_CC) -+extern void _http_requestpool_object_free(zend_object *object TSRMLS_DC); -+ -+PHP_METHOD(HttpRequestPool, __construct); -+PHP_METHOD(HttpRequestPool, __destruct); -+PHP_METHOD(HttpRequestPool, attach); -+PHP_METHOD(HttpRequestPool, detach); -+PHP_METHOD(HttpRequestPool, send); -+PHP_METHOD(HttpRequestPool, reset); -+PHP_METHOD(HttpRequestPool, socketPerform); -+PHP_METHOD(HttpRequestPool, socketSelect); -+PHP_METHOD(HttpRequestPool, valid); -+PHP_METHOD(HttpRequestPool, current); -+PHP_METHOD(HttpRequestPool, key); -+PHP_METHOD(HttpRequestPool, next); -+PHP_METHOD(HttpRequestPool, rewind); -+PHP_METHOD(HttpRequestPool, count); -+PHP_METHOD(HttpRequestPool, getAttachedRequests); -+PHP_METHOD(HttpRequestPool, getFinishedRequests); -+PHP_METHOD(HttpRequestPool, enablePipelining); -+PHP_METHOD(HttpRequestPool, enableEvents); -+ -+#endif -+#endif -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_response_object.h -@@ -0,0 +1,67 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_response_object.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_RESPONSE_OBJECT_H -+#define PHP_HTTP_RESPONSE_OBJECT_H -+#ifdef ZEND_ENGINE_2 -+#ifndef WONKY -+ -+extern zend_class_entry *http_response_object_ce; -+extern zend_function_entry http_response_object_fe[]; -+ -+extern PHP_MINIT_FUNCTION(http_response_object); -+ -+PHP_METHOD(HttpResponse, setHeader); -+PHP_METHOD(HttpResponse, getHeader); -+PHP_METHOD(HttpResponse, setETag); -+PHP_METHOD(HttpResponse, getETag); -+PHP_METHOD(HttpResponse, setLastModified); -+PHP_METHOD(HttpResponse, getLastModified); -+PHP_METHOD(HttpResponse, setContentDisposition); -+PHP_METHOD(HttpResponse, getContentDisposition); -+PHP_METHOD(HttpResponse, setContentType); -+PHP_METHOD(HttpResponse, getContentType); -+PHP_METHOD(HttpResponse, guessContentType); -+PHP_METHOD(HttpResponse, setCache); -+PHP_METHOD(HttpResponse, getCache); -+PHP_METHOD(HttpResponse, setCacheControl); -+PHP_METHOD(HttpResponse, getCacheControl); -+PHP_METHOD(HttpResponse, setGzip); -+PHP_METHOD(HttpResponse, getGzip); -+PHP_METHOD(HttpResponse, setThrottleDelay); -+PHP_METHOD(HttpResponse, getThrottleDelay); -+PHP_METHOD(HttpResponse, setBufferSize); -+PHP_METHOD(HttpResponse, getBufferSize); -+PHP_METHOD(HttpResponse, setData); -+PHP_METHOD(HttpResponse, getData); -+PHP_METHOD(HttpResponse, setFile); -+PHP_METHOD(HttpResponse, getFile); -+PHP_METHOD(HttpResponse, setStream); -+PHP_METHOD(HttpResponse, getStream); -+PHP_METHOD(HttpResponse, send); -+PHP_METHOD(HttpResponse, capture); -+ -+#endif -+#endif -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_send_api.h -@@ -0,0 +1,91 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_send_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_SEND_API_H -+#define PHP_HTTP_SEND_API_H -+ -+typedef enum _http_send_mode_t { -+ SEND_DATA, -+ SEND_RSRC -+} http_send_mode; -+ -+#define HTTP_REDIRECT 0L -+#define HTTP_REDIRECT_PERM 301L -+#define HTTP_REDIRECT_FOUND 302L -+#define HTTP_REDIRECT_POST 303L -+#define HTTP_REDIRECT_PROXY 305L -+#define HTTP_REDIRECT_TEMP 307L -+ -+extern PHP_MINIT_FUNCTION(http_send); -+ -+#define http_send_status(s) sapi_header_op(SAPI_HEADER_SET_STATUS, (void *) (long) (s) TSRMLS_CC) -+#define http_send_header(n, v, r) _http_send_header_ex((n), strlen(n), (v), strlen(v), (r), NULL TSRMLS_CC) -+#define http_send_header_ex(n, nl, v, vl, r, s) _http_send_header_ex((n), (nl), (v), (vl), (r), (s) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_send_header_ex(const char *name, size_t name_len, const char *value, size_t value_len, zend_bool replace, char **sent_header TSRMLS_DC); -+#define http_send_header_string(h) _http_send_status_header_ex(0, (h), strlen(h), 1 TSRMLS_CC) -+#define http_send_header_string_ex(h, l, r) _http_send_status_header_ex(0, (h), (l), (r) TSRMLS_CC) -+#define http_send_status_header(s, h) _http_send_status_header_ex((s), (h), (h)?strlen(h):0, 1 TSRMLS_CC) -+#define http_send_status_header_ex(s, h, l, r) _http_send_status_header_ex((s), (h), (l), (r) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_send_status_header_ex(int status, const char *header, size_t header_len, zend_bool replace TSRMLS_DC); -+ -+#define http_send_header_zval(n, z, r) http_send_header_zval_ex((n), strlen(n), (z), (r)) -+#define http_send_header_zval_ex(n, l, z, r) _http_send_header_zval_ex((n), (l), (z), (r) TSRMLS_CC) -+PHP_HTTP_API void _http_send_header_zval_ex(const char *name, size_t name_len, zval **val, zend_bool replace TSRMLS_DC); -+ -+#define http_hide_header(h) http_hide_header_ex((h), strlen(h)) -+#define http_hide_header_ex(h, l) _http_hide_header_ex((h), (l) TSRMLS_CC) -+PHP_HTTP_API void _http_hide_header_ex(const char *name, size_t name_len TSRMLS_DC); -+ -+#define http_send_last_modified(t) _http_send_last_modified_ex((t), NULL TSRMLS_CC) -+#define http_send_last_modified_ex(t, s) _http_send_last_modified_ex((t), (s) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_send_last_modified_ex(time_t t, char **sent_header TSRMLS_DC); -+ -+#define http_send_etag(e, l) _http_send_etag_ex((e), (l), NULL TSRMLS_CC) -+#define http_send_etag_ex(e, l, s) _http_send_etag_ex((e), (l), (s) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_send_etag_ex(const char *etag, size_t etag_len, char **sent_header TSRMLS_DC); -+ -+#define http_send_cache_control(cc, cl) http_send_header_ex("Cache-Control", lenof("Cache-Control"), (cc), (cl), 1, NULL) -+ -+#define http_send_content_type(c, l) _http_send_content_type((c), (l) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_send_content_type(const char *content_type, size_t ct_len TSRMLS_DC); -+ -+#define http_send_content_disposition(f, l, i) _http_send_content_disposition((f), (l), (i) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_send_content_disposition(const char *filename, size_t f_len, zend_bool send_inline TSRMLS_DC); -+ -+#define http_send_data(d, l) http_send((d), (l), SEND_DATA) -+#define http_send_data_ex(d, l, nc) http_send_ex((d), (l), SEND_DATA, (nc)) -+#define http_send(d, s, m) _http_send_ex((d), (s), (m), 0 TSRMLS_CC) -+#define http_send_ex(d, s, m, nc) _http_send_ex((d), (s), (m), (nc) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_send_ex(const void *data, size_t data_size, http_send_mode mode, zend_bool no_cache TSRMLS_DC); -+ -+#define http_send_file(f) http_send_stream_ex(php_stream_open_wrapper_ex(f, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT), 1, 0) -+#define http_send_file_ex(f, nc) http_send_stream_ex(php_stream_open_wrapper_ex(f, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT), 1, (nc)) -+#define http_send_stream(s) http_send_stream_ex((s), 0, 0) -+#define http_send_stream_ex(s, c, nc) _http_send_stream_ex((s), (c), (nc) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_send_stream_ex(php_stream *s, zend_bool close_stream, zend_bool no_cache TSRMLS_DC); -+ -+#define http_guess_content_type(mf, mm, d, l, m) _http_guess_content_type((mf), (mm), (d), (l), (m) TSRMLS_CC) -+PHP_HTTP_API char *_http_guess_content_type(const char *magic_file, long magic_mode, void *data_ptr, size_t data_len, http_send_mode mode TSRMLS_DC); -+ -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_std_defs.h -@@ -0,0 +1,410 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_std_defs.h 323304 2012-02-17 21:13:24Z mike $ */ -+ -+#ifndef PHP_HTTP_STD_DEFS_H -+#define PHP_HTTP_STD_DEFS_H -+ -+#if defined(PHP_WIN32) -+# if defined(HTTP_EXPORTS) -+# define PHP_HTTP_API __declspec(dllexport) -+# elif defined(COMPILE_DL_HTTP) -+# define PHP_HTTP_API __declspec(dllimport) -+# else -+# define PHP_HTTP_API -+# endif -+#else -+# define PHP_HTTP_API -+#endif -+ -+/* make functions that return SUCCESS|FAILURE more obvious */ -+typedef int STATUS; -+ -+/* lenof() */ -+#define lenof(S) (sizeof(S) - 1) -+ -+#ifndef MIN -+# define MIN(a,b) (ab?a:b) -+#endif -+ -+/* STR_SET() */ -+#ifndef STR_SET -+# define STR_SET(STR, SET) \ -+ { \ -+ STR_FREE(STR); \ -+ STR = SET; \ -+ } -+#endif -+ -+#define STR_PTR(s) (s?s:"") -+ -+#define INIT_ZARR(zv, ht) \ -+ { \ -+ INIT_PZVAL(&(zv)); \ -+ Z_TYPE(zv) = IS_ARRAY; \ -+ Z_ARRVAL(zv) = (ht); \ -+ } -+ -+/* return bool (v == SUCCESS) */ -+#define RETVAL_SUCCESS(v) RETVAL_BOOL(SUCCESS == (v)) -+#define RETURN_SUCCESS(v) RETURN_BOOL(SUCCESS == (v)) -+/* return object(values) */ -+#define RETVAL_OBJECT(o, addref) \ -+ RETVAL_OBJVAL((o)->value.obj, addref) -+#define RETURN_OBJECT(o, addref) \ -+ RETVAL_OBJECT(o, addref); \ -+ return -+#define RETVAL_OBJVAL(ov, addref) \ -+ ZVAL_OBJVAL(return_value, ov, addref) -+#define RETURN_OBJVAL(ov, addref) \ -+ RETVAL_OBJVAL(ov, addref); \ -+ return -+#define ZVAL_OBJVAL(zv, ov, addref) \ -+ (zv)->type = IS_OBJECT; \ -+ (zv)->value.obj = (ov);\ -+ if (addref && Z_OBJ_HT_P(zv)->add_ref) { \ -+ Z_OBJ_HT_P(zv)->add_ref((zv) TSRMLS_CC); \ -+ } -+/* return property */ -+#define RETVAL_PROP(n) RETVAL_PROP_EX(getThis(), n) -+#define RETURN_PROP(n) RETURN_PROP_EX(getThis(), n) -+#define RETVAL_PROP_EX(this, n) \ -+ { \ -+ zval *__prop = zend_read_property(THIS_CE, this, ZEND_STRS(#n)-1, 0 TSRMLS_CC); \ -+ RETVAL_ZVAL(__prop, 1, 0); \ -+ } -+#define RETURN_PROP_EX(this, n) \ -+ { \ -+ zval *__prop = zend_read_property(THIS_CE, this, ZEND_STRS(#n)-1, 0 TSRMLS_CC); \ -+ RETURN_ZVAL(__prop, 1, 0); \ -+ } -+ -+/* function accepts no args */ -+#define NO_ARGS zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ""); -+ -+/* CR LF */ -+#define HTTP_CRLF "\r\n" -+ -+/* default cache control */ -+#define HTTP_DEFAULT_CACHECONTROL "private, must-revalidate, max-age=0" -+ -+/* max URL length */ -+#define HTTP_URL_MAXLEN 4096 -+ -+/* max request method length */ -+#define HTTP_REQUEST_METHOD_MAXLEN 31 -+ -+/* def URL arg separator */ -+#define HTTP_URL_ARGSEP "&" -+ -+/* send buffer size */ -+#define HTTP_SENDBUF_SIZE 40960 -+ -+/* CURL buffer size */ -+#define HTTP_CURLBUF_SIZE 16384 -+ -+/* known methods */ -+#define HTTP_KNOWN_METHODS \ -+ /* HTTP 1.1 */ \ -+ "GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE, CONNECT, " \ -+ /* WebDAV - RFC 2518 */ \ -+ "PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK, " \ -+ /* WebDAV Versioning - RFC 3253 */ \ -+ "VERSION-CONTROL, REPORT, CHECKOUT, CHECKIN, UNCHECKOUT, " \ -+ "MKWORKSPACE, UPDATE, LABEL, MERGE, BASELINE-CONTROL, MKACTIVITY, " \ -+ /* WebDAV Access Control - RFC 3744 */ \ -+ "ACL, " \ -+ /* END */ -+ -+#ifdef ZEND_ENGINE_2 -+# include "ext/standard/file.h" -+# define HTTP_DEFAULT_STREAM_CONTEXT FG(default_context) -+#else -+# define HTTP_DEFAULT_STREAM_CONTEXT NULL -+#endif -+ -+#define HTTP_PHP_INI_ENTRY(entry, default, scope, updater, global) \ -+ STD_PHP_INI_ENTRY(entry, default, scope, updater, global, zend_http_globals, http_globals) -+#define HTTP_PHP_INI_ENTRY_EX(entry, default, scope, updater, displayer, global) \ -+ STD_PHP_INI_ENTRY_EX(entry, default, scope, updater, global, zend_http_globals, http_globals, displayer) -+ -+ -+#define HTTP_LONG_CONSTANT(name, const) REGISTER_LONG_CONSTANT(name, const, CONST_CS | CONST_PERSISTENT) -+ -+/* {{{ objects & properties */ -+#ifdef ZEND_ENGINE_2 -+ -+# define HTTP_STATIC_ME_ALIAS(me, al, ai) ZEND_FENTRY(me, ZEND_FN(al), ai, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) -+ -+# define HTTP_REGISTER_CLASS_EX(classname, name, parent, flags) \ -+ { \ -+ zend_class_entry ce; \ -+ memset(&ce, 0, sizeof(zend_class_entry)); \ -+ INIT_CLASS_ENTRY(ce, #classname, name## _fe); \ -+ ce.create_object = _ ##name## _new; \ -+ name## _ce = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \ -+ name## _ce->ce_flags |= flags; \ -+ memcpy(& name## _handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); \ -+ } -+ -+# define HTTP_REGISTER_CLASS(classname, name, parent, flags) \ -+ { \ -+ zend_class_entry ce; \ -+ memset(&ce, 0, sizeof(zend_class_entry)); \ -+ INIT_CLASS_ENTRY(ce, #classname, name## _fe); \ -+ ce.create_object = NULL; \ -+ name## _ce = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \ -+ name## _ce->ce_flags |= flags; \ -+ } -+ -+# define HTTP_REGISTER_EXCEPTION(classname, cename, parent) \ -+ { \ -+ zend_class_entry ce; \ -+ memset(&ce, 0, sizeof(zend_class_entry)); \ -+ INIT_CLASS_ENTRY(ce, #classname, NULL); \ -+ ce.create_object = NULL; \ -+ cename = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \ -+ } -+ -+# define getObject(t, o) getObjectEx(t, o, getThis()) -+# define getObjectEx(t, o, v) t * o = ((t *) zend_object_store_get_object(v TSRMLS_CC)) -+# define putObject(t, o) zend_objects_store_put(o, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) _ ##t## _free, NULL TSRMLS_CC); -+# if defined(ZEND_ENGINE_2_4) -+# define freeObject(o) \ -+ zend_object_std_dtor(o TSRMLS_CC); \ -+ efree(o); -+# elif !defined(WONKY) -+# define freeObject(o) \ -+ if (OBJ_GUARDS(o)) { \ -+ zend_hash_destroy(OBJ_GUARDS(o)); \ -+ FREE_HASHTABLE(OBJ_GUARDS(o)); \ -+ } \ -+ if (OBJ_PROP(o)) { \ -+ zend_hash_destroy(OBJ_PROP(o)); \ -+ FREE_HASHTABLE(OBJ_PROP(o)); \ -+ } \ -+ efree(o); -+# else -+# define freeObject(o) \ -+ if (OBJ_PROP(o)) { \ -+ zend_hash_destroy(OBJ_PROP(o)); \ -+ FREE_HASHTABLE(OBJ_PROP(o)); \ -+ } \ -+ efree(o); -+# endif -+# define OBJ_PROP(o) (o)->zo.properties -+# define OBJ_GUARDS(o) (o)->zo.guards -+ -+# define ACC_PROP_PRIVATE(ce, flags) ((flags & ZEND_ACC_PRIVATE) && (EG(scope) && ce == EG(scope)) -+# define ACC_PROP_PROTECTED(ce, flags) ((flags & ZEND_ACC_PROTECTED) && (zend_check_protected(ce, EG(scope)))) -+# define ACC_PROP_PUBLIC(flags) (flags & ZEND_ACC_PUBLIC) -+# define ACC_PROP(ce, flags) (ACC_PROP_PUBLIC(flags) || ACC_PROP_PRIVATE(ce, flags) || ACC_PROP_PROTECTED(ce, flags)) -+ -+# define SET_EH_THROW_HTTP() SET_EH_THROW_EX(http_exception_get_default()) -+# define SET_EH_THROW_EX(ex) php_set_error_handling(EH_THROW, ex TSRMLS_CC) -+# define SET_EH_NORMAL() php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC) -+ -+#endif /* ZEND_ENGINE_2 */ -+/* }}} */ -+ -+#ifdef ZEND_ENGINE_2 -+# define with_error_handling(eh, ec) \ -+ { \ -+ error_handling_t __eh = GLOBAL_ERROR_HANDLING; \ -+ zend_class_entry *__ec= GLOBAL_EXCEPTION_CLASS; \ -+ php_set_error_handling(eh, ec TSRMLS_CC); -+# define end_error_handling() \ -+ php_set_error_handling(__eh, __ec TSRMLS_CC); \ -+ } -+#else -+# define with_error_handling(eh, ec) -+# define end_error_handling() -+#endif -+ -+#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 2) || PHP_MAJOR_VERSION > 5 -+# define ZEND_EXCEPTION_GET_DEFAULT() zend_exception_get_default(TSRMLS_C) -+#else -+# define ZEND_EXCEPTION_GET_DEFAULT() zend_exception_get_default() -+#endif -+ -+#ifndef E_THROW -+# define E_THROW 0 -+#endif -+#ifdef ZEND_ENGINE_2 -+# define HE_THROW E_THROW TSRMLS_CC -+# define HE_NOTICE (HTTP_G->only_exceptions ? E_THROW : E_NOTICE) TSRMLS_CC -+# define HE_WARNING (HTTP_G->only_exceptions ? E_THROW : E_WARNING) TSRMLS_CC -+# define HE_ERROR (HTTP_G->only_exceptions ? E_THROW : E_ERROR) TSRMLS_CC -+#else -+# define HE_THROW E_WARNING TSRMLS_CC -+# define HE_NOTICE E_NOTICE TSRMLS_CC -+# define HE_WARNING E_WARNING TSRMLS_CC -+# define HE_ERROR E_ERROR TSRMLS_CC -+#endif -+ -+#define HTTP_E_RUNTIME 1L -+#define HTTP_E_INVALID_PARAM 2L -+#define HTTP_E_HEADER 3L -+#define HTTP_E_MALFORMED_HEADERS 4L -+#define HTTP_E_REQUEST_METHOD 5L -+#define HTTP_E_MESSAGE_TYPE 6L -+#define HTTP_E_ENCODING 7L -+#define HTTP_E_REQUEST 8L -+#define HTTP_E_REQUEST_POOL 9L -+#define HTTP_E_SOCKET 10L -+#define HTTP_E_RESPONSE 11L -+#define HTTP_E_URL 12L -+#define HTTP_E_QUERYSTRING 13L -+ -+#ifdef ZEND_ENGINE_2 -+# define HTTP_BEGIN_ARGS_EX(class, method, ret_ref, req_args) HTTP_STATIC_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(args_for_ ##class## _ ##method , 0, ret_ref, req_args) -+# define HTTP_BEGIN_ARGS_AR(class, method, ret_ref, req_args) HTTP_STATIC_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(args_for_ ##class## _ ##method , 1, ret_ref, req_args) -+# define HTTP_END_ARGS } -+# define HTTP_EMPTY_ARGS_EX(class, method, ret_ref) HTTP_BEGIN_ARGS_EX(class, method, ret_ref, 0) HTTP_END_ARGS -+# define HTTP_ARGS(class, method) args_for_ ##class## _ ##method -+# define HTTP_ARG_VAL(name, pass_ref) ZEND_ARG_INFO(pass_ref, name) -+# define HTTP_ARG_OBJ(class, name, allow_null) ZEND_ARG_OBJ_INFO(0, name, class, allow_null) -+#endif -+ -+#ifdef ZEND_ENGINE_2 -+# define EMPTY_FUNCTION_ENTRY {NULL, NULL, NULL, 0, 0} -+#else -+# define EMPTY_FUNCTION_ENTRY {NULL, NULL, NULL} -+#endif -+ -+#ifdef HTTP_HAVE_CURL -+# ifdef ZEND_ENGINE_2 -+# define HTTP_DECLARE_ARG_PASS_INFO() \ -+ HTTP_STATIC_ARG_INFO \ -+ ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_2, 0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(1) \ -+ ZEND_END_ARG_INFO(); \ -+ \ -+ HTTP_STATIC_ARG_INFO \ -+ ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_3, 0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(1) \ -+ ZEND_END_ARG_INFO(); \ -+ \ -+ HTTP_STATIC_ARG_INFO \ -+ ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_4, 0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(1) \ -+ ZEND_END_ARG_INFO(); \ -+ \ -+ HTTP_STATIC_ARG_INFO \ -+ ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_5, 0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(1) \ -+ ZEND_END_ARG_INFO(); -+ -+# else -+# define HTTP_DECLARE_ARG_PASS_INFO() \ -+ static unsigned char http_arg_pass_ref_2[] = {2, BYREF_NONE, BYREF_FORCE}; \ -+ static unsigned char http_arg_pass_ref_3[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE}; \ -+ static unsigned char http_arg_pass_ref_4[] = {4, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE}; \ -+ static unsigned char http_arg_pass_ref_5[] = {5, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE}; -+# endif /* ZEND_ENGINE_2 */ -+#else -+# ifdef ZEND_ENGINE_2 -+# define HTTP_DECLARE_ARG_PASS_INFO() \ -+ HTTP_STATIC_ARG_INFO \ -+ ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_2, 0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(1) \ -+ ZEND_END_ARG_INFO(); \ -+\ -+ HTTP_STATIC_ARG_INFO \ -+ ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_3, 0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(1) \ -+ ZEND_END_ARG_INFO(); \ -+\ -+ HTTP_STATIC_ARG_INFO \ -+ ZEND_BEGIN_ARG_INFO(http_arg_pass_ref_4, 0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(0) \ -+ ZEND_ARG_PASS_INFO(1) \ -+ ZEND_END_ARG_INFO(); -+# else -+# define HTTP_DECLARE_ARG_PASS_INFO() \ -+ static unsigned char http_arg_pass_ref_2[] = {2, BYREF_NONE, BYREF_FORCE}; \ -+ static unsigned char http_arg_pass_ref_3[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE}; \ -+ static unsigned char http_arg_pass_ref_4[] = {4, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE}; -+# endif /* ZEND_ENGINE_2 */ -+#endif /* HTTP_HAVE_CURL */ -+ -+ -+#ifndef HAVE_CURL_SHARE_STRERROR -+# define curl_share_strerror(dummy) "unknown error" -+#endif -+#ifndef HAVE_CURL_EASY_STRERROR -+# define curl_easy_strerror(dummy) "unknown error" -+#endif -+#ifndef HAVE_CURL_MULTI_STRERROR -+# define curl_multi_strerror(dummy) "unknown error" -+#endif -+ -+#define PHP_MINIT_CALL(func) PHP_MINIT(func)(INIT_FUNC_ARGS_PASSTHRU) -+#define PHP_RINIT_CALL(func) PHP_RINIT(func)(INIT_FUNC_ARGS_PASSTHRU) -+#define PHP_MSHUTDOWN_CALL(func) PHP_MSHUTDOWN(func)(SHUTDOWN_FUNC_ARGS_PASSTHRU) -+#define PHP_RSHUTDOWN_CALL(func) PHP_RSHUTDOWN(func)(SHUTDOWN_FUNC_ARGS_PASSTHRU) -+ -+#define Z_OBJ_DELREF(z) \ -+ if (Z_OBJ_HT(z)->del_ref) { \ -+ Z_OBJ_HT(z)->del_ref(&(z) TSRMLS_CC); \ -+ } -+#define Z_OBJ_ADDREF(z) \ -+ if (Z_OBJ_HT(z)->add_ref) { \ -+ Z_OBJ_HT(z)->add_ref(&(z) TSRMLS_CC); \ -+ } -+#define Z_OBJ_DELREF_P(z) \ -+ if (Z_OBJ_HT_P(z)->del_ref) { \ -+ Z_OBJ_HT_P(z)->del_ref((z) TSRMLS_CC); \ -+ } -+#define Z_OBJ_ADDREF_P(z) \ -+ if (Z_OBJ_HT_P(z)->add_ref) { \ -+ Z_OBJ_HT_P(z)->add_ref((z) TSRMLS_CC); \ -+ } -+#define Z_OBJ_DELREF_PP(z) \ -+ if (Z_OBJ_HT_PP(z)->del_ref) { \ -+ Z_OBJ_HT_PP(z)->del_ref(*(z) TSRMLS_CC); \ -+ } -+#define Z_OBJ_ADDREF_PP(z) \ -+ if (Z_OBJ_HT_PP(z)->add_ref) { \ -+ Z_OBJ_HT_PP(z)->add_ref(*(z) TSRMLS_CC); \ -+ } -+ -+#endif /* PHP_HTTP_STD_DEFS_H */ -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_url_api.h -@@ -0,0 +1,165 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_url_api.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_URL_API_H -+#define PHP_HTTP_URL_API_H -+ -+#include "ext/standard/url.h" -+ -+extern PHP_MINIT_FUNCTION(http_url); -+ -+#define http_absolute_url(u) _http_absolute_url_ex((u), HTTP_URL_REPLACE TSRMLS_CC) -+#define http_absolute_url_ex(u, f) _http_absolute_url_ex((u), (f) TSRMLS_CC) -+PHP_HTTP_API char *_http_absolute_url_ex(const char *url, int flags TSRMLS_DC); -+ -+#define HTTP_URL_REPLACE 0x000 -+#define HTTP_URL_JOIN_PATH 0x001 -+#define HTTP_URL_JOIN_QUERY 0x002 -+#define HTTP_URL_STRIP_USER 0x004 -+#define HTTP_URL_STRIP_PASS 0x008 -+#define HTTP_URL_STRIP_AUTH (HTTP_URL_STRIP_USER|HTTP_URL_STRIP_PASS) -+#define HTTP_URL_STRIP_PORT 0x020 -+#define HTTP_URL_STRIP_PATH 0x040 -+#define HTTP_URL_STRIP_QUERY 0x080 -+#define HTTP_URL_STRIP_FRAGMENT 0x100 -+#define HTTP_URL_STRIP_ALL ( \ -+ HTTP_URL_STRIP_AUTH | \ -+ HTTP_URL_STRIP_PORT | \ -+ HTTP_URL_STRIP_PATH | \ -+ HTTP_URL_STRIP_QUERY | \ -+ HTTP_URL_STRIP_FRAGMENT \ -+) -+#define HTTP_URL_FROM_ENV 0x1000 -+ -+#define http_build_url(f, o, n, p, s, l) _http_build_url((f), (o), (n), (p), (s), (l) TSRMLS_CC) -+PHP_HTTP_API void _http_build_url(int flags, const php_url *old_url, const php_url *new_url, php_url **url_ptr, char **url_str, size_t *url_len TSRMLS_DC); -+ -+#define http_urlencode_hash(h, q) _http_urlencode_hash_ex((h), 1, NULL, 0, (q), NULL TSRMLS_CC) -+#define http_urlencode_hash_ex(h, o, p, pl, q, ql) _http_urlencode_hash_ex((h), (o), (p), (pl), (q), (ql) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_urlencode_hash_ex(HashTable *hash, zend_bool override_argsep, char *pre_encoded_data, size_t pre_encoded_len, char **encoded_data, size_t *encoded_len TSRMLS_DC); -+ -+#define http_urlencode_hash_recursive(ht, s, as, al, pr, pl) _http_urlencode_hash_recursive((ht), (s), (as), (al), (pr), (pl) TSRMLS_CC) -+PHP_HTTP_API STATUS _http_urlencode_hash_recursive(HashTable *ht, phpstr *str, const char *arg_sep, size_t arg_sep_len, const char *prefix, size_t prefix_len TSRMLS_DC); -+ -+#define http_url_from_struct(u, ht) _http_url_from_struct((u), (ht) TSRMLS_CC) -+static inline php_url *_http_url_from_struct(php_url *url, HashTable *ht TSRMLS_DC) -+{ -+ zval **e; -+ -+ if (!url) { -+ url = ecalloc(1, sizeof(php_url)); -+ } -+ -+ if ((SUCCESS == zend_hash_find(ht, "scheme", sizeof("scheme"), (void *) &e)) -+ && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) { -+ url->scheme = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e)); -+ } -+ if ((SUCCESS == zend_hash_find(ht, "user", sizeof("user"), (void *) &e)) -+ && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) { -+ url->user = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e)); -+ } -+ if ((SUCCESS == zend_hash_find(ht, "pass", sizeof("pass"), (void *) &e)) -+ && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) { -+ url->pass = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e)); -+ } -+ if ((SUCCESS == zend_hash_find(ht, "host", sizeof("host"), (void *) &e)) -+ && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) { -+ url->host = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e)); -+ } -+ if ((SUCCESS == zend_hash_find(ht, "path", sizeof("path"), (void *) &e)) -+ && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) { -+ url->path = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e)); -+ } -+ if ((SUCCESS == zend_hash_find(ht, "query", sizeof("query"), (void *) &e)) -+ && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) { -+ url->query = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e)); -+ } -+ if ((SUCCESS == zend_hash_find(ht, "fragment", sizeof("fragment"), (void *) &e)) -+ && (Z_TYPE_PP(e) == IS_STRING) && Z_STRLEN_PP(e)) { -+ url->fragment = estrndup(Z_STRVAL_PP(e), Z_STRLEN_PP(e)); -+ } -+ if (SUCCESS == zend_hash_find(ht, "port", sizeof("port"), (void *) &e)) { -+ if (Z_TYPE_PP(e) == IS_LONG) { -+ url->port = (unsigned short) Z_LVAL_PP(e); -+ } else { -+ zval *o = http_zsep(IS_LONG, *e); -+ -+ url->port = (unsigned short) Z_LVAL_P(o); -+ zval_ptr_dtor(&o); -+ } -+ } -+ -+ return url; -+} -+ -+#define http_url_tostruct(u, strct) _http_url_tostruct((u), (strct) TSRMLS_CC) -+static inline HashTable *_http_url_tostruct(php_url *url, zval *strct TSRMLS_DC) -+{ -+ zval arr; -+ -+ if (strct) { -+ switch (Z_TYPE_P(strct)) { -+ default: -+ zval_dtor(strct); -+ array_init(strct); -+ case IS_ARRAY: -+ case IS_OBJECT: -+ INIT_ZARR(arr, HASH_OF(strct)); -+ } -+ } else { -+ INIT_PZVAL(&arr); -+ array_init(&arr); -+ } -+ -+ if (url) { -+ if (url->scheme) { -+ add_assoc_string(&arr, "scheme", url->scheme, 1); -+ } -+ if (url->user) { -+ add_assoc_string(&arr, "user", url->user, 1); -+ } -+ if (url->pass) { -+ add_assoc_string(&arr, "pass", url->pass, 1); -+ } -+ if (url->host) { -+ add_assoc_string(&arr, "host", url->host, 1); -+ } -+ if (url->port) { -+ add_assoc_long(&arr, "port", (long) url->port); -+ } -+ if (url->path) { -+ add_assoc_string(&arr, "path", url->path, 1); -+ } -+ if (url->query) { -+ add_assoc_string(&arr, "query", url->query, 1); -+ } -+ if (url->fragment) { -+ add_assoc_string(&arr, "fragment", url->fragment, 1); -+ } -+ } -+ -+ return Z_ARRVAL(arr); -+} -+ -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/php_http_util_object.h -@@ -0,0 +1,35 @@ -+/* -+ +--------------------------------------------------------------------+ -+ | PECL :: http | -+ +--------------------------------------------------------------------+ -+ | Redistribution and use in source and binary forms, with or without | -+ | modification, are permitted provided that the conditions mentioned | -+ | in the accompanying LICENSE file are met. | -+ +--------------------------------------------------------------------+ -+ | Copyright (c) 2004-2010, Michael Wallner | -+ +--------------------------------------------------------------------+ -+*/ -+ -+/* $Id: php_http_util_object.h 292841 2009-12-31 08:48:57Z mike $ */ -+ -+#ifndef PHP_HTTP_UTIL_OBJECT_H -+#define PHP_HTTP_UTIL_OBJECT_H -+#ifdef ZEND_ENGINE_2 -+ -+extern zend_class_entry *http_util_object_ce; -+extern zend_function_entry http_util_object_fe[]; -+ -+extern PHP_MINIT_FUNCTION(http_util_object); -+ -+#endif -+#endif -+ -+/* -+ * 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 -+ */ -+ ---- /dev/null -+++ b/ext/http/phpstr/phpstr.c -@@ -0,0 +1,379 @@ -+ -+/* $Id: phpstr.c 211942 2006-04-24 17:17:09Z mike $ */ -+ -+#include "php.h" -+#include "phpstr.h" -+ -+PHPSTR_API phpstr *phpstr_init_ex(phpstr *buf, size_t chunk_size, int flags) -+{ -+ if (!buf) { -+ buf = pemalloc(sizeof(phpstr), flags & PHPSTR_INIT_PERSISTENT); -+ } -+ -+ if (buf) { -+ buf->size = (chunk_size) ? chunk_size : PHPSTR_DEFAULT_SIZE; -+ buf->pmem = (flags & PHPSTR_INIT_PERSISTENT) ? 1 : 0; -+ buf->data = (flags & PHPSTR_INIT_PREALLOC) ? pemalloc(buf->size, buf->pmem) : NULL; -+ buf->free = (flags & PHPSTR_INIT_PREALLOC) ? buf->size : 0; -+ buf->used = 0; -+ } -+ -+ return buf; -+} -+ -+PHPSTR_API phpstr *phpstr_from_string_ex(phpstr *buf, const char *string, size_t length) -+{ -+ if ((buf = phpstr_init(buf))) { -+ if (PHPSTR_NOMEM == phpstr_append(buf, string, length)) { -+ pefree(buf, buf->pmem); -+ buf = NULL; -+ } -+ } -+ return buf; -+} -+ -+PHPSTR_API size_t phpstr_resize_ex(phpstr *buf, size_t len, size_t override_size, int allow_error) -+{ -+ char *ptr = NULL; -+#if 0 -+ fprintf(stderr, "RESIZE: size=%lu, used=%lu, free=%lu\n", buf->size, buf->used, buf->free); -+#endif -+ if (buf->free < len) { -+ size_t size = override_size ? override_size : buf->size; -+ -+ while ((size + buf->free) < len) { -+ size <<= 1; -+ } -+ -+ if (allow_error) { -+ ptr = perealloc_recoverable(buf->data, buf->used + buf->free + size, buf->pmem); -+ } else { -+ ptr = perealloc(buf->data, buf->used + buf->free + size, buf->pmem); -+ } -+ -+ if (ptr) { -+ buf->data = ptr; -+ } else { -+ return PHPSTR_NOMEM; -+ } -+ -+ buf->free += size; -+ return size; -+ } -+ return 0; -+} -+ -+PHPSTR_API size_t phpstr_shrink(phpstr *buf) -+{ -+ /* avoid another realloc on fixation */ -+ if (buf->free > 1) { -+ char *ptr = perealloc(buf->data, buf->used + 1, buf->pmem); -+ -+ if (ptr) { -+ buf->data = ptr; -+ } else { -+ return PHPSTR_NOMEM; -+ } -+ buf->free = 1; -+ } -+ return buf->used; -+} -+ -+PHPSTR_API size_t phpstr_append(phpstr *buf, const char *append, size_t append_len) -+{ -+ if (PHPSTR_NOMEM == phpstr_resize(buf, append_len)) { -+ return PHPSTR_NOMEM; -+ } -+ memcpy(buf->data + buf->used, append, append_len); -+ buf->used += append_len; -+ buf->free -= append_len; -+ return append_len; -+} -+ -+PHPSTR_API size_t phpstr_appendf(phpstr *buf, const char *format, ...) -+{ -+ va_list argv; -+ char *append; -+ size_t append_len, alloc; -+ -+ va_start(argv, format); -+ append_len = vspprintf(&append, 0, format, argv); -+ va_end(argv); -+ -+ alloc = phpstr_append(buf, append, append_len); -+ efree(append); -+ -+ if (PHPSTR_NOMEM == alloc) { -+ return PHPSTR_NOMEM; -+ } -+ return append_len; -+} -+ -+PHPSTR_API size_t phpstr_insert(phpstr *buf, const char *insert, size_t insert_len, size_t offset) -+{ -+ if (PHPSTR_NOMEM == phpstr_resize(buf, insert_len)) { -+ return PHPSTR_NOMEM; -+ } -+ memmove(buf->data + offset + insert_len, buf->data + offset, insert_len); -+ memcpy(buf->data + offset, insert, insert_len); -+ buf->used += insert_len; -+ buf->free -= insert_len; -+ return insert_len; -+} -+ -+PHPSTR_API size_t phpstr_insertf(phpstr *buf, size_t offset, const char *format, ...) -+{ -+ va_list argv; -+ char *insert; -+ size_t insert_len, alloc; -+ -+ va_start(argv, format); -+ insert_len = vspprintf(&insert, 0, format, argv); -+ va_end(argv); -+ -+ alloc = phpstr_insert(buf, insert, insert_len, offset); -+ efree(insert); -+ -+ if (PHPSTR_NOMEM == alloc) { -+ return PHPSTR_NOMEM; -+ } -+ return insert_len; -+} -+ -+PHPSTR_API size_t phpstr_prepend(phpstr *buf, const char *prepend, size_t prepend_len) -+{ -+ if (PHPSTR_NOMEM == phpstr_resize(buf, prepend_len)) { -+ return PHPSTR_NOMEM; -+ } -+ memmove(buf->data + prepend_len, buf->data, buf->used); -+ memcpy(buf->data, prepend, prepend_len); -+ buf->used += prepend_len; -+ buf->free -= prepend_len; -+ return prepend_len; -+} -+ -+PHPSTR_API size_t phpstr_prependf(phpstr *buf, const char *format, ...) -+{ -+ va_list argv; -+ char *prepend; -+ size_t prepend_len, alloc; -+ -+ va_start(argv, format); -+ prepend_len = vspprintf(&prepend, 0, format, argv); -+ va_end(argv); -+ -+ alloc = phpstr_prepend(buf, prepend, prepend_len); -+ efree(prepend); -+ -+ if (PHPSTR_NOMEM == alloc) { -+ return PHPSTR_NOMEM; -+ } -+ return prepend_len; -+} -+ -+PHPSTR_API char *phpstr_data(const phpstr *buf, char **into, size_t *len) -+{ -+ char *copy = ecalloc(1, buf->used + 1); -+ memcpy(copy, buf->data, buf->used); -+ if (into) { -+ *into = copy; -+ } -+ if (len) { -+ *len = buf->used; -+ } -+ return copy; -+} -+ -+PHPSTR_API phpstr *phpstr_dup(const phpstr *buf) -+{ -+ phpstr *dup = phpstr_clone(buf); -+ if (PHPSTR_NOMEM == phpstr_append(dup, buf->data, buf->used)) { -+ phpstr_free(&dup); -+ } -+ return dup; -+} -+ -+PHPSTR_API size_t phpstr_cut(phpstr *buf, size_t offset, size_t length) -+{ -+ if (offset >= buf->used) { -+ return 0; -+ } -+ if (offset + length > buf->used) { -+ length = buf->used - offset; -+ } -+ memmove(buf->data + offset, buf->data + offset + length, buf->used - length); -+ buf->used -= length; -+ buf->free += length; -+ return length; -+} -+ -+PHPSTR_API phpstr *phpstr_sub(const phpstr *buf, size_t offset, size_t length) -+{ -+ if (offset >= buf->used) { -+ return NULL; -+ } else { -+ size_t need = 1 + ((length + offset) > buf->used ? (buf->used - offset) : (length - offset)); -+ phpstr *sub = phpstr_init_ex(NULL, need, PHPSTR_INIT_PREALLOC | (buf->pmem ? PHPSTR_INIT_PERSISTENT:0)); -+ if (sub) { -+ if (PHPSTR_NOMEM == phpstr_append(sub, buf->data + offset, need)) { -+ phpstr_free(&sub); -+ } else { -+ sub->size = buf->size; -+ } -+ } -+ return sub; -+ } -+} -+ -+PHPSTR_API phpstr *phpstr_right(const phpstr *buf, size_t length) -+{ -+ if (length < buf->used) { -+ return phpstr_sub(buf, buf->used - length, length); -+ } else { -+ return phpstr_sub(buf, 0, buf->used); -+ } -+} -+ -+ -+PHPSTR_API phpstr *phpstr_merge_va(phpstr *buf, unsigned argc, va_list argv) -+{ -+ unsigned i = 0; -+ buf = phpstr_init(buf); -+ -+ if (buf) { -+ while (argc > i++) { -+ phpstr_free_t f = va_arg(argv, phpstr_free_t); -+ phpstr *current = va_arg(argv, phpstr *); -+ phpstr_append(buf, current->data, current->used); -+ FREE_PHPSTR(f, current); -+ } -+ } -+ -+ return buf; -+} -+ -+PHPSTR_API phpstr *phpstr_merge_ex(phpstr *buf, unsigned argc, ...) -+{ -+ va_list argv; -+ phpstr *ret; -+ -+ va_start(argv, argc); -+ ret = phpstr_merge_va(buf, argc, argv); -+ va_end(argv); -+ return ret; -+} -+ -+PHPSTR_API phpstr *phpstr_merge(unsigned argc, ...) -+{ -+ va_list argv; -+ phpstr *ret; -+ -+ va_start(argv, argc); -+ ret = phpstr_merge_va(NULL, argc, argv); -+ va_end(argv); -+ return ret; -+} -+ -+PHPSTR_API phpstr *phpstr_fix(phpstr *buf) -+{ -+ if (PHPSTR_NOMEM == phpstr_resize_ex(buf, 1, 1, 0)) { -+ return NULL; -+ } -+ buf->data[buf->used] = '\0'; -+ return buf; -+} -+ -+PHPSTR_API int phpstr_cmp(phpstr *left, phpstr *right) -+{ -+ if (left->used > right->used) { -+ return -1; -+ } else if (right->used > left->used) { -+ return 1; -+ } else { -+ return memcmp(left->data, right->data, left->used); -+ } -+} -+ -+PHPSTR_API void phpstr_reset(phpstr *buf) -+{ -+ buf->free += buf->used; -+ buf->used = 0; -+} -+ -+PHPSTR_API void phpstr_dtor(phpstr *buf) -+{ -+ if (buf->data) { -+ pefree(buf->data, buf->pmem); -+ buf->data = NULL; -+ } -+ buf->used = 0; -+ buf->free = 0; -+} -+ -+PHPSTR_API void phpstr_free(phpstr **buf) -+{ -+ if (*buf) { -+ phpstr_dtor(*buf); -+ pefree(*buf, (*buf)->pmem); -+ *buf = NULL; -+ } -+} -+ -+PHPSTR_API size_t phpstr_chunk_buffer(phpstr **s, const char *data, size_t data_len, char **chunk, size_t chunk_size) -+{ -+ phpstr *storage; -+ -+ *chunk = NULL; -+ -+ if (!*s) { -+ *s = phpstr_init_ex(NULL, chunk_size << 1, chunk_size ? PHPSTR_INIT_PREALLOC : 0); -+ } -+ storage = *s; -+ -+ if (data_len) { -+ phpstr_append(storage, data, data_len); -+ } -+ -+ if (!chunk_size) { -+ phpstr_data(storage, chunk, &chunk_size); -+ phpstr_free(s); -+ return chunk_size; -+ } -+ -+ if (storage->used >= (chunk_size = storage->size >> 1)) { -+ *chunk = estrndup(storage->data, chunk_size); -+ phpstr_cut(storage, 0, chunk_size); -+ return chunk_size; -+ } -+ -+ return 0; -+} -+ -+PHPSTR_API void phpstr_chunked_output(phpstr **s, const char *data, size_t data_len, size_t chunk_len, phpstr_passthru_func passthru, void *opaque TSRMLS_DC) -+{ -+ char *chunk = NULL; -+ size_t got = 0; -+ -+ while ((got = phpstr_chunk_buffer(s, data, data_len, &chunk, chunk_len))) { -+ passthru(opaque, chunk, got TSRMLS_CC); -+ if (!chunk_len) { -+ /* we already got the last chunk, -+ and freed all resources */ -+ break; -+ } -+ data = NULL; -+ data_len = 0; -+ STR_SET(chunk, NULL); -+ } -+ STR_FREE(chunk); -+} -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim600: sw=4 ts=4 fdm=marker -+ * vim<600: sw=4 ts=4 -+ */ -+ ---- /dev/null -+++ b/ext/http/phpstr/phpstr.h -@@ -0,0 +1,224 @@ -+ -+/* $Id: phpstr.h 229282 2007-02-07 15:31:50Z mike $ */ -+ -+#ifndef _PHPSTR_H_ -+#define _PHPSTR_H_ -+ -+#ifndef PHPSTR_DEFAULT_SIZE -+# define PHPSTR_DEFAULT_SIZE 256 -+#endif -+ -+#define PHPSTR_NOMEM ((size_t) -1) -+ -+#ifndef STR_FREE -+# define STR_FREE(STR) \ -+ { \ -+ if (STR) { \ -+ efree(STR); \ -+ } \ -+ } -+#endif -+#ifndef STR_SET -+# define STR_SET(STR, SET) \ -+ { \ -+ STR_FREE(STR); \ -+ STR = SET; \ -+ } -+#endif -+#ifndef TSRMLS_D -+# define TSRMLS_D -+# define TSRMLS_DC -+# define TSRMLS_CC -+# define TSRMLS_C -+#endif -+#ifdef PHP_ATTRIBUTE_FORMAT -+# define PHPSTR_ATTRIBUTE_FORMAT(f, a, b) PHP_ATTRIBUTE_FORMAT(f, a, b) -+#else -+# define PHPSTR_ATTRIBUTE_FORMAT(f, a, b) -+#endif -+#ifndef pemalloc -+# define pemalloc(s,p) malloc(s) -+# define pefree(x,p) free(x) -+# define perealloc(x,s,p) realloc(x,s) -+# define perealloc_recoverable perealloc -+# define ecalloc calloc -+static inline void *estrndup(void *p, size_t s) -+{ -+ char *r = (char *) malloc(s+1); -+ if (r) memcpy((void *) r, p, s), r[s] = '\0'; -+ return (void *) r; -+} -+#endif -+ -+#if defined(PHP_WIN32) -+# if defined(PHPSTR_EXPORTS) -+# define PHPSTR_API __declspec(dllexport) -+# elif defined(COMPILE_DL_PHPSTR) -+# define PHPSTR_API __declspec(dllimport) -+# else -+# define PHPSTR_API -+# endif -+#else -+# define PHPSTR_API -+#endif -+ -+#define PHPSTR(p) ((phpstr *) (p)) -+#define PHPSTR_VAL(p) (PHPSTR(p))->data -+#define PHPSTR_LEN(p) (PHPSTR(p))->used -+ -+#define FREE_PHPSTR_PTR(STR) pefree(STR, STR->pmem) -+#define FREE_PHPSTR_VAL(STR) phpstr_dtor(STR) -+#define FREE_PHPSTR_ALL(STR) phpstr_free(&(STR)) -+#define FREE_PHPSTR(free, STR) \ -+ switch (free) \ -+ { \ -+ case PHPSTR_FREE_NOT: break; \ -+ case PHPSTR_FREE_PTR: pefree(STR, STR->pmem); break; \ -+ case PHPSTR_FREE_VAL: phpstr_dtor(STR); break; \ -+ case PHPSTR_FREE_ALL: \ -+ { \ -+ phpstr *PTR = (STR); \ -+ phpstr_free(&PTR); \ -+ } \ -+ break; \ -+ default: break; \ -+ } -+ -+#define RETURN_PHPSTR_PTR(STR) RETURN_PHPSTR((STR), PHPSTR_FREE_PTR, 0) -+#define RETURN_PHPSTR_VAL(STR) RETURN_PHPSTR((STR), PHPSTR_FREE_NOT, 0) -+#define RETURN_PHPSTR_DUP(STR) RETURN_PHPSTR((STR), PHPSTR_FREE_NOT, 1) -+#define RETVAL_PHPSTR_PTR(STR) RETVAL_PHPSTR((STR), PHPSTR_FREE_PTR, 0) -+#define RETVAL_PHPSTR_VAL(STR) RETVAL_PHPSTR((STR), PHPSTR_FREE_NOT, 0) -+#define RETVAL_PHPSTR_DUP(STR) RETVAL_PHPSTR((STR), PHPSTR_FREE_NOT, 1) -+/* RETURN_PHPSTR(buf, PHPSTR_FREE_PTR, 0) */ -+#define RETURN_PHPSTR(STR, free, dup) \ -+ RETVAL_PHPSTR((STR), (free), (dup)); \ -+ return; -+ -+#define RETVAL_PHPSTR(STR, free, dup) \ -+ phpstr_fix(STR); \ -+ RETVAL_STRINGL((STR)->data, (STR)->used, (dup)); \ -+ FREE_PHPSTR((free), (STR)); -+ -+typedef struct _phpstr_t { -+ char *data; -+ size_t used; -+ size_t free; -+ size_t size; -+ unsigned pmem:1; -+ unsigned reserved:31; -+} phpstr; -+ -+typedef enum _phpstr_free_t { -+ PHPSTR_FREE_NOT = 0, -+ PHPSTR_FREE_PTR, /* pefree() */ -+ PHPSTR_FREE_VAL, /* phpstr_dtor() */ -+ PHPSTR_FREE_ALL /* phpstr_free() */ -+} phpstr_free_t; -+ -+#define PHPSTR_ALL_FREE(STR) PHPSTR_FREE_ALL,(STR) -+#define PHPSTR_PTR_FREE(STR) PHPSTR_FREE_PTR,(STR) -+#define PHPSTR_VAL_FREE(STR) PHPSTR_FREE_VAL,(STR) -+#define PHPSTR_NOT_FREE(STR) PHPSTR_FREE_NOT,(STR) -+ -+#define PHPSTR_INIT_PREALLOC 0x01 -+#define PHPSTR_INIT_PERSISTENT 0x02 -+ -+/* create a new phpstr */ -+#define phpstr_new() phpstr_init(NULL) -+#define phpstr_init(b) phpstr_init_ex(b, PHPSTR_DEFAULT_SIZE, 0) -+#define phpstr_clone(phpstr_pointer) phpstr_init_ex(NULL, (phpstr_pointer)->size, (phpstr_pointer)->pmem ? PHPSTR_INIT_PERSISTENT:0) -+PHPSTR_API phpstr *phpstr_init_ex(phpstr *buf, size_t chunk_size, int flags); -+ -+/* create a phpstr from a zval or c-string */ -+#define phpstr_from_zval(z) phpstr_from_string(Z_STRVAL(z), Z_STRLEN(z)) -+#define phpstr_from_zval_ex(b, z) phpstr_from_string_ex(b, Z_STRVAL(z), Z_STRLEN(z)) -+#define phpstr_from_string(s, l) phpstr_from_string_ex(NULL, (s), (l)) -+PHPSTR_API phpstr *phpstr_from_string_ex(phpstr *buf, const char *string, size_t length); -+ -+/* usually only called from within the internal functions */ -+#define phpstr_resize(b, s) phpstr_resize_ex((b), (s), 0, 0) -+PHPSTR_API size_t phpstr_resize_ex(phpstr *buf, size_t len, size_t override_size, int allow_error); -+ -+/* shrink memory chunk to actually used size (+1) */ -+PHPSTR_API size_t phpstr_shrink(phpstr *buf); -+ -+/* append data to the phpstr */ -+#define phpstr_appends(b, a) phpstr_append((b), (a), sizeof(a)-1) -+#define phpstr_appendl(b, a) phpstr_append((b), (a), strlen(a)) -+PHPSTR_API size_t phpstr_append(phpstr *buf, const char *append, size_t append_len); -+PHPSTR_API size_t phpstr_appendf(phpstr *buf, const char *format, ...) PHPSTR_ATTRIBUTE_FORMAT(printf, 2, 3); -+ -+/* insert data at a specific position of the phpstr */ -+#define phpstr_inserts(b, i, o) phpstr_insert((b), (i), sizeof(i)-1, (o)) -+#define phpstr_insertl(b, i, o) phpstr_insert((b), (i), strlen(i), (o)) -+PHPSTR_API size_t phpstr_insert(phpstr *buf, const char *insert, size_t insert_len, size_t offset); -+PHPSTR_API size_t phpstr_insertf(phpstr *buf, size_t offset, const char *format, ...) PHPSTR_ATTRIBUTE_FORMAT(printf, 3, 4); -+ -+/* prepend data */ -+#define phpstr_prepends(b, p) phpstr_prepend((b), (p), sizeof(p)-1) -+#define phpstr_prependl(b, p) phpstr_prepend((b), (p), strlen(p)) -+PHPSTR_API size_t phpstr_prepend(phpstr *buf, const char *prepend, size_t prepend_len); -+PHPSTR_API size_t phpstr_prependf(phpstr *buf, const char *format, ...) PHPSTR_ATTRIBUTE_FORMAT(printf, 2, 3); -+ -+/* get a zero-terminated string */ -+PHPSTR_API char *phpstr_data(const phpstr *buf, char **into, size_t *len); -+ -+/* get a part of the phpstr */ -+#define phpstr_mid(b, o, l) phpstr_sub((b), (o), (l)) -+#define phpstr_left(b, l) phpstr_sub((b), 0, (l)) -+PHPSTR_API phpstr *phpstr_right(const phpstr *buf, size_t length); -+PHPSTR_API phpstr *phpstr_sub(const phpstr *buf, size_t offset, size_t len); -+ -+/* remove a substring */ -+PHPSTR_API size_t phpstr_cut(phpstr *buf, size_t offset, size_t length); -+ -+/* get a complete phpstr duplicate */ -+PHPSTR_API phpstr *phpstr_dup(const phpstr *buf); -+ -+/* merge several phpstr objects -+ use like: -+ -+ phpstr *final = phpstr_merge(3, -+ PHPSTR_NOT_FREE(&keep), -+ PHPSTR_ALL_FREE(middle_ptr), -+ PHPSTR_VAL_FREE(&local); -+*/ -+PHPSTR_API phpstr *phpstr_merge(unsigned argc, ...); -+PHPSTR_API phpstr *phpstr_merge_ex(phpstr *buf, unsigned argc, ...); -+PHPSTR_API phpstr *phpstr_merge_va(phpstr *buf, unsigned argc, va_list argv); -+ -+/* sets a trailing NUL byte */ -+PHPSTR_API phpstr *phpstr_fix(phpstr *buf); -+ -+/* memcmp for phpstr objects */ -+PHPSTR_API int phpstr_cmp(phpstr *left, phpstr *right); -+ -+/* reset phpstr object */ -+PHPSTR_API void phpstr_reset(phpstr *buf); -+ -+/* free a phpstr objects contents */ -+PHPSTR_API void phpstr_dtor(phpstr *buf); -+ -+/* free a phpstr object completely */ -+PHPSTR_API void phpstr_free(phpstr **buf); -+ -+/* stores data in a phpstr until it reaches chunk_size */ -+PHPSTR_API size_t phpstr_chunk_buffer(phpstr **s, const char *data, size_t data_len, char **chunk, size_t chunk_size); -+ -+typedef void (*phpstr_passthru_func)(void *opaque, const char *, size_t TSRMLS_DC); -+ -+/* wrapper around phpstr_chunk_buffer, which passes available chunks to passthru() */ -+PHPSTR_API void phpstr_chunked_output(phpstr **s, const char *data, size_t data_len, size_t chunk_size, phpstr_passthru_func passthru, void *opaque TSRMLS_DC); -+ -+#endif -+ -+ -+/* -+ * Local variables: -+ * tab-width: 4 -+ * c-basic-offset: 4 -+ * End: -+ * vim600: sw=4 ts=4 fdm=marker -+ * vim<600: sw=4 ts=4 -+ */ ---- /dev/null -+++ b/ext/http/tests/HttpMessage_001.phpt -@@ -0,0 +1,70 @@ -+--TEST-- -+HttpMessage -+--SKIPIF-- -+ -+--FILE-- -+getResponseStatus()); -+ -+$x = $m->getParentMessage(); -+$x = $m->getParentMessage(); -+$x = $m->getParentMessage(); -+ -+var_dump($m->getBody()); -+var_dump(HttpMessage::fromString($m->toString(true))->toString(true)); -+try { -+ do { -+ var_dump($m->toString()); -+ } while ($m = $m->getParentMessage()); -+} catch (HttpException $ex) { -+} -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+string(15) "Partial content" -+string(1) "X" -+string(190) "HTTP/1.1 301 -+Location: /anywhere -+HTTP/1.1 302 -+Location: /somewhere -+HTTP/1.1 206 Partial content -+Content-Range: bytes=2-3 -+X-Original-Transfer-Encoding: chunked -+Content-Length: 1 -+ -+X -+" -+string(119) "HTTP/1.1 206 Partial content -+Content-Range: bytes=2-3 -+X-Original-Transfer-Encoding: chunked -+Content-Length: 1 -+ -+X -+" -+string(36) "HTTP/1.1 302 -+Location: /somewhere -+" -+string(35) "HTTP/1.1 301 -+Location: /anywhere -+" -+Done ---- /dev/null -+++ b/ext/http/tests/HttpMessage_002.phpt -@@ -0,0 +1,65 @@ -+--TEST-- -+HttpMessage properties -+--SKIPIF-- -+ -+--FILE-- -+var_property); -+ var_dump($this->public_property); -+ var_dump($this->protected_property); -+ var_dump($this->private_property); -+ var_dump($this->non_ex_property); -+ $this->var_property.='_property'; -+ $this->public_property.='_property'; -+ $this->protected_property.='_property'; -+ $this->private_property.='_property'; -+ $this->non_ex_property = 'non_ex'; -+ var_dump($this->var_property); -+ var_dump($this->public_property); -+ var_dump($this->protected_property); -+ var_dump($this->private_property); -+ var_dump($this->non_ex_property); -+ -+ print_r($this->headers); -+ $this->headers['Foo'] = 'Bar'; -+ } -+} -+ -+error_reporting(E_ALL|E_STRICT); -+ -+echo "-TEST\n"; -+$m = new Message; -+$m->test(); -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+string(3) "var" -+string(6) "public" -+string(9) "protected" -+string(7) "private" -+ -+Notice: Undefined property: Message::$non_ex_property in %s -+NULL -+string(12) "var_property" -+string(15) "public_property" -+string(18) "protected_property" -+string(16) "private_property" -+string(6) "non_ex" -+Array -+( -+) -+%aFatal error%sCannot access HttpMessage properties by reference or array key/index in%s ---- /dev/null -+++ b/ext/http/tests/HttpMessage_003.phpt -@@ -0,0 +1,70 @@ -+--TEST-- -+HttpMessage implements Serializable, Countable -+--SKIPIF-- -+ -+--FILE-- -+count()); -+var_dump($m->serialize()); -+$m->unserialize("HTTP/1.1 200 Ok\r\nServer: Funky/1.0"); -+var_dump($m); -+var_dump($m->count()); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+int(3) -+string(148) "HTTP/1.1 301 -+Location: /anywhere -+HTTP/1.1 302 -+Location: /somewhere -+HTTP/1.1 200 -+X-Original-Transfer-Encoding: chunked -+Content-Length: 1 -+ -+X -+" -+object(HttpMessage)#%d (%d) { -+ ["type%s]=> -+ int(2) -+ ["body%s]=> -+ string(0) "" -+ ["requestMethod%s]=> -+ string(0) "" -+ ["requestUrl%s]=> -+ string(0) "" -+ ["responseStatus%s]=> -+ string(2) "Ok" -+ ["responseCode%s]=> -+ int(200) -+ ["httpVersion%s]=> -+ float(1.1) -+ ["headers%s]=> -+ array(1) { -+ ["Server"]=> -+ string(9) "Funky/1.0" -+ } -+ ["parentMessage%s]=> -+ NULL -+} -+int(1) -+Done ---- /dev/null -+++ b/ext/http/tests/HttpMessage_004.phpt -@@ -0,0 +1,36 @@ -+--TEST-- -+HttpMessage::detach() -+--SKIPIF-- -+ -+--FILE-- -+detach(); -+$d->addHeaders(array('Server'=>'Funky/2.0')); -+var_dump($d->getHeaders() == $m->getHeaders()); -+var_dump($d->getBody()); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+bool(false) -+string(3) "Hi!" -+Done -\ No newline at end of file ---- /dev/null -+++ b/ext/http/tests/HttpMessage_005.phpt -@@ -0,0 +1,86 @@ -+--TEST-- -+HttpMessage::prepend() -+--SKIPIF-- -+ -+--FILE-- -+prepend($m2); -+$m2 = NULL; -+echo $m1->toString(true); -+ -+$m1->prepend($m1->detach(), false); -+echo $m1->toString(true); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+GET http://example.com/ HTTP/1.0 -+HTTP/1.1 200 ok -+Server: Funky/2.0 -+Content-Type: text/html -+Content-Length: 9 -+ -+Hi there! -+GET / HTTP/1.1 -+Host: example.com -+Accept: */* -+Connection: close -+HTTP/1.1 200 ok -+Server: Funky/1.0 -+Content-Type: text/plain -+Content-Length: 3 -+ -+Hi! -+GET http://example.com/ HTTP/1.0 -+HTTP/1.1 200 ok -+Server: Funky/2.0 -+Content-Type: text/html -+Content-Length: 9 -+ -+Hi there! -+GET / HTTP/1.1 -+Host: example.com -+Accept: */* -+Connection: close -+HTTP/1.1 200 ok -+Server: Funky/1.0 -+Content-Type: text/plain -+Content-Length: 3 -+ -+Hi! -+HTTP/1.1 200 ok -+Server: Funky/1.0 -+Content-Type: text/plain -+Content-Length: 3 -+ -+Hi! -+Done -\ No newline at end of file ---- /dev/null -+++ b/ext/http/tests/HttpMessage_006.phpt -@@ -0,0 +1,35 @@ -+--TEST-- -+HttpMessage iterator -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+== -+HTTP/1.1 304 Not Modified -+== -+GET /foo HTTP/1.1 -+== -+HTTP/1.1 200 OK -+== -+GET / HTTP/1.1 -+Done -\ No newline at end of file ---- /dev/null -+++ b/ext/http/tests/HttpMessage_007.phpt -@@ -0,0 +1,46 @@ -+--TEST-- -+HttpMessage::reverse() -+--SKIPIF-- -+ -+--FILE-- -+toString(true); -+echo "===\n"; -+echo HttpMessage::fromString($s)->reverse()->toString(true); -+ -+$m = new HttpMessage($s); -+$r = $m->reverse(); -+unset($m); -+var_dump($r->count()); -+echo $r->toString(true); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+GET /first HTTP/1.1 -+HTTP/1.1 200 Ok-first -+GET /second HTTP/1.1 -+HTTP/1.1 200 Ok-second -+GET /third HTTP/1.1 -+HTTP/1.1 200 Ok-third -+=== -+HTTP/1.1 200 Ok-third -+GET /third HTTP/1.1 -+HTTP/1.1 200 Ok-second -+GET /second HTTP/1.1 -+HTTP/1.1 200 Ok-first -+GET /first HTTP/1.1 -+int(6) -+HTTP/1.1 200 Ok-third -+GET /third HTTP/1.1 -+HTTP/1.1 200 Ok-second -+GET /second HTTP/1.1 -+HTTP/1.1 200 Ok-first -+GET /first HTTP/1.1 -+Done ---- /dev/null -+++ b/ext/http/tests/HttpMessage_008.phpt -@@ -0,0 +1,41 @@ -+--TEST-- -+HttpMessage::toMessageTypeObject() -+--SKIPIF-- -+ -+--FILE-- -+"b",1=>2),null); -+ -+$m = new HttpMessage; -+$m->setType(HttpMessage::TYPE_REQUEST); -+$m->setRequestMethod('POST'); -+$m->setRequestUrl("http://www.example.com"); -+$m->setHttpVersion('1.1'); -+$m->addHeaders( -+ array( -+ "Content-Type" => "application/x-www-form-urlencoded", -+ "Host" => "www.example.com", -+ "Content-Length"=> strlen($b), -+ ) -+); -+$m->setBody($b); -+$r = $m->toMessageTypeObject(); -+echo $m,"\n"; -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+POST http://www.example.com HTTP/1.1 -+Content-Type: application/x-www-form-urlencoded -+Host: www.example.com -+Content-Length: 7 -+ -+a=b&1=2 -+ -+Done ---- /dev/null -+++ b/ext/http/tests/HttpMessage_009_bug16700.phpt -@@ -0,0 +1,24 @@ -+--TEST-- -+Bug #16700 - child classes of HttpMessage cannot not have array properties -+--SKIPIF-- -+ -+--FILE-- -+properties['foo'] = 'bar'; -+echo $child->properties['foo'], "\n"; -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+bar -+Done ---- /dev/null -+++ b/ext/http/tests/HttpQueryString_001.phpt -@@ -0,0 +1,116 @@ -+--TEST-- -+HttpQueryString global -+--SKIPIF-- -+ -+--FILE-- -+'b','c'=>'3.4','r'=>array(1,2,3)); -+$_SERVER['QUERY_STRING'] = 'a=b&c=3.4&r[0]=1&r[1]=2&r[2]=3'; -+ -+var_dump(HttpQueryString::singleton()->get()); -+var_dump(HttpQueryString::singleton()->get('n')); -+var_dump(HttpQueryString::singleton()->get('a')); -+var_dump(HttpQueryString::singleton()->get('a', "i", 0, true)); -+var_dump(HttpQueryString::singleton()->get('a', "string", 'hi!')); -+var_dump(HttpQueryString::singleton()->get('c')); -+var_dump(HttpQueryString::singleton()->get('c', HttpQueryString::TYPE_INT)); -+var_dump(HttpQueryString::singleton()->get('c', HttpQueryString::TYPE_FLOAT)); -+var_dump(HttpQueryString::singleton()->get('c', HttpQueryString::TYPE_BOOL)); -+var_dump(HttpQueryString::singleton()->get('r')); -+var_dump(HttpQueryString::singleton()->get('r', HttpQueryString::TYPE_ARRAY)); -+var_dump(HttpQueryString::singleton()->get('r', HttpQueryString::TYPE_OBJECT)); -+ -+HttpQueryString::singleton()->set(new HttpQueryString(false, 'z[0]=2')); -+ -+HttpQueryString::singleton()->set(array('a'=>'b', 'c'=> "3.4")); -+HttpQueryString::singleton()->set(array('a' => NULL)); -+ -+var_dump(HttpQueryString::singleton()); -+var_dump($_GET); -+var_dump($_SERVER['QUERY_STRING']); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+string(42) "a=b&c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3" -+NULL -+string(1) "b" -+int(0) -+string(3) "hi!" -+string(3) "3.4" -+int(3) -+float(3.4) -+bool(true) -+array(3) { -+ [0]=> -+ int(1) -+ [1]=> -+ int(2) -+ [2]=> -+ int(3) -+} -+array(3) { -+ [0]=> -+ int(1) -+ [1]=> -+ int(2) -+ [2]=> -+ int(3) -+} -+object(stdClass)#%d (%d) { -+ [0]=> -+ int(1) -+ [1]=> -+ int(2) -+ [2]=> -+ int(3) -+} -+object(HttpQueryString)#1 (2) { -+ ["queryArray%s]=> -+ &array(3) { -+ ["c"]=> -+ string(3) "3.4" -+ ["r"]=> -+ array(3) { -+ [0]=> -+ int(1) -+ [1]=> -+ int(2) -+ [2]=> -+ int(3) -+ } -+ ["z"]=> -+ array(1) { -+ [0]=> -+ string(1) "2" -+ } -+ } -+ ["queryString%s]=> -+ &string(49) "c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3&z%5B0%5D=2" -+} -+array(3) { -+ ["c"]=> -+ string(3) "3.4" -+ ["r"]=> -+ array(3) { -+ [0]=> -+ int(1) -+ [1]=> -+ int(2) -+ [2]=> -+ int(3) -+ } -+ ["z"]=> -+ array(1) { -+ [0]=> -+ string(1) "2" -+ } -+} -+string(49) "c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3&z%5B0%5D=2" -+Done -\ No newline at end of file ---- /dev/null -+++ b/ext/http/tests/HttpQueryString_002.phpt -@@ -0,0 +1,108 @@ -+--TEST-- -+HttpQueryString local -+--SKIPIF-- -+ -+--FILE-- -+'b','c'=>'3.4','r'=>array(1,2,3))); -+var_dump($q->get()); -+var_dump($q->get('n')); -+var_dump($q->get('a')); -+var_dump($q->get('a', "i", 0, true)); -+var_dump($q->get('a', "string", 'hi!')); -+var_dump($q->get('c')); -+var_dump($q->get('c', HttpQueryString::TYPE_INT)); -+var_dump($q->get('c', HttpQueryString::TYPE_FLOAT)); -+var_dump($q->get('c', HttpQueryString::TYPE_BOOL)); -+var_dump($q->get('r')); -+var_dump($q->get('r', HttpQueryString::TYPE_ARRAY)); -+var_dump($q->get('r', HttpQueryString::TYPE_OBJECT)); -+ -+$q->set('z[0]=2'); -+$q->set(array('a'=>'b', 'c'=> "3.4")); -+$q->set(array('a' => NULL)); -+ -+var_dump($q); -+var_dump($array); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+string(42) "a=b&c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3" -+NULL -+string(1) "b" -+int(0) -+string(3) "hi!" -+string(3) "3.4" -+int(3) -+float(3.4) -+bool(true) -+array(3) { -+ [0]=> -+ int(1) -+ [1]=> -+ int(2) -+ [2]=> -+ int(3) -+} -+array(3) { -+ [0]=> -+ int(1) -+ [1]=> -+ int(2) -+ [2]=> -+ int(3) -+} -+object(stdClass)#%d (%d) { -+ [0]=> -+ int(1) -+ [1]=> -+ int(2) -+ [2]=> -+ int(3) -+} -+object(HttpQueryString)#1 (2) { -+ ["queryArray%s]=> -+ array(3) { -+ ["c"]=> -+ string(3) "3.4" -+ ["r"]=> -+ array(3) { -+ [0]=> -+ int(1) -+ [1]=> -+ int(2) -+ [2]=> -+ int(3) -+ } -+ ["z"]=> -+ array(1) { -+ [0]=> -+ string(1) "2" -+ } -+ } -+ ["queryString%s]=> -+ string(49) "c=3.4&r%5B0%5D=1&r%5B1%5D=2&r%5B2%5D=3&z%5B0%5D=2" -+} -+array(3) { -+ ["a"]=> -+ string(1) "b" -+ ["c"]=> -+ string(3) "3.4" -+ ["r"]=> -+ array(3) { -+ [0]=> -+ int(1) -+ [1]=> -+ int(2) -+ [2]=> -+ int(3) -+ } -+} -+Done -\ No newline at end of file ---- /dev/null -+++ b/ext/http/tests/HttpQueryString_003.phpt -@@ -0,0 +1,24 @@ -+--TEST-- -+HttpQueryString xlate -+--SKIPIF-- -+ -+--FILE-- -+get()); -+$qs->xlate("latin1", "utf8"); -+var_dump($qs->get()); -+$qs->xlate("utf8", "latin1"); -+var_dump($qs->get()); -+echo "Done\n"; -+--EXPECTF-- -+%aTEST -+string(29) "%E4%5B0%5D=%FC&%F6%5Ba%5D=%DF" -+string(41) "%C3%A4%5B0%5D=%C3%BC&%C3%B6%5Ba%5D=%C3%9F" -+string(29) "%E4%5B0%5D=%FC&%F6%5Ba%5D=%DF" -+Done ---- /dev/null -+++ b/ext/http/tests/HttpQueryString_004.phpt -@@ -0,0 +1,54 @@ -+--TEST-- -+HttpQueryString w/ objects -+--SKIPIF-- -+ -+--FILE-- -+bar = (object) array("baz"=>1); -+ $this->dont_show = 'xxx'; -+ $this->dont_show2 = 'zzz'; -+ } -+} -+$foo = new test_props; -+var_dump($q = new HttpQueryString(false, $foo)); -+$foo->bar->baz = 0; -+var_dump($q->mod($foo)); -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+object(HttpQueryString)#3 (2) { -+ ["queryArray%s]=> -+ array(1) { -+ ["bar"]=> -+ array(1) { -+ ["baz"]=> -+ int(1) -+ } -+ } -+ ["queryString%s]=> -+ string(14) "bar%5Bbaz%5D=1" -+} -+object(HttpQueryString)#4 (2) { -+ ["queryArray%s]=> -+ array(1) { -+ ["bar"]=> -+ array(1) { -+ ["baz"]=> -+ int(0) -+ } -+ } -+ ["queryString%s]=> -+ string(14) "bar%5Bbaz%5D=0" -+} -+Done ---- /dev/null -+++ b/ext/http/tests/HttpRequestDataShare_001.phpt -@@ -0,0 +1,38 @@ -+--TEST-- -+HttpRequestDataShare -+--SKIPIF-- -+ -+--FILE-- -+dns = true; -+$s->cookie = true; -+ -+$r1 = new HttpRequest("http://www.google.com/"); -+$r2 = new HttpRequest("http://www.google.com/"); -+ -+$r1->enableCookies(); -+$r2->enableCookies(); -+ -+$s->attach($r1); -+$s->attach($r2); -+ -+$r1->send(); -+$r2->send(); -+ -+$s->reset(); -+ -+var_dump(current($r1->getResponseCookies())->cookies["PREF"] === HttpUtil::parseCookie($r2->getRequestMessage()->getHeader("Cookie"))->cookies["PREF"]); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+bool(true) -+Done ---- /dev/null -+++ b/ext/http/tests/HttpRequestDataShare_002.phpt -@@ -0,0 +1,52 @@ -+--TEST-- -+HttpRequestDataShare global -+--SKIPIF-- -+ -+--FILE-- -+cookie = true; -+var_dump($s); -+ -+$r1 = new HttpRequest("http://www.google.com/"); -+$r2 = new HttpRequest("http://www.google.com/"); -+ -+$r1->enableCookies(); -+$r2->enableCookies(); -+ -+$s->attach($r1); -+$s->attach($r2); -+ -+$r1->send(); -+$r2->send(); -+ -+$s->reset(); -+ -+if (current($r1->getResponseCookies())->cookies["PREF"] !== HttpUtil::parseCookie($r2->getRequestMessage()->getHeader("Cookie"))->cookies["PREF"]) { -+ var_dump( -+ current($r1->getResponseCookies())->cookies["PREF"], -+ HttpUtil::parseCookie($r2->getRequestMessage()->getHeader("Cookie"))->cookies["PREF"] -+ ); -+} -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+object(HttpRequestDataShare)#1 (4) { -+ ["cookie"]=> -+ bool(true) -+ ["dns"]=> -+ bool(true) -+ ["ssl"]=> -+ bool(false) -+ ["connect"]=> -+ bool(false) -+} -+Done ---- /dev/null -+++ b/ext/http/tests/HttpRequestPool_001.phpt -@@ -0,0 +1,51 @@ -+--TEST-- -+HttpRequestPool -+--SKIPIF-- -+ -+--FILE-- -+addPostFields(array('a'=>1,'b'=>2)) ; -+ -+$pool = new HttpRequestPool( -+ new HttpRequest('http://www.php.net/', HTTP_METH_HEAD), -+ $post -+); -+ -+$pool->send(); -+ -+foreach ($pool as $req) { -+ echo $req->getUrl(), '=', -+ $req->getResponseCode(), ':', -+ $req->getResponseMessage()->getResponseCode(), "\n"; -+} -+ -+foreach ($pool as $req) { -+ try { -+ $pool->attach(new HttpRequest('http://foo.bar')); -+ } catch (HttpRequestPoolException $x) { -+ echo ".\n"; -+ } -+} -+ -+foreach ($pool as $req) { -+ $pool->detach($req); -+} -+ -+echo "Done\n"; -+?> -+ -+--EXPECTF-- -+%aTEST -+http://www.php.net/=200:200 -+http://dev.iworks.at/ext-http/.print_request.php=200:200 -+. -+. -+Done ---- /dev/null -+++ b/ext/http/tests/HttpRequestPool_002.phpt -@@ -0,0 +1,51 @@ -+--TEST-- -+extending HttpRequestPool -+--SKIPIF-- -+ -+--FILE-- -+socketPerform()) { -+ if (!$this->socketSelect()) { -+ throw new HttpSocketException; -+ } -+ } -+ } -+ -+ protected final function socketPerform() -+ { -+ $result = parent::socketPerform(); -+ -+ echo "."; -+ foreach ($this->getFinishedRequests() as $r) { -+ echo "=", $r->getResponseCode(), "="; -+ $this->detach($r); -+ } -+ -+ return $result; -+ } -+} -+ -+$pool = new MyPool( -+ new HttpRequest('http://www.php.net/', HTTP_METH_HEAD), -+ new HttpRequest('http://www.php.net/', HTTP_METH_HEAD), -+ new HttpRequest('http://www.php.net/', HTTP_METH_HEAD) -+); -+ -+$pool->send(); -+ -+echo "\nDone\n"; -+?> -+--EXPECTREGEX-- -+.+TEST -+\.*=200=\.*=200=\.*=200= -+Done ---- /dev/null -+++ b/ext/http/tests/HttpRequestPool_003.phpt -@@ -0,0 +1,175 @@ -+--TEST-- -+HttpRequestPool chain -+--SKIPIF-- -+ -+--FILE-- -+dir = (is_dir($cache_dir) or @mkdir($cache_dir)) ? $cache_dir : null; -+ -+ foreach (array_map('trim', file($urls_file)) as $url) { -+ $this->all[$url] = $this->dir ? $this->dir .'/'. md5($url) : null; -+ } -+ -+ $this->send(); -+ } -+ -+ public final function send() -+ { -+ if (RMAX) { -+ $now = array_slice($this->all, 0, RMAX); -+ $this->rem = array_slice($this->all, RMAX); -+ } else { -+ $now = $urls; -+ $this->rem = array(); -+ } -+ -+ foreach ($now as $url => $file) { -+ $this->attach( -+ new HttpRequest( -+ $url, -+ HttpRequest::METH_GET, -+ array( -+ 'redirect' => 5, -+ 'compress' => GZIP, -+ 'timeout' => TOUT, -+ 'connecttimeout' => TOUT, -+ 'lastmodified' => is_file($file)?filemtime($file):0 -+ ) -+ ) -+ ); -+ } -+ -+ while ($this->socketPerform()) { -+ if (!$this->socketSelect()) { -+ throw new HttpSocketException; -+ } -+ } -+ } -+ -+ protected final function socketPerform() -+ { -+ try { -+ $rc = parent::socketPerform(); -+ } catch (HttpRequestException $x) { -+ // a request may have thrown an exception, -+ // but it is still save to continue -+ echo $x->getMessage(), "\n"; -+ } -+ -+ foreach ($this->getFinishedRequests() as $r) { -+ $this->detach($r); -+ -+ $u = $r->getUrl(); -+ $c = $r->getResponseCode(); -+ $b = $r->getResponseBody(); -+ -+ printf("%d %s %d\n", $c, $u, strlen($b)); -+ -+ if ($c == 200 && $this->dir) { -+ file_put_contents($this->all[$u], $b); -+ } -+ -+ if ($a = each($this->rem)) { -+ list($url, $file) = $a; -+ $this->attach( -+ new HttpRequest( -+ $url, -+ HttpRequest::METH_GET, -+ array( -+ 'redirect' => 5, -+ 'compress' => GZIP, -+ 'timeout' => TOUT, -+ 'connecttimeout' => TOUT, -+ 'lastmodified' => is_file($file)?filemtime($file):0 -+ ) -+ ) -+ ); -+ } -+ } -+ return $rc; -+ } -+} -+ -+define('GZIP', true); -+define('TOUT', 50); -+define('RMAX', 10); -+chdir(dirname(__FILE__)); -+ -+$time = microtime(true); -+$pool = new Pool(); -+printf("Elapsed: %0.3fs\n", microtime(true)-$time); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+%d %s %d -+Elapsed: %fs -+Done ---- /dev/null -+++ b/ext/http/tests/HttpRequestPool_004.phpt -@@ -0,0 +1,19 @@ -+--TEST-- -+HttpRequestPool::__destruct() invalid curl handle -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+Done ---- /dev/null -+++ b/ext/http/tests/HttpRequestPool_005.phpt -@@ -0,0 +1,46 @@ -+--TEST-- -+HttpRequestPool exception -+--SKIPIF-- -+ -+--FILE-- -+send(); -+} catch (HttpRequestPoolException $x) { -+ for ($i=0; $x; ++$i, $x = @$x->innerException) { -+ printf("%s%s: %s\n", str_repeat("\t", $i), get_class($x), $x->getMessage()); -+ } -+ var_dump($i); -+} -+$p = new HttpRequestPool(new HttpRequest('http://_____'), new HttpRequest('http://_____')); -+try { -+ $p->send(); -+} catch (HttpRequestPoolException $x) { -+ for ($i=0; $x; ++$i, $x = @$x->innerException) { -+ printf("%s%s: %s\n", str_repeat("\t", $i), get_class($x), $x->getMessage()); -+ } -+ var_dump($i); -+} -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+HttpRequestPoolException: Exception caused by 2 inner exception(s) -+ HttpInvalidParamException: Empty or too short HTTP message: '' -+ HttpRequestException: %souldn't resolve host name; %s (http://_____/) -+int(3) -+HttpRequestPoolException: Exception caused by 4 inner exception(s) -+ HttpInvalidParamException: Empty or too short HTTP message: '' -+ HttpRequestException: %souldn't resolve host name; %s (http://_____/) -+ HttpInvalidParamException: Empty or too short HTTP message: '' -+ HttpRequestException: %souldn't resolve host name; %s (http://_____/) -+int(5) -+Done -+ ---- /dev/null -+++ b/ext/http/tests/HttpRequestPool_006.phpt -@@ -0,0 +1,50 @@ -+--TEST-- -+HttpRequestPool detaching in callbacks -+--SKIPIF-- -+ -+--FILE-- -+getUrl()])) { -+ $i[$this->getUrl()] = true; -+ try { -+ $GLOBALS['p']->detach($this); -+ } catch (Exception $ex) { -+ echo $ex, "\n"; -+ } -+ } -+ } -+ function onFinish() { -+ $GLOBALS['p']->detach($this); -+ } -+} -+$p = new HttpRequestPool(new r("http://at.php.net"), new r("http://de.php.net")); -+$p->send(); -+var_dump($p->getAttachedRequests()); -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+exception 'HttpRequestPoolException' with message 'HttpRequest object(#%d) cannot be detached from the HttpRequestPool while executing the progress callback' in %aHttpRequestPool_006.php:%d -+Stack trace: -+#0 %aHttpRequestPool_006.php(%d): HttpRequestPool->detach(Object(r)) -+#1 [internal function]: r->onProgress(Array) -+#2 %aHttpRequestPool_006.php(%d): HttpRequestPool->send() -+#3 {main} -+exception 'HttpRequestPoolException' with message 'HttpRequest object(#%d) cannot be detached from the HttpRequestPool while executing the progress callback' in %aHttpRequestPool_006.php:%d -+Stack trace: -+#0 %aHttpRequestPool_006.php(%d): HttpRequestPool->detach(Object(r)) -+#1 [internal function]: r->onProgress(Array) -+#2 %aHttpRequestPool_006.php(%d): HttpRequestPool->send() -+#3 {main} -+array(0) { -+} -+Done ---- /dev/null -+++ b/ext/http/tests/HttpRequest_001.phpt -@@ -0,0 +1,51 @@ -+--TEST-- -+HttpRequest options -+--SKIPIF-- -+ -+--FILE-- -+11, 'headers'=>array('X-Foo'=>'Bar'))); -+$r2 = new HttpRequest; -+$r2->setOptions(array('redirect'=>99, 'headers'=>array('X-Bar'=>'Foo'))); -+$o1 = $r1->getOptions(); -+$o2 = $r2->getOptions(); -+$r1->setOptions($o2); -+$r2->setOptions($o1); -+print_r(array($o1, $o2)); -+var_dump(serialize($r1->getOptions()) === serialize($r2->getOptions())); -+$r1 = null; -+$r2 = null; -+?> -+--EXPECTF-- -+%aTEST -+Array -+( -+ [0] => Array -+ ( -+ [headers] => Array -+ ( -+ [X-Foo] => Bar -+ [X-Bar] => Foo -+ ) -+ -+ [redirect] => 11 -+ ) -+ -+ [1] => Array -+ ( -+ [headers] => Array -+ ( -+ [X-Bar] => Foo -+ [X-Foo] => Bar -+ ) -+ -+ [redirect] => 99 -+ ) -+ -+) -+bool(false) ---- /dev/null -+++ b/ext/http/tests/HttpRequest_002.phpt -@@ -0,0 +1,86 @@ -+--TEST-- -+HttpRequest GET/POST -+--SKIPIF-- -+ -+--FILE-- -+send(); -+print_r($r->getResponseInfo()); -+ -+$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HTTP_METH_POST); -+$r->addCookies(array('MyCookie' => 'foobar')); -+$r->addQueryData(array('gq'=>'foobar','gi'=>10)); -+$r->addPostFields(array('pq'=>'foobar','pi'=>10)); -+$r->addPostFile('upload', dirname(__FILE__).'/data.txt', 'text/plain'); -+$r->send(); -+echo $r->getResponseBody(); -+var_dump($r->getResponseMessage()->getResponseCode()); -+ -+echo "Done"; -+?> -+--EXPECTF-- -+%aTEST -+Array -+( -+ [effective_url] => http://www.google.com/ -+ [response_code] => 302 -+ [total_time] => %f -+ [namelookup_time] => %f -+ [connect_time] => %f -+ [pretransfer_time] => %f -+ [size_upload] => %d -+ [size_download] => %d -+ [speed_download] => %d -+ [speed_upload] => %d -+ [header_size] => %d -+ [request_size] => %d -+ [ssl_verifyresult] => %d -+ [filetime] => -1 -+ [content_length_download] => %d -+ [content_length_upload] => %d -+ [starttransfer_time] => %f -+ [content_type] => %s -+ [redirect_time] => %d -+ [redirect_count] => %d -+ [connect_code] => %d -+ [httpauth_avail] => %d -+ [proxyauth_avail] => %d -+ [os_errno] => %d -+ [num_connects] => %d -+ [ssl_engines] => Array -+ %a -+ [cookies] => Array -+ %a -+ [error] => -+) -+Array -+( -+ [gq] => foobar -+ [gi] => 10 -+ [pq] => foobar -+ [pi] => 10 -+ [MyCookie] => foobar -+) -+Array -+( -+ [upload] => Array -+ ( -+ [name] => data.txt -+ [type] => text/plain -+ [tmp_name] => %a -+ [error] => 0 -+ [size] => 1010 -+ ) -+ -+) -+int(200) -+Done ---- /dev/null -+++ b/ext/http/tests/HttpRequest_003.phpt -@@ -0,0 +1,54 @@ -+--TEST-- -+HttpRequest SSL -+--SKIPIF-- -+ -+--FILE-- -+ '3', 'ssl' => array('version' => '3', 'verifyhost' => '1')); -+$r = new HttpRequest('https://ssl.irmler.at/iworks/data.txt'); -+$r->setOptions($o); -+$r->send(); -+var_dump($r->getResponseBody()); -+var_dump(is_object($r->getResponseMessage())); -+var_dump(is_object($r->getResponseMessage())); -+var_dump(is_object($r->getResponseMessage())); -+var_dump($o); -+$r->setOptions($o); -+$r->send(); -+var_dump($o); -+?> -+--EXPECTF-- -+%aTEST -+string(10) "1234567890" -+bool(true) -+bool(true) -+bool(true) -+array(2) { -+ ["redirect"]=> -+ string(1) "3" -+ ["ssl"]=> -+ array(2) { -+ ["version"]=> -+ string(1) "3" -+ ["verifyhost"]=> -+ string(1) "1" -+ } -+} -+array(2) { -+ ["redirect"]=> -+ string(1) "3" -+ ["ssl"]=> -+ array(2) { -+ ["version"]=> -+ string(1) "3" -+ ["verifyhost"]=> -+ string(1) "1" -+ } -+} -+ ---- /dev/null -+++ b/ext/http/tests/HttpRequest_004.phpt -@@ -0,0 +1,162 @@ -+--TEST-- -+HttpRequest multiple posts -+--SKIPIF-- -+ -+--FILE-- -+ 1, 'dbl' => M_PI), -+ array('str' => 'something', 'nil' => null) -+); -+ -+echo "\nFirst Request\n"; -+$r = new HttpRequest('http://dev.iworks.at/ext-http/.print_request.php', HttpRequest::METH_POST); -+$r->setPostFields($fields[0]); -+$r->addPostFields($fields[1]); -+var_dump($r->send()->getBody()); -+var_dump($fields); -+ -+echo "\nSecond Request\n"; -+$r->setPostFields($fields); -+var_dump($r->send()->getBody()); -+var_dump($fields); -+ -+echo "\nThird Request\n"; -+$r->addPostFields(array('x' => 'X')); -+var_dump($r->send()->getBody()); -+var_dump($fields); -+ -+echo "\nFourth Request\n"; -+$r->setPostFields(array()); -+var_dump($r->send()->getBody()); -+var_dump($fields); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+ -+First Request -+string(%d) "Array -+( -+ [int] => 1 -+ [dbl] => 3.1415926535898 -+ [str] => something -+ [nil] => -+) -+string(44) "int=1&dbl=3.1415926535898&str=something&nil=" -+" -+array(2) { -+ [0]=> -+ array(2) { -+ ["int"]=> -+ int(1) -+ ["dbl"]=> -+ float(3.1415926535898) -+ } -+ [1]=> -+ array(2) { -+ ["str"]=> -+ string(9) "something" -+ ["nil"]=> -+ NULL -+ } -+} -+ -+Second Request -+string(%d) "Array -+( -+ [0] => Array -+ ( -+ [int] => 1 -+ [dbl] => 3.1415926535898 -+ ) -+ -+ [1] => Array -+ ( -+ [str] => something -+ [nil] => -+ ) -+ -+) -+string(72) "0%5Bint%5D=1&0%5Bdbl%5D=3.1415926535898&1%5Bstr%5D=something&1%5Bnil%5D=" -+" -+array(2) { -+ [0]=> -+ array(2) { -+ ["int"]=> -+ int(1) -+ ["dbl"]=> -+ float(3.1415926535898) -+ } -+ [1]=> -+ array(2) { -+ ["str"]=> -+ string(9) "something" -+ ["nil"]=> -+ NULL -+ } -+} -+ -+Third Request -+string(%d) "Array -+( -+ [0] => Array -+ ( -+ [int] => 1 -+ [dbl] => 3.1415926535898 -+ ) -+ -+ [1] => Array -+ ( -+ [str] => something -+ [nil] => -+ ) -+ -+ [x] => X -+) -+string(76) "0%5Bint%5D=1&0%5Bdbl%5D=3.1415926535898&1%5Bstr%5D=something&1%5Bnil%5D=&x=X" -+" -+array(2) { -+ [0]=> -+ array(2) { -+ ["int"]=> -+ int(1) -+ ["dbl"]=> -+ float(3.1415926535898) -+ } -+ [1]=> -+ array(2) { -+ ["str"]=> -+ string(9) "something" -+ ["nil"]=> -+ NULL -+ } -+} -+ -+Fourth Request -+string(13) "string(0) "" -+" -+array(2) { -+ [0]=> -+ array(2) { -+ ["int"]=> -+ int(1) -+ ["dbl"]=> -+ float(3.1415926535898) -+ } -+ [1]=> -+ array(2) { -+ ["str"]=> -+ string(9) "something" -+ ["nil"]=> -+ NULL -+ } -+} -+Done -+ ---- /dev/null -+++ b/ext/http/tests/HttpRequest_005.phpt -@@ -0,0 +1,24 @@ -+--TEST-- -+HttpRequest accessors -+--SKIPIF-- -+ -+--FILE-- -+ 3 && substr($method, 0, 3) == 'get') -+ $x = $r->$method(); -+ } catch (HttpException $e) { -+ } -+} -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+Done ---- /dev/null -+++ b/ext/http/tests/HttpRequest_006.phpt -@@ -0,0 +1,147 @@ -+--TEST-- -+HttpRequest XMLRPC -+--SKIPIF-- -+ -+--FILE-- -+setContentType('text/xml'); -+$r->setBody(xmlrpc_encode_request('testMethod', array('foo' => 'bar'))); -+var_dump($r->send()); -+var_dump($r->send()); -+var_dump($r->send()); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+object(HttpMessage)#%d (%d) { -+ ["type:protected"]=> -+ int(2) -+ ["body:protected"]=> -+ string(309) "string(294) " -+ -+testMethod -+ -+ -+ -+ -+ -+ foo -+ -+ bar -+ -+ -+ -+ -+ -+ -+ -+" -+" -+ ["requestMethod:protected"]=> -+ string(0) "" -+ ["requestUrl:protected"]=> -+ string(0) "" -+ ["responseStatus:protected"]=> -+ string(2) "OK" -+ ["responseCode:protected"]=> -+ int(200) -+ ["httpVersion:protected"]=> -+ float(1.1) -+ ["headers:protected"]=> -+ array(6) { -+ %a -+ } -+ ["parentMessage:protected"]=> -+ NULL -+} -+object(HttpMessage)#%d (%d) { -+ ["type:protected"]=> -+ int(2) -+ ["body:protected"]=> -+ string(309) "string(294) " -+ -+testMethod -+ -+ -+ -+ -+ -+ foo -+ -+ bar -+ -+ -+ -+ -+ -+ -+ -+" -+" -+ ["requestMethod:protected"]=> -+ string(0) "" -+ ["requestUrl:protected"]=> -+ string(0) "" -+ ["responseStatus:protected"]=> -+ string(2) "OK" -+ ["responseCode:protected"]=> -+ int(200) -+ ["httpVersion:protected"]=> -+ float(1.1) -+ ["headers:protected"]=> -+ array(6) { -+ %a -+ } -+ ["parentMessage:protected"]=> -+ NULL -+} -+object(HttpMessage)#%d (%d) { -+ ["type:protected"]=> -+ int(2) -+ ["body:protected"]=> -+ string(309) "string(294) " -+ -+testMethod -+ -+ -+ -+ -+ -+ foo -+ -+ bar -+ -+ -+ -+ -+ -+ -+ -+" -+" -+ ["requestMethod:protected"]=> -+ string(0) "" -+ ["requestUrl:protected"]=> -+ string(0) "" -+ ["responseStatus:protected"]=> -+ string(2) "OK" -+ ["responseCode:protected"]=> -+ int(200) -+ ["httpVersion:protected"]=> -+ float(1.1) -+ ["headers:protected"]=> -+ array(6) { -+ %a -+ } -+ ["parentMessage:protected"]=> -+ NULL -+} -+Done ---- /dev/null -+++ b/ext/http/tests/HttpRequest_007.phpt -@@ -0,0 +1,63 @@ -+--TEST-- -+HttpRequest PUT -+--SKIPIF-- -+ -+--FILE-- -+recordHistory = true; -+$r->addHeaders(array('content-type' => 'text/plain')); -+$r->setPutFile(__FILE__); -+$r->send(); -+var_dump($r->getHistory()->toString(true)); -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+string(%d) "PUT /ext-http/.print_put.php5 HTTP/1.1 -+User-Agent: PECL::HTTP/%a -+Host: dev.iworks.at -+Accept: */* -+Content-Type: text/plain -+Content-Length: %d -+Expect: 100-continue -+ -+recordHistory = true; -+$r->addHeaders(array('content-type' => 'text/plain')); -+$r->setPutFile(__FILE__); -+$r->send(); -+var_dump($r->getHistory()->toString(true)); -+echo "Done\n"; -+?> -+ -+HTTP/1.1 100 Continue -+HTTP/1.1 200 OK -+Date: %a -+Server: %a -+Vary: Accept-Encoding -+Content-Length: %d -+Content-Type: text/html -+ -+recordHistory = true; -+$r->addHeaders(array('content-type' => 'text/plain')); -+$r->setPutFile(__FILE__); -+$r->send(); -+var_dump($r->getHistory()->toString(true)); -+echo "Done\n"; -+?> -+ -+" -+Done ---- /dev/null -+++ b/ext/http/tests/HttpRequest_008.phpt -@@ -0,0 +1,32 @@ -+--TEST-- -+HttpRequest custom request method -+--SKIPIF-- -+ -+--FILE-- -+setContentType('text/plain'); -+$r->setBody('Yep, this is FOOBAR!'); -+var_dump($r->send()->getResponseCode()); -+var_dump($r->getRawRequestMessage()); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+int(200) -+string(%d) "FOOBAR /ext-http/.print_request.php HTTP/1.1 -+User-Agent: %a -+Host: dev.iworks.at -+Accept: */* -+Content-Type: text/plain -+Content-Length: 20 -+ -+Yep, this is FOOBAR!" -+Done ---- /dev/null -+++ b/ext/http/tests/HttpRequest_009.phpt -@@ -0,0 +1,48 @@ -+--TEST-- -+HttpRequest callbacks -+--SKIPIF-- -+ -+--FILE-- -+getResponseCode()); -+ } -+} -+ -+$r = new _R('http://dev.iworks.at/ext-http/.print_request.php', HTTP_METH_POST); -+$r->addPostFile('upload', __FILE__, 'text/plain'); -+$r->send(); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+Array -+( -+ [dltotal] => %f -+ [dlnow] => %f -+ [ultotal] => %f -+ [ulnow] => %f -+) -+%array -+( -+ [dltotal] => %f -+ [dlnow] => %f -+ [ultotal] => %f -+ [ulnow] => %f -+) -+int(200) -+Done ---- /dev/null -+++ b/ext/http/tests/HttpRequest_010.phpt -@@ -0,0 +1,48 @@ -+--TEST-- -+HttpRequest cookie API -+--SKIPIF-- -+ -+--FILE-- -+send(); -+$c[0] = $r->getResponseInfo("cookies"); -+if (!empty($c[0])) { -+ var_dump('$c[0]', $c[0]); -+} -+ -+var_dump($r->enableCookies()); -+$r->send(); -+ -+$c[1] = $r->getResponseInfo("cookies"); -+if (empty($c[1])) { -+ var_dump('$c[1]', $c[1]); -+} -+ -+var_dump($r->resetCookies()); -+$r->send(); -+ -+$c[2] = $r->getResponseInfo("cookies"); -+if ($c[1] === $c[2]) { -+ var_dump('$c[1]', $c[1], '$c[2]', $c[2]); -+} -+ -+$r->send(); -+$c[3] = $r->getResponseInfo("cookies"); -+if ($c[2] !== $c[3]) { -+ var_dump('$c[2]', $c[2], '$c[3]', $c[3]); -+} -+ -+echo "Done\n"; -+--EXPECTF-- -+%aTEST -+bool(true) -+bool(true) -+Done ---- /dev/null -+++ b/ext/http/tests/HttpResponse_001.phpt -@@ -0,0 +1,25 @@ -+--TEST-- -+HttpResponse - send data with caching headers -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%a -+Cache-Control: public, must-revalidate, max-age=3600 -+Last-Modified: %a, %d %a 20%d %d:%d:%d GMT -+Content-Type: %a -+Accept-Ranges: bytes -+ETag: "3858f62230ac3c915f300c664312c63f" -+Content-Length: 6 -+ -+foobar ---- /dev/null -+++ b/ext/http/tests/HttpResponse_002.phpt -@@ -0,0 +1,25 @@ -+--TEST-- -+HttpResponse - send gzipped file -+--SKIPIF-- -+ -+--ENV-- -+HTTP_ACCEPT_ENCODING=gzip -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%a -+Content-Type: %a -+Accept-Ranges: bytes -+Content-Encoding: gzip -+Vary: Accept-Encoding -+ -+%a ---- /dev/null -+++ b/ext/http/tests/HttpResponse_003.phpt -@@ -0,0 +1,30 @@ -+--TEST-- -+HttpResponse - send gzipped file with caching headers -+--SKIPIF-- -+ -+--ENV-- -+HTTP_ACCEPT_ENCODING=gzip -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%a -+Cache-Control: public, must-revalidate, max-age=3600 -+Last-Modified: %a, %d %a 20%d %d:%d:%d GMT -+Content-Type: %a -+Accept-Ranges: bytes -+ETag: "%a" -+Content-Encoding: gzip -+Vary: Accept-Encoding -+ -+%a ---- /dev/null -+++ b/ext/http/tests/HttpResponse_004.phpt -@@ -0,0 +1,27 @@ -+--TEST-- -+HttpResponse - send cached gzipped data -+--SKIPIF-- -+ -+--ENV-- -+HTTP_IF_NONE_MATCH="900150983cd24fb0d6963f7d28e17f72" -+HTTP_ACCEPT_ENCODING=gzip -+--FILE-- -+ -+--EXPECTF-- -+Status: 304%s -+X-Powered-By: PHP/%s -+Cache-Control: public, must-revalidate, max-age=3600 -+Last-Modified: %s -+Accept-Ranges: bytes -+ETag: "900150983cd24fb0d6963f7d28e17f72" ---- /dev/null -+++ b/ext/http/tests/HttpResponse_005.phpt -@@ -0,0 +1,24 @@ -+--TEST-- -+HttpResponse file not found -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+Status: 404%s -+X-Powered-By: PHP/%s -+Content-Type: text/plain -+ -+File not found ---- /dev/null -+++ b/ext/http/tests/allowed_methods_002.phpt -@@ -0,0 +1,21 @@ -+--TEST-- -+allowed methods -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+Status: 405%s -+X-Powered-By: PHP/%a -+Allow: POST -+Content-type: %a -+ ---- /dev/null -+++ b/ext/http/tests/allowed_methods_002_logging.phpt -@@ -0,0 +1,21 @@ -+--TEST-- -+logging allowed methods -+--SKIPIF-- -+ -+--ENV-- -+HTTP_HOST=example.com -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [405-ALLOWED] Allow: POST <%a> -+Done ---- /dev/null -+++ b/ext/http/tests/bug_15800.phpt -@@ -0,0 +1,49 @@ -+--TEST-- -+Bug #15800 Double free when zval is separated in convert_to_* -+--SKIPIF-- -+ -+--FILE-- -+ array('verifypeer'=>'1')); -+debug_zval_dump($o); -+ -+$r = new HttpRequest('http://www.google.com'); -+$r->setOptions($o); -+$r->send(); -+debug_zval_dump($o); -+ -+unset($r); -+debug_zval_dump($o); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+array(1) refcount(2){ -+ ["ssl"]=> -+ array(1) refcount(1){ -+ ["verifypeer"]=> -+ string(1) "1" refcount(1) -+ } -+} -+array(1) refcount(2){ -+ ["ssl"]=> -+ array(1) refcount(1){ -+ ["verifypeer"]=> -+ string(1) "1" refcount(3) -+ } -+} -+array(1) refcount(2){ -+ ["ssl"]=> -+ array(1) refcount(1){ -+ ["verifypeer"]=> -+ string(1) "1" refcount(1) -+ } -+} -+Done ---- /dev/null -+++ b/ext/http/tests/build_str_001.phpt -@@ -0,0 +1,30 @@ -+--TEST-- -+http_build_str -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+a=b -+a=b&c%5B0%5D=1 -+a=b&c%5B0%5D=1&d%5Be%5D=f -+foo%5B0%5D=1&foo%5B1%5D=2&foo%5B2%5D%5B0%5D=3 -+Done ---- /dev/null -+++ b/ext/http/tests/build_url_001.phpt -@@ -0,0 +1,18 @@ -+--TEST-- -+http_build_url() with relative paths -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+http://%a/page -+http://%a/with/some/path/ -+Done ---- /dev/null -+++ b/ext/http/tests/build_url_002.phpt -@@ -0,0 +1,30 @@ -+--TEST-- -+http_build_url() with parse_url() -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+https://www.example.com:9999/replaced?q=1#n -+https://www.example.com:9999/replaced?q=1#n -+Array -+( -+ [scheme] => https -+ [host] => www.example.com -+ [port] => 9999 -+ [path] => /replaced -+ [query] => q=1 -+ [fragment] => n -+) -+Done ---- /dev/null -+++ b/ext/http/tests/build_url_003.phpt -@@ -0,0 +1,26 @@ -+--TEST-- -+http_build_url() -+--SKIPIF-- -+ -+--ENV-- -+HTTP_HOST=www.example.com -+--FILE-- -+ 'https'))); -+printf("-%s-\n", http_build_url($url, array('scheme' => 'https', 'host' => 'ssl.example.com'))); -+printf("-%s-\n", http_build_url($url, array('scheme' => 'ftp', 'host' => 'ftp.example.com', 'port' => 21))); -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+-http://www.example.com/path/?query#anchor- -+-https://www.example.com/path/?query#anchor- -+-https://ssl.example.com/path/?query#anchor- -+-ftp://ftp.example.com/path/?query#anchor- -+Done ---- /dev/null -+++ b/ext/http/tests/build_url_004.phpt -@@ -0,0 +1,22 @@ -+--TEST-- -+http_build_url flags -+--SKPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+http://www.example.com/foo/baz -+http://www.example.com/foo/baz -+http://mike@www.example.com/foo/baz -+http://www.example.com/?a%5B0%5D=1&a%5B1%5D=b&b=c -+Done ---- /dev/null -+++ b/ext/http/tests/chunked_decode_001.phpt -@@ -0,0 +1,25 @@ -+--TEST-- -+http_chunked_decode() "\r\n" -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+string(12) "abra -+cadabra" -+ ---- /dev/null -+++ b/ext/http/tests/chunked_decode_002.phpt -@@ -0,0 +1,25 @@ -+--TEST-- -+http_chunked_decode() "\n" -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+string(12) "abra -+cadabra" -+ ---- /dev/null -+++ b/ext/http/tests/chunked_decode_003.phpt -@@ -0,0 +1,27 @@ -+--TEST-- -+http_chunked_decode() truncated message -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+%aWarning%ahttp_chunked_decode()%aTruncated message: chunk size 255 exceeds remaining data size 12 at pos 34 of 46 in%a -+string(24) "abra -+cadabra -+all we got -+" ---- /dev/null -+++ b/ext/http/tests/chunked_decode_004.phpt -@@ -0,0 +1,26 @@ -+--TEST-- -+http_chunked_decode() truncated message ending with NUL after a chunk -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+string(24) "abra -+cadabra -+all we got -+" ---- /dev/null -+++ b/ext/http/tests/cloning_001.phpt -@@ -0,0 +1,29 @@ -+--TEST-- -+cloning -+--SKIPIF-- -+ -+--FILE-- -+setOptions(array('redirect' => 3)); -+var_dump($r1->getOptions() == $r2->getOptions()); -+$r1->setUrl('http://www.google.com/'); -+var_dump($r1->getUrl() == $r2->getUrl()); -+$r1->send(); -+var_dump($r1->getResponseInfo() == $r2->getResponseInfo()); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+bool(false) -+bool(false) -+bool(false) -+Done ---- /dev/null -+++ b/ext/http/tests/data.txt -@@ -0,0 +1,10 @@ -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 ---- /dev/null -+++ b/ext/http/tests/date_001.phpt -@@ -0,0 +1,17 @@ -+--TEST-- -+http_date() with timestamp -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+Thu, 01 Jan 1970 00:00:01 GMT -+Fri, 13 Feb 2009 23:31:30 GMT -+ ---- /dev/null -+++ b/ext/http/tests/date_002.phpt -@@ -0,0 +1,21 @@ -+--TEST-- -+http_date() without timestamp -+--SKIPIF-- -+ -+--FILE-- -+ 1); -+echo "$t\n$d\nDone\n"; -+?> -+--EXPECTF-- -+%aTEST -+bool(true) -+%d -+%a, %d %a %d %d:%d:%d GMT -+Done ---- /dev/null -+++ b/ext/http/tests/encoding_objects_001.phpt -@@ -0,0 +1,35 @@ -+--TEST-- -+encoding stream objects -+--SKIPIF-- -+ -+--FILE-- -+flush($d->flush("Hi ")); -+echo $i->finish($d->finish("there!\n")); -+echo $i->finish($d->finish("Yo...\n")); -+ -+$id = $i->update($d->update($pd = file_get_contents(__FILE__))); -+foreach (glob('*.phpt') as $f) { -+ $id .= $i->update($d->update($tmp = file_get_contents($f))); -+ $pd .= $tmp; -+} -+$id .= $i->finish($d->finish()); -+ -+var_dump($id == $pd); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+Hi there! -+Yo... -+bool(true) -+Done -+ ---- /dev/null -+++ b/ext/http/tests/encodings.phpt -@@ -0,0 +1,44 @@ -+--TEST-- -+encodings -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+bool(true) -+bool(true) -+bool(true) -+Done ---- /dev/null -+++ b/ext/http/tests/etag_mode_031.phpt -@@ -0,0 +1,23 @@ -+--TEST-- -+crc32 etag (may fail because PHPs crc32 is actually crc32b) -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%a -+Cache-Control: private, must-revalidate, max-age=0 -+Accept-Ranges: bytes -+ETag: "4e818847" -+Content-Length: 4 -+Content-type: %a -+ -+abc ---- /dev/null -+++ b/ext/http/tests/etag_mode_032.phpt -@@ -0,0 +1,23 @@ -+--TEST-- -+sha1 etag -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%a -+Cache-Control: private, must-revalidate, max-age=0 -+Accept-Ranges: bytes -+ETag: "03cfd743661f07975fa2f1220c5194cbaff48451" -+Content-Length: 4 -+Content-type: %a -+ -+abc ---- /dev/null -+++ b/ext/http/tests/etag_mode_033.phpt -@@ -0,0 +1,23 @@ -+--TEST-- -+md5 etag -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%a -+Cache-Control: private, must-revalidate, max-age=0 -+Accept-Ranges: bytes -+ETag: "0bee89b07a248e27c83fc3d5951213c1" -+Content-Length: 4 -+Content-type: %a -+ -+abc ---- /dev/null -+++ b/ext/http/tests/etag_mode_034.phpt -@@ -0,0 +1,24 @@ -+--TEST-- -+ext/hash etag -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%a -+Cache-Control: private, must-revalidate, max-age=0 -+Accept-Ranges: bytes -+ETag: "edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb" -+Content-Length: 4 -+Content-type: %a -+ -+abc ---- /dev/null -+++ b/ext/http/tests/etag_mode_041.phpt -@@ -0,0 +1,21 @@ -+--TEST-- -+ob crc32 etag (may fail because PHPs crc32 is actually crc32b) -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%a -+Cache-Control: private, must-revalidate, max-age=0 -+ETag: "4e818847" -+Content-type: %a -+ -+abc ---- /dev/null -+++ b/ext/http/tests/etag_mode_042.phpt -@@ -0,0 +1,21 @@ -+--TEST-- -+ob sha1 etag -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%a -+Cache-Control: private, must-revalidate, max-age=0 -+ETag: "03cfd743661f07975fa2f1220c5194cbaff48451" -+Content-type: %a -+ -+abc ---- /dev/null -+++ b/ext/http/tests/etag_mode_043.phpt -@@ -0,0 +1,21 @@ -+--TEST-- -+ob md5 etag -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%a -+Cache-Control: private, must-revalidate, max-age=0 -+ETag: "0bee89b07a248e27c83fc3d5951213c1" -+Content-type: %a -+ -+abc ---- /dev/null -+++ b/ext/http/tests/etag_mode_044.phpt -@@ -0,0 +1,22 @@ -+--TEST-- -+ob ext/hash etag -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%a -+Cache-Control: private, must-revalidate, max-age=0 -+ETag: "edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb" -+Content-type: %a -+ -+abc ---- /dev/null -+++ b/ext/http/tests/exceptions.phpt -@@ -0,0 +1,53 @@ -+--TEST-- -+exceptions -+--SKIPIF-- -+ -+--FILE-- -+ 'Runtime', -+ HTTP_E_INVALID_PARAM => 'InvalidParam', -+ HTTP_E_HEADER => 'Header', -+ HTTP_E_MALFORMED_HEADERS => 'MalformedHeaders', -+ HTTP_E_REQUEST_METHOD => 'RequestMethod', -+ HTTP_E_MESSAGE_TYPE => 'MessageType', -+ HTTP_E_ENCODING => 'Encoding', -+ HTTP_E_REQUEST => 'Request', -+ HTTP_E_REQUEST_POOL => 'RequestPool', -+ HTTP_E_SOCKET => 'Socket', -+ HTTP_E_RESPONSE => 'Response', -+ HTTP_E_URL => 'Url', -+); -+ -+foreach ($e as $i => $c) { -+ try { -+ $n = "Http{$c}Exception"; -+ throw new $n; -+ } catch (HttpException $x) { -+ printf("%2d: %s\n", $i, get_class($x)); -+ } -+} -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+ 1: HttpRuntimeException -+ 2: HttpInvalidParamException -+ 3: HttpHeaderException -+ 4: HttpMalformedHeadersException -+ 5: HttpRequestMethodException -+ 6: HttpMessageTypeException -+ 7: HttpEncodingException -+ 8: HttpRequestException -+ 9: HttpRequestPoolException -+10: HttpSocketException -+11: HttpResponseException -+12: HttpUrlException -+Done ---- /dev/null -+++ b/ext/http/tests/get_request_data_001.phpt -@@ -0,0 +1,40 @@ -+--TEST-- -+get request data -+--SKIPIF-- -+ -+--POST-- -+a=b&c=d -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+Array -+( -+ [Accept-Charset] => iso-8859-1, * -+ [Accept-Encoding] => none -+ [Host] => localhost -+ [User-Agent] => Mozilla/5.0 -+) -+string(7) "a=b&c=d" -+string(7) "a=b&c=d" -+string(7) "a=b&c=d" -+string(7) "a=b&c=d" -+Done ---- /dev/null -+++ b/ext/http/tests/log.inc -@@ -0,0 +1,23 @@ -+ ---- /dev/null -+++ b/ext/http/tests/match_request_header_001.phpt -@@ -0,0 +1,23 @@ -+--TEST-- -+http_match_request_header() -+--SKIPIF-- -+ -+--ENV-- -+HTTP_FOO=bar -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+bool(true) -+bool(true) -+bool(false) -+Done ---- /dev/null -+++ b/ext/http/tests/negotiation_001.phpt -@@ -0,0 +1,64 @@ -+--TEST-- -+negotiation -+--SKIPIF-- -+ -+--ENV-- -+HTTP_ACCEPT=application/xml, application/xhtml+xml, text/html ; q = .8 -+HTTP_ACCEPT_LANGUAGE=de-AT,de-DE;q=0.8,en-GB;q=0.3,en-US;q=0.2 -+HTTP_ACCEPT_CHARSET=ISO-8859-1,utf-8;q=0.7,*;q=0.7 -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+string(2) "de" -+string(2) "de" -+string(10) "iso-8859-1" -+string(10) "iso-8859-1" -+string(21) "application/xhtml+xml" -+string(21) "application/xhtml+xml" -+string(7) "unknown" -+string(7) "unknown" -+string(7) "unknown" -+Array -+( -+ [de] => 900 -+ [en] => 0.27 -+) -+Array -+( -+ [iso-8859-1] => 1000 -+ [utf-8] => 0.7 -+) -+Array -+( -+ [application/xhtml+xml] => 999 -+ [text/html] => 0.8 -+) -+Done ---- /dev/null -+++ b/ext/http/tests/ob_deflatehandler_001.phpt -@@ -0,0 +1,23 @@ -+--TEST-- -+ob_deflatehandler -+--SKIPIF-- -+ -+--ENV-- -+HTTP_ACCEPT_ENCODING=gzip -+--FILE-- -+ -+--EXPECTF-- -+%a -+Content-Encoding: gzip -+Vary: Accept-Encoding -+%a -+ ---- /dev/null -+++ b/ext/http/tests/ob_inflatehandler_001.phpt -@@ -0,0 +1,16 @@ -+--TEST-- -+ob_inflatehandler -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+ ---- /dev/null -+++ b/ext/http/tests/parse_cookie_001.phpt -@@ -0,0 +1,41 @@ -+--TEST-- -+parse cookie -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+object(stdClass)%a { -+ ["cookies"]=> -+ array(3) { -+ ["name"]=> -+ string(5) "value" -+ ["foo"]=> -+ string(7) "bar"baz" -+ ["hey"]=> -+ string(6) "got"it" -+ } -+ ["extras"]=> -+ array(1) { -+ ["comment"]=> -+ string(0) "" -+ } -+ ["flags"]=> -+ int(32) -+ ["expires"]=> -+ int(1) -+ ["path"]=> -+ string(1) "/" -+ ["domain"]=> -+ string(0) "" -+} -+Done ---- /dev/null -+++ b/ext/http/tests/parse_cookie_002.phpt -@@ -0,0 +1,80 @@ -+--TEST-- -+parse cookie -+--SKIPIF-- -+ -+--FILE-- -+cookies['foo']); -+var_dump(http_parse_cookie('foo;')->cookies['foo']); -+var_dump(http_parse_cookie('foo ')->cookies['foo']); -+var_dump(http_parse_cookie('foo ;')->cookies['foo']); -+var_dump(http_parse_cookie('foo ; ')->cookies['foo']); -+var_dump(http_parse_cookie('foo=')->cookies['foo']); -+var_dump(http_parse_cookie('foo=;')->cookies['foo']); -+var_dump(http_parse_cookie('foo =')->cookies['foo']); -+var_dump(http_parse_cookie('foo =;')->cookies['foo']); -+var_dump(http_parse_cookie('foo= ')->cookies['foo']); -+var_dump(http_parse_cookie('foo= ;')->cookies['foo']); -+ -+var_dump(http_parse_cookie('foo=1')->cookies['foo']); -+var_dump(http_parse_cookie('foo=1;')->cookies['foo']); -+var_dump(http_parse_cookie('foo=1 ;')->cookies['foo']); -+var_dump(http_parse_cookie('foo= 1;')->cookies['foo']); -+var_dump(http_parse_cookie('foo = 1;')->cookies['foo']); -+var_dump(http_parse_cookie('foo = 1 ;')->cookies['foo']); -+var_dump(http_parse_cookie('foo=1')->cookies['foo']); -+var_dump(http_parse_cookie('foo= 1')->cookies['foo']); -+ -+var_dump(http_parse_cookie('foo="1"')->cookies['foo']); -+var_dump(http_parse_cookie('foo="1" ')->cookies['foo']); -+var_dump(http_parse_cookie('foo="1";')->cookies['foo']); -+var_dump(http_parse_cookie('foo = "1" ;')->cookies['foo']); -+var_dump(http_parse_cookie('foo= "1" ')->cookies['foo']); -+ -+var_dump(http_parse_cookie('foo=""')->cookies['foo']); -+var_dump(http_parse_cookie('foo="\""')->cookies['foo']); -+var_dump(http_parse_cookie('foo=" "')->cookies['foo']); -+var_dump(http_parse_cookie('foo= "')->cookies['foo']); -+var_dump(http_parse_cookie('foo=" ')->cookies['foo']); -+var_dump(http_parse_cookie('foo= " ')->cookies['foo']); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+string(0) "" -+string(0) "" -+string(0) "" -+string(0) "" -+string(0) "" -+string(0) "" -+string(0) "" -+string(0) "" -+string(0) "" -+string(0) "" -+string(0) "" -+string(1) "1" -+string(1) "1" -+string(1) "1" -+string(1) "1" -+string(1) "1" -+string(1) "1" -+string(1) "1" -+string(1) "1" -+string(1) "1" -+string(1) "1" -+string(1) "1" -+string(1) "1" -+string(1) "1" -+string(0) "" -+string(1) """ -+string(1) " " -+string(1) """ -+string(1) """ -+string(1) """ -+Done ---- /dev/null -+++ b/ext/http/tests/parse_headers_001.phpt -@@ -0,0 +1,41 @@ -+--TEST-- -+http_parse_headers() -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+Array -+( -+ [Host] => Array -+ ( -+ [0] => localhost -+ [1] => ambigious -+ ) -+ -+ [Nospace] => here -+ [Muchspace] => there -+ [Empty] => -+ [Empty2] => -+ [Folded] => one -+ two -+ three -+) -+ ---- /dev/null -+++ b/ext/http/tests/parse_message_001.phpt -@@ -0,0 +1,18 @@ -+--TEST-- -+http_parse_message() -+--SKIPIF-- -+ -+--FILE-- -+body; -+echo "Done\n"; -+--EXPECTF-- -+%aTEST -+%aThe document has moved%a -+Done ---- /dev/null -+++ b/ext/http/tests/parse_message_002.phpt -@@ -0,0 +1,39 @@ -+--TEST-- -+identity encoding trap -+--SKIPIF-- -+ -+--FILE-- -+ 2 -+ [httpVersion] => 1.1 -+ [responseCode] => 200 -+ [responseStatus] => Ok -+ [headers] => Array -+ ( -+ [Transfer-Encoding] => identity -+ [Content-Length] => 3 -+ [Content-Type] => text/plain -+ ) -+ -+ [body] => Hi! -+ [parentMessage] => -+) -+Done ---- /dev/null -+++ b/ext/http/tests/parse_message_003.phpt -@@ -0,0 +1,31 @@ -+--TEST-- -+content range message -+--SKIPIF-- -+ -+--FILE-- -+body); -+ -+$message = -+"HTTP/1.1 200 Ok\n". -+"Content-Range: bytes 0-1/1\n\n". -+"X\n"; -+ -+$msg = http_parse_message($message); -+ -+echo "Done\n"; -+--EXPECTF-- -+%aTEST -+string(2) "OK" -+%a Invalid Content-Range header: bytes 0-1/1 in%a -+Done ---- /dev/null -+++ b/ext/http/tests/parse_message_004.phpt -@@ -0,0 +1,115 @@ -+--TEST-- -+http_parse_message() recursive -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+object(stdClass)%a { -+ ["type"]=> -+ int(2) -+ ["httpVersion"]=> -+ float(1.1) -+ ["responseCode"]=> -+ int(200) -+ ["responseStatus"]=> -+ string(2) "Ok" -+ ["headers"]=> -+ array(2) { -+ ["Server"]=> -+ string(9) "Funky/1.0" -+ ["Content-Length"]=> -+ string(2) "10" -+ } -+ ["body"]=> -+ string(10) "1234567890" -+ ["parentMessage"]=> -+ object(stdClass)%a { -+ ["type"]=> -+ int(1) -+ ["httpVersion"]=> -+ float(1.1) -+ ["requestMethod"]=> -+ string(3) "GET" -+ ["requestUrl"]=> -+ string(1) "/" -+ ["headers"]=> -+ array(2) { -+ ["Host"]=> -+ string(15) "www.example.com" -+ ["Accept"]=> -+ string(3) "*/*" -+ } -+ ["body"]=> -+ string(0) "" -+ ["parentMessage"]=> -+ object(stdClass)%a { -+ ["type"]=> -+ int(2) -+ ["httpVersion"]=> -+ float(1.1) -+ ["responseCode"]=> -+ int(200) -+ ["responseStatus"]=> -+ string(2) "Ok" -+ ["headers"]=> -+ array(2) { -+ ["Server"]=> -+ string(9) "Funky/1.0" -+ ["Content-Length"]=> -+ string(2) "10" -+ } -+ ["body"]=> -+ string(0) "" -+ ["parentMessage"]=> -+ object(stdClass)%a { -+ ["type"]=> -+ int(1) -+ ["httpVersion"]=> -+ float(1.1) -+ ["requestMethod"]=> -+ string(4) "HEAD" -+ ["requestUrl"]=> -+ string(1) "/" -+ ["headers"]=> -+ array(2) { -+ ["Host"]=> -+ string(15) "www.example.com" -+ ["Accept"]=> -+ string(3) "*/*" -+ } -+ ["body"]=> -+ string(0) "" -+ ["parentMessage"]=> -+ NULL -+ } -+ } -+ } -+} -+Done ---- /dev/null -+++ b/ext/http/tests/parse_message_005.phpt -@@ -0,0 +1,60 @@ -+--TEST-- -+http_parse_message() content range header w/(o) = -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+stdClass Object -+( -+ [type] => 2 -+ [httpVersion] => 1.1 -+ [responseCode] => 206 -+ [responseStatus] => -+ [headers] => Array -+ ( -+ [Server] => Funky/1.0 -+ [Content-Range] => bytes 0-0/100 -+ ) -+ -+ [body] => 1 -+ [parentMessage] => stdClass Object -+ ( -+ [type] => 2 -+ [httpVersion] => 1.1 -+ [responseCode] => 206 -+ [responseStatus] => -+ [headers] => Array -+ ( -+ [Server] => Funky/1.0 -+ [Content-Range] => bytes: 0-0/100 -+ ) -+ -+ [body] => 1 -+ [parentMessage] => -+ ) -+ -+) -+Done ---- /dev/null -+++ b/ext/http/tests/parse_message_006.phpt -@@ -0,0 +1,38 @@ -+--TEST-- -+mixed EOL trap -+--SKIPIF-- -+ -+--FILE-- -+ 2 -+ [httpVersion] => 1.1 -+ [responseCode] => 200 -+ [responseStatus] => Ok -+ [headers] => Array -+ ( -+ [Header] => Value -+ [Connection] => close -+ ) -+ -+ [body] => Bug! -+ [parentMessage] => -+) -+Done ---- /dev/null -+++ b/ext/http/tests/parse_params_001.phpt -@@ -0,0 +1,75 @@ -+--TEST-- -+http_parse_params -+--SKIPIF-- -+ -+--FILE-- -+params[0]); -+$p = http_parse_params('a=b'); var_dump($p->params[0]); -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+object(stdClass)%a { -+ ["params"]=> -+ array(2) { -+ [0]=> -+ string(9) "text/html" -+ [1]=> -+ array(1) { -+ ["charset"]=> -+ string(10) "iso-8859-1" -+ } -+ } -+} -+object(stdClass)%a { -+ ["params"]=> -+ array(2) { -+ [0]=> -+ string(9) "text/html" -+ [1]=> -+ array(1) { -+ ["charset"]=> -+ string(10) "iso-8859-1" -+ } -+ } -+} -+object(stdClass)%a { -+ ["params"]=> -+ array(2) { -+ [0]=> -+ string(10) "attachment" -+ [1]=> -+ array(1) { -+ ["filename"]=> -+ string(13) "gol;got,a.ext" -+ } -+ } -+} -+object(stdClass)%a { -+ ["params"]=> -+ array(3) { -+ [0]=> -+ string(6) "public" -+ [1]=> -+ string(15) "must-revalidate" -+ [2]=> -+ array(1) { -+ ["max-age"]=> -+ string(1) "0" -+ } -+ } -+} -+string(1) "a" -+array(1) { -+ ["a"]=> -+ string(1) "b" -+} -+Done ---- /dev/null -+++ b/ext/http/tests/persistent_handles_001.phpt -@@ -0,0 +1,91 @@ -+--TEST-- -+persistent handles -+--SKIPIF-- -+ -+--INI-- -+http.persistent.handles.limit=-1 -+http.persistent.handles.ident=GLOBAL -+--FILE-- -+ $idents) { -+ foreach ((array)$idents as $ident => $counts) { -+ if (!empty($counts["free"])) { -+ printf("%a, %a, %a\n", $provider, $ident, $counts["free"]); -+ } -+ } -+} -+ -+http_get("http://www.google.com/", null, $info[]); -+ -+echo "One free request handle within GLOBAL: "; -+var_dump(http_persistent_handles_count()->http_request["GLOBAL"]["free"]); -+ -+echo "Reusing request handle: "; -+http_get("http://www.google.com/", null, $info[]); -+var_dump($info[0]["pretransfer_time"] > 10 * $info[1]["pretransfer_time"], $info[0]["pretransfer_time"], $info[1]["pretransfer_time"]); -+ -+echo "Handles' been cleaned up:\n"; -+http_persistent_handles_clean(); -+print_r(http_persistent_handles_count()); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+No free handles! -+One free request handle within GLOBAL: int(1) -+Reusing request handle: bool(true) -+float(%f) -+float(%f) -+Handles' been cleaned up: -+stdClass Object -+( -+ [http_request] => Array -+ ( -+ [GLOBAL] => Array -+ ( -+ [used] => 0 -+ [free] => 0 -+ ) -+ -+ ) -+ -+ [http_request_datashare] => Array -+ ( -+ [GLOBAL] => Array -+ ( -+ [used] => 0 -+ [free] => 0 -+ ) -+ -+ ) -+ -+ [http_request_datashare_lock] => Array -+ ( -+ [GLOBAL] => Array -+ ( -+ [used] => 0 -+ [free] => 0 -+ ) -+ -+ ) -+ -+ [http_request_pool] => Array -+ ( -+ [GLOBAL] => Array -+ ( -+ [used] => 0 -+ [free] => 0 -+ ) -+ -+ ) -+ -+) -+Done ---- /dev/null -+++ b/ext/http/tests/persistent_handles_002.phpt -@@ -0,0 +1,83 @@ -+--TEST-- -+persistent handles -+--SKIPIF-- -+ -+--INI-- -+http.persistent.handles.limit=-1 -+http.persistent.handles.ident=GLOBAL -+--FILE-- -+ $idents) { -+ foreach ((array)$idents as $ident => $counts) { -+ if (!empty($counts["free"])) { -+ printf("%a, %a, %a\n", $provider, $ident, $counts["free"]); -+ } -+ } -+} -+ -+http_get("http://www.google.com/", null, $info[]); -+ -+echo "One free request handle within GLOBAL: "; -+$h = http_persistent_handles_count(); -+var_dump($h->http_request["GLOBAL"]["free"]); -+ -+echo "Reusing request handle: "; -+http_get("http://www.google.com/", null, $info[]); -+var_dump($info[0]["pretransfer_time"] > 10 * $info[1]["pretransfer_time"], $info[0]["pretransfer_time"], $info[1]["pretransfer_time"]); -+ -+echo "Handles' been cleaned up:\n"; -+http_persistent_handles_clean(); -+print_r(http_persistent_handles_count()); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+No free handles! -+One free request handle within GLOBAL: int(1) -+Reusing request handle: bool(true) -+float(%f) -+float(%f) -+Handles' been cleaned up: -+stdClass Object -+( -+ [http_request] => Array -+ ( -+ [GLOBAL] => Array -+ ( -+ [used] => 0 -+ [free] => 0 -+ ) -+ -+ ) -+ -+ [http_request_datashare] => Array -+ ( -+ [GLOBAL] => Array -+ ( -+ [used] => 0 -+ [free] => 0 -+ ) -+ -+ ) -+ -+ [http_request_pool] => Array -+ ( -+ [GLOBAL] => Array -+ ( -+ [used] => 0 -+ [free] => 0 -+ ) -+ -+ ) -+ -+) -+Done ---- /dev/null -+++ b/ext/http/tests/persistent_handles_003.phpt -@@ -0,0 +1,62 @@ -+--TEST-- -+persistent handles -+--SKIPIF-- -+ -+--INI-- -+http.persistent.handles.limit=-1 -+http.persistent.handles.ident=GLOBAL -+--FILE-- -+ $idents) { -+ foreach ((array)$idents as $ident => $counts) { -+ if (!empty($counts["free"])) { -+ printf("%a, %a, %a\n", $provider, $ident, $counts["free"]); -+ } -+ } -+} -+ -+http_get("http://www.google.com/", null, $info[]); -+ -+echo "One free request handle within GLOBAL: "; -+$h = http_persistent_handles_count(); -+var_dump($h->http_request["GLOBAL"]["free"]); -+ -+echo "Reusing request handle: "; -+http_get("http://www.google.com/", null, $info[]); -+var_dump($info[0]["pretransfer_time"] > 10 * $info[1]["pretransfer_time"], $info[0]["pretransfer_time"], $info[1]["pretransfer_time"]); -+ -+echo "Handles' been cleaned up:\n"; -+http_persistent_handles_clean(); -+print_r(http_persistent_handles_count()); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+No free handles! -+One free request handle within GLOBAL: int(1) -+Reusing request handle: bool(true) -+float(%f) -+float(%f) -+Handles' been cleaned up: -+stdClass Object -+( -+ [http_request] => Array -+ ( -+ [GLOBAL] => Array -+ ( -+ [used] => 0 -+ [free] => 0 -+ ) -+ -+ ) -+ -+) -+Done ---- /dev/null -+++ b/ext/http/tests/redirect_011.phpt -@@ -0,0 +1,24 @@ -+--TEST-- -+http_redirect() with params -+--SKIPIF-- -+ -+--ENV-- -+HTTP_HOST=localhost -+--FILE-- -+ 1, 'b' => 2)); -+?> -+--EXPECTF-- -+Status: 302%s -+X-Powered-By: PHP/%a -+Location: http://localhost/redirect?a=1&b=2 -+Content-type: %a -+ -+Redirecting to http://localhost/redirect?a=1&b=2. -+ ---- /dev/null -+++ b/ext/http/tests/redirect_011_logging.phpt -@@ -0,0 +1,21 @@ -+--TEST-- -+logging redirects -+--SKIPIF-- -+ -+--ENV-- -+HTTP_HOST=example.com -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [302-REDIRECT] Location: http%a <%a> -+Done ---- /dev/null -+++ b/ext/http/tests/redirect_012.phpt -@@ -0,0 +1,27 @@ -+--TEST-- -+http_redirect() with session -+--SKIPIF-- -+ -+--ENV-- -+HTTP_HOST=localhost -+--FILE-- -+ 1), true); -+?> -+--EXPECTF-- -+Status: 302%s -+X-Powered-By: PHP/%a -+Set-Cookie: PHPSESSID=%a; path=/ -+Expires: %a -+Cache-Control: %a -+Pragma: %a -+Location: http://localhost/redirect?a=1&PHPSESSID=%a -+Content-type: %a ---- /dev/null -+++ b/ext/http/tests/redirect_012_logging.phpt -@@ -0,0 +1,22 @@ -+--TEST-- -+logging redirects -+--SKIPIF-- -+ -+--ENV-- -+HTTP_HOST=example.com -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [302-REDIRECT] Location: http%a <%a> -+Done ---- /dev/null -+++ b/ext/http/tests/redirect_013.phpt -@@ -0,0 +1,24 @@ -+--TEST-- -+http_redirect() permanent -+--SKIPIF-- -+ -+--ENV-- -+HTTP_HOST=localhost -+--FILE-- -+ -+--EXPECTF-- -+Status: 301%s -+X-Powered-By: PHP/%a -+Location: http://localhost/redirect -+Content-type: %a -+ -+Redirecting to http://localhost/redirect. -+ ---- /dev/null -+++ b/ext/http/tests/redirect_013_logging.phpt -@@ -0,0 +1,21 @@ -+--TEST-- -+logging redirects -+--SKIPIF-- -+ -+--ENV-- -+HTTP_HOST=example.com -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+%d%d%d%d-%d%d-%d%d %d%d:%d%d:%d%d [301-REDIRECT] Location: http%a <%a> -+Done ---- /dev/null -+++ b/ext/http/tests/request_cookies.phpt -@@ -0,0 +1,52 @@ -+--TEST-- -+urlencoded cookies -+--SKIPIF-- -+ -+--FILE-- -+ "val=ue"); -+ -+$r = new HttpRequest("http://dev.iworks.at/ext-http/.print_request.php", HTTP_METH_GET, array("cookies" => $cookies)); -+$r->recordHistory = true; -+$r->send(); -+$r->setOptions(array('encodecookies' => false)); -+$r->send(); -+echo $r->getHistory()->toString(true); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+GET /ext-http/.print_request.php HTTP/1.1 -+User-Agent: %a -+Host: dev.iworks.at -+Accept: */* -+Cookie: name=val%3Due -+HTTP/1.1 200 OK -+%a -+ -+Array -+( -+ [name] => val=ue -+) -+ -+GET /ext-http/.print_request.php HTTP/1.1 -+User-Agent: %a -+Host: dev.iworks.at -+Accept: */* -+Cookie: name=val=ue; -+HTTP/1.1 200 OK -+%a -+ -+Array -+( -+ [name] => val=ue -+) -+ -+Done ---- /dev/null -+++ b/ext/http/tests/request_etag.phpt -@@ -0,0 +1,21 @@ -+--TEST-- -+request etag -+--SKIPIF-- -+ -+--FILE-- -+ '"26ad3a-5-95eb19c0"'))); -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+string(%d) "HTTP/1.1 304 Not Modified -+Date: %a -+Server: %a -+ETag: "26ad3a-5-95eb19c0" -+" -+Done -\ No newline at end of file ---- /dev/null -+++ b/ext/http/tests/request_gzip.phpt -@@ -0,0 +1,51 @@ -+--TEST-- -+GZIP request -+--SKIPIF-- -+ -+--FILE-- -+ true)))); -+ -+echo "Done\n"; -+--EXPECTF-- -+%aTEST -+object(stdClass)%a { -+ ["type"]=> -+ int(2) -+ ["httpVersion"]=> -+ float(1.1) -+ ["responseCode"]=> -+ int(200) -+ ["responseStatus"]=> -+ string(2) "OK" -+ ["headers"]=> -+ array(%d) { -+ %a -+ ["Vary"]=> -+ string(15) "Accept-Encoding" -+ ["Content-Length"]=> -+ string(2) "26" -+ ["Content-Type"]=> -+ string(9) "text/html" -+ ["X-Original-Content-Encoding"]=> -+ string(4) "gzip" -+ ["X-Original-Content-Length"]=> -+ string(2) "51" -+ } -+ ["body"]=> -+ string(26) "Array -+( -+ [gzip] => 1 -+) -+" -+ ["parentMessage"]=> -+ NULL -+} -+Done -+ ---- /dev/null -+++ b/ext/http/tests/request_methods.phpt -@@ -0,0 +1,144 @@ -+--TEST-- -+request methods -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+int(0) -+UNKNOWN -+int(0) -+int(1) -+GET -+int(1) -+int(2) -+HEAD -+int(2) -+int(3) -+POST -+int(3) -+int(4) -+PUT -+int(4) -+int(5) -+DELETE -+int(5) -+int(6) -+OPTIONS -+int(6) -+int(7) -+TRACE -+int(7) -+int(8) -+CONNECT -+int(8) -+int(9) -+PROPFIND -+int(9) -+int(10) -+PROPPATCH -+int(10) -+int(11) -+MKCOL -+int(11) -+int(12) -+COPY -+int(12) -+int(13) -+MOVE -+int(13) -+int(14) -+LOCK -+int(14) -+int(15) -+UNLOCK -+int(15) -+int(16) -+VERSION-CONTROL -+int(16) -+int(17) -+REPORT -+int(17) -+int(18) -+CHECKOUT -+int(18) -+int(19) -+CHECKIN -+int(19) -+int(20) -+UNCHECKOUT -+int(20) -+int(21) -+MKWORKSPACE -+int(21) -+int(22) -+UPDATE -+int(22) -+int(23) -+LABEL -+int(23) -+int(24) -+MERGE -+int(24) -+int(25) -+BASELINE-CONTROL -+int(25) -+int(26) -+MKACTIVITY -+int(26) -+int(27) -+ACL -+int(27) -+int(0) -+UNKNOWN -+int(0) -+int(28) -+int(28) -+int(29) -+int(29) -+int(30) -+int(30) -+int(31) -+int(31) -+int(32) -+int(32) -+bool(true) -+int(0) -+int(0) -+bool(true) -+int(0) -+int(0) -+bool(true) -+int(0) -+int(0) -+bool(true) -+int(0) -+int(0) -+bool(true) -+int(0) -+int(0) -+Done ---- /dev/null -+++ b/ext/http/tests/request_put_data.phpt -@@ -0,0 +1,22 @@ -+--TEST-- -+http_put_data() -+--SKIPIF-- -+ -+--FILE-- -+ CURLBUF_SIZE */); -+$resp = http_put_data("http://dev.iworks.at/ext-http/.print_put.php5", $data); -+$mess = http_parse_message($resp); -+var_dump($data === $mess->body); -+ -+echo "Done\n"; -+?> -+--EXPECTF-- -+%aTEST -+bool(true) -+Done ---- /dev/null -+++ b/ext/http/tests/send_data_001.phpt -@@ -0,0 +1,24 @@ -+--TEST-- -+http_send_data() NIL-NUM range -+--SKIPIF-- -+ -+--ENV-- -+HTTP_RANGE=bytes=-5 -+--FILE-- -+ -+--EXPECTF-- -+Status: 206%s -+X-Powered-By: PHP/%s -+Content-Type: text/plain -+Accept-Ranges: bytes -+Content-Range: bytes 5995-5999/6000 -+Content-Length: 5 -+ -+23abc ---- /dev/null -+++ b/ext/http/tests/send_data_002.phpt -@@ -0,0 +1,24 @@ -+--TEST-- -+http_send_data() NUM-NUM range -+--SKIPIF-- -+ -+--ENV-- -+HTTP_RANGE=bytes=5-6 -+--FILE-- -+ -+--EXPECTF-- -+Status: 206%s -+X-Powered-By: PHP/%s -+Content-Type: text/plain -+Accept-Ranges: bytes -+Content-Range: bytes 5-6/6000 -+Content-Length: 2 -+ -+c1 ---- /dev/null -+++ b/ext/http/tests/send_data_003.phpt -@@ -0,0 +1,24 @@ -+--TEST-- -+http_send_data() NUM-NIL range -+--SKIPIF-- -+ -+--ENV-- -+HTTP_RANGE=bytes=5981- -+--FILE-- -+ -+--EXPECTF-- -+Status: 206%s -+X-Powered-By: PHP/%s -+Content-Type: text/plain -+Accept-Ranges: bytes -+Content-Range: bytes 5981-5999/6000 -+Content-Length: 19 -+ -+c123abc123abc123abc ---- /dev/null -+++ b/ext/http/tests/send_data_004.phpt -@@ -0,0 +1,22 @@ -+--TEST-- -+http_send_data() syntactically invalid range -+--SKIPIF-- -+ -+--ENV-- -+HTTP_RANGE=bytes=123,-wtf ? -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%s -+Content-Type: text/plain -+Accept-Ranges: bytes -+Content-Length: 6000 -+ -+123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc123abc -\ No newline at end of file ---- /dev/null -+++ b/ext/http/tests/send_data_005.phpt -@@ -0,0 +1,17 @@ -+--TEST-- -+http_send_data() oversized range -+--SKIPIF-- -+ -+--ENV-- -+HTTP_RANGE=bytes=5990-6000 -+--FILE-- -+ -+--EXPECTF-- -+Status: 416%a -\ No newline at end of file ---- /dev/null -+++ b/ext/http/tests/send_data_006.phpt -@@ -0,0 +1,38 @@ -+--TEST-- -+http_send_data() multiple ranges -+--SKIPIF-- -+ -+--ENV-- -+HTTP_RANGE=bytes=0-3, 4-5,9-11 -+--FILE-- -+ -+--EXPECTF-- -+Status: 206%s -+X-Powered-By: PHP/%s -+Accept-Ranges: bytes -+Content-Type: multipart/byteranges; boundary=%d.%d -+ -+ -+--%d.%d -+Content-Type: text/plain -+Content-Range: bytes 0-3/6000 -+ -+123a -+--%d.%d -+Content-Type: text/plain -+Content-Range: bytes 4-5/6000 -+ -+bc -+--%d.%d -+Content-Type: text/plain -+Content-Range: bytes 9-11/6000 -+ -+abc -+--%d.%d-- ---- /dev/null -+++ b/ext/http/tests/send_data_010.phpt -@@ -0,0 +1,20 @@ -+--TEST-- -+http_send_data() HTTP_SENDBUF_SIZE long string -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%s -+Accept-Ranges: bytes -+Content-Length: 20 -+Content-type: %s -+ -+00000000000000000000 ---- /dev/null -+++ b/ext/http/tests/send_data_011.phpt -@@ -0,0 +1,22 @@ -+--TEST-- -+http_send_data() last modified caching -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%s -+Cache-Control: private, must-revalidate, max-age=0 -+Last-Modified: %s, %d %s %d %d:%d:%d GMT -+Accept-Ranges: bytes -+Content-Length: 4 -+Content-type: %s -+ -+abc ---- /dev/null -+++ b/ext/http/tests/send_failed_precond_001.phpt -@@ -0,0 +1,23 @@ -+--TEST-- -+http_send() failed precondition -+--SKIPIF-- -+ -+--ENV-- -+HTTP_RANGE=bytes=0-1 -+HTTP_IF_UNMODIFIED_SINCE=Thu, 01 Jan 1970 00:16:40 GMT -+--FILE-- -+ -+--EXPECTF-- -+Status: 412%s -+X-Powered-By: %s -+Cache-Control: private, must-revalidate, max-age=0 -+Last-Modified: %s -+Accept-Ranges: bytes -+Content-type: text/html ---- /dev/null -+++ b/ext/http/tests/send_file_005.phpt -@@ -0,0 +1,38 @@ -+--TEST-- -+http_send_file() multiple ranges -+--SKIPIF-- -+ -+--ENV-- -+HTTP_RANGE=bytes=0-3, 4-5,9-11 -+--FILE-- -+ -+--EXPECTF-- -+Status: 206%s -+X-Powered-By: PHP/%s -+Accept-Ranges: bytes -+Content-Type: multipart/byteranges; boundary=%d.%d -+ -+ -+--%d.%d -+Content-Type: text/plain -+Content-Range: bytes 0-3/1010 -+ -+0123 -+--%d.%d -+Content-Type: text/plain -+Content-Range: bytes 4-5/1010 -+ -+45 -+--%d.%d -+Content-Type: text/plain -+Content-Range: bytes 9-11/1010 -+ -+901 -+--%d.%d-- ---- /dev/null -+++ b/ext/http/tests/send_file_008.phpt -@@ -0,0 +1,28 @@ -+--TEST-- -+http_send_file() -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%s -+Accept-Ranges: bytes -+Content-Length: 1010 -+Content-type: %s -+ -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 ---- /dev/null -+++ b/ext/http/tests/send_file_009.phpt -@@ -0,0 +1,23 @@ -+--TEST-- -+http_send_file() NUM-NUM range -+--SKIPIF-- -+ -+--ENV-- -+HTTP_RANGE=bytes=5-9 -+--FILE-- -+ -+--EXPECTF-- -+Status: 206%s -+X-Powered-By: PHP/%s -+Accept-Ranges: bytes -+Content-Range: bytes 5-9/1010 -+Content-Length: 5 -+Content-type: %s -+ -+56789 ---- /dev/null -+++ b/ext/http/tests/send_file_010.phpt -@@ -0,0 +1,23 @@ -+--TEST-- -+http_send_file() NIL-NUM range -+--SKIPIF-- -+ -+--ENV-- -+HTTP_RANGE=bytes=-9 -+--FILE-- -+ -+--EXPECTF-- -+Status: 206%s -+X-Powered-By: PHP/%s -+Accept-Ranges: bytes -+Content-Range: bytes 1001-1009/1010 -+Content-Length: 9 -+Content-type: %s -+ -+23456789 ---- /dev/null -+++ b/ext/http/tests/send_file_011.phpt -@@ -0,0 +1,23 @@ -+--TEST-- -+http_send_file() NUM-NIL range -+--SKIPIF-- -+ -+--ENV-- -+HTTP_RANGE=bytes=1000- -+--FILE-- -+ -+--EXPECTF-- -+Status: 206%s -+X-Powered-By: PHP/%s -+Accept-Ranges: bytes -+Content-Range: bytes 1000-1009/1010 -+Content-Length: 10 -+Content-type: %s -+ -+123456789 ---- /dev/null -+++ b/ext/http/tests/send_file_012.phpt -@@ -0,0 +1,30 @@ -+--TEST-- -+http_send_file() syntactically invalid range -+--SKIPIF-- -+ -+--ENV-- -+HTTP_RANGE=bytes=xxx -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: PHP/%s -+Accept-Ranges: bytes -+Content-Length: 1010 -+Content-type: %s -+ -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 ---- /dev/null -+++ b/ext/http/tests/send_file_013.phpt -@@ -0,0 +1,19 @@ -+--TEST-- -+http_send_file() oversized range -+--SKIPIF-- -+ -+--ENV-- -+HTTP_RANGE=bytes=-1111 -+--FILE-- -+ -+--EXPECTF-- -+Status: 416 -+X-Powered-By: PHP/%s -+Accept-Ranges: bytes -+Content-type: %s ---- /dev/null -+++ b/ext/http/tests/send_ifrange_001.phpt -@@ -0,0 +1,27 @@ -+--TEST-- -+http_send() If-Range -+--SKIPIF-- -+ -+--ENV-- -+HTTP_RANGE=bytes=0-1 -+HTTP_IF_RANGE="abc" -+--FILE-- -+ -+--EXPECTF-- -+Status: 206%s -+X-Powered-By: %s -+Cache-Control: private, must-revalidate, max-age=0 -+ETag: "abc" -+Accept-Ranges: bytes -+Content-Range: bytes 0-1/%d -+Content-Length: 2 -+Content-type: text/html -+ -+ -+--ENV-- -+HTTP_RANGE=bytes=0-1 -+HTTP_IF_RANGE="abcd" -+--FILE-- -+ -+--EXPECTF-- -+X-Powered-By: %s -+Cache-Control: private, must-revalidate, max-age=0 -+ETag: "abc" -+Accept-Ranges: bytes -+Content-Length: %d -+Content-type: text/html -+ -+%a ---- /dev/null -+++ b/ext/http/tests/skip.inc -@@ -0,0 +1,15 @@ -+= v%s",$ver)); } -+function checkmax($ver) { skipif(version_compare(PHP_VERSION, $ver) > 0, sprintf("need PHP <= v%s",$ver)); } -+function checkurl($url) { skipif(!@fsockopen($url, 80), "$url not responsive"); } -+function checkcls($cls) { skipif(!class_exists($cls), "need class $cls"); } -+function checkver($ver) { checkmin($ver); } -+checkext('http'); -+?> ---- /dev/null -+++ b/ext/http/tests/stream_filters_001.phpt -@@ -0,0 +1,45 @@ -+--TEST-- -+stream filters -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+string(30) "5 -+Here -+2 -+we -+5 -+ go! -+ -+0 -+" -+string(12) "Here we go! -+" -+Done ---- /dev/null -+++ b/ext/http/tests/stream_filters_002.phpt -@@ -0,0 +1,50 @@ -+--TEST-- -+gzip stream filters -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+bool(true) -+bool(true) -+bool(true) -+Done ---- /dev/null -+++ b/ext/http/tests/stream_filters_003.phpt -@@ -0,0 +1,42 @@ -+--TEST-- -+stream filter fun -+--SKIPIF-- -+ -+--FILE-- -+ -+--EXPECTF-- -+%aTEST -+This is some stream filter fun; we'll see if it bails out or not. -+The text should come out at the other end of the stream exactly like written to it. -+Go figure! ---- /dev/null -+++ b/ext/http/tests/urls.txt -@@ -0,0 +1,49 @@ -+http://www.microsoft.com -+http://www.opensource.org -+http://www.google.com -+http://www.yahoo.com -+http://www.ibm.com -+http://www.mysql.com -+http://www.oracle.com -+http://www.ripe.net -+http://www.iana.org -+http://www.amazon.com -+http://www.netcraft.com -+http://www.heise.de -+http://www.chip.de -+http://www.ca.com -+http://www.cnet.com -+http://www.news.com -+http://www.cnn.com -+http://www.wikipedia.org -+http://www.dell.com -+http://www.hp.com -+http://www.cert.org -+http://www.mit.edu -+http://www.nist.gov -+http://www.ebay.com -+http://www.playstation.com -+http://www.uefa.com -+http://www.ieee.org -+http://www.apple.com -+http://www.sony.com -+http://www.symantec.com -+http://www.zdnet.com -+http://www.fujitsu.com -+http://www.supermicro.com -+http://www.hotmail.com -+http://www.ecma.com -+http://www.bbc.co.uk -+http://news.google.com -+http://www.foxnews.com -+http://www.msn.com -+http://www.wired.com -+http://www.sky.com -+http://www.usatoday.com -+http://www.cbs.com -+http://www.nbc.com -+http://slashdot.org -+http://www.bloglines.com -+http://www.techweb.com -+http://www.newslink.org -+http://www.un.org -\ No newline at end of file -- 2.11.0