summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorStig Bakken <ssb@php.net>1999-04-22 02:48:28 +0000
committerStig Bakken <ssb@php.net>1999-04-22 02:48:28 +0000
commit2c0ad3ee25cd8e449b02c4668a39f48998507739 (patch)
tree8064c7ee59309ffed3d9c5b8fd5c329ede193561 /ext
parent2a78f92804ae6f3e32cd278afbb9aa8ec3d2f52d (diff)
downloadphp-git-2c0ad3ee25cd8e449b02c4668a39f48998507739.tar.gz
last bunch of extensions moving to ext/
fhttpd module taken out of functions, functions is ready to go. The only extensions I have tested are gd+freetype and odbc(solid). Please try compiling in your favourite extensions and let me know how it works.
Diffstat (limited to 'ext')
-rw-r--r--ext/imap/Makefile.in13
-rw-r--r--ext/informix/Makefile.am3
-rw-r--r--ext/informix/config.h.stub11
-rw-r--r--ext/informix/readme.ifx0
-rw-r--r--ext/informix/setup.stub9
-rw-r--r--ext/interbase/Makefile.am6
-rw-r--r--ext/interbase/config.h.stub3
-rw-r--r--ext/interbase/config.m429
-rw-r--r--ext/interbase/interbase.c1129
-rw-r--r--ext/interbase/php3_interbase.h108
-rw-r--r--ext/interbase/setup.stub7
-rw-r--r--ext/pdf/Makefile.am6
-rw-r--r--ext/pdf/config.h.stub2
-rw-r--r--ext/pdf/config.m437
-rw-r--r--ext/pdf/pdf.c1797
-rw-r--r--ext/pdf/php3_pdf.h106
-rw-r--r--ext/pdf/setup.stub7
-rw-r--r--ext/pgsql/Makefile.am6
-rw-r--r--ext/pgsql/config.h.stub8
-rw-r--r--ext/pgsql/config.m438
-rw-r--r--ext/pgsql/pgsql.c1490
-rw-r--r--ext/pgsql/php3_pgsql.h120
-rw-r--r--ext/pgsql/setup.stub8
-rw-r--r--ext/snmp/Makefile.am6
-rw-r--r--ext/snmp/Makefile.in270
-rw-r--r--ext/snmp/config.h.stub2
-rw-r--r--ext/snmp/config.m431
-rw-r--r--ext/snmp/php3_snmp.h56
-rw-r--r--ext/snmp/snmp.c298
-rw-r--r--ext/standard/Makefile.am4
-rw-r--r--ext/standard/basic_functions.c26
-rw-r--r--ext/standard/config.h.stub12
-rw-r--r--ext/standard/config.m4111
-rw-r--r--ext/standard/fsock.c2
-rw-r--r--ext/standard/mime.c249
-rw-r--r--ext/standard/mime.h8
-rw-r--r--ext/standard/php3_standard.h3
-rw-r--r--ext/standard/post.c498
-rw-r--r--ext/standard/post.h43
-rw-r--r--ext/standard/string.c2
-rw-r--r--ext/standard/var.c2
-rw-r--r--ext/sybase/Makefile.am6
-rw-r--r--ext/sybase/Makefile.in270
-rw-r--r--ext/sybase/config.h.stub6
-rw-r--r--ext/sybase/config.m473
-rw-r--r--ext/sybase/php3_sybase-ct.h123
-rw-r--r--ext/sybase/php3_sybase.h141
-rw-r--r--ext/sybase/setup.stub11
-rw-r--r--ext/sybase/sybase-ct.c1652
-rw-r--r--ext/sybase/sybase.c1258
-rw-r--r--ext/sysvsem/Makefile.am6
-rw-r--r--ext/sysvsem/Makefile.in270
-rw-r--r--ext/sysvsem/config.h.stub7
-rw-r--r--ext/sysvsem/config.m437
-rw-r--r--ext/sysvsem/php3_sysvsem.h74
-rw-r--r--ext/sysvsem/setup.stub5
-rw-r--r--ext/sysvsem/sysvsem.c343
-rw-r--r--ext/sysvshm/Makefile.am6
-rw-r--r--ext/sysvshm/Makefile.in270
-rw-r--r--ext/sysvshm/config.h.stub3
-rw-r--r--ext/sysvshm/config.m417
-rw-r--r--ext/sysvshm/php3_sysvshm.h101
-rw-r--r--ext/sysvshm/setup.stub5
-rw-r--r--ext/sysvshm/sysvshm.c485
-rw-r--r--ext/xml/Makefile.am6
-rw-r--r--ext/xml/Makefile.in270
-rw-r--r--ext/xml/config.h.stub4
-rw-r--r--ext/xml/config.m424
-rw-r--r--ext/xml/php3_xml.h117
-rw-r--r--ext/xml/xml.c1307
-rw-r--r--ext/zlib/Makefile.am6
-rw-r--r--ext/zlib/Makefile.in270
-rw-r--r--ext/zlib/config.h.stub2
-rw-r--r--ext/zlib/config.m438
-rw-r--r--ext/zlib/php3_zlib.h63
-rw-r--r--ext/zlib/setup.stub7
-rw-r--r--ext/zlib/zlib.c926
77 files changed, 14727 insertions, 48 deletions
diff --git a/ext/imap/Makefile.in b/ext/imap/Makefile.in
index d9d006134b..e2c360cc60 100644
--- a/ext/imap/Makefile.in
+++ b/ext/imap/Makefile.in
@@ -75,18 +75,13 @@ EXT_SUBDIRS = @EXT_SUBDIRS@
FHTTPD_LIB = @FHTTPD_LIB@
FHTTPD_TARGET = @FHTTPD_TARGET@
HSREGEX = @HSREGEX@
-IBASE_LFLAGS = @IBASE_LFLAGS@
-IBASE_LIBS = @IBASE_LIBS@
INSTALL_IT = @INSTALL_IT@
LDFLAGS_SHLIB = @LDFLAGS_SHLIB@
LDFLAGS_SHLIB_EXPORT = @LDFLAGS_SHLIB_EXPORT@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
-PDFLIB_LIBS = @PDFLIB_LIBS@
PERL_PATH = @PERL_PATH@
-PGSQL_LFLAGS = @PGSQL_LFLAGS@
-PGSQL_LIBS = @PGSQL_LIBS@
PHP_BUILD_DATE = @PHP_BUILD_DATE@
PHP_DEBUG = @PHP_DEBUG@
PHP_LIBS = @PHP_LIBS@
@@ -95,18 +90,10 @@ PROG_SENDMAIL = @PROG_SENDMAIL@
RANLIB = @RANLIB@
RDYNAMIC_LFLAGS = @RDYNAMIC_LFLAGS@
REGEX_LIB = @REGEX_LIB@
-SNMP_LFLAGS = @SNMP_LFLAGS@
-SNMP_LIBS = @SNMP_LIBS@
STRONGHOLD = @STRONGHOLD@
-SYBASE_CT_LFLAGS = @SYBASE_CT_LFLAGS@
-SYBASE_CT_LIBS = @SYBASE_CT_LIBS@
-SYBASE_LFLAGS = @SYBASE_LFLAGS@
-SYBASE_LIBS = @SYBASE_LIBS@
VERSION = @VERSION@
WARNING_LEVEL = @WARNING_LEVEL@
-XML_LIBS = @XML_LIBS@
YACC = @YACC@
-ZLIB_LIBS = @ZLIB_LIBS@
INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
noinst_LIBRARIES=libphpext_imap.a
diff --git a/ext/informix/Makefile.am b/ext/informix/Makefile.am
index 7122ce04f5..18b8a4fd08 100644
--- a/ext/informix/Makefile.am
+++ b/ext/informix/Makefile.am
@@ -10,3 +10,6 @@ ifx.c: ifx.ec
else \
touch ifx.c; \
fi)
+
+clean:
+ -rm -f ifx.c
diff --git a/ext/informix/config.h.stub b/ext/informix/config.h.stub
index 4b90981e71..a61d630e4d 100644
--- a/ext/informix/config.h.stub
+++ b/ext/informix/config.h.stub
@@ -1,2 +1,9 @@
-/* define if you want to use the informix extension */
-/* #undef HAVE_LIBINFORMIX */
+#ifndef HAVE_IFX
+#define HAVE_IFX 0
+#endif
+#ifndef HAVE_IFX_IUS
+#define HAVE_IFX_IUS 0
+#endif
+#ifndef IFX_VERSION
+#define IFX_VERSION 0
+#endif
diff --git a/ext/informix/readme.ifx b/ext/informix/readme.ifx
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/ext/informix/readme.ifx
diff --git a/ext/informix/setup.stub b/ext/informix/setup.stub
index a7476fb79e..9a9d1ad841 100644
--- a/ext/informix/setup.stub
+++ b/ext/informix/setup.stub
@@ -1,6 +1,9 @@
# $Source$
# $Id$
-define_option with-informix 'informix support?' yesnodir no \
-' Whether to build the informix extension.'
-
+define_option with-informix 'Informix support?' yesnodir \
+ "no $INFORMIXDIR Informix home" \
+' Whether to build PHP with Informix support. If you have not set up your\n
+ Informix environment, enter what $INFORMIXDIR is usually set to here.\n
+ You MUST set $INFORMIXDIR before trying to compile!\n
+ More info about Informix can be found at http://www.informix.com/.'
diff --git a/ext/interbase/Makefile.am b/ext/interbase/Makefile.am
new file mode 100644
index 0000000000..494e3b9ef9
--- /dev/null
+++ b/ext/interbase/Makefile.am
@@ -0,0 +1,6 @@
+# $Id$
+
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_interbase.a
+libphpext_interbase_a_SOURCES=interbase.c
+
diff --git a/ext/interbase/config.h.stub b/ext/interbase/config.h.stub
new file mode 100644
index 0000000000..d54ee2a9d6
--- /dev/null
+++ b/ext/interbase/config.h.stub
@@ -0,0 +1,3 @@
+#ifndef HAVE_IBASE
+#define HAVE_IBASE 0
+#endif
diff --git a/ext/interbase/config.m4 b/ext/interbase/config.m4
new file mode 100644
index 0000000000..2328e25e1a
--- /dev/null
+++ b/ext/interbase/config.m4
@@ -0,0 +1,29 @@
+dnl $Id$
+
+AC_MSG_CHECKING(for InterBase support)
+AC_ARG_WITH(interbase,
+[ --with-interbase[=DIR] Include InterBase support. DIR is the InterBase base
+ install directory, defaults to /usr/interbase],
+[
+ if test "$withval" != "no"; then
+ if test "$withval" = "yes"; then
+ IBASE_INCDIR=/usr/interbase/include
+ IBASE_LIBDIR=/usr/interbase/lib
+ else
+ IBASE_INCDIR=$withval/include
+ IBASE_LIBDIR=$withval/lib
+ fi
+ IBASE_INCLUDE=-I$IBASE_INCDIR
+ IBASE_LFLAGS=-L$IBASE_LIBDIR
+ IBASE_LIBS="-lgds"
+ AC_DEFINE(HAVE_IBASE)
+ AC_MSG_RESULT(yes)
+ EXTRA_LIBS="$EXTRA_LIBS $IBASE_LFLAGS $IBASE_LIBS"
+ INCLUDES="$INCLUDES $IBASE_INCLUDE"
+ PHP_EXTENSION(interbase)
+ else
+ AC_MSG_RESULT(no)
+ fi
+],[
+ AC_MSG_RESULT(no)
+])
diff --git a/ext/interbase/interbase.c b/ext/interbase/interbase.c
new file mode 100644
index 0000000000..c239cb610c
--- /dev/null
+++ b/ext/interbase/interbase.c
@@ -0,0 +1,1129 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Jouni Ahto <jah@cultnet.fi> |
+ | |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+/* TODO: A lot... */
+
+#include "config.h"
+#include "php.h"
+#include "php3_interbase.h"
+
+#if HAVE_IBASE
+#include <ibase.h>
+#include <time.h>
+#include "php3_string.h"
+#include "php_globals.h"
+
+/* {{{ extension definition structures */
+function_entry ibase_functions[] = {
+ {"ibase_connect", php3_ibase_connect, NULL},
+ {"ibase_pconnect", php3_ibase_pconnect, NULL},
+ {"ibase_close", php3_ibase_close, NULL},
+ {"ibase_query", php3_ibase_query, NULL},
+ {"ibase_fetch_row", php3_ibase_fetch_row, NULL},
+ {"ibase_free_result", php3_ibase_free_result, NULL},
+ {"ibase_prepare", php3_ibase_prepare, NULL},
+ {"ibase_bind", php3_ibase_bind, NULL},
+ {"ibase_execute", php3_ibase_execute, NULL},
+ {"ibase_free_query", php3_ibase_free_query, NULL},
+ {"ibase_timefmt", php3_ibase_timefmt, NULL},
+ {NULL, NULL, NULL}
+};
+
+php3_module_entry ibase_module_entry =
+{
+ "InterBase",
+ ibase_functions,
+ php3_minit_ibase,
+ NULL,
+ php3_rinit_ibase,
+ NULL,
+ php3_info_ibase,
+ STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+/* {{{ thread safety stuff */
+#if defined(THREAD_SAFE)
+typedef ibase_global_struct{
+ ibase_module php3_ibase_module;
+} ibase_global_struct;
+
+#define IBASE_GLOBAL(a) ibase_globals->a
+
+#define IBASE_TLS_VARS \
+ ibase_global_struct *ibase_globals; \
+ ibase_globals=TlsGetValue(IBASETls);
+
+#else
+#define IBASE_GLOBAL(a) a
+#define IBASE_TLS_VARS
+ibase_module php3_ibase_module;
+#endif
+/* }}} */
+
+/* {{{ _php3_ibase_close_link() */
+static void _php3_ibase_close_link(isc_db_handle db)
+{
+ ISC_STATUS status[20];
+ IBASE_TLS_VARS;
+
+ isc_detach_database(status, &db);
+ IBASE_GLOBAL(php3_ibase_module).num_links--;
+}
+/* }}} */
+
+/* {{{ _php3_ibase_close_plink() */
+static void _php3_ibase_close_plink(isc_db_handle db)
+{
+ ISC_STATUS status[20];
+ IBASE_TLS_VARS;
+
+ isc_detach_database(status, &db);
+ php3_ibase_module.num_persistent--;
+ php3_ibase_module.num_links--;
+}
+/* }}} */
+
+/* {{{ _php3_ibase_free_result() */
+static void _php3_ibase_free_result(ibase_result_handle *result)
+{
+ int i;
+ ISC_STATUS status[20];
+ IBASE_TLS_VARS;
+
+ if (!IBASE_GLOBAL(php3_ibase_module).manualtransactions && result->commitok) {
+ isc_commit_transaction(status, &result->trans);
+ }
+ if (result->sqlda != NULL) {
+ for (i = 0; i < result->sqlda->sqld; i++) {
+ efree(result->sqlda->sqlvar[i].sqldata);
+ efree(result->sqlda->sqlvar[i].sqlind);
+ }
+ efree(result->sqlda);
+ }
+ isc_dsql_free_statement(status, &result->result, DSQL_drop);
+ efree(result);
+}
+/* }}} */
+
+/* {{{ _php3_ibase_free_query() */
+static void _php3_ibase_free_query(ibase_query_handle *query)
+{
+ int i;
+ ISC_STATUS status[20];
+
+ if (query->sqlda != NULL) {
+ if (query->alloced) {
+ for (i = 0; i < query->sqlda->sqld; i++) {
+ efree(query->sqlda->sqlvar[i].sqldata);
+ efree(query->sqlda->sqlvar[i].sqlind);
+ }
+ }
+ efree(query->sqlda);
+ }
+ isc_dsql_free_statement(status, &query->query, DSQL_drop);
+ efree(query);
+}
+/* }}} */
+
+/* {{{ startup, shutdown and info functions */
+int php3_minit_ibase(INIT_FUNC_ARGS)
+{
+ IBASE_TLS_VARS;
+
+ if (cfg_get_long("ibase.allow_persistent", &IBASE_GLOBAL(php3_ibase_module).allow_persistent) == FAILURE) {
+ IBASE_GLOBAL(php3_ibase_module).allow_persistent = 1;
+ }
+ if (cfg_get_long("ibase.max_persistent", &IBASE_GLOBAL(php3_ibase_module).max_persistent) == FAILURE) {
+ IBASE_GLOBAL(php3_ibase_module).max_persistent = -1;
+ }
+ if (cfg_get_long("ibase.max_links", &IBASE_GLOBAL(php3_ibase_module).max_links) == FAILURE) {
+ IBASE_GLOBAL(php3_ibase_module).max_links = -1;
+ }
+ /*
+ if (cfg_get_long("ibase.manualtransactions", &IBASE_GLOBAL(php3_ibase_module).manualtransactions) == FAILURE) {
+ IBASE_GLOBAL(php3_ibase_module).manualtransactions = 0;
+ }
+ */
+ IBASE_GLOBAL(php3_ibase_module).manualtransactions = 0;
+ if (cfg_get_string("ibase.default_user", &IBASE_GLOBAL(php3_ibase_module).default_user) == FAILURE
+ || IBASE_GLOBAL(php3_ibase_module).default_user[0] == 0) {
+ IBASE_GLOBAL(php3_ibase_module).default_user = "";
+ }
+ if (cfg_get_string("ibase.default_password", &IBASE_GLOBAL(php3_ibase_module).default_password) == FAILURE
+ || IBASE_GLOBAL(php3_ibase_module).default_password[0] == 0) {
+ IBASE_GLOBAL(php3_ibase_module).default_password = "";
+ }
+ if (cfg_get_string("ibase.timeformat", &IBASE_GLOBAL(php3_ibase_module).timeformat) == FAILURE) {
+ IBASE_GLOBAL(php3_ibase_module).timeformat = "%Y-%m-%d %H:%M:%S";
+ }
+ IBASE_GLOBAL(php3_ibase_module).num_persistent=0;
+ IBASE_GLOBAL(php3_ibase_module).le_result = register_list_destructors(_php3_ibase_free_result, NULL);
+ IBASE_GLOBAL(php3_ibase_module).le_query = register_list_destructors(_php3_ibase_free_query, NULL);
+ IBASE_GLOBAL(php3_ibase_module).le_link = register_list_destructors(_php3_ibase_close_link, NULL);
+ IBASE_GLOBAL(php3_ibase_module).le_plink = register_list_destructors(NULL, _php3_ibase_close_plink);
+ return SUCCESS;
+}
+
+int php3_rinit_ibase(INIT_FUNC_ARGS)
+{
+ IBASE_TLS_VARS;
+
+ IBASE_GLOBAL(php3_ibase_module).default_link=-1;
+ IBASE_GLOBAL(php3_ibase_module).num_links = php3_ibase_module.num_persistent;
+ return SUCCESS;
+}
+
+/* TODO IF NEEDED
+
+int php3_mfinish_ibase(void)
+{
+}
+
+int php3_rfinish_ibase(void)
+{
+}
+*/
+
+void php3_info_ibase(void)
+{
+ /* TODO */
+}
+/* }}} */
+
+/* {{{ _php_ibase_attach_db() */
+static int _php_ibase_attach_db(char *server, char *uname, int uname_len, char *passwd, int passwd_len, isc_db_handle *db)
+{
+ ISC_STATUS status[20];
+ int db_parbuf_len = 4;
+ short foo = 4;
+ char dpb[255], *db_parbuf;
+
+ if (uname_len) {
+ db_parbuf_len += uname_len + 2;
+ }
+
+ if (passwd_len) {
+ db_parbuf_len += passwd_len + 2;
+ }
+
+ db_parbuf = dpb;
+ *db_parbuf++ = isc_dpb_version1;
+ *db_parbuf++ = isc_dpb_num_buffers;
+ *db_parbuf++ = 1;
+ *db_parbuf++ = 90;
+
+ if (uname_len) {
+ if (passwd_len) {
+ isc_expand_dpb(&db_parbuf, &foo, isc_dpb_user_name, uname, isc_dpb_password, passwd, NULL);
+ } else {
+ isc_expand_dpb(&db_parbuf, &foo, isc_dpb_user_name, uname, NULL);
+ }
+ }
+
+ isc_attach_database(status, strlen(server), server, db, db_parbuf_len, dpb);
+
+ if (status[0] == 1 && status[1]) {
+ php3_error(E_WARNING,"Unable to connect to InterBase server: %s", "XXX");
+ return 1;
+ }
+ return 0;
+}
+/* }}} */
+
+/* {{{ _php3_ibase_connect() */
+static void _php3_ibase_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
+{
+ pval *server, *uname, *passwd;
+
+ char *ib_server, *ib_uname, *ib_passwd;
+ int ib_server_len, ib_uname_len, ib_passwd_len;
+ isc_db_handle db_handle = NULL;
+ char *hashed_details;
+ int hashed_details_length;
+ IBASE_TLS_VARS;
+
+ ib_uname = IBASE_GLOBAL(php3_ibase_module).default_user;
+ ib_passwd = IBASE_GLOBAL(php3_ibase_module).default_password;
+ ib_uname_len = ib_uname ? strlen(ib_uname) : 0;
+ ib_passwd_len = ib_passwd ? strlen(ib_passwd) : 0;
+
+ switch(ARG_COUNT(ht)) {
+ case 1:
+ {
+ if (getParameters(ht, 1, &server) == FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string(server);
+ ib_server = server->value.str.val;
+ ib_server_len = server->value.str.len;
+ hashed_details_length = server->value.str.len+ib_uname_len+ib_passwd_len+5+3;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details, "ibase_%s_%s_%s", ib_server, ib_uname, ib_passwd);
+ }
+ break;
+ case 2:
+ {
+ if (getParameters(ht, 2, &server, &uname) == FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string(server);
+ convert_to_string(uname);
+ ib_server = server->value.str.val;
+ ib_uname = uname->value.str.val;
+ ib_server_len = server->value.str.len;
+ ib_uname_len = uname->value.str.len;
+ hashed_details_length = server->value.str.len+uname->value.str.len+ib_passwd_len+5+3;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details, "ibase_%s_%s_%s", ib_server, ib_uname, ib_passwd);
+ }
+ break;
+ case 3:
+ {
+ if (getParameters(ht, 3, &server, &uname, &passwd) == FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string(server);
+ convert_to_string(uname);
+ convert_to_string(passwd);
+ ib_server = server->value.str.val;
+ ib_uname = uname->value.str.val;
+ ib_passwd = passwd->value.str.val;
+ ib_server_len = server->value.str.len;
+ ib_uname_len = uname->value.str.len;
+ ib_passwd_len = passwd->value.str.len;
+ hashed_details_length = server->value.str.len+uname->value.str.len+passwd->value.str.len+5+3;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details, "ibase_%s_%s_%s", ib_server, ib_uname, ib_passwd);
+ }
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ if (persistent) {
+ list_entry *le;
+
+ if (_php3_hash_find(plist, hashed_details, hashed_details_length+1, (void **) &le)==FAILURE) {
+ list_entry new_le;
+
+ if (IBASE_GLOBAL(php3_ibase_module).max_links!=-1 && IBASE_GLOBAL(php3_ibase_module).num_links>=IBASE_GLOBAL(php3_ibase_module).max_links) {
+ php3_error(E_WARNING,"InterBase: Too many open links (%d)", IBASE_GLOBAL(php3_ibase_module).num_links);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ if (IBASE_GLOBAL(php3_ibase_module).max_persistent!=-1 && IBASE_GLOBAL(php3_ibase_module).num_persistent>=IBASE_GLOBAL(php3_ibase_module).max_persistent) {
+ php3_error(E_WARNING,"InterBase: Too many open persistent links (%d)", IBASE_GLOBAL(php3_ibase_module).num_persistent);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ /* create the link */
+
+ if (_php_ibase_attach_db(ib_server, ib_uname, ib_uname_len, ib_passwd, ib_passwd_len, &db_handle)) {
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ /* hash it up */
+ new_le.type = php3_ibase_module.le_plink;
+ new_le.ptr = db_handle;
+ if (_php3_hash_update(plist, hashed_details, hashed_details_length+1, (void *) &new_le, sizeof(list_entry), NULL)==FAILURE) {
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ IBASE_GLOBAL(php3_ibase_module).num_links++;
+ IBASE_GLOBAL(php3_ibase_module).num_persistent++;
+ } else {
+ if (le->type != IBASE_GLOBAL(php3_ibase_module).le_plink) {
+ RETURN_FALSE;
+ }
+ /* TODO: ensure that the link did not die */
+
+ db_handle = (isc_db_handle) le->ptr;
+ }
+ return_value->value.lval = php3_list_insert(db_handle, IBASE_GLOBAL(php3_ibase_module).le_plink);
+ return_value->type = IS_LONG;
+ } else {
+ list_entry *index_ptr, new_index_ptr;
+
+ /* first we check the hash for the hashed_details key. if it exists,
+ * it should point us to the right offset where the actual pgsql link sits.
+ * if it doesn't, open a new pgsql link, add it to the resource list,
+ * and add a pointer to it with hashed_details as the key.
+ */
+ if (_php3_hash_find(list,hashed_details,hashed_details_length+1,(void **) &index_ptr)==SUCCESS) {
+ int type,link;
+ void *ptr;
+
+ if (index_ptr->type != le_index_ptr) {
+ RETURN_FALSE;
+ }
+ link = (int) index_ptr->ptr;
+ ptr = php3_list_find(link,&type); /* check if the link is still there */
+ if (ptr && (type==IBASE_GLOBAL(php3_ibase_module).le_link || type==IBASE_GLOBAL(php3_ibase_module).le_plink)) {
+ return_value->value.lval = IBASE_GLOBAL(php3_ibase_module).default_link = link;
+ return_value->type = IS_LONG;
+ efree(hashed_details);
+ return;
+ } else {
+ _php3_hash_del(list,hashed_details,hashed_details_length+1);
+ }
+ }
+ if (IBASE_GLOBAL(php3_ibase_module).max_links!=-1 && IBASE_GLOBAL(php3_ibase_module).num_links>=IBASE_GLOBAL(php3_ibase_module).max_links) {
+ php3_error(E_WARNING,"InterBase: Too many open links (%d)", IBASE_GLOBAL(php3_ibase_module).num_links);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ /* create the link */
+
+ if (_php_ibase_attach_db(ib_server, ib_uname, ib_uname_len, ib_passwd, ib_passwd_len, &db_handle)) {
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ /* add it to the list */
+ return_value->value.lval = php3_list_insert(db_handle, IBASE_GLOBAL(php3_ibase_module).le_link);
+ return_value->type = IS_LONG;
+
+ /* add it to the hash */
+ new_index_ptr.ptr = (void *) return_value->value.lval;
+ new_index_ptr.type = le_index_ptr;
+ if (_php3_hash_update(list,hashed_details,hashed_details_length+1,(void *) &new_index_ptr, sizeof(list_entry), NULL)==FAILURE) {
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ IBASE_GLOBAL(php3_ibase_module).num_links++;
+ }
+ efree(hashed_details);
+ IBASE_GLOBAL(php3_ibase_module).default_link=return_value->value.lval;
+}
+/* }}} */
+
+/* {{{ proto int ibase_connect(string database [, string username] [, string password])
+ Open a connection to an InterBase database */
+void php3_ibase_connect(INTERNAL_FUNCTION_PARAMETERS)
+{
+ _php3_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ proto int ibase_pconnect(string database [, string username] [, string password])
+ Open a persistent connection to an InterBase database */
+void php3_ibase_pconnect(INTERNAL_FUNCTION_PARAMETERS)
+{
+ _php3_ibase_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ proto int ibase_close([int link_identifier])
+ Close an InterBase connection */
+void php3_ibase_close(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *ibase_link;
+ int id, type;
+ isc_db_handle db_handle;
+ IBASE_TLS_VARS;
+
+ switch (ARG_COUNT(ht)) {
+ case 0:
+ id = IBASE_GLOBAL(php3_ibase_module).default_link;
+ break;
+ case 1:
+ if (getParameters(ht, 1, &ibase_link) == FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(ibase_link);
+ id = ibase_link->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ db_handle = (isc_db_handle) php3_list_find(id, &type);
+ if (type!=IBASE_GLOBAL(php3_ibase_module).le_link && type!=IBASE_GLOBAL(php3_ibase_module).le_plink) {
+ php3_error(E_WARNING, "%d is not an InterBase link index",id);
+ RETURN_FALSE;
+ }
+
+ php3_list_delete(ibase_link->value.lval);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ _php3_ibase_prepare() */
+static XSQLDA *_php3_ibase_prepare(isc_db_handle db, isc_tr_handle tr, isc_stmt_handle *query_handle, char *query)
+{
+ ISC_STATUS status[20];
+ XSQLDA *isqlda;
+
+ isqlda = (XSQLDA *) emalloc(XSQLDA_LENGTH(0));
+ isqlda->sqln = 0;
+ isqlda->version = SQLDA_VERSION1;
+
+ if (isc_dsql_allocate_statement(status, &db, query_handle)) {
+ php3_error(E_WARNING, "InterBase: couldn't allocate space for query");
+ return NULL;
+ }
+
+ if (isc_dsql_prepare(status, &tr, query_handle, 0, query, 1, isqlda)) {
+ php3_error(E_WARNING, "InterBase: couldn't prepare query");
+ return NULL;
+ }
+
+ /*
+ * Check if query has placeholders and needs binding. If it has, allocate
+ * input sqlda big enough and return it.
+ */
+
+
+ if (isc_dsql_describe_bind(status, query_handle, 1, isqlda)) {
+ php3_error(E_WARNING, "InterBase: couldn't describe placeholders in query");
+ }
+
+ if (isqlda->sqld > 1) {
+ isqlda = (XSQLDA *) erealloc(isqlda, XSQLDA_LENGTH(isqlda->sqld));
+ isqlda->sqln = isqlda->sqld;
+ isqlda->version = SQLDA_VERSION1;
+ if (isc_dsql_describe(status, query_handle, 1, isqlda)) {
+ php3_error(E_WARNING, "InterBase: couldn't describe query");
+ }
+ return isqlda;
+ } else if (isqlda->sqld == 1) {
+ return isqlda;
+ } else {
+ efree(isqlda);
+ return NULL;
+ }
+}
+/* }}} */
+
+/* {{{ _php3_ibase_execute() */
+static XSQLDA *_php3_ibase_execute(isc_tr_handle tr_handle, isc_stmt_handle query_handle, XSQLDA *isqlda, ISC_STATUS *status)
+{
+ int i, coltype;
+ static char query_info[] = { isc_info_sql_stmt_type };
+ char info_buffer[18];
+ short l;
+ long query_type;
+ XSQLDA *osqlda;
+
+ /*
+ * Find out what kind of query is to be executed.
+ */
+
+ if (!isc_dsql_sql_info(status, &query_handle, sizeof(query_info), query_info, sizeof(info_buffer), info_buffer)) {
+ l = (short) isc_vax_integer((char ISC_FAR *) info_buffer + 1, 2);
+ query_type = isc_vax_integer((char ISC_FAR *) info_buffer + 3, l);
+ }
+
+ if (query_type == isc_info_sql_stmt_select || query_type == isc_info_sql_stmt_select_for_upd) {
+ /*
+ * Select, need to allocate output sqlda and and prepare it for use.
+ */
+
+ osqlda = (XSQLDA *) emalloc(XSQLDA_LENGTH(0));
+ osqlda->sqln = 0;
+ osqlda->version = SQLDA_VERSION1;
+
+ if (isc_dsql_describe(status, &query_handle, 1, osqlda)) {
+ php3_error(E_WARNING, "InterBase: couldn't describe query");
+ }
+
+ if (osqlda->sqld) {
+ osqlda = (XSQLDA *) erealloc(osqlda, XSQLDA_LENGTH(osqlda->sqld));
+ osqlda->sqln = osqlda->sqld;
+ osqlda->version = SQLDA_VERSION1;
+ if (isc_dsql_describe(status, &query_handle, 1, osqlda)) {
+ php3_error(E_WARNING, "InterBase: couldn't describe query");
+ }
+ }
+ for (i = 0; i < osqlda->sqld; i++) {
+ osqlda->sqlvar[i].sqlind = (short *) emalloc(sizeof(short));
+ coltype = osqlda->sqlvar[i].sqltype & ~1;
+ switch(coltype)
+ {
+ case SQL_TEXT:
+ osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(char)*(osqlda->sqlvar[i].sqllen));
+ break;
+ case SQL_VARYING:
+ osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(char)*(osqlda->sqlvar[i].sqllen+2));
+ break;
+ case SQL_SHORT:
+ osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(short));
+ break;
+ case SQL_LONG:
+ osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(long));
+ break;
+ case SQL_FLOAT:
+ osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(float));
+ break;
+ case SQL_DOUBLE:
+ osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(double));
+ break;
+ case SQL_DATE:
+ osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(ISC_QUAD));
+ break;
+ case SQL_BLOB:
+ osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(ISC_QUAD));
+ break;
+ case SQL_ARRAY:
+ osqlda->sqlvar[i].sqldata = (char *) emalloc(sizeof(ISC_QUAD));
+ break;
+ }
+ }
+ if (isqlda == NULL) {
+ if (isc_dsql_execute(status, &tr_handle, &query_handle, 1, NULL)) {
+ php3_error(E_WARNING, "InterBase: couldn't execute query");
+ return NULL;
+ } else {
+ return osqlda;
+ }
+
+ } else {
+ if (isc_dsql_execute2(status, &tr_handle, &query_handle, 1, isqlda, osqlda)) {
+ php3_error(E_WARNING, "InterBase: couldn't execute query");
+ return NULL;
+ } else {
+ return osqlda;
+ }
+
+ }
+ } else {
+ /* Not select */
+ if (isc_dsql_execute(status, &tr_handle, &query_handle, 1, isqlda)) {
+ php3_error(E_WARNING, "InterBase: couldn't execute query");
+ }
+ /*
+ if (!php3_ibase_module.manualtransactions) {
+ if(0) {
+ isc_commit_transaction(status, tr_handle);
+ } else {
+ isc_rollback_transaction(status, tr_handle);
+ }
+ }
+ */
+ }
+
+ return NULL;
+}
+/* }}} */
+
+/* {{{ proto int ibase_query([int link_identifier, ]string query)
+ Execute a query (without parameter placeholders). */
+void php3_ibase_query(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *query, *ibase_link;
+ int id, type;
+ isc_db_handle db_handle;
+ isc_tr_handle tr_handle = NULL;
+ isc_stmt_handle query_handle = NULL;
+ ISC_STATUS status[20];
+ XSQLDA *isqlda, *osqlda;
+ ibase_result_handle *ibase_result;
+ IBASE_TLS_VARS;
+
+ switch (ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &query) == FAILURE) {
+ RETURN_FALSE;
+ }
+ id = IBASE_GLOBAL(php3_ibase_module).default_link;
+ break;
+ case 2:
+ if (getParameters(ht, 2, &ibase_link, &query) == FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(ibase_link);
+ id = ibase_link->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ db_handle = (isc_db_handle) php3_list_find(id, &type);
+ if (type!=IBASE_GLOBAL(php3_ibase_module).le_link && type!=IBASE_GLOBAL(php3_ibase_module).le_plink) {
+ php3_error(E_WARNING, "%d is not an InterBase link index", id);
+ RETURN_FALSE;
+ }
+
+ convert_to_string(query);
+
+ if (!IBASE_GLOBAL(php3_ibase_module).manualtransactions) {
+ if (isc_start_transaction(status, &tr_handle, 1, &db_handle, 0, NULL)) {
+ php3_error(E_WARNING, "InterBase: couldn't start transaction");
+ RETURN_FALSE;
+ }
+ }
+
+ isqlda = _php3_ibase_prepare(db_handle, tr_handle, &query_handle, query->value.str.val);
+ if (isqlda != NULL) {
+ isc_rollback_transaction(status, &tr_handle);
+ isc_dsql_free_statement(status, &query_handle, DSQL_drop);
+ php3_error(E_WARNING, "InterBase: ibase_query doesn't support parameter placeholders in query");
+ RETURN_FALSE;
+ }
+
+ osqlda = _php3_ibase_execute(tr_handle, query_handle, isqlda, status);
+ if (osqlda != NULL) {
+ ibase_result = (ibase_result_handle *) emalloc(sizeof(ibase_result_handle));
+ ibase_result->result = query_handle;
+ ibase_result->sqlda = osqlda;
+ ibase_result->trans = tr_handle;
+ ibase_result->commitok = 1;
+ return_value->value.lval = php3_list_insert(ibase_result, php3_ibase_module.le_result);
+ return_value->type = IS_LONG;
+ } else {
+ if (status[0] == 1 && status[1]) {
+ if (!IBASE_GLOBAL(php3_ibase_module).manualtransactions) {
+ isc_rollback_transaction(status, &tr_handle);
+ isc_dsql_free_statement(status, &query_handle, DSQL_drop);
+ RETURN_FALSE;
+ }
+ } else {
+ if (!IBASE_GLOBAL(php3_ibase_module).manualtransactions) {
+ isc_commit_transaction(status, &tr_handle);
+ isc_dsql_free_statement(status, &query_handle, DSQL_drop);
+ RETURN_FALSE;
+ }
+ }
+ }
+}
+/* }}} */
+
+/* {{{ proto int ibase_fetch_row(int result)
+ Fetch a row from the results of a query. */
+void php3_ibase_fetch_row(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *result;
+ pval *pval_ptr;
+ int type;
+ int i, coltype, collen;
+ char string_data[255];
+ char *fieldname;
+ char *char_data;
+ /*
+ struct tm t;
+ */
+ ibase_result_handle *ibase_result;
+ ISC_STATUS status[20];
+ XSQLVAR *var;
+ IBASE_VCHAR *vchar;
+ IBASE_TLS_VARS;
+ PLS_FETCH();
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &result)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(result);
+ ibase_result = (ibase_result_handle *) php3_list_find(result->value.lval, &type);
+
+ if (type!=IBASE_GLOBAL(php3_ibase_module).le_result) {
+ php3_error(E_WARNING,"%d is not an InterBase result index", result->value.lval);
+ RETURN_FALSE;
+ }
+
+ if (ibase_result->sqlda == NULL) {
+ php3_error(E_WARNING,"InterBase: trying to fetch results from a non-select query");
+ RETURN_FALSE;
+ }
+
+ var = ibase_result->sqlda->sqlvar;
+
+ if (isc_dsql_fetch(status, &ibase_result->result, 1, ibase_result->sqlda) != 100L) {
+ if (array_init(return_value)==FAILURE) {
+ RETURN_FALSE;
+ }
+
+ for (i = 0; i < ibase_result->sqlda->sqld; i++) {
+ var[i].sqlname[var[i].sqlname_length] = '\0';
+ fieldname = var[i].sqlname;
+ if (*var[i].sqlind < 0) {
+ /* XXX. Column is NULL. This is not the best idea to do, think something... */
+ add_get_index_stringl(return_value, i, NULL, 0, (void **) &pval_ptr, 1);
+ _php3_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr);
+ continue;
+ }
+ coltype = var[i].sqltype & ~1;
+ switch(coltype) {
+ case SQL_TEXT:
+ {
+ int len = var[i].sqllen;
+ char_data = (char *)emalloc(sizeof(char)*(var[i].sqllen));
+ collen = sprintf(char_data, "%*.*s", len, len, ibase_result->sqlda->sqlvar[i].sqldata);
+ if (PG(magic_quotes_runtime)) {
+ int newlen;
+ char *tmp = _php3_addslashes(char_data, collen, &newlen, 0);
+ add_get_index_stringl(return_value, i, tmp, newlen, (void **) &pval_ptr, 0);
+ } else {
+ add_get_index_stringl(return_value, i, char_data, collen, (void **) &pval_ptr, 1);
+ }
+ _php3_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr);
+ efree(char_data);
+ }
+ break;
+ case SQL_VARYING:
+ {
+ vchar = (IBASE_VCHAR *) var[i].sqldata;
+ char_data = (char *)emalloc(sizeof(char)*(vchar->var_len));
+ collen = sprintf(char_data, "%*.*s", vchar->var_len, vchar->var_len, vchar->var_str);
+ if (PG(magic_quotes_runtime)) {
+ int newlen;
+ char *tmp = _php3_addslashes(char_data, collen, &newlen, 0);
+ add_get_index_stringl(return_value, i, tmp, newlen, (void **) &pval_ptr, 0);
+ } else {
+ add_get_index_stringl(return_value, i, char_data, collen, (void **) &pval_ptr, 1);
+ }
+ _php3_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr);
+ efree(char_data);
+ }
+ break;
+ case SQL_SHORT:
+ collen = sprintf(string_data, "%d", *(short *)(var[i].sqldata));
+ add_get_index_stringl(return_value, i, string_data, collen, (void **) &pval_ptr, 1);
+ _php3_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr);
+ break;
+ case SQL_LONG:
+ if (var[i].sqlscale) {
+ int j, f = 1;
+ float n;
+ n = *(long *)(var[i].sqldata);
+ for (j = 0; j < -var[i].sqlscale; j++)
+ f *= 10;
+ n /= f;
+ collen = sprintf(string_data, "%.*f", -var[i].sqlscale, n);
+
+ } else {
+ collen = sprintf(string_data, "%ld", *(long *)(var[i].sqldata));
+ }
+ add_get_index_stringl(return_value, i, string_data, collen, (void **) &pval_ptr, 1);
+ _php3_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr);
+ break;
+ case SQL_FLOAT:
+ collen = sprintf(string_data, "%f", *(float *)(var[i].sqldata));
+ add_get_index_stringl(return_value, i, string_data, collen, (void **) &pval_ptr, 1);
+ _php3_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr);
+ break;
+ case SQL_DOUBLE:
+ if (ibase_result->sqlda->sqlvar[i].sqlscale) {
+ collen = sprintf(string_data, "%.*f", -var[i].sqlscale, *(double *)(var[i].sqldata));
+ } else {
+ collen = sprintf(string_data, "%f", *(double *)(var[i].sqldata));
+ }
+ add_get_index_stringl(return_value, i, string_data, collen, (void **) &pval_ptr, 1);
+ _php3_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr);
+ break;
+ case SQL_DATE: {
+ struct tm *t;
+ t = emalloc(sizeof(struct tm));
+
+ isc_decode_date((ISC_QUAD *) var[i].sqldata, t);
+ /*
+#if HAVE_STRFTIME
+ collen = (int) strftime(string_data, 255, IBASE_GLOBAL(php3_ibase_module).timeformat, t);
+#else
+ */
+ collen = sprintf(string_data, "%4d-%02d-%02d %02d:%02d:%02d", t->tm_year+1900, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
+ /* #endif */
+ add_get_index_stringl(return_value, i, string_data, collen, (void **) &pval_ptr, 1);
+ _php3_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr);
+ efree(t);
+ }
+ break;
+ case SQL_BLOB:
+ case SQL_ARRAY:
+ {
+ /* TODO, currently just show the id */
+ ISC_QUAD bid;
+ bid = *(ISC_QUAD ISC_FAR *) var[i].sqldata;
+ sprintf(string_data, "%lx:%lx", bid.isc_quad_high, bid.isc_quad_low);
+ add_get_index_stringl(return_value, i, string_data, collen, (void **) &pval_ptr, 1);
+ _php3_hash_pointer_update(return_value->value.ht, fieldname, var[i].sqlname_length+1, pval_ptr);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto int ibase_free_result(int result)
+ Free the memory used by a result. */
+void php3_ibase_free_result(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *result;
+ ibase_result_handle *ibase_result;
+ int type;
+ IBASE_TLS_VARS;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &result)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(result);
+ if (result->value.lval==0) {
+ RETURN_FALSE;
+ }
+
+ ibase_result = (ibase_result_handle *) php3_list_find(result->value.lval,&type);
+
+ if (type!=IBASE_GLOBAL(php3_ibase_module).le_result) {
+ php3_error(E_WARNING,"%d is not an InterBase result index",result->value.lval);
+ RETURN_FALSE;
+ }
+ php3_list_delete(result->value.lval);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int ibase_prepare([int link_identifier, ]string query)
+ Prepare a query for later binding of parameter placeholders and execution. */
+void php3_ibase_prepare(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *query, *ibase_link;
+ int id, type;
+ isc_db_handle db_handle;
+ isc_tr_handle tr_handle = NULL;
+ isc_stmt_handle query_handle = NULL;
+ ISC_STATUS status[20];
+ XSQLDA *isqlda;
+ ibase_query_handle *ibase_query;
+ IBASE_TLS_VARS;
+
+ switch (ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &query) == FAILURE) {
+ RETURN_FALSE;
+ }
+ id = IBASE_GLOBAL(php3_ibase_module).default_link;
+ break;
+ case 2:
+ if (getParameters(ht, 2, &ibase_link, &query) == FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(ibase_link);
+ id = ibase_link->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ db_handle = (isc_db_handle) php3_list_find(id, &type);
+ if (type!=IBASE_GLOBAL(php3_ibase_module).le_link && type!=IBASE_GLOBAL(php3_ibase_module).le_plink) {
+ php3_error(E_WARNING, "%d is not an InterBase link index", id);
+ RETURN_FALSE;
+ }
+
+ convert_to_string(query);
+
+ if (!IBASE_GLOBAL(php3_ibase_module).manualtransactions) {
+ if (isc_start_transaction(status, &tr_handle, 1, &db_handle, 0, NULL)) {
+ php3_error(E_WARNING, "InterBase: couldn't start transaction");
+ RETURN_FALSE;
+ }
+ }
+
+ isqlda = _php3_ibase_prepare(db_handle, tr_handle, &query_handle, query->value.str.val);
+ ibase_query = (ibase_query_handle *) emalloc(sizeof(ibase_query_handle));
+ ibase_query->query = query_handle;
+ ibase_query->sqlda = isqlda;
+ ibase_query->trans = tr_handle;
+ ibase_query->alloced = 0;
+ return_value->value.lval = php3_list_insert(ibase_query, php3_ibase_module.le_query);
+ return_value->type = IS_LONG;
+}
+/* }}} */
+
+/* {{{ proto int ibase_bind (int query)
+ Bind parameter placeholders in a previously prepared query. Still nonfunctional. */
+void php3_ibase_bind(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *query;
+ ibase_query_handle *ibase_query;
+ int type;
+ IBASE_TLS_VARS;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &query)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(query);
+ if (query->value.lval==0) {
+ RETURN_FALSE;
+ }
+
+ ibase_query = (ibase_query_handle *) php3_list_find(query->value.lval,&type);
+
+ if (type!=IBASE_GLOBAL(php3_ibase_module).le_query) {
+ php3_error(E_WARNING,"%d is not an InterBase query index",query->value.lval);
+ RETURN_FALSE;
+ }
+
+ if (ibase_query->sqlda == NULL) {
+ php3_error(E_WARNING,"InterBase: trying to bind a query having no parameter placeholders");
+ RETURN_FALSE;
+ }
+
+ /* TODO
+ for (i = 0; i < ibase_query->sqlda->sqld; i++) {
+ ibase_query->sqlda->sqlvar[i].sqlind = (short *) emalloc(sizeof(short));
+ coltype = ibase_query->sqlda->sqlvar[i].sqltype & ~1;
+ switch(coltype)
+ {
+ case SQL_TEXT:
+ break;
+ case SQL_VARYING:
+ break;
+ case SQL_SHORT:
+ break;
+ case SQL_LONG:
+ break;
+ case SQL_FLOAT:
+ break;
+ case SQL_DOUBLE:
+ break;
+ case SQL_DATE:
+ break;
+ case SQL_BLOB:
+ break;
+ case SQL_ARRAY:
+ break;
+ }
+ }
+ */
+}
+/* }}} */
+
+/* {{{ proto int ibase_execute(int query)
+ Execute a previously prepared (and possibly binded) query. */
+void php3_ibase_execute(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *query;
+ ibase_query_handle *ibase_query;
+ ibase_result_handle *ibase_result;
+ int type;
+ ISC_STATUS status[20];
+ XSQLDA *osqlda;
+ IBASE_TLS_VARS;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &query)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(query);
+ if (query->value.lval==0) {
+ RETURN_FALSE;
+ }
+
+ ibase_query = (ibase_query_handle *) php3_list_find(query->value.lval,&type);
+
+ if (type!=IBASE_GLOBAL(php3_ibase_module).le_query) {
+ php3_error(E_WARNING,"%d is not an InterBase query index", query->value.lval);
+ RETURN_FALSE;
+ }
+
+ osqlda = _php3_ibase_execute(ibase_query->trans, ibase_query->query, ibase_query->sqlda, status);
+ ibase_result = (ibase_result_handle *) emalloc(sizeof(ibase_result_handle));
+ ibase_result->result = ibase_query->query;
+ ibase_result->sqlda = osqlda;
+ return_value->value.lval = php3_list_insert(ibase_result, IBASE_GLOBAL(php3_ibase_module).le_result);
+ return_value->type = IS_LONG;
+}
+/* }}} */
+
+/* {{{ proto int ibase_free_query(int query)
+ Free memory used by a query */
+void php3_ibase_free_query(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *query;
+ ibase_query_handle *ibase_query;
+ int type;
+ IBASE_TLS_VARS;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &query)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(query);
+ if (query->value.lval==0) {
+ RETURN_FALSE;
+ }
+
+ ibase_query = (ibase_query_handle *) php3_list_find(query->value.lval, &type);
+
+ if (type!=IBASE_GLOBAL(php3_ibase_module).le_query) {
+ php3_error(E_WARNING,"%d is not an InterBase query index", query->value.lval);
+ RETURN_FALSE;
+ }
+ php3_list_delete(query->value.lval);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int ibase_timefmt(string format)
+ Sets the format of datetime columns returned from queries. Still nonfunctional. */
+void php3_ibase_timefmt(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *pmode;
+ IBASE_TLS_VARS;
+
+#if HAVE_STRFTIME
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &pmode)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string(pmode);
+
+ RETURN_TRUE;
+#else
+ php3_error(E_WARNING,"InterBase: ibase_timefmt not supported on this platform");
+ RETURN_FALSE;
+#endif
+}
+/* }}} */
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/interbase/php3_interbase.h b/ext/interbase/php3_interbase.h
new file mode 100644
index 0000000000..47da79d574
--- /dev/null
+++ b/ext/interbase/php3_interbase.h
@@ -0,0 +1,108 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Jouni Ahto <jah@cultnet.fi> |
+ | |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifndef _PHP3_IBASE_H
+#define _PHP3_IBASE_H
+
+#if COMPILE_DL
+#undef HAVE_IBASE
+#define HAVE_IBASE 1
+#endif
+
+#if HAVE_IBASE
+#include <ibase.h>
+
+extern php3_module_entry ibase_module_entry;
+#define php3_ibase_module_ptr &ibase_module_entry
+
+extern int php3_minit_ibase(INIT_FUNC_ARGS);
+extern int php3_rinit_ibase(INIT_FUNC_ARGS);
+extern int php3_mfinish_ibase(void);
+extern void php3_info_ibase(void);
+extern void php3_ibase_connect(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_ibase_pconnect(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_ibase_close(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_ibase_query(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_ibase_fetch_row(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_ibase_free_result(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_ibase_prepare(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_ibase_bind(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_ibase_execute(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_ibase_free_query(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_ibase_timefmt(INTERNAL_FUNCTION_PARAMETERS);
+
+typedef struct {
+ long default_link;
+ long num_links, num_persistent;
+ long max_links, max_persistent;
+ long allow_persistent;
+ int le_link, le_plink, le_result, le_query;
+ char *default_user, *default_password;
+ long manualtransactions;
+ char *timeformat;
+} ibase_module;
+
+typedef struct _php3_ibase_result {
+ isc_stmt_handle result;
+ isc_tr_handle trans;
+ XSQLDA *sqlda;
+ int commitok;
+} ibase_result_handle;
+
+typedef struct _php3_ibase_query {
+ isc_stmt_handle query;
+ isc_tr_handle trans;
+ XSQLDA *sqlda;
+ int alloced;
+} ibase_query_handle;
+
+typedef struct _php3_ibase_varchar {
+ short var_len;
+ char var_str[1];
+} IBASE_VCHAR;
+
+extern ibase_module php3_ibase_module;
+
+#else
+
+#define php3_ibase_module_ptr NULL
+
+#endif /* HAVE_IBASE */
+
+#endif /* _PHP3_IBASE_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/interbase/setup.stub b/ext/interbase/setup.stub
new file mode 100644
index 0000000000..3c6a41fe0f
--- /dev/null
+++ b/ext/interbase/setup.stub
@@ -0,0 +1,7 @@
+# $Source$
+# $Id$
+
+define_option with-interbase 'InterBase support?' yesnodir \
+ 'no /usr/interbase InterBase base install' \
+' Whether to build PHP with InterBase support. More\n
+ information about InterBase can be found at http://www.interbase.com/.'
diff --git a/ext/pdf/Makefile.am b/ext/pdf/Makefile.am
new file mode 100644
index 0000000000..6b4304d337
--- /dev/null
+++ b/ext/pdf/Makefile.am
@@ -0,0 +1,6 @@
+# $Id$
+
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_pdf.a
+libphpext_pdf_a_SOURCES=pdf.c
+
diff --git a/ext/pdf/config.h.stub b/ext/pdf/config.h.stub
new file mode 100644
index 0000000000..11c404a9f7
--- /dev/null
+++ b/ext/pdf/config.h.stub
@@ -0,0 +1,2 @@
+/* Define if you have the pdflib library */
+#define HAVE_PDFLIB 0
diff --git a/ext/pdf/config.m4 b/ext/pdf/config.m4
new file mode 100644
index 0000000000..c421e2a1c7
--- /dev/null
+++ b/ext/pdf/config.m4
@@ -0,0 +1,37 @@
+dnl $Id$
+
+AC_MSG_CHECKING(whether to include pdflib support)
+AC_ARG_WITH(pdflib,
+[ --with-pdflib[=DIR] Include pdflib support (tested with 0.6).
+ DIR is the pdflib install directory,
+ defaults to /usr/local.],
+[
+ case "$withval" in
+ no)
+ AC_MSG_RESULT(no) ;;
+ yes)
+ AC_MSG_RESULT(yes)
+ PHP_EXTENSION(pdf)
+ AC_CHECK_LIB(pdf, PDF_open, [AC_DEFINE(HAVE_PDFLIB) PDFLIB_LIBS="-lpdf"],
+ [AC_MSG_ERROR(pdflib extension requires pdflib 0.6.)])
+ EXTRA_LIBS="$EXTRA_LIBS $PDFLIB_LIBS"
+ ;;
+ *)
+ test -f $withval/include/pdf.h && PDFLIB_INCLUDE="-I$withval/include"
+ if test -n "$PDFLIB_INCLUDE" ; then
+ AC_MSG_RESULT(yes)
+ PHP_EXTENSION(pdf)
+ old_LIBS=$LIBS
+ LIBS="$LIBS -L$withval/lib"
+ AC_CHECK_LIB(pdf, PDF_open, [AC_DEFINE(HAVE_PDFLIB) PDFLIB_LIBS="-L$withval/lib -lpdf"],
+ [AC_MSG_ERROR(pdflib extension requires pdflib 0.6.)])
+ LIBS=$old_LIBS
+ EXTRA_LIBS="$EXTRA_LIBS $PDFLIB_LIBS"
+ INCLUDES="$INCLUDES $PDFLIB_INCLUDE"
+ else
+ AC_MSG_RESULT(no)
+ fi ;;
+ esac
+],[
+ AC_MSG_RESULT(no)
+])
diff --git a/ext/pdf/pdf.c b/ext/pdf/pdf.c
new file mode 100644
index 0000000000..2e90f5aa2e
--- /dev/null
+++ b/ext/pdf/pdf.c
@@ -0,0 +1,1797 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Uwe Steinmann <Uwe.Steinmann@fernuni-hagen.de> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+/* pdflib 0.6 is subject to the ALADDIN FREE PUBLIC LICENSE.
+ Copyright (C) 1997 Thomas Merz. */
+
+/* Note that there is no code from the pdflib package in this file */
+
+#if !PHP_31 && defined(THREAD_SAFE)
+#undef THREAD_SAFE
+#endif
+
+#include "php.h"
+#include "ext/standard/head.h"
+#include <math.h>
+#include "php3_pdf.h"
+
+#if HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#if WIN32|WINNT
+# include <io.h>
+# include <fcntl.h>
+#endif
+
+#if HAVE_PDFLIB
+
+#ifdef THREAD_SAFE
+DWORD PDFlibTls;
+static int numthreads=0;
+
+typedef struct pdflib_global_struct{
+ int le_pdf_info;
+ int le_pdf;
+} pdflib_global_struct;
+
+# define PDF_GLOBAL(a) pdflib_globals->a
+# define PDF_TLS_VARS pdflib_global_struct *pdflib_globals=TlsGetValue(PDFlibTls)
+
+#else
+# define PDF_GLOBAL(a) a
+# define PDF_TLS_VARS
+int le_pdf_info;
+int le_pdf;
+#endif
+
+function_entry pdf_functions[] = {
+ {"pdf_get_info", php3_pdf_get_info, NULL},
+ {"pdf_set_info_creator", php3_pdf_set_info_creator, NULL},
+ {"pdf_set_info_title", php3_pdf_set_info_title, NULL},
+ {"pdf_set_info_subject", php3_pdf_set_info_subject, NULL},
+ {"pdf_set_info_author", php3_pdf_set_info_author, NULL},
+ {"pdf_set_info_keywords", php3_pdf_set_info_keywords, NULL},
+ {"pdf_open", php3_pdf_open, NULL},
+ {"pdf_close", php3_pdf_close, NULL},
+ {"pdf_begin_page", php3_pdf_begin_page, NULL},
+ {"pdf_end_page", php3_pdf_end_page, NULL},
+ {"pdf_show", php3_pdf_show, NULL},
+ {"pdf_show_xy", php3_pdf_show_xy, NULL},
+ {"pdf_set_font", php3_pdf_set_font, NULL},
+ {"pdf_set_leading", php3_pdf_set_leading, NULL},
+ {"pdf_set_text_rendering", php3_pdf_set_text_rendering,NULL},
+ {"pdf_set_horiz_scaling", php3_pdf_set_horiz_scaling, NULL},
+ {"pdf_set_text_rise", php3_pdf_set_text_rise, NULL},
+ {"pdf_set_text_matrix", php3_pdf_set_text_matrix, NULL},
+ {"pdf_set_text_pos", php3_pdf_set_text_pos, NULL},
+ {"pdf_set_char_spacing", php3_pdf_set_char_spacing, NULL},
+ {"pdf_set_word_spacing", php3_pdf_set_word_spacing, NULL},
+ {"pdf_continue_text", php3_pdf_continue_text, NULL},
+ {"pdf_stringwidth", php3_pdf_stringwidth, NULL},
+ {"pdf_save", php3_pdf_save, NULL},
+ {"pdf_restore", php3_pdf_restore, NULL},
+ {"pdf_translate", php3_pdf_translate, NULL},
+ {"pdf_scale", php3_pdf_scale, NULL},
+ {"pdf_rotate", php3_pdf_rotate, NULL},
+ {"pdf_setflat", php3_pdf_setflat, NULL},
+ {"pdf_setlinejoin", php3_pdf_setlinejoin, NULL},
+ {"pdf_setlinecap", php3_pdf_setlinecap, NULL},
+ {"pdf_setmiterlimit", php3_pdf_setmiterlimit, NULL},
+ {"pdf_setlinewidth", php3_pdf_setlinewidth, NULL},
+ {"pdf_setdash", php3_pdf_setdash, NULL},
+ {"pdf_moveto", php3_pdf_moveto, NULL},
+ {"pdf_lineto", php3_pdf_lineto, NULL},
+ {"pdf_curveto", php3_pdf_curveto, NULL},
+ {"pdf_circle", php3_pdf_circle, NULL},
+ {"pdf_arc", php3_pdf_arc, NULL},
+ {"pdf_rect", php3_pdf_rect, NULL},
+ {"pdf_closepath", php3_pdf_closepath, NULL},
+ {"pdf_stroke", php3_pdf_stroke, NULL},
+ {"pdf_closepath_stroke", php3_pdf_closepath_stroke, NULL},
+ {"pdf_fill", php3_pdf_fill, NULL},
+ {"pdf_fill_stroke", php3_pdf_fill_stroke, NULL},
+ {"pdf_closepath_fill_stroke", php3_pdf_closepath_fill_stroke, NULL},
+ {"pdf_endpath", php3_pdf_endpath, NULL},
+ {"pdf_clip", php3_pdf_clip, NULL},
+ {"pdf_setgray_fill", php3_pdf_setgray_fill, NULL},
+ {"pdf_setgray_stroke", php3_pdf_setgray_stroke, NULL},
+ {"pdf_setgray", php3_pdf_setgray, NULL},
+ {"pdf_setrgbcolor_fill", php3_pdf_setrgbcolor_fill, NULL},
+ {"pdf_setrgbcolor_stroke", php3_pdf_setrgbcolor_stroke,NULL},
+ {"pdf_setrgbcolor", php3_pdf_setrgbcolor, NULL},
+ {"pdf_add_outline", php3_pdf_add_outline, NULL},
+ {"pdf_set_transition", php3_pdf_set_transition, NULL},
+ {"pdf_set_duration", php3_pdf_set_duration, NULL},
+ {NULL, NULL, NULL}
+};
+
+php3_module_entry pdf_module_entry = {
+ "pdf", pdf_functions, php3_minit_pdf, php3_mend_pdf, NULL, NULL, php3_info_pdf, STANDARD_MODULE_PROPERTIES
+};
+
+#if COMPILE_DL
+#include "dl/phpdl.h"
+DLEXPORT php3_module_entry *get_module(void) { return &pdf_module_entry; }
+#endif
+
+static void _free_pdf_info(PDF_info *info)
+{
+ if(info->Title) efree(info->Title);
+ if(info->Subject) efree(info->Subject);
+ if(info->Author) efree(info->Author);
+ if(info->Keywords) efree(info->Keywords);
+ if(info->Creator) efree(info->Creator);
+}
+
+int php3_minit_pdf(INIT_FUNC_ARGS)
+{
+ PDF_GLOBAL(le_pdf_info) = register_list_destructors(_free_pdf_info, NULL);
+ PDF_GLOBAL(le_pdf) = register_list_destructors(php3_pdf_close, NULL);
+ return SUCCESS;
+}
+
+void php3_info_pdf(void) {
+ /* need to use a PHPAPI function here because it is external module in windows */
+ php3_printf("%s. AFM files in %s", PDFLIB_VERSION, PDF_DEFAULT_FONT_PATH);
+}
+
+int php3_mend_pdf(void){
+ return SUCCESS;
+}
+
+/* {{{ proto int pdf_get_info(void)
+ Returns a default info structure for a pdf document */
+void php3_pdf_get_info(INTERNAL_FUNCTION_PARAMETERS) {
+ PDF_info *pdf_info;
+ int id;
+ PDF_TLS_VARS;
+
+ pdf_info = PDF_get_info();
+
+ if(!pdf_info) {
+ php3_error(E_WARNING, "Could not get PDF info");
+ RETURN_FALSE;
+ }
+
+ id = php3_list_insert(pdf_info,PDF_GLOBAL(le_pdf_info));
+ RETURN_LONG(id);
+}
+/* }}} */
+
+/* {{{ proto pdf_set_info_creator(int info, string creator)
+ Fills the creator field of the info structure */
+void php3_pdf_set_info_creator(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF_info *pdf_info;
+ PDF_TLS_VARS;
+
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_string(arg2);
+ id=arg1->value.lval;
+ pdf_info = php3_list_find(id,&type);
+ if (!pdf_info || type!=PDF_GLOBAL(le_pdf_info)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d (type=%d)",id, type);
+ RETURN_FALSE;
+ }
+
+ pdf_info->Creator = estrdup(arg2->value.str.val);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto pdf_set_info_title(int info, string title)
+ Fills the title field of the info structure */
+void php3_pdf_set_info_title(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF_info *pdf_info;
+ PDF_TLS_VARS;
+
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_string(arg2);
+ id=arg1->value.lval;
+ pdf_info = php3_list_find(id,&type);
+ if (!pdf_info || type!=PDF_GLOBAL(le_pdf_info)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d (type=%d)",id, type);
+ RETURN_FALSE;
+ }
+
+ pdf_info->Title = estrdup(arg2->value.str.val);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto pdf_set_info_subject(int info, string subject)
+ Fills the subject field of the info structure */
+void php3_pdf_set_info_subject(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF_info *pdf_info;
+ PDF_TLS_VARS;
+
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_string(arg2);
+ id=arg1->value.lval;
+ pdf_info = php3_list_find(id,&type);
+ if (!pdf_info || type!=PDF_GLOBAL(le_pdf_info)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d (type=%d)",id, type);
+ RETURN_FALSE;
+ }
+
+ pdf_info->Subject = estrdup(arg2->value.str.val);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto pdf_set_info_author(int info, string author)
+ Fills the author field of the info structure */
+void php3_pdf_set_info_author(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF_info *pdf_info;
+ PDF_TLS_VARS;
+
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_string(arg2);
+ id=arg1->value.lval;
+ pdf_info = php3_list_find(id,&type);
+ if (!pdf_info || type!=PDF_GLOBAL(le_pdf_info)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d (type=%d)",id, type);
+ RETURN_FALSE;
+ }
+
+ pdf_info->Author = estrdup(arg2->value.str.val);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto pdf_set_info_keywords(int info, string keywords)
+ Fills the keywords field of the info structure */
+void php3_pdf_set_info_keywords(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF_info *pdf_info;
+ PDF_TLS_VARS;
+
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_string(arg2);
+ id=arg1->value.lval;
+ pdf_info = php3_list_find(id,&type);
+ if (!pdf_info || type!=PDF_GLOBAL(le_pdf_info)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d (type=%d)",id, type);
+ RETURN_FALSE;
+ }
+
+ pdf_info->Keywords = estrdup(arg2->value.str.val);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int pdf_open(int filedesc, int info)
+ Opens a new pdf document */
+void php3_pdf_open(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *file;
+ pval *info;
+ int id, type;
+ FILE *fp;
+ PDF_info *pdf_info;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &file, &info) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(file);
+ convert_to_long(info);
+ id=file->value.lval;
+ fp = php3_list_find(id,&type);
+ if (!fp || type!=php3i_get_le_fp()) {
+ php3_error(E_WARNING,"Unable to find file identifier %d (type=%d)",id, type);
+ RETURN_FALSE;
+ }
+
+ id=info->value.lval;
+ pdf_info = php3_list_find(id,&type);
+ if (!pdf_info || type!=PDF_GLOBAL(le_pdf_info)) {
+ php3_error(E_WARNING,"Unable to find pdf info identifier %d (%d!=%d)",id, type, PDF_GLOBAL(le_pdf_info));
+ RETURN_FALSE;
+ }
+
+ pdf = PDF_open(fp, pdf_info);
+ if(!pdf)
+ RETURN_FALSE;
+
+ id = php3_list_insert(pdf,PDF_GLOBAL(le_pdf));
+ RETURN_LONG(id);
+}
+/* }}} */
+
+/* {{{ proto void pdf_close(int pdfdoc)
+ Closes the pdf document */
+void php3_pdf_close(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_close(pdf);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_begin_page(int pdfdoc, double height, double width)
+ Starts page */
+void php3_pdf_begin_page(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3;
+ int id, type;
+ double height, width;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ convert_to_double(arg3);
+ id=arg1->value.lval;
+ height = arg2->value.dval;
+ width = arg3->value.dval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_begin_page(pdf, (float) height, (float) width);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_end_page(int pdfdoc)
+ Ends page */
+void php3_pdf_end_page(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_end_page(pdf);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_show(int pdfdoc, string text)
+ Output text at current position */
+void php3_pdf_show(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_string(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_show(pdf, arg2->value.str.val);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_show_xy(int pdfdoc, string text)
+ Output text at position */
+void php3_pdf_show_xy(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3, *arg4;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_string(arg2);
+ convert_to_double(arg3);
+ convert_to_double(arg4);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_show_xy(pdf, arg2->value.str.val, (float) arg3->value.dval, (float) arg4->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_set_font(int pdfdoc, string font, double size, string encoding)
+ Select the current font face and size */
+void php3_pdf_set_font(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3, *arg4;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_string(arg2);
+ convert_to_double(arg3);
+ convert_to_string(arg4);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_set_font(pdf, arg2->value.str.val, (float) arg3->value.dval, builtin);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_set_leading(int pdfdoc, double distance)
+ Sets distance between text lines */
+void php3_pdf_set_leading(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_set_leading(pdf, (float) arg2->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_set_text_rendering(int pdfdoc, int mode)
+ Determines how text is rendered */
+void php3_pdf_set_text_rendering(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_long(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_set_text_rendering(pdf, (byte) arg2->value.lval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_set_horiz_scaling(int pdfdoc, double scale)
+ Sets horizontal scaling of text */
+void php3_pdf_set_horiz_scaling(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_set_horiz_scaling(pdf, (float) arg2->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_set_text_rise(int pdfdoc, double value)
+ Sets the text rise */
+void php3_pdf_set_text_rise(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_set_text_rise(pdf, (float) arg2->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_set_text_matrix(int pdfdoc, arry matrix)
+ Sets the text matrix */
+void php3_pdf_set_text_matrix(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *data;
+ int id, type, i;
+ HashTable *matrix;
+ PDF *pdf;
+ PDF_matrix pdfmatrix;
+ float *pdfmatrixptr;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_array(arg2);
+ id=arg1->value.lval;
+ matrix=arg2->value.ht;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ if(_php3_hash_num_elements(matrix) != 6) {
+ php3_error(E_WARNING,"Text matrix must have 6 elements");
+ RETURN_FALSE;
+ }
+
+ pdfmatrixptr = (float *) &pdfmatrix;
+ _php3_hash_internal_pointer_reset(matrix);
+ for(i=0; i<_php3_hash_num_elements(matrix); i++) {
+ _php3_hash_get_current_data(matrix, (void *) &data);
+ switch(data->type) {
+ case IS_DOUBLE:
+ *pdfmatrixptr++ = (float) data->value.dval;
+ default:
+ *pdfmatrixptr++ = 0.0;
+ }
+ _php3_hash_move_forward(matrix);
+ }
+
+ PDF_set_text_matrix(pdf, pdfmatrix);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_set_text_pos(int pdfdoc, double x, double y)
+ */
+void php3_pdf_set_text_pos(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ convert_to_double(arg3);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_set_text_pos(pdf, (float) arg2->value.dval, (float) arg3->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_set_char_spacing(int pdfdoc, double space)
+ Sets character spacing */
+void php3_pdf_set_char_spacing(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_set_char_spacing(pdf, (float) arg2->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_set_word_spacing(int pdfdoc, double space)
+ Sets spacing between words */
+void php3_pdf_set_word_spacing(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_set_word_spacing(pdf, (float) arg2->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_continue_text(int pdfdoc, string text)
+ Output text in next line */
+void php3_pdf_continue_text(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_string(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_continue_text(pdf, arg2->value.str.val);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto double pdf_stringwidth(int pdfdoc, string text)
+ Returns width of text in current font*/
+void php3_pdf_stringwidth(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ double width;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_string(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ width = (double) PDF_stringwidth(pdf, arg2->value.str.val);
+
+ RETURN_DOUBLE((double)width);
+}
+/* }}} */
+
+/* {{{ proto void pdf_save(int pdfdoc)
+ Saves current enviroment */
+void php3_pdf_save(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_save(pdf);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_restore(int pdfdoc)
+ Restores formerly saved enviroment */
+void php3_pdf_restore(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_restore(pdf);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_translate(int pdfdoc, double x, double y)
+ Sets origin of coordinate system */
+void php3_pdf_translate(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ convert_to_double(arg3);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_translate(pdf, (float) arg2->value.dval, (float) arg3->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_scale(int pdfdoc, double x-scale, double y-scale)
+ Sets scaling */
+void php3_pdf_scale(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ convert_to_double(arg3);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_scale(pdf, (float) arg2->value.dval, (float) arg3->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_rotate(int pdfdoc, double angle)
+ Sets rotation */
+void php3_pdf_rotate(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_rotate(pdf, (float) arg2->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_setflat(int pdfdoc, double value)
+ Sets flatness */
+void php3_pdf_setflat(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ if((arg2->value.lval > 100) && (arg2->value.lval < 0)) {
+ php3_error(E_WARNING,"Parameter of pdf_setflat() has to between 0 and 100");
+ RETURN_FALSE;
+ }
+
+ PDF_setflat(pdf, (float) arg2->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_setlinejoin(int pdfdoc, int value)
+ Sets linejoin parameter */
+void php3_pdf_setlinejoin(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_long(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ if((arg2->value.lval > 2) && (arg2->value.lval < 0)) {
+ php3_error(E_WARNING,"Parameter of pdf_setlinejoin() has to between 0 and 2");
+ RETURN_FALSE;
+ }
+
+ PDF_setlinejoin(pdf, (byte) arg2->value.lval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_setlinecap(int pdfdoc, int value)
+ Sets linecap parameter */
+void php3_pdf_setlinecap(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_long(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ if((arg2->value.lval > 2) && (arg2->value.lval < 0)) {
+ php3_error(E_WARNING,"Parameter of pdf_setlinecap() has to be > 0 and =< 2");
+ RETURN_FALSE;
+ }
+
+ PDF_setlinecap(pdf, (byte) arg2->value.lval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_setmiterlimit(int pdfdoc, double value)
+ Sets miter limit */
+void php3_pdf_setmiterlimit(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ if(arg2->value.dval < 1) {
+ php3_error(E_WARNING,"Parameter of pdf_setmiterlimit() has to be >= 1");
+ RETURN_FALSE;
+ }
+
+ PDF_setmiterlimit(pdf, (float) arg2->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_setlinewidth(int pdfdoc, double width)
+ Sets line width */
+void php3_pdf_setlinewidth(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_setlinewidth(pdf, (float) arg2->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_setdash(int pdfdoc, double white, double black)
+ Sets dash pattern */
+void php3_pdf_setdash(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ convert_to_double(arg3);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_setdash(pdf, (float) arg2->value.dval, (float) arg3->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_moveto(int pdfdoc, double x, double y)
+ Sets current point */
+void php3_pdf_moveto(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ convert_to_double(arg3);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_moveto(pdf, (float) arg2->value.dval, (float) arg3->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_curveto(int pdfdoc, double x1, double y1, double x2, double y2, double x3, double y3)
+ Draws a curve */
+void php3_pdf_curveto(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3, *arg4, *arg5, *arg6, *arg7;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 7 || getParameters(ht, 7, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ convert_to_double(arg3);
+ convert_to_double(arg4);
+ convert_to_double(arg5);
+ convert_to_double(arg6);
+ convert_to_double(arg7);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_curveto(pdf, (float) arg2->value.dval,
+ (float) arg3->value.dval,
+ (float) arg4->value.dval,
+ (float) arg5->value.dval,
+ (float) arg6->value.dval,
+ (float) arg7->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_lineto(int pdfdoc, double x, double y)
+ Draws a line */
+void php3_pdf_lineto(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ convert_to_double(arg3);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_lineto(pdf, (float) arg2->value.dval, (float) arg3->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_circle(int pdfdoc, double x, double y, double radius)
+ Draws a circle */
+void php3_pdf_circle(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3, *arg4;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ convert_to_double(arg3);
+ convert_to_double(arg4);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_circle(pdf, (float) arg2->value.dval, (float) arg3->value.dval, (float) arg4->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_arc(int pdfdoc, double x, double y, double radius, double start, double end)
+ Draws an arc */
+void php3_pdf_arc(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3, *arg4, *arg5, *arg6;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 6 || getParameters(ht, 6, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ convert_to_double(arg3);
+ convert_to_double(arg4);
+ convert_to_double(arg5);
+ convert_to_double(arg6);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_arc(pdf, (float) arg2->value.dval, (float) arg3->value.dval, (float) arg4->value.dval, (float) arg5->value.dval, (float) arg6->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_rect(int pdfdoc, double x, double y, double width, double height)
+ Draws a rectangle */
+void php3_pdf_rect(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3, *arg4, *arg5;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 5 || getParameters(ht, 5, &arg1, &arg2, &arg3, &arg4, &arg5) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ convert_to_double(arg3);
+ convert_to_double(arg4);
+ convert_to_double(arg5);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_rect(pdf, (float) arg2->value.dval,
+ (float) arg3->value.dval,
+ (float) arg4->value.dval,
+ (float) arg5->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_closepath(int pdfdoc)
+ Close path */
+void php3_pdf_closepath(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_closepath(pdf);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_closepath_stroke(int pdfdoc)
+ Close path and draw line along path */
+void php3_pdf_closepath_stroke(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_closepath_stroke(pdf);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_closepath_stroke(int pdfdoc)
+ Draw line along path path */
+void php3_pdf_stroke(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_stroke(pdf);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_fill(int pdfdoc)
+ Fill current path */
+void php3_pdf_fill(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_fill(pdf);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_fill_stroke(int pdfdoc)
+ Fill and stroke current path */
+void php3_pdf_fill_stroke(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_fill_stroke(pdf);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_closepath_fill_stroke(int pdfdoc)
+ Close, fill and stroke current path */
+void php3_pdf_closepath_fill_stroke(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_closepath_fill_stroke(pdf);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_endpath(int pdfdoc)
+ Ends current path */
+void php3_pdf_endpath(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_endpath(pdf);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_clip(int pdfdoc)
+ Clips to current path */
+void php3_pdf_clip(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_clip(pdf);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_setgray_fill(int pdfdoc, double value)
+ Sets filling color to gray value */
+void php3_pdf_setgray_fill(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_setgray_fill(pdf, (float) arg2->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_setgray_stroke(int pdfdoc, double value)
+ Sets drawing color to gray value */
+void php3_pdf_setgray_stroke(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_setgray_stroke(pdf, (float) arg2->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_setgray(int pdfdoc, double value)
+ Sets drawing and filling color to gray value */
+void php3_pdf_setgray(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_setgray(pdf, (float) arg2->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_setrgbcolor_fill(int pdfdoc, double red, double green, double blue)
+ Sets filling color to rgb color value */
+void php3_pdf_setrgbcolor_fill(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3, *arg4;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_setrgbcolor_fill(pdf, (float) arg2->value.dval, (float) arg3->value.dval, (float) arg4->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_setrgbcolor_stroke(int pdfdoc, double red, double green, double blue)
+ Sets drawing color to rgb color value */
+void php3_pdf_setrgbcolor_stroke(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3, *arg4;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_setrgbcolor_stroke(pdf, (float) arg2->value.dval, (float) arg3->value.dval, (float) arg4->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_setrgbcolor(int pdfdoc, double red, double green, double blue)
+ Sets drawing and filling color to rgb color value */
+void php3_pdf_setrgbcolor(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3, *arg4;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_setrgbcolor(pdf, (float) arg2->value.dval, (float) arg3->value.dval, (float) arg4->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_add_outline(int pdfdoc, string text);
+ Add bookmark for current page */
+void php3_pdf_add_outline(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_string(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_add_outline(pdf, arg2->value.str.val);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_set_transition(int pdfdoc, int transition)
+ Sets transition between pages */
+void php3_pdf_set_transition(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_long(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_set_transition(pdf, arg2->value.lval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void pdf_set_duration(int pdfdoc, double duration)
+ Sets duration between pages */
+void php3_pdf_set_duration(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int id, type;
+ PDF *pdf;
+ PDF_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(arg1);
+ convert_to_double(arg2);
+ id=arg1->value.lval;
+ pdf = php3_list_find(id,&type);
+ if(!pdf || type!=PDF_GLOBAL(le_pdf)) {
+ php3_error(E_WARNING,"Unable to find file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ PDF_set_duration(pdf, (float) arg2->value.dval);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/pdf/php3_pdf.h b/ext/pdf/php3_pdf.h
new file mode 100644
index 0000000000..2f97e60243
--- /dev/null
+++ b/ext/pdf/php3_pdf.h
@@ -0,0 +1,106 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Uwe Steinmann |
+ +----------------------------------------------------------------------+
+ */
+/* $Id$ */
+
+#ifndef _PHP3_PDF_H
+#define _PHP3_PDF_H
+
+#if HAVE_PDFLIB
+
+#include <pdf.h>
+
+extern int le_fp;
+
+extern php3_module_entry pdf_module_entry;
+#define pdf_module_ptr &pdf_module_entry
+
+extern void php3_info_pdf(void);
+extern int php3_minit_pdf(INIT_FUNC_ARGS);
+extern int php3_mend_pdf(void);
+extern void php3_pdf_get_info(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_info_creator(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_info_title(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_info_subject(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_info_author(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_info_keywords(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_open(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_close(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_begin_page(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_end_page(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_show(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_show_xy(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_font(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_leading(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_text_rendering(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_horiz_scaling(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_text_rise(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_text_matrix(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_text_pos(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_char_spacing(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_word_spacing(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_continue_text(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_stringwidth(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_save(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_restore(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_translate(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_scale(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_rotate(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_setflat(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_setlinejoin(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_setlinecap(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_setmiterlimit(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_setlinewidth(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_setdash(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_moveto(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_curveto(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_lineto(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_circle(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_arc(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_rect(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_closepath(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_closepath_stroke(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_stroke(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_fill(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_fill_stroke(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_closepath_fill_stroke(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_endpath(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_clip(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_setgray_fill(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_setgray_stroke(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_setgray(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_setrgbcolor_fill(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_setrgbcolor_stroke(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_setrgbcolor(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_add_outline(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_transition(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pdf_set_duration(INTERNAL_FUNCTION_PARAMETERS);
+#else
+#define pdf_module_ptr NULL
+#endif
+#endif /* _PHP3_PDF_H */
diff --git a/ext/pdf/setup.stub b/ext/pdf/setup.stub
new file mode 100644
index 0000000000..a6df9c669c
--- /dev/null
+++ b/ext/pdf/setup.stub
@@ -0,0 +1,7 @@
+# $Source$
+# $Id$
+
+define_option with-pdflib 'pdflib 0.6 support? ' yesnodir \
+ 'no /usr/local pdflib install' \
+' Whether to use the pdflib support to write .pdf-files.\n
+ Tested for version 0.6!'
diff --git a/ext/pgsql/Makefile.am b/ext/pgsql/Makefile.am
new file mode 100644
index 0000000000..fa41b29721
--- /dev/null
+++ b/ext/pgsql/Makefile.am
@@ -0,0 +1,6 @@
+# $Id$
+
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_pgsql.a
+libphpext_pgsql_a_SOURCES=pgsql.c
+
diff --git a/ext/pgsql/config.h.stub b/ext/pgsql/config.h.stub
new file mode 100644
index 0000000000..fa21acc568
--- /dev/null
+++ b/ext/pgsql/config.h.stub
@@ -0,0 +1,8 @@
+#ifndef HAVE_PGSQL
+#define HAVE_PGSQL 0
+#endif
+
+#ifndef HAVE_PQCMDTUPLES
+#define HAVE_PQCMDTUPLES 0
+#endif
+
diff --git a/ext/pgsql/config.m4 b/ext/pgsql/config.m4
new file mode 100644
index 0000000000..22aa33ceb6
--- /dev/null
+++ b/ext/pgsql/config.m4
@@ -0,0 +1,38 @@
+dnl $Id$
+
+AC_MSG_CHECKING(for PostgresSQL support)
+AC_ARG_WITH(pgsql,
+[ --with-pgsql[=DIR] Include PostgresSQL support. DIR is the PostgresSQL
+ base install directory, defaults to /usr/local/pgsql.],
+[
+ if test "$withval" != "no"; then
+ if test "$withval" = "yes"; then
+ PGSQL_INCDIR=/usr/local/pgsql/include
+ PGSQL_LIBDIR=/usr/local/pgsql/lib
+ else
+ PGSQL_INCDIR=$withval/include
+ test -d $withval/include/pgsql && PGSQL_INCDIR=$withval/include/pgsql
+ PGSQL_LIBDIR=$withval/lib
+ test -d $withval/lib/pgsql && PGSQL_LIBDIR=$withval/lib/pgsql
+ fi
+ PGSQL_INCLUDE=-I$PGSQL_INCDIR
+ PGSQL_LFLAGS=-L$PGSQL_LIBDIR
+ PGSQL_LIBS=-lpq
+
+ old_CFLAGS=$CFLAGS; old_LDFLAGS=$LDFLAGS; old_LIBS=$LIBS
+ CFLAGS="$CFLAGS $PGSQL_INCLUDE"
+ LDFLAGS="$LDFLAGS $PGSQL_LFLAGS"
+ LIBS="$LIBS $PGSQL_LIBS"
+ AC_DEFINE(HAVE_PGSQL)
+ AC_MSG_RESULT(yes)
+ AC_CHECK_FUNC(PQcmdTuples,AC_DEFINE(HAVE_PQCMDTUPLES))
+ CFLAGS=$old_CFLAGS; LDFLAGS=$old_LDFLAGS; LIBS=$old_LIBS
+ PHP_EXTENSION(pgsql)
+ EXTRA_LIBS="$EXTRA_LIBS $PGSQL_LFLAGS $PGSQL_LIBS"
+ INCLUDES="$INCLUDES $PGSQL_INCLUDE"
+ else
+ AC_MSG_RESULT(no)
+ fi
+],[
+ AC_MSG_RESULT(no)
+])
diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c
new file mode 100644
index 0000000000..fa38715d25
--- /dev/null
+++ b/ext/pgsql/pgsql.c
@@ -0,0 +1,1490 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Zeev Suraski <zeev@zend.com> |
+ | Jouni Ahto <jah@cultnet.fi> (large object interface) |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#include <stdlib.h>
+
+#ifndef MSVC5
+#include "config.h"
+#endif
+#include "php.h"
+#include "php3_pgsql.h"
+#include "ext/standard/php3_standard.h"
+#include "php_globals.h"
+
+#if HAVE_PGSQL
+
+
+
+function_entry pgsql_functions[] = {
+ {"pg_connect", php3_pgsql_connect, NULL},
+ {"pg_pconnect", php3_pgsql_pconnect, NULL},
+ {"pg_close", php3_pgsql_close, NULL},
+ {"pg_cmdtuples", php3_pgsql_cmdtuples, NULL},
+ {"pg_dbname", php3_pgsql_dbname, NULL},
+ {"pg_errormessage", php3_pgsql_error_message, NULL},
+ {"pg_options", php3_pgsql_options, NULL},
+ {"pg_port", php3_pgsql_port, NULL},
+ {"pg_tty", php3_pgsql_tty, NULL},
+ {"pg_host", php3_pgsql_host, NULL},
+ {"pg_exec", php3_pgsql_exec, NULL},
+ {"pg_numrows", php3_pgsql_num_rows, NULL},
+ {"pg_numfields", php3_pgsql_num_fields, NULL},
+ {"pg_fieldname", php3_pgsql_field_name, NULL},
+ {"pg_fieldsize", php3_pgsql_field_size, NULL},
+ {"pg_fieldtype", php3_pgsql_field_type, NULL},
+ {"pg_fieldnum", php3_pgsql_field_number, NULL},
+ {"pg_result", php3_pgsql_result, NULL},
+ {"pg_fetch_row", php3_pgsql_fetch_row, NULL},
+ {"pg_fetch_array", php3_pgsql_fetch_array, NULL},
+ {"pg_fetch_object", php3_pgsql_fetch_object, NULL},
+ {"pg_fieldprtlen", php3_pgsql_data_length, NULL},
+ {"pg_fieldisnull", php3_pgsql_data_isnull, NULL},
+ {"pg_freeresult", php3_pgsql_free_result, NULL},
+ {"pg_getlastoid", php3_pgsql_last_oid, NULL},
+ {"pg_locreate", php3_pgsql_lo_create, NULL},
+ {"pg_lounlink", php3_pgsql_lo_unlink, NULL},
+ {"pg_loopen", php3_pgsql_lo_open, NULL},
+ {"pg_loclose", php3_pgsql_lo_close, NULL},
+ {"pg_loread", php3_pgsql_lo_read, NULL},
+ {"pg_lowrite", php3_pgsql_lo_write, NULL},
+ {"pg_loreadall", php3_pgsql_lo_readall, NULL},
+ {NULL, NULL, NULL}
+};
+
+php3_module_entry pgsql_module_entry = {
+ "PostgreSQL", pgsql_functions, php3_minit_pgsql, NULL, php3_rinit_pgsql, NULL, NULL, STANDARD_MODULE_PROPERTIES
+};
+
+#if COMPILE_DL
+php3_module_entry *get_module() { return &pgsql_module_entry; }
+#endif
+
+THREAD_LS pgsql_module php3_pgsql_module;
+
+static void _close_pgsql_link(PGconn *link)
+{
+ PQfinish(link);
+ php3_pgsql_module.num_links--;
+}
+
+
+static void _close_pgsql_plink(PGconn *link)
+{
+ PQfinish(link);
+ php3_pgsql_module.num_persistent--;
+ php3_pgsql_module.num_links--;
+}
+
+
+static void _free_ptr(pgLofp *lofp)
+{
+ efree(lofp);
+}
+
+
+static void _free_result(pgsql_result_handle *pg_result)
+{
+ PQclear(pg_result->result);
+ efree(pg_result);
+}
+
+
+int php3_minit_pgsql(INIT_FUNC_ARGS)
+{
+ if (cfg_get_long("pgsql.allow_persistent",&php3_pgsql_module.allow_persistent)==FAILURE) {
+ php3_pgsql_module.allow_persistent=1;
+ }
+ if (cfg_get_long("pgsql.max_persistent",&php3_pgsql_module.max_persistent)==FAILURE) {
+ php3_pgsql_module.max_persistent=-1;
+ }
+ if (cfg_get_long("pgsql.max_links",&php3_pgsql_module.max_links)==FAILURE) {
+ php3_pgsql_module.max_links=-1;
+ }
+ php3_pgsql_module.num_persistent=0;
+ php3_pgsql_module.le_link = register_list_destructors(_close_pgsql_link,NULL);
+ php3_pgsql_module.le_plink = register_list_destructors(NULL,_close_pgsql_plink);
+ /* php3_pgsql_module.le_result = register_list_destructors(PQclear,NULL); */
+ php3_pgsql_module.le_result = register_list_destructors(_free_result,NULL);
+ php3_pgsql_module.le_lofp = register_list_destructors(_free_ptr,NULL);
+ php3_pgsql_module.le_string = register_list_destructors(_free_ptr,NULL);
+ return SUCCESS;
+}
+
+
+int php3_rinit_pgsql(INIT_FUNC_ARGS)
+{
+ php3_pgsql_module.default_link=-1;
+ php3_pgsql_module.num_links = php3_pgsql_module.num_persistent;
+ return SUCCESS;
+}
+
+
+void php3_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS,int persistent)
+{
+ char *host=NULL,*port=NULL,*options=NULL,*tty=NULL,*dbname=NULL,*connstring=NULL;
+ char *hashed_details;
+ int hashed_details_length;
+ PGconn *pgsql;
+
+ switch(ARG_COUNT(ht)) {
+ case 1: { /* new style, using connection string */
+ pval *yyconnstring;
+ if (getParameters(ht, 1, &yyconnstring) == FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string(yyconnstring);
+ connstring = yyconnstring->value.str.val;
+ hashed_details_length = yyconnstring->value.str.len+5+1;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details,"pgsql_%s",connstring); /* SAFE */
+ }
+ break;
+ case 3: { /* host, port, dbname */
+ pval *yyhost, *yyport, *yydbname;
+
+ if (getParameters(ht, 3, &yyhost, &yyport, &yydbname) == FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string(yyhost);
+ convert_to_string(yyport);
+ convert_to_string(yydbname);
+ host = yyhost->value.str.val;
+ port = yyport->value.str.val;
+ dbname = yydbname->value.str.val;
+ options=tty=NULL;
+ hashed_details_length = yyhost->value.str.len+yyport->value.str.len+yydbname->value.str.len+5+5;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details,"pgsql_%s_%s___%s",host,port,dbname); /* SAFE */
+ }
+ break;
+ case 4: { /* host, port, options, dbname */
+ pval *yyhost, *yyport, *yyoptions, *yydbname;
+
+ if (getParameters(ht, 4, &yyhost, &yyport, &yyoptions, &yydbname) == FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string(yyhost);
+ convert_to_string(yyport);
+ convert_to_string(yyoptions);
+ convert_to_string(yydbname);
+ host = yyhost->value.str.val;
+ port = yyport->value.str.val;
+ options = yyoptions->value.str.val;
+ dbname = yydbname->value.str.val;
+ tty=NULL;
+ hashed_details_length = yyhost->value.str.len+yyport->value.str.len+yyoptions->value.str.len+yydbname->value.str.len+5+5;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details,"pgsql_%s_%s_%s__%s",host,port,options,dbname); /* SAFE */
+ }
+ break;
+ case 5: { /* host, port, options, tty, dbname */
+ pval *yyhost, *yyport, *yyoptions, *yytty, *yydbname;
+
+ if (getParameters(ht, 5, &yyhost, &yyport, &yyoptions, &yytty, &yydbname) == FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string(yyhost);
+ convert_to_string(yyport);
+ convert_to_string(yyoptions);
+ convert_to_string(yytty);
+ convert_to_string(yydbname);
+ host = yyhost->value.str.val;
+ port = yyport->value.str.val;
+ options = yyoptions->value.str.val;
+ tty = yytty->value.str.val;
+ dbname = yydbname->value.str.val;
+ hashed_details_length = yyhost->value.str.len+yyport->value.str.len+yyoptions->value.str.len+yytty->value.str.len+yydbname->value.str.len+5+5;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details,"pgsql_%s_%s_%s_%s_%s",host,port,options,tty,dbname); /* SAFE */
+ }
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ if (persistent) {
+ list_entry *le;
+
+ /* try to find if we already have this link in our persistent list */
+ if (_php3_hash_find(plist, hashed_details, hashed_details_length+1, (void **) &le)==FAILURE) { /* we don't */
+ list_entry new_le;
+
+ if (php3_pgsql_module.max_links!=-1 && php3_pgsql_module.num_links>=php3_pgsql_module.max_links) {
+ php3_error(E_WARNING,"PostgresSQL: Too many open links (%d)",php3_pgsql_module.num_links);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ if (php3_pgsql_module.max_persistent!=-1 && php3_pgsql_module.num_persistent>=php3_pgsql_module.max_persistent) {
+ php3_error(E_WARNING,"PostgresSQL: Too many open persistent links (%d)",php3_pgsql_module.num_persistent);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ /* create the link */
+ if (connstring) {
+ pgsql=PQconnectdb(connstring);
+ } else {
+ pgsql=PQsetdb(host,port,options,tty,dbname);
+ }
+ if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) {
+ php3_error(E_WARNING,"Unable to connect to PostgresSQL server: %s",PQerrorMessage(pgsql));
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ /* hash it up */
+ new_le.type = php3_pgsql_module.le_plink;
+ new_le.ptr = pgsql;
+ if (_php3_hash_update(plist, hashed_details, hashed_details_length+1, (void *) &new_le, sizeof(list_entry), NULL)==FAILURE) {
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ php3_pgsql_module.num_links++;
+ php3_pgsql_module.num_persistent++;
+ } else { /* we do */
+ if (le->type != php3_pgsql_module.le_plink) {
+ RETURN_FALSE;
+ }
+ /* ensure that the link did not die */
+ if (PQstatus(le->ptr)==CONNECTION_BAD) { /* the link died */
+ if (connstring) {
+ le->ptr=PQconnectdb(connstring);
+ } else {
+ le->ptr=PQsetdb(host,port,options,tty,dbname);
+ }
+ if (le->ptr==NULL || PQstatus(le->ptr)==CONNECTION_BAD) {
+ php3_error(E_WARNING,"PostgresSQL link lost, unable to reconnect");
+ _php3_hash_del(plist,hashed_details,hashed_details_length+1);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ }
+ pgsql = (PGconn *) le->ptr;
+ }
+ return_value->value.lval = php3_list_insert(pgsql,php3_pgsql_module.le_plink);
+ return_value->type = IS_LONG;
+ } else {
+ list_entry *index_ptr,new_index_ptr;
+
+ /* first we check the hash for the hashed_details key. if it exists,
+ * it should point us to the right offset where the actual pgsql link sits.
+ * if it doesn't, open a new pgsql link, add it to the resource list,
+ * and add a pointer to it with hashed_details as the key.
+ */
+ if (_php3_hash_find(list,hashed_details,hashed_details_length+1,(void **) &index_ptr)==SUCCESS) {
+ int type,link;
+ void *ptr;
+
+ if (index_ptr->type != le_index_ptr) {
+ RETURN_FALSE;
+ }
+ link = (int) index_ptr->ptr;
+ ptr = php3_list_find(link,&type); /* check if the link is still there */
+ if (ptr && (type==php3_pgsql_module.le_link || type==php3_pgsql_module.le_plink)) {
+ return_value->value.lval = php3_pgsql_module.default_link = link;
+ return_value->type = IS_LONG;
+ efree(hashed_details);
+ return;
+ } else {
+ _php3_hash_del(list,hashed_details,hashed_details_length+1);
+ }
+ }
+ if (php3_pgsql_module.max_links!=-1 && php3_pgsql_module.num_links>=php3_pgsql_module.max_links) {
+ php3_error(E_WARNING,"PostgresSQL: Too many open links (%d)",php3_pgsql_module.num_links);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ if (connstring) {
+ pgsql=PQconnectdb(connstring);
+ } else {
+ pgsql=PQsetdb(host,port,options,tty,dbname);
+ }
+ if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) {
+ php3_error(E_WARNING,"Unable to connect to PostgresSQL server: %s",PQerrorMessage(pgsql));
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ /* add it to the list */
+ return_value->value.lval = php3_list_insert(pgsql,php3_pgsql_module.le_link);
+ return_value->type = IS_LONG;
+
+ /* add it to the hash */
+ new_index_ptr.ptr = (void *) return_value->value.lval;
+ new_index_ptr.type = le_index_ptr;
+ if (_php3_hash_update(list,hashed_details,hashed_details_length+1,(void *) &new_index_ptr, sizeof(list_entry), NULL)==FAILURE) {
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ php3_pgsql_module.num_links++;
+ }
+ efree(hashed_details);
+ php3_pgsql_module.default_link=return_value->value.lval;
+}
+
+
+int php3_pgsql_get_default_link(INTERNAL_FUNCTION_PARAMETERS)
+{
+ if (php3_pgsql_module.default_link==-1) { /* no link opened yet, implicitly open one */
+ HashTable tmp;
+
+ _php3_hash_init(&tmp,0,NULL,NULL,0);
+ php3_pgsql_do_connect(&tmp,return_value,list,plist,0);
+ _php3_hash_destroy(&tmp);
+ }
+ return php3_pgsql_module.default_link;
+}
+
+/* {{{ proto int pg_connect([string connection_string] | [string host, string port, [string options, [string tty,]] string database)
+ Open a PostgreSQL connection */
+void php3_pgsql_connect(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
+}
+/* }}} */
+
+/* {{{ proto int pg_connect([string connection_string] | [string host, string port, [string options, [string tty,]] string database)
+ Open a persistent PostgreSQL connection */
+void php3_pgsql_pconnect(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
+}
+/* }}} */
+
+/* {{{ proto bool pg_close([int connection])
+ Close a PostgreSQL connection */
+void php3_pgsql_close(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *pgsql_link;
+ int id,type;
+ PGconn *pgsql;
+
+ switch (ARG_COUNT(ht)) {
+ case 0:
+ id = php3_pgsql_module.default_link;
+ break;
+ case 1:
+ if (getParameters(ht, 1, &pgsql_link)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(pgsql_link);
+ id = pgsql_link->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ pgsql = (PGconn *) php3_list_find(id,&type);
+ if (type!=php3_pgsql_module.le_link && type!=php3_pgsql_module.le_plink) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL link index",id);
+ RETURN_FALSE;
+ }
+
+ php3_list_delete(pgsql_link->value.lval);
+ RETURN_TRUE;
+}
+/* }}} */
+
+
+#define PHP3_PG_DBNAME 1
+#define PHP3_PG_ERROR_MESSAGE 2
+#define PHP3_PG_OPTIONS 3
+#define PHP3_PG_PORT 4
+#define PHP3_PG_TTY 5
+#define PHP3_PG_HOST 6
+
+void php3_pgsql_get_link_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
+{
+ pval *pgsql_link;
+ int id,type;
+ PGconn *pgsql;
+
+ switch(ARG_COUNT(ht)) {
+ case 0:
+ id = php3_pgsql_module.default_link;
+ break;
+ case 1:
+ if (getParameters(ht, 1, &pgsql_link)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(pgsql_link);
+ id = pgsql_link->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ pgsql = (PGconn *) php3_list_find(id,&type);
+ if (type!=php3_pgsql_module.le_link && type!=php3_pgsql_module.le_plink) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL link index",id);
+ RETURN_FALSE;
+ }
+
+ switch(entry_type) {
+ case PHP3_PG_DBNAME:
+ return_value->value.str.val = PQdb(pgsql);
+ break;
+ case PHP3_PG_ERROR_MESSAGE:
+ return_value->value.str.val = PQerrorMessage(pgsql);
+ break;
+ case PHP3_PG_OPTIONS:
+ return_value->value.str.val = PQoptions(pgsql);
+ break;
+ case PHP3_PG_PORT:
+ return_value->value.str.val = PQport(pgsql);
+ break;
+ case PHP3_PG_TTY:
+ return_value->value.str.val = PQtty(pgsql);
+ break;
+ case PHP3_PG_HOST:
+ return_value->value.str.val = PQhost(pgsql);
+ break;
+ default:
+ RETURN_FALSE;
+ }
+ return_value->value.str.len = strlen(return_value->value.str.val);
+ return_value->value.str.val = (char *) estrdup(return_value->value.str.val);
+ return_value->type = IS_STRING;
+}
+
+/* {{{ proto string pg_dbname([int connection])
+ Get the database name */
+void php3_pgsql_dbname(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_DBNAME);
+}
+/* }}} */
+
+/* {{{ proto string pg_errormessage([int connection])
+ Get the error message string */
+void php3_pgsql_error_message(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_ERROR_MESSAGE);
+}
+/* }}} */
+
+/* {{{ proto string pg_options([int connection])
+ Get the options associated with the connection */
+void php3_pgsql_options(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_OPTIONS);
+}
+/* }}} */
+
+/* {{{ proto int pg_port([int connection])
+ Return the port number associated with the connection */
+void php3_pgsql_port(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_PORT);
+}
+/* }}} */
+
+/* {{{ proto string pg_tty([int connection])
+ Return the tty name associated with the connection */
+void php3_pgsql_tty(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_TTY);
+}
+/* }}} */
+
+/* {{{ proto string pg_host([int connection])
+ Returns the host name associated with the connection */
+void php3_pgsql_host(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_HOST);
+}
+/* }}} */
+
+/* {{{ proto int pg_exec([int connection,] string query)
+ Execute a query */
+void php3_pgsql_exec(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *query,*pgsql_link;
+ int id,type;
+ PGconn *pgsql;
+ PGresult *pgsql_result;
+ ExecStatusType status;
+ pgsql_result_handle *pg_result;
+
+ switch(ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &query)==FAILURE) {
+ RETURN_FALSE;
+ }
+ id = php3_pgsql_module.default_link;
+ break;
+ case 2:
+ if (getParameters(ht, 2, &pgsql_link, &query)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(pgsql_link);
+ id = pgsql_link->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ pgsql = (PGconn *) php3_list_find(id,&type);
+ if (type!=php3_pgsql_module.le_link && type!=php3_pgsql_module.le_plink) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL link index",id);
+ RETURN_FALSE;
+ }
+
+ convert_to_string(query);
+ pgsql_result=PQexec(pgsql,query->value.str.val);
+
+ if (pgsql_result) {
+ status = PQresultStatus(pgsql_result);
+ } else {
+ status = (ExecStatusType) PQstatus(pgsql);
+ }
+
+
+ switch (status) {
+ case PGRES_EMPTY_QUERY:
+ case PGRES_BAD_RESPONSE:
+ case PGRES_NONFATAL_ERROR:
+ case PGRES_FATAL_ERROR:
+ php3_error(E_WARNING,"PostgresSQL query failed: %s",PQerrorMessage(pgsql));
+ RETURN_FALSE;
+ break;
+ case PGRES_COMMAND_OK: /* successful command that did not return rows */
+ default:
+ if (pgsql_result) {
+ pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
+ pg_result->conn = pgsql;
+ pg_result->result = pgsql_result;
+ return_value->value.lval = php3_list_insert(pg_result,php3_pgsql_module.le_result);
+ return_value->type = IS_LONG;
+ } else {
+ RETURN_FALSE;
+ }
+ break;
+ }
+}
+/* }}} */
+
+#define PHP3_PG_NUM_ROWS 1
+#define PHP3_PG_NUM_FIELDS 2
+#define PHP3_PG_CMD_TUPLES 3
+
+void php3_pgsql_get_result_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
+{
+ pval *result;
+ PGresult *pgsql_result;
+ pgsql_result_handle *pg_result;
+ int type;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &result)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(result);
+ pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type);
+
+ if (type!=php3_pgsql_module.le_result) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval);
+ RETURN_FALSE;
+ }
+
+ pgsql_result = pg_result->result;
+
+ switch (entry_type) {
+ case PHP3_PG_NUM_ROWS:
+ return_value->value.lval = PQntuples(pgsql_result);
+ break;
+ case PHP3_PG_NUM_FIELDS:
+ return_value->value.lval = PQnfields(pgsql_result);
+ break;
+ case PHP3_PG_CMD_TUPLES:
+#if HAVE_PQCMDTUPLES
+ return_value->value.lval = atoi(PQcmdTuples(pgsql_result));
+#else
+ php3_error(E_WARNING,"This compilation does not support pg_cmdtuples()");
+ return_value->value.lval = 0;
+#endif
+ break;
+ default:
+ RETURN_FALSE;
+ }
+ return_value->type = IS_LONG;
+}
+
+/* {{{ proto int pg_numrows(int result)
+ Return the number of rows in the result */
+void php3_pgsql_num_rows(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_NUM_ROWS);
+}
+/* }}} */
+
+/* {{{ proto int pg_numfields(int result)
+ Return the number of fields in the result */
+void php3_pgsql_num_fields(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_NUM_FIELDS);
+}
+/* }}} */
+
+/* {{{ proto int pg_cmdtuples(int result)
+ Returns the number of affected tuples */
+void php3_pgsql_cmdtuples(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_CMD_TUPLES);
+}
+/* }}} */
+
+
+char *get_field_name(PGconn *pgsql, Oid oid, HashTable *list)
+{
+ PGresult *result;
+ char hashed_oid_key[32];
+ list_entry *field_type;
+ char *ret=NULL;
+
+ /* try to lookup the type in the resource list */
+ snprintf(hashed_oid_key,31,"pgsql_oid_%d",(int) oid);
+ hashed_oid_key[31]=0;
+
+ if (_php3_hash_find(list,hashed_oid_key,strlen(hashed_oid_key)+1,(void **) &field_type)==SUCCESS) {
+ ret = estrdup((char *)field_type->ptr);
+ } else { /* hash all oid's */
+ int i,num_rows;
+ int oid_offset,name_offset;
+ char *tmp_oid, *tmp_name;
+ list_entry new_oid_entry;
+
+ if ((result=PQexec(pgsql,"select oid,typname from pg_type"))==NULL) {
+ return empty_string;
+ }
+ num_rows=PQntuples(result);
+ oid_offset = PQfnumber(result,"oid");
+ name_offset = PQfnumber(result,"typname");
+
+ for (i=0; i<num_rows; i++) {
+ if ((tmp_oid=PQgetvalue(result,i,oid_offset))==NULL) {
+ continue;
+ }
+ snprintf(hashed_oid_key,31,"pgsql_oid_%s",tmp_oid);
+ if ((tmp_name=PQgetvalue(result,i,name_offset))==NULL) {
+ continue;
+ }
+ new_oid_entry.type = php3_pgsql_module.le_string;
+ new_oid_entry.ptr = estrdup(tmp_name);
+ _php3_hash_update(list,hashed_oid_key,strlen(hashed_oid_key)+1,(void *) &new_oid_entry, sizeof(list_entry), NULL);
+ if (!ret && atoi(tmp_oid)==oid) {
+ ret = estrdup(tmp_name);
+ }
+ }
+ }
+ return ret;
+}
+
+
+#define PHP3_PG_FIELD_NAME 1
+#define PHP3_PG_FIELD_SIZE 2
+#define PHP3_PG_FIELD_TYPE 3
+
+void php3_pgsql_get_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
+{
+ pval *result,*field;
+ PGresult *pgsql_result;
+ pgsql_result_handle *pg_result;
+ int type;
+
+ if (ARG_COUNT(ht)!=2 || getParameters(ht, 2, &result, &field)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(result);
+ pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type);
+
+ if (type!=php3_pgsql_module.le_result) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval);
+ RETURN_FALSE;
+ }
+
+ pgsql_result = pg_result->result;
+ convert_to_long(field);
+
+ if (field->value.lval<0 || field->value.lval>=PQnfields(pgsql_result)) {
+ php3_error(E_WARNING,"Bad field offset specified");
+ RETURN_FALSE;
+ }
+
+ switch (entry_type) {
+ case PHP3_PG_FIELD_NAME:
+ return_value->value.str.val = PQfname(pgsql_result,field->value.lval);
+ return_value->value.str.len = strlen(return_value->value.str.val);
+ return_value->value.str.val = estrndup(return_value->value.str.val,return_value->value.str.len);
+ return_value->type = IS_STRING;
+ break;
+ case PHP3_PG_FIELD_SIZE:
+ return_value->value.lval = PQfsize(pgsql_result,field->value.lval);
+ return_value->type = IS_LONG;
+ break;
+ case PHP3_PG_FIELD_TYPE:
+ return_value->value.str.val = get_field_name(pg_result->conn,PQftype(pgsql_result,field->value.lval),list);
+ return_value->value.str.len = strlen(return_value->value.str.val);
+ return_value->type = IS_STRING;
+ break;
+ default:
+ RETURN_FALSE;
+ }
+}
+
+/* {{{ proto string pg_fieldname(int result, int field_number)
+ Returns the name of the field */
+void php3_pgsql_field_name(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_FIELD_NAME);
+}
+/* }}} */
+
+/* {{{ proto pg_fieldsize(int result, int field_number)
+ Returns the internal size of the field */
+void php3_pgsql_field_size(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_FIELD_SIZE);
+}
+/* }}} */
+
+/* {{{ proto string pg_fieldtype(int result, int field_number)
+ Returns the type name for the given field */
+void php3_pgsql_field_type(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP3_PG_FIELD_TYPE);
+}
+/* }}} */
+
+/* {{{ proto int pg_fieldnum(int result, string field_name)
+ Returns the field number of the named field */
+void php3_pgsql_field_number(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *result,*field;
+ PGresult *pgsql_result;
+ pgsql_result_handle *pg_result;
+ int type;
+
+ if (ARG_COUNT(ht)!=2 || getParameters(ht, 2, &result, &field)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(result);
+ pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type);
+
+ if (type!=php3_pgsql_module.le_result) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval);
+ RETURN_FALSE;
+ }
+ pgsql_result = pg_result->result;
+
+ convert_to_string(field);
+ return_value->value.lval = PQfnumber(pgsql_result,field->value.str.val);
+ return_value->type = IS_LONG;
+}
+/* }}} */
+
+/* {{{ proto mixed pg_result(int result, int row_number, mixed field_name)
+ Returns values from a result identifier */
+void php3_pgsql_result(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *result, *row, *field=NULL;
+ PGresult *pgsql_result;
+ pgsql_result_handle *pg_result;
+ int type,field_offset;
+
+
+ if (ARG_COUNT(ht)!=3 || getParameters(ht, 3, &result, &row, &field)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(result);
+ pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type);
+
+ if (type!=php3_pgsql_module.le_result) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval);
+ RETURN_FALSE;
+ }
+ pgsql_result = pg_result->result;
+
+ convert_to_long(row);
+ if (row->value.lval<0 || row->value.lval>=PQntuples(pgsql_result)) {
+ php3_error(E_WARNING,"Unable to jump to row %d on PostgresSQL result index %d",row->value.lval,result->value.lval);
+ RETURN_FALSE;
+ }
+ switch(field->type) {
+ case IS_STRING:
+ field_offset = PQfnumber(pgsql_result,field->value.str.val);
+ break;
+ default:
+ convert_to_long(field);
+ field_offset = field->value.lval;
+ break;
+ }
+ if (field_offset<0 || field_offset>=PQnfields(pgsql_result)) {
+ php3_error(E_WARNING,"Bad column offset specified");
+ RETURN_FALSE;
+ }
+
+ return_value->value.str.val = PQgetvalue(pgsql_result,row->value.lval,field_offset);
+ return_value->value.str.len = (return_value->value.str.val ? strlen(return_value->value.str.val) : 0);
+ return_value->value.str.val = safe_estrndup(return_value->value.str.val,return_value->value.str.len);
+ return_value->type = IS_STRING;
+}
+/* }}} */
+
+/* {{{ proto array pg_fetchrow(int result, int row)
+ Get a row as an enumerated array */
+void php3_pgsql_fetch_row(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *result, *row;
+ PGresult *pgsql_result;
+ pgsql_result_handle *pg_result;
+ int type;
+ int i,num_fields;
+ char *element;
+ uint element_len;
+ PLS_FETCH();
+
+
+ if (ARG_COUNT(ht)!=2 || getParameters(ht, 2, &result, &row)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(result);
+ pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type);
+
+ if (type!=php3_pgsql_module.le_result) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval);
+ RETURN_FALSE;
+ }
+ pgsql_result = pg_result->result;
+
+ convert_to_long(row);
+ if (row->value.lval<0 || row->value.lval>=PQntuples(pgsql_result)) {
+ php3_error(E_WARNING,"Unable to jump to row %d on PostgresSQL result index %d",row->value.lval,result->value.lval);
+ RETURN_FALSE;
+ }
+ array_init(return_value);
+ for (i=0,num_fields=PQnfields(pgsql_result); i<num_fields; i++) {
+ element = PQgetvalue(pgsql_result,row->value.lval,i);
+ element_len = (element ? strlen(element) : 0);
+ element = safe_estrndup(element,element_len);
+ if (element) {
+ if (PG(magic_quotes_runtime)) {
+ char *tmp=_php3_addslashes(element,element_len,&element_len,0);
+
+ add_index_stringl(return_value, i, tmp, element_len, 0);
+ } else {
+ add_index_stringl(return_value, i, element, element_len, 1);
+ }
+ } else {
+ /* NULL field, don't set it */
+ /*add_index_stringl(return_value, i, empty_string, 0, 1);*/
+ }
+ }
+}
+/* }}} */
+
+void php3_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *result, *row, *pval_ptr;
+ PGresult *pgsql_result;
+ pgsql_result_handle *pg_result;
+ int type;
+ int i,num_fields;
+ char *element,*field_name;
+ uint element_len;
+ PLS_FETCH();
+
+
+ if (ARG_COUNT(ht)!=2 || getParameters(ht, 2, &result, &row)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(result);
+ pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type);
+
+ if (type!=php3_pgsql_module.le_result) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval);
+ RETURN_FALSE;
+ }
+ pgsql_result = pg_result->result;
+
+ convert_to_long(row);
+ if (row->value.lval<0 || row->value.lval>=PQntuples(pgsql_result)) {
+ php3_error(E_WARNING,"Unable to jump to row %d on PostgresSQL result index %d",row->value.lval,result->value.lval);
+ RETURN_FALSE;
+ }
+ array_init(return_value);
+ for (i=0,num_fields=PQnfields(pgsql_result); i<num_fields; i++) {
+ element = PQgetvalue(pgsql_result,row->value.lval,i);
+ element_len = (element ? strlen(element) : 0);
+ element = safe_estrndup(element,element_len);
+ if (element) {
+ if (PG(magic_quotes_runtime)) {
+ char *tmp=_php3_addslashes(element,element_len,&element_len,0);
+
+ add_get_index_stringl(return_value, i, tmp, element_len, (void **) &pval_ptr, 0);
+ } else {
+ add_get_index_stringl(return_value, i, element, element_len, (void **) &pval_ptr, 1);
+ }
+ field_name = PQfname(pgsql_result,i);
+ _php3_hash_pointer_update(return_value->value.ht, field_name, strlen(field_name)+1, pval_ptr);
+ } else {
+ /* NULL field, don't set it */
+ /* add_get_index_stringl(return_value, i, empty_string, 0, (void **) &pval_ptr); */
+ }
+ }
+}
+
+/* ?? This is a rather odd function - why not just point pg_fetcharray() directly at fetch_hash ? -RL */
+/* {{{ proto array pg_fetch_array(int result, int row)
+ Fetch a row as an array */
+void php3_pgsql_fetch_array(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+/* }}} */
+
+/* {{{ proto object pg_fetch_object(int result, int row)
+ Fetch a row as an object */
+void php3_pgsql_fetch_object(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ if (return_value->type==IS_ARRAY) {
+ return_value->type = IS_OBJECT;
+ }
+}
+/* }}} */
+
+#define PHP3_PG_DATA_LENGTH 1
+#define PHP3_PG_DATA_ISNULL 2
+
+void php3_pgsql_data_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
+{
+ pval *result,*row,*field;
+ PGresult *pgsql_result;
+ pgsql_result_handle *pg_result;
+ int type,field_offset;
+
+ if (ARG_COUNT(ht)!=3 || getParameters(ht, 3, &result, &row, &field)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(result);
+ pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type);
+
+ if (type!=php3_pgsql_module.le_result) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval);
+ RETURN_FALSE;
+ }
+ pgsql_result = pg_result->result;
+
+ convert_to_long(row);
+ if (row->value.lval<0 || row->value.lval>=PQntuples(pgsql_result)) {
+ php3_error(E_WARNING,"Unable to jump to row %d on PostgresSQL result index %d",row->value.lval,result->value.lval);
+ RETURN_FALSE;
+ }
+ switch(field->type) {
+ case IS_STRING:
+ field_offset = PQfnumber(pgsql_result,field->value.str.val);
+ break;
+ default:
+ convert_to_long(field);
+ field_offset = field->value.lval;
+ break;
+ }
+ if (field_offset<0 || field_offset>=PQnfields(pgsql_result)) {
+ php3_error(E_WARNING,"Bad column offset specified");
+ RETURN_FALSE;
+ }
+
+ switch (entry_type) {
+ case PHP3_PG_DATA_LENGTH:
+ return_value->value.lval = PQgetlength(pgsql_result,row->value.lval,field_offset);
+ break;
+ case PHP3_PG_DATA_ISNULL:
+ return_value->value.lval = PQgetisnull(pgsql_result,row->value.lval,field_offset);
+ break;
+ }
+ return_value->type = IS_LONG;
+}
+
+/* {{{ proto int pg_fieldprtlen(int result, int row, mixed field_name_or_number)
+ Returns the printed length */
+void php3_pgsql_data_length(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_data_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP3_PG_DATA_LENGTH);
+}
+/* }}} */
+
+/* {{{ proto int pg_fieldisnull(int result, int row, mixed field_name_or_number)
+ Test if a field is NULL */
+void php3_pgsql_data_isnull(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_pgsql_data_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP3_PG_DATA_ISNULL);
+}
+/* }}} */
+
+/* {{{ proto int pg_freeresult(int result)
+ Free result memory */
+void php3_pgsql_free_result(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *result;
+ pgsql_result_handle *pg_result;
+ int type;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &result)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(result);
+ if (result->value.lval==0) {
+ RETURN_FALSE;
+ }
+ pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type);
+
+ if (type!=php3_pgsql_module.le_result) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval);
+ RETURN_FALSE;
+ }
+ php3_list_delete(result->value.lval);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int pg_getlastoid(int result)
+ Returns the last object identifier */
+void php3_pgsql_last_oid(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *result;
+ PGresult *pgsql_result;
+ pgsql_result_handle *pg_result;
+ int type;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &result)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(result);
+ pg_result = (pgsql_result_handle *) php3_list_find(result->value.lval,&type);
+
+ if (type!=php3_pgsql_module.le_result) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL result index",result->value.lval);
+ RETURN_FALSE;
+ }
+ pgsql_result = pg_result->result;
+ return_value->value.str.val = (char *) PQoidStatus(pgsql_result);
+ if (return_value->value.str.val) {
+ return_value->value.str.len = strlen(return_value->value.str.val);
+ return_value->value.str.val = estrndup(return_value->value.str.val, return_value->value.str.len);
+ return_value->type = IS_STRING;
+ } else {
+ return_value->value.str.val = empty_string;
+ }
+}
+/* }}} */
+
+/* {{{ proto int pg_locreate(int connection)
+ Create a large object */
+void php3_pgsql_lo_create(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *pgsql_link;
+ PGconn *pgsql;
+ Oid pgsql_oid;
+ int id, type;
+
+ switch(ARG_COUNT(ht)) {
+ case 0:
+ id = php3_pgsql_module.default_link;
+ break;
+ case 1:
+ if (getParameters(ht, 1, &pgsql_link)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(pgsql_link);
+ id = pgsql_link->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ pgsql = (PGconn *) php3_list_find(id,&type);
+ if (type!=php3_pgsql_module.le_link && type!=php3_pgsql_module.le_plink) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL link index",id);
+ RETURN_FALSE;
+ }
+
+ /* XXX: Archive modes not supported until I get some more data. Don't think anybody's
+ using it anyway. I believe it's also somehow related to the 'time travel' feature of
+ PostgreSQL, that's on the list of features to be removed... Create modes not supported.
+ What's the use of an object that can be only written to, but not read from, and vice
+ versa? Beats me... And the access type (r/w) must be specified again when opening
+ the object, probably (?) overrides this. (Jouni)
+ */
+
+ if ((pgsql_oid=lo_creat(pgsql, INV_READ|INV_WRITE))==0) {
+ php3_error(E_WARNING,"Unable to create PostgresSQL large object");
+ RETURN_FALSE;
+ }
+
+ return_value->value.lval = pgsql_oid;
+ return_value->type = IS_LONG;
+}
+/* }}} */
+
+/* {{{ proto void pg_lounlink([int connection, ] int large_obj_id)
+ Delete a large object */
+void php3_pgsql_lo_unlink(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *pgsql_link, *oid;
+ PGconn *pgsql;
+ Oid pgsql_oid;
+ int id, type;
+
+ switch(ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &oid)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(oid);
+ pgsql_oid = oid->value.lval;
+ id = php3_pgsql_module.default_link;
+ break;
+ case 2:
+ if (getParameters(ht, 2, &pgsql_link, &oid)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(pgsql_link);
+ id = pgsql_link->value.lval;
+ convert_to_long(oid);
+ pgsql_oid = oid->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ pgsql = (PGconn *) php3_list_find(id,&type);
+ if (type!=php3_pgsql_module.le_link && type!=php3_pgsql_module.le_plink) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL link index",id);
+ RETURN_FALSE;
+ }
+
+ if (lo_unlink(pgsql, pgsql_oid)==-1) {
+ php3_error(E_WARNING,"Unable to delete PostgresSQL large object %d", (int) pgsql_oid);
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int pg_loopen([int connection,] int objoid, string mode)
+ Open a large object and return fd */
+void php3_pgsql_lo_open(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *pgsql_link, *oid, *mode;
+ PGconn *pgsql;
+ Oid pgsql_oid;
+ int id, type, pgsql_mode=0, pgsql_lofd;
+ int create=0;
+ char *mode_string=NULL;
+ pgLofp *pgsql_lofp;
+
+ switch(ARG_COUNT(ht)) {
+ case 2:
+ if (getParameters(ht, 2, &oid, &mode)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(oid);
+ pgsql_oid = oid->value.lval;
+ convert_to_string(mode);
+ mode_string = mode->value.str.val;
+ id = php3_pgsql_module.default_link;
+ break;
+ case 3:
+ if (getParameters(ht, 3, &pgsql_link, &oid, &mode)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(pgsql_link);
+ id = pgsql_link->value.lval;
+ convert_to_long(oid);
+ pgsql_oid = oid->value.lval;
+ convert_to_string(mode);
+ mode_string = mode->value.str.val;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ pgsql = (PGconn *) php3_list_find(id,&type);
+ if (type!=php3_pgsql_module.le_link && type!=php3_pgsql_module.le_plink) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL link index",id);
+ RETURN_FALSE;
+ }
+
+ /* r/w/+ is little bit more PHP-like than INV_READ/INV_WRITE and a lot of
+ faster to type. Unfortunately, doesn't behave the same way as fopen()...
+ (Jouni)
+ */
+
+ if (strchr(mode_string, 'r')==mode_string) {
+ pgsql_mode |= INV_READ;
+ if (strchr(mode_string, '+')==mode_string+1) {
+ pgsql_mode |= INV_WRITE;
+ }
+ }
+ if (strchr(mode_string, 'w')==mode_string) {
+ pgsql_mode |= INV_WRITE;
+ create = 1;
+ if (strchr(mode_string, '+')==mode_string+1) {
+ pgsql_mode |= INV_READ;
+ }
+ }
+
+
+ pgsql_lofp = (pgLofp *) emalloc(sizeof(pgLofp));
+
+ if ((pgsql_lofd=lo_open(pgsql, pgsql_oid, pgsql_mode))==-1) {
+ if (create) {
+ if ((pgsql_oid=lo_creat(pgsql, INV_READ|INV_WRITE))==0) {
+ efree(pgsql_lofp);
+ php3_error(E_WARNING,"Unable to create PostgresSQL large object");
+ RETURN_FALSE;
+ } else {
+ if ((pgsql_lofd=lo_open(pgsql, pgsql_oid, pgsql_mode))==-1) {
+ if (lo_unlink(pgsql, pgsql_oid)==-1) {
+ efree(pgsql_lofp);
+ php3_error(E_WARNING,"Something's really messed up!!! Your database is badly corrupted in a way NOT related to PHP.");
+ RETURN_FALSE;
+ }
+ efree(pgsql_lofp);
+ php3_error(E_WARNING,"Unable to open PostgresSQL large object");
+ RETURN_FALSE;
+ } else {
+ pgsql_lofp->conn = pgsql;
+ pgsql_lofp->lofd = pgsql_lofd;
+ return_value->value.lval = php3_list_insert(pgsql_lofp, php3_pgsql_module.le_lofp);
+ return_value->type = IS_LONG;
+ }
+ }
+ } else {
+ efree(pgsql_lofp);
+ php3_error(E_WARNING,"Unable to open PostgresSQL large object");
+ RETURN_FALSE;
+ }
+ } else {
+ pgsql_lofp->conn = pgsql;
+ pgsql_lofp->lofd = pgsql_lofd;
+ return_value->value.lval = php3_list_insert(pgsql_lofp, php3_pgsql_module.le_lofp);
+ return_value->type = IS_LONG;
+ }
+}
+/* }}} */
+
+/* {{{ proto void pg_loclose(int fd)
+ Close a large object */
+void php3_pgsql_lo_close(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *pgsql_lofp;
+ int id, type;
+ pgLofp *pgsql;
+
+ switch(ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &pgsql_lofp)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(pgsql_lofp);
+ id = pgsql_lofp->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ pgsql = (pgLofp *) php3_list_find(id,&type);
+ if (type!=php3_pgsql_module.le_lofp) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL large object index",id);
+ RETURN_FALSE;
+ }
+
+ if (lo_close((PGconn *)pgsql->conn, pgsql->lofd)<0) {
+ php3_error(E_WARNING,"Unable to close PostgresSQL large object descriptor %d", pgsql->lofd);
+ RETVAL_FALSE;
+ } else {
+ RETVAL_TRUE;
+ }
+ php3_list_delete(id);
+ return;
+}
+/* }}} */
+
+/* {{{ proto string pg_loread(int fd, int len)
+ Read a large object */
+void php3_pgsql_lo_read(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *pgsql_id, *len;
+ int id, buf_len, type, nbytes;
+ char *buf;
+ pgLofp *pgsql;
+
+ switch(ARG_COUNT(ht)) {
+ case 2:
+ if (getParameters(ht, 2, &pgsql_id, &len)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(pgsql_id);
+ id = pgsql_id->value.lval;
+ convert_to_long(len);
+ buf_len = len->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ pgsql = (pgLofp *) php3_list_find(id,&type);
+ if (type!=php3_pgsql_module.le_lofp) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL large object index",id);
+ RETURN_FALSE;
+ }
+
+ buf = (char *) emalloc(sizeof(char)*(buf_len+1));
+ if ((nbytes = lo_read((PGconn *)pgsql->conn, pgsql->lofd, buf, buf_len))<0) {
+ efree(buf);
+ RETURN_FALSE;
+ }
+ return_value->value.str.val = buf;
+ return_value->value.str.len = nbytes;
+ return_value->value.str.val[nbytes] = 0;
+ return_value->type = IS_STRING;
+}
+/* }}} */
+
+/* {{{ proto int pg_lowrite(int fd, string buf)
+ Write a large object */
+void php3_pgsql_lo_write(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *pgsql_id, *str;
+ int id, buf_len, nbytes, type;
+ char *buf;
+ pgLofp *pgsql;
+
+ switch(ARG_COUNT(ht)) {
+ case 2:
+ if (getParameters(ht, 2, &pgsql_id, &str)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(pgsql_id);
+ id = pgsql_id->value.lval;
+ convert_to_string(str);
+ buf = str->value.str.val;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ pgsql = (pgLofp *) php3_list_find(id,&type);
+ if (type!=php3_pgsql_module.le_lofp) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL large object index",id);
+ RETURN_FALSE;
+ }
+
+ buf_len = str->value.str.len;
+ if ((nbytes = lo_write((PGconn *)pgsql->conn, pgsql->lofd, buf, buf_len))==-1) {
+ RETURN_FALSE;
+ }
+ return_value->value.lval = nbytes;
+ return_value->type = IS_LONG;
+}
+/* }}} */
+
+/* {{{ proto void pg_loreadall(int fd)
+ Read a large object and send straight to browser */
+void php3_pgsql_lo_readall(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *pgsql_id;
+ int i, id, tbytes, type;
+ volatile int nbytes;
+ char buf[8192];
+ pgLofp *pgsql;
+ int output=1;
+
+ switch(ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &pgsql_id)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(pgsql_id);
+ id = pgsql_id->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ pgsql = (pgLofp *) php3_list_find(id,&type);
+ if (type!=php3_pgsql_module.le_lofp) {
+ php3_error(E_WARNING,"%d is not a PostgresSQL large object index",id);
+ RETURN_FALSE;
+ }
+
+ tbytes = 0;
+ while ((nbytes = lo_read((PGconn *)pgsql->conn, pgsql->lofd, buf, 8192))>0) {
+ for(i=0; i<nbytes; i++) {
+ if (output) PUTC(buf[i]);
+ }
+ tbytes += i;
+ }
+ return_value->value.lval = tbytes;
+ return_value->type = IS_LONG;
+}
+/* }}} */
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/pgsql/php3_pgsql.h b/ext/pgsql/php3_pgsql.h
new file mode 100644
index 0000000000..097e168d94
--- /dev/null
+++ b/ext/pgsql/php3_pgsql.h
@@ -0,0 +1,120 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Jouni Ahto |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifndef _PHP3_PGSQL_H
+#define _PHP3_PGSQL_H
+
+#if COMPILE_DL
+#undef HAVE_PGSQL
+#define HAVE_PGSQL 1
+#endif
+
+#if HAVE_PGSQL
+
+extern php3_module_entry pgsql_module_entry;
+#define pgsql_module_ptr &pgsql_module_entry
+
+
+#include <libpq-fe.h>
+#include <libpq/libpq-fs.h>
+
+extern int php3_minit_pgsql(INIT_FUNC_ARGS);
+extern int php3_rinit_pgsql(INIT_FUNC_ARGS);
+extern void php3_pgsql_connect(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_pconnect(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_close(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_dbname(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_error_message(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_options(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_port(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_tty(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_host(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_exec(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_num_rows(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_num_fields(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_cmdtuples(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_field_name(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_field_size(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_field_type(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_field_number(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_result(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_fetch_row(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_fetch_array(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_fetch_object(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_data_length(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_data_isnull(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_free_result(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_last_oid(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_lo_create(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_lo_unlink(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_lo_open(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_lo_close(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_lo_read(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_lo_write(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_pgsql_lo_readall(INTERNAL_FUNCTION_PARAMETERS);
+
+void php3_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS,int persistent);
+int php3_pgsql_get_default_link(INTERNAL_FUNCTION_PARAMETERS);
+void php3_pgsql_get_link_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type);
+void php3_pgsql_get_result_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type);
+char *get_field_name(PGconn *pgsql, Oid oid, HashTable *list);
+void php3_pgsql_get_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type);
+void php3_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS);
+void php3_pgsql_data_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type);
+
+
+typedef struct pgLofp {
+ PGconn *conn;
+ int lofd;
+} pgLofp;
+
+typedef struct _php3_pgsql_result_handle {
+ PGconn *conn;
+ PGresult *result;
+} pgsql_result_handle;
+
+typedef struct {
+ long default_link;
+ long num_links,num_persistent;
+ long max_links,max_persistent;
+ long allow_persistent;
+ int le_link,le_plink,le_result,le_lofp,le_string;
+} pgsql_module;
+
+extern pgsql_module php3_pgsql_module;
+
+#else
+
+#define pgsql_module_ptr NULL
+
+#endif
+
+#endif /* _PHP3_PGSQL_H */
diff --git a/ext/pgsql/setup.stub b/ext/pgsql/setup.stub
new file mode 100644
index 0000000000..e4019461bc
--- /dev/null
+++ b/ext/pgsql/setup.stub
@@ -0,0 +1,8 @@
+# $Source$
+# $Id$
+
+define_option with-pgsql 'PostgreSQL support?' yesnodir \
+ 'no /usr/local/pgsql PostgreSQL base install' \
+' Whether to build PHP with PostgreSQL support.\n
+ More info about PostgreSQL can be found at\n
+ http://www.postgreSQL.org/.'
diff --git a/ext/snmp/Makefile.am b/ext/snmp/Makefile.am
new file mode 100644
index 0000000000..ebb5c25b5c
--- /dev/null
+++ b/ext/snmp/Makefile.am
@@ -0,0 +1,6 @@
+# $Id$
+
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_snmp.a
+libphpext_snmp_a_SOURCES=snmp.c
+
diff --git a/ext/snmp/Makefile.in b/ext/snmp/Makefile.in
new file mode 100644
index 0000000000..a010158376
--- /dev/null
+++ b/ext/snmp/Makefile.in
@@ -0,0 +1,270 @@
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# $Id$
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+APACHE_INCLUDE = @APACHE_INCLUDE@
+APACHE_TARGET = @APACHE_TARGET@
+APXS = @APXS@
+APXS_LDFLAGS = @APXS_LDFLAGS@
+BINNAME = @BINNAME@
+CC = @CC@
+CFLAGS = @CFLAGS@
+CFLAGS_SHLIB = @CFLAGS_SHLIB@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+EXTINFO_DEPS = @EXTINFO_DEPS@
+EXTRA_LIBS = @EXTRA_LIBS@
+EXT_LIBS = @EXT_LIBS@
+EXT_SUBDIRS = @EXT_SUBDIRS@
+FHTTPD_LIB = @FHTTPD_LIB@
+FHTTPD_TARGET = @FHTTPD_TARGET@
+HSREGEX = @HSREGEX@
+INSTALL_IT = @INSTALL_IT@
+LDFLAGS_SHLIB = @LDFLAGS_SHLIB@
+LDFLAGS_SHLIB_EXPORT = @LDFLAGS_SHLIB_EXPORT@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+PERL_PATH = @PERL_PATH@
+PHP_BUILD_DATE = @PHP_BUILD_DATE@
+PHP_DEBUG = @PHP_DEBUG@
+PHP_LIBS = @PHP_LIBS@
+PHP_VERSION = @PHP_VERSION@
+PROG_SENDMAIL = @PROG_SENDMAIL@
+RANLIB = @RANLIB@
+RDYNAMIC_LFLAGS = @RDYNAMIC_LFLAGS@
+REGEX_LIB = @REGEX_LIB@
+STRONGHOLD = @STRONGHOLD@
+VERSION = @VERSION@
+WARNING_LEVEL = @WARNING_LEVEL@
+YACC = @YACC@
+
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_snmp.a
+libphpext_snmp_a_SOURCES=snmp.c
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libphpext_snmp_a_LIBADD =
+libphpext_snmp_a_OBJECTS = snmp.o
+AR = ar
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+SOURCES = $(libphpext_snmp_a_SOURCES)
+OBJECTS = $(libphpext_snmp_a_OBJECTS)
+
+all: Makefile $(LIBRARIES)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps ext/snmp/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+ $(COMPILE) -c $<
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libphpext_snmp.a: $(libphpext_snmp_a_OBJECTS) $(libphpext_snmp_a_DEPENDENCIES)
+ -rm -f libphpext_snmp.a
+ $(AR) cru libphpext_snmp.a $(libphpext_snmp_a_OBJECTS) $(libphpext_snmp_a_LIBADD)
+ $(RANLIB) libphpext_snmp.a
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = ext/snmp
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
+ done
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
+install-strip:
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+
+
+mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -rm -f Makefile $(DISTCLEANFILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-tags mostlyclean-generic
+
+clean: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+ mostlyclean
+
+distclean: distclean-noinstLIBRARIES distclean-compile distclean-tags \
+ distclean-generic clean
+ -rm -f config.status
+
+maintainer-clean: maintainer-clean-noinstLIBRARIES \
+ maintainer-clean-compile maintainer-clean-tags \
+ maintainer-clean-generic distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info dvi installcheck \
+install-exec install-data install uninstall all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/ext/snmp/config.h.stub b/ext/snmp/config.h.stub
new file mode 100644
index 0000000000..e400f18f01
--- /dev/null
+++ b/ext/snmp/config.h.stub
@@ -0,0 +1,2 @@
+/* Define if you want the SNMP interface */
+#define HAVE_SNMP 0
diff --git a/ext/snmp/config.m4 b/ext/snmp/config.m4
new file mode 100644
index 0000000000..928dad4187
--- /dev/null
+++ b/ext/snmp/config.m4
@@ -0,0 +1,31 @@
+dnl $Id$
+
+AC_MSG_CHECKING(for SNMP support)
+AC_ARG_WITH(snmp,
+[ --with-snmp[=DIR] Include SNMP support. DIR is the SNMP base
+ install directory, defaults to /usr/local],
+[
+ if test "$withval" != "no"; then
+ if test "$withval" = "yes"; then
+ SNMP_INCDIR=/usr/local/include
+ test -d /usr/local/include/ucd-snmp && SNMP_INCDIR=/usr/local/include/ucd-snmp
+ SNMP_LIBDIR=/usr/local/lib
+ else
+ SNMP_INCDIR=$withval/include
+ test -d $withval/include/ucd-snmp && SNMP_INCDIR=$withval/include/ucd-snmp
+ SNMP_LIBDIR=$withval/lib
+ fi
+ SNMP_INCLUDE=-I$SNMP_INCDIR
+ SNMP_LFLAGS=-L$SNMP_LIBDIR
+ SNMP_LIBS="-lsnmp"
+ AC_DEFINE(HAVE_SNMP)
+ AC_MSG_RESULT(yes)
+ PHP_EXTENSION(snmp)
+ EXTRA_LIBS="$EXTRA_LIBS $SNMP_LFLAGS $SNMP_LIBS"
+ INCLUDES="$INCLUDES $SNMP_INCLUDE"
+ else
+ AC_MSG_RESULT(no)
+ fi
+],[
+ AC_MSG_RESULT(no)
+])
diff --git a/ext/snmp/php3_snmp.h b/ext/snmp/php3_snmp.h
new file mode 100644
index 0000000000..c35962cf8f
--- /dev/null
+++ b/ext/snmp/php3_snmp.h
@@ -0,0 +1,56 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
+ +----------------------------------------------------------------------+
+ */
+/* $Id$ */
+#ifndef _PHP3_SNMP_H
+#define _PHP3_SNMP_H
+
+#if COMPILE_DL
+#undef HAVE_SNMP
+#define HAVE_SNMP 1
+#endif
+#if HAVE_SNMP
+#ifndef DLEXPORT
+#define DLEXPORT
+#endif
+
+extern php3_module_entry snmp_module_entry;
+#define snmp_module_ptr &snmp_module_entry
+
+extern int php3i_snmp_init(INIT_FUNC_ARGS);
+extern PHP_FUNCTION(snmpget);
+extern PHP_FUNCTION(snmpwalk);
+extern PHP_FUNCTION(snmprealwalk);
+extern void php3_info_snmp(void);
+#else
+
+#define snmp_module_ptr NULL
+
+#endif /* HAVE_SNMP */
+
+#endif /* _PHP3_SNMP_H */
diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c
new file mode 100644
index 0000000000..05c35f3b54
--- /dev/null
+++ b/ext/snmp/snmp.c
@@ -0,0 +1,298 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
+ +----------------------------------------------------------------------+
+ */
+/* $Id$ */
+
+#include "php.h"
+#if defined(COMPILE_DL)
+#include "phpdl.h"
+#include "functions/dl.h"
+#endif
+#include "php3_snmp.h"
+#include <sys/types.h>
+#if MSVC5
+#include <winsock.h>
+#include <errno.h>
+#include <process.h>
+#include "win32/time.h"
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/errno.h>
+#include <netdb.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_SNMP
+
+#ifndef __P
+#ifdef __GNUC__
+#define __P(args) args
+#else
+#define __P(args) ()
+#endif
+#endif
+
+#include "asn1.h"
+#include "snmp_api.h"
+#include "snmp_client.h"
+#include "snmp_impl.h"
+#include "snmp.h"
+#include "parse.h"
+#include "mib.h"
+
+/* ucd-snmp 3.3.1 changed the name of a few #defines... They've been changed back to the original ones in 3.5.3! */
+#ifndef SNMP_MSG_GET
+#define SNMP_MSG_GET GET_REQ_MSG
+#define SNMP_MSG_GETNEXT GETNEXT_REQ_MSG
+#endif
+
+void _php3_snmp(INTERNAL_FUNCTION_PARAMETERS, int st);
+
+/* constant - can be shared among threads */
+static oid objid_mib[] = {1, 3, 6, 1, 2, 1};
+
+/* Add missing prototype */
+void sprint_variable(char *, oid *, int, struct variable_list *);
+
+function_entry snmp_functions[] = {
+ PHP_FE(snmpget, NULL)
+ PHP_FE(snmpwalk, NULL)
+ PHP_FE(snmprealwalk, NULL)
+ {NULL,NULL,NULL}
+};
+
+php3_module_entry snmp_module_entry = {
+ "SNMP",snmp_functions,php3i_snmp_init,NULL,NULL,NULL,php3_info_snmp,STANDARD_MODULE_PROPERTIES
+};
+
+#if COMPILE_DL
+DLEXPORT php3_module_entry *get_module() { return &snmp_module_entry; };
+#endif
+
+/* THREAD_LS snmp_module php3_snmp_module; - may need one of these at some point */
+
+int php3i_snmp_init(INIT_FUNC_ARGS) {
+ init_mib();
+ return SUCCESS;
+}
+
+void php3_info_snmp(void) {
+ php3_printf("ucd-snmp");
+}
+
+
+/*
+ * Generic SNMP object fetcher
+ *
+ * st=1 GET
+ * st=2 WALK
+ * st=3 WALK (returns OIDs additionally)
+ */
+void _php3_snmp(INTERNAL_FUNCTION_PARAMETERS, int st) {
+ pval *a1, *a2, *a3, *a4, *a5;
+ struct snmp_session session, *ss;
+ struct snmp_pdu *pdu=NULL, *response;
+ struct variable_list *vars;
+ char *objid;
+ oid name[MAX_NAME_LEN];
+ int name_length;
+ int status, count,rootlen=0,gotroot=0;
+ oid root[MAX_NAME_LEN];
+ char buf[2048];
+ char buf2[2048];
+ int keepwalking=1;
+ long timeout=SNMP_DEFAULT_TIMEOUT;
+ long retries=SNMP_DEFAULT_RETRIES;
+ int myargc = ARG_COUNT(ht);
+
+ if (myargc<3 || myargc>5 || getParameters(ht, myargc, &a1, &a2, &a3, &a4, &a5) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string(a1);
+ convert_to_string(a2);
+ convert_to_string(a3);
+ if(myargc>3) {
+ convert_to_long(a4);
+ timeout=a4->value.lval;
+ }
+ if(myargc>4) {
+ convert_to_long(a5);
+ retries=a5->value.lval;
+ }
+ objid=a3->value.str.val;
+
+ if (st>=2) { /* walk */
+ rootlen = MAX_NAME_LEN;
+ if (strlen(objid)) { /* on a walk, an empty string means top of tree - no error */
+ if (read_objid(objid, root, &rootlen)) {
+ gotroot = 1;
+ } else {
+ php3_error(E_WARNING,"Invalid object identifier: %s\n", objid);
+ }
+ }
+ if (gotroot == 0) {
+ memmove((char *)root, (char *)objid_mib, sizeof(objid_mib));
+ rootlen = sizeof(objid_mib) / sizeof(oid);
+ gotroot = 1;
+ }
+ }
+
+ memset(&session, 0, sizeof(struct snmp_session));
+ session.peername = a1->value.str.val;
+
+ session.version = SNMP_VERSION_1;
+ /*
+ * FIXME: potential memory leak
+ * This is a workaround for an "artifact" (Mike Slifcak)
+ * in (at least) ucd-snmp 3.6.1 which frees
+ * memory it did not allocate
+ */
+ session.community = (u_char *) strdup(a2->value.str.val);
+ session.community_len = a2->value.str.len;
+ session.retries = retries;
+ session.timeout = timeout;
+
+ session.authenticator = NULL;
+ snmp_synch_setup(&session);
+ ss = snmp_open(&session);
+ if (ss == NULL){
+ php3_error(E_WARNING,"Couldn't open snmp\n");
+ RETURN_FALSE;
+ }
+ if (st>=2) {
+ memmove((char *)name, (char *)root, rootlen * sizeof(oid));
+ name_length = rootlen;
+ /* prepare result array */
+ array_init(return_value);
+ }
+
+ while(keepwalking) {
+ keepwalking=0;
+ if (st==1) pdu = snmp_pdu_create(SNMP_MSG_GET);
+ else if (st>=2) pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
+
+ if (st==1) {
+ name_length = MAX_NAME_LEN;
+ if (!read_objid(objid, name, &name_length)) {
+ php3_error(E_WARNING,"Invalid object identifier: %s\n", objid);
+ RETURN_FALSE;
+ }
+ }
+ snmp_add_null_var(pdu, name, name_length);
+
+retry:
+ status = snmp_synch_response(ss, pdu, &response);
+ if (status == STAT_SUCCESS) {
+ if (response->errstat == SNMP_ERR_NOERROR) {
+ for(vars = response->variables; vars; vars = vars->next_variable) {
+ if (st>=2 && (vars->name_length < rootlen || memcmp(root, vars->name, rootlen * sizeof(oid))))
+ continue; /* not part of this subtree */
+
+ sprint_value(buf,vars->name, vars->name_length, vars);
+#if 0
+ Debug("snmp response is: %s\n",buf);
+#endif
+ if (st==1) {
+ RETVAL_STRING(buf,1);
+ } else if (st==2) {
+ /* Add to returned array */
+ add_next_index_string(return_value,buf,1);
+ } else if (st==3) {
+ sprint_objid(buf2, name, name_length);
+ add_assoc_string(return_value,buf2,buf,1);
+ }
+ if (st>=2) {
+ if (vars->type != SNMP_ENDOFMIBVIEW && vars->type != SNMP_NOSUCHOBJECT && vars->type != SNMP_NOSUCHINSTANCE) {
+ memmove((char *)name, (char *)vars->name,vars->name_length * sizeof(oid));
+ name_length = vars->name_length;
+ keepwalking = 1;
+ }
+ }
+ }
+ } else {
+ if (st!=2 || response->errstat != SNMP_ERR_NOSUCHNAME) {
+ php3_error(E_WARNING,"Error in packet.\nReason: %s\n", snmp_errstring(response->errstat));
+ if (response->errstat == SNMP_ERR_NOSUCHNAME) {
+ for(count=1, vars = response->variables; vars && count != response->errindex;
+ vars = vars->next_variable, count++);
+ if (vars) sprint_objid(buf,vars->name, vars->name_length);
+ php3_error(E_WARNING,"This name does not exist: %s\n",buf);
+ }
+ if (st==1) {
+ if ((pdu = snmp_fix_pdu(response, SNMP_MSG_GET)) != NULL) goto retry;
+ } else if (st>=2) {
+ if ((pdu = snmp_fix_pdu(response, SNMP_MSG_GETNEXT)) != NULL) goto retry;
+ }
+ RETURN_FALSE;
+ }
+ }
+ } else if (status == STAT_TIMEOUT) {
+ php3_error(E_WARNING,"No Response from %s\n", a1->value.str.val);
+ RETURN_FALSE;
+ } else { /* status == STAT_ERROR */
+ php3_error(E_WARNING,"An error occurred, Quitting\n");
+ RETURN_FALSE;
+ }
+ if (response) snmp_free_pdu(response);
+ } /* keepwalking */
+ snmp_close(ss);
+}
+
+/* {{{ proto string snmpget(string host, string community, string object_id [, int timeout [, int retries]])
+ Fetch an SNMP object */
+void php3_snmpget(INTERNAL_FUNCTION_PARAMETERS) {
+ _php3_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
+}
+/* }}} */
+
+/* {{{ proto string snmpwalk(string host, string community, string object_id [, int timeout [, int retries]])
+ Return all objects under the specified object id */
+void php3_snmpwalk(INTERNAL_FUNCTION_PARAMETERS) {
+ return _php3_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,2);
+}
+/* }}} */
+
+/* {{{ proto string snmprealwalk(string host, string community, string object_id [, int timeout [, int retries]])
+ Return all objects including their respective object id withing the specified one */
+PHP_FUNCTION(snmprealwalk)
+{
+ return _php3_snmp(INTERNAL_FUNCTION_PARAM_PASSTHRU,3);
+}
+/* }}} */
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/standard/Makefile.am b/ext/standard/Makefile.am
index 7f6ed0f0b5..a78a0b99dc 100644
--- a/ext/standard/Makefile.am
+++ b/ext/standard/Makefile.am
@@ -7,5 +7,7 @@ libphpext_standard_a_SOURCES=\
html.c image.c info.c link.c mail.c math.c md5.c microtime.c \
pack.c pageinfo.c rand.c reg.c soundex.c string.c \
syslog.c type.c uniqid.c url.c iptc.c var.c quot_print.c \
- cyr_convert.c flock_compat.c crypt.c dl.c head.c
+ cyr_convert.c flock_compat.c crypt.c dl.c head.c mime.c post.c
+#number.o: number.c
+# $(CC) $(CFLAGS) -w@WARNING_LEVEL@ -c $< -o $@
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index bf0a5da21a..e2865ac83f 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -52,32 +52,6 @@
#include <strings.h>
#endif
#include "safe_mode.h"
-/*
-#include "functions/basic_functions.h"
-#include "functions/phpmath.h"
-#include "functions/php3_string.h"
-#include "functions/dns.h"
-#include "functions/md5.h"
-#include "functions/html.h"
-#include "functions/post.h"
-#include "functions/exec.h"
-#include "functions/info.h"
-#include "functions/url.h"
-#include "functions/datetime.h"
-#include "functions/fsock.h"
-#include "functions/image.h"
-#include "functions/php3_link.h"
-#include "functions/php3_filestat.h"
-#include "functions/microtime.h"
-#include "functions/pageinfo.h"
-#include "functions/uniqid.h"
-#include "functions/base64.h"
-#include "functions/php3_mail.h"
-#include "functions/php3_var.h"
-#include "functions/php3_iptc.h"
-#include "functions/quot_print.h"
-#include "functions/cyr_convert.h"
-*/
#if WIN32|WINNT
#include "win32/unistd.h"
#endif
diff --git a/ext/standard/config.h.stub b/ext/standard/config.h.stub
index 50703755eb..69ee82467f 100644
--- a/ext/standard/config.h.stub
+++ b/ext/standard/config.h.stub
@@ -1,2 +1,14 @@
/* Define if you have the crypt() function */
#define HAVE_CRYPT 1
+
+/* Define if you have and want to use libcrypt */
+#define HAVE_LIBCRYPT 0
+
+/* crypt capability checks */
+#undef PHP3_STD_DES_CRYPT
+#undef PHP3_EXT_DES_CRYPT
+#undef PHP3_MD5_CRYPT
+#undef PHP3_BLOWFISH_CRYPT
+
+/* Define if you have libdl (used for dynamic linking) */
+#define HAVE_LIBDL 0
diff --git a/ext/standard/config.m4 b/ext/standard/config.m4
index f44a1df39f..c20daccc4a 100644
--- a/ext/standard/config.m4
+++ b/ext/standard/config.m4
@@ -1,3 +1,114 @@
dnl $Id$ -*- sh -*-
+divert(1)
+
+dnl
+dnl Check for crypt() capabilities
+dnl
+AC_DEFUN(AC_CRYPT_CAP,[
+
+ AC_MSG_CHECKING([for standard DES crypt])
+ AC_TRY_RUN([
+main() {
+#if HAVE_CRYPT
+ exit (strcmp((char *)crypt("rasmuslerdorf","rl"),"rl.3StKT.4T8M"));
+#else
+ exit(0);
+#endif
+}],[
+ AC_DEFINE(PHP3_STD_DES_CRYPT,1)
+ AC_MSG_RESULT(yes)
+ ],[
+ AC_DEFINE(PHP3_STD_DES_CRYPT,0)
+ AC_MSG_RESULT(no)
+ ],[
+ AC_DEFINE(PHP3_STD_DES_CRYPT,1)
+ AC_MSG_RESULT(cannot check, guessing yes)
+ ])
+
+ AC_MSG_CHECKING([for extended DES crypt])
+ AC_TRY_RUN([
+main() {
+#if HAVE_CRYPT
+ exit (strcmp((char *)crypt("rasmuslerdorf","_J9..rasm"),"_J9..rasmBYk8r9AiWNc"));
+#else
+ exit(0);
+#endif
+}],[
+ AC_DEFINE(PHP3_EXT_DES_CRYPT,1)
+ AC_MSG_RESULT(yes)
+ ],[
+ AC_DEFINE(PHP3_EXT_DES_CRYPT,0)
+ AC_MSG_RESULT(no)
+ ],[
+ AC_DEFINE(PHP3_EXT_DES_CRYPT,0)
+ AC_MSG_RESULT(cannot check, guessing no)
+ ])
+
+ AC_MSG_CHECKING([for MD5 crypt])
+ AC_TRY_RUN([
+main() {
+#if HAVE_CRYPT
+ char salt[15], answer[40];
+
+ salt[0]='$'; salt[1]='1'; salt[2]='$';
+ salt[3]='r'; salt[4]='a'; salt[5]='s';
+ salt[6]='m'; salt[7]='u'; salt[8]='s';
+ salt[9]='l'; salt[10]='e'; salt[11]='$';
+ salt[12]='\0';
+ strcpy(answer,salt);
+ strcat(answer,"rISCgZzpwk3UhDidwXvin0");
+ exit (strcmp((char *)crypt("rasmuslerdorf",salt),answer));
+#else
+ exit(0);
+#endif
+}],[
+ AC_DEFINE(PHP3_MD5_CRYPT,1)
+ AC_MSG_RESULT(yes)
+ ],[
+ AC_DEFINE(PHP3_MD5_CRYPT,0)
+ AC_MSG_RESULT(no)
+ ],[
+ AC_DEFINE(PHP3_MD5_CRYPT,0)
+ AC_MSG_RESULT(cannot check, guessing no)
+ ])
+
+ AC_MSG_CHECKING([for Blowfish crypt])
+ AC_TRY_RUN([
+main() {
+#if HAVE_CRYPT
+ char salt[25], answer[70];
+
+ salt[0]='$'; salt[1]='2'; salt[2]='a'; salt[3]='$'; salt[4]='0'; salt[5]='7'; salt[6]='$'; salt[7]='\0';
+ strcat(salt,"rasmuslerd");
+ strcpy(answer,salt);
+ strcpy(&answer[16],"O............gl95GkTKn53Of.H4YchXl5PwvvW.5ri");
+ exit (strcmp((char *)crypt("rasmuslerdorf",salt),answer));
+#else
+ exit(0);
+#endif
+}],[
+ AC_DEFINE(PHP3_BLOWFISH_CRYPT,1)
+ AC_MSG_RESULT(yes)
+ ],[
+ AC_DEFINE(PHP3_BLOWFISH_CRYPT,0)
+ AC_MSG_RESULT(no)
+ ],[
+ AC_DEFINE(PHP3_BLOWFISH_CRYPT,0)
+ AC_MSG_RESULT(cannot check, guessing no)
+ ])
+])
+
+AC_CHECK_LIB(c, dlopen, [
+ # fake it
+ AC_DEFINE(HAVE_LIBDL) ], [
+ AC_CHECK_LIB(dl, dlopen, [
+ LIBS="-ldl $LIBS"
+ AC_DEFINE(HAVE_LIBDL) ], []) ])
+
+AC_CRYPT_CAP
+
+divert(3)
+
PHP_EXTENSION(standard)
+
diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c
index b664f03afb..6e210281cf 100644
--- a/ext/standard/fsock.c
+++ b/ext/standard/fsock.c
@@ -60,7 +60,7 @@
#include "base64.h"
#include "file.h"
-#include "functions/post.h"
+#include "post.h"
#include "url.h"
#include "fsock.h"
diff --git a/ext/standard/mime.c b/ext/standard/mime.c
new file mode 100644
index 0000000000..fdc794a87c
--- /dev/null
+++ b/ext/standard/mime.c
@@ -0,0 +1,249 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
+ +----------------------------------------------------------------------+
+ */
+/* $Id$ */
+#ifdef THREAD_SAFE
+#include "tls.h"
+#endif
+#include <stdio.h>
+#include "php.h"
+#include "ext/standard/php3_standard.h"
+#include "post.h"
+#include "mime.h"
+#include "zend_globals.h"
+#include "php_globals.h"
+
+#ifndef THREAD_SAFE
+int le_uploads;
+extern HashTable list;
+#endif
+
+#define NEW_BOUNDARY_CHECK 1
+#define SAFE_RETURN { if (namebuf) efree(namebuf); if (filenamebuf) efree(filenamebuf); if (lbuf) efree(lbuf); return; }
+
+/*
+ * Split raw mime stream up into appropriate components
+ */
+void php3_mime_split(char *buf, int cnt, char *boundary, pval *http_post_vars PLS_DC)
+{
+ char *ptr, *loc, *loc2, *s, *name, *filename, *u, *fn;
+ int len, state = 0, Done = 0, rem, urem;
+ long bytes, max_file_size = 0;
+ char *namebuf=NULL, *filenamebuf=NULL, *lbuf=NULL;
+ FILE *fp;
+ int itype;
+ ELS_FETCH();
+
+ ptr = buf;
+ rem = cnt;
+ len = strlen(boundary);
+ while ((ptr - buf < cnt) && !Done) {
+ switch (state) {
+ case 0: /* Looking for mime boundary */
+ loc = memchr(ptr, *boundary, cnt);
+ if (loc) {
+ if (!strncmp(loc, boundary, len)) {
+
+ state = 1;
+ rem -= (loc - ptr) + len + 2;
+ ptr = loc + len + 2;
+ } else {
+ rem -= (loc - ptr) + 1;
+ ptr = loc + 1;
+ }
+ } else {
+ Done = 1;
+ }
+ break;
+ case 1: /* Check content-disposition */
+ if (strncasecmp(ptr, "Content-Disposition: form-data;", 31)) {
+ if (rem < 31) {
+ SAFE_RETURN;
+ }
+ php3_error(E_WARNING, "File Upload Mime headers garbled [%c%c%c%c%c]", *ptr, *(ptr + 1), *(ptr + 2), *(ptr + 3), *(ptr + 4));
+ SAFE_RETURN;
+ }
+ loc = memchr(ptr, '\n', rem);
+ name = strstr(ptr, " name=\"");
+ if (name && name < loc) {
+ name += 7;
+ s = memchr(name, '\"', loc - name);
+ if (!s) {
+ php3_error(E_WARNING, "File Upload Mime headers garbled [%c%c%c%c%c]", *name, *(name + 1), *(name + 2), *(name + 3), *(name + 4));
+ SAFE_RETURN;
+ }
+ if (namebuf) {
+ efree(namebuf);
+ }
+ namebuf = estrndup(name, s-name);
+ if (lbuf) {
+ efree(lbuf);
+ }
+ lbuf = emalloc(s-name + MAX(MAX(sizeof("_name"),sizeof("_size")),sizeof("_type")));
+ state = 2;
+ loc2 = memchr(loc + 1, '\n', rem);
+ rem -= (loc2 - ptr) + 1;
+ ptr = loc2 + 1;
+ } else {
+ php3_error(E_WARNING, "File upload error - no name component in content disposition");
+ SAFE_RETURN;
+ }
+ filename = strstr(s, " filename=\"");
+ if (filename && filename < loc) {
+ filename += 11;
+ s = memchr(filename, '\"', loc - filename);
+ if (!s) {
+ php3_error(E_WARNING, "File Upload Mime headers garbled [%c%c%c%c%c]", *filename, *(filename + 1), *(filename + 2), *(filename + 3), *(filename + 4));
+ SAFE_RETURN;
+ }
+ if (filenamebuf) {
+ efree(filenamebuf);
+ }
+ filenamebuf = estrndup(filename, s-filename);
+ sprintf(lbuf, "%s_name", namebuf);
+ s = strrchr(filenamebuf, '\\');
+ if (s && s > filenamebuf) {
+ SET_VAR_STRING(lbuf, estrdup(s + 1));
+ } else {
+ SET_VAR_STRING(lbuf, estrdup(filenamebuf));
+ }
+ state = 3;
+ if ((loc2 - loc) > 2) {
+ if (!strncasecmp(loc + 1, "Content-Type:", 13)) {
+ *(loc2 - 1) = '\0';
+ sprintf(lbuf, "%s_type", namebuf);
+ SET_VAR_STRING(lbuf, estrdup(loc + 15));
+ *(loc2 - 1) = '\n';
+ }
+ rem -= 2;
+ ptr += 2;
+ }
+ }
+ break;
+
+ case 2: /* handle form-data fields */
+ loc = memchr(ptr, *boundary, rem);
+ u = ptr;
+ while (loc) {
+ if (!strncmp(loc, boundary, len))
+ break;
+ u = loc + 1;
+ urem = rem - (loc - ptr) - 1;
+ loc = memchr(u, *boundary, urem);
+ }
+ if (!loc) {
+ php3_error(E_WARNING, "File Upload Field Data garbled");
+ SAFE_RETURN;
+ }
+ *(loc - 4) = '\0';
+
+ /* Magic function that figures everything out */
+ _php3_parse_gpc_data(ptr,namebuf,http_post_vars);
+
+ /* And a little kludge to pick out special MAX_FILE_SIZE */
+ itype = php3_check_ident_type(namebuf);
+ if (itype) {
+ u = strchr(namebuf, '[');
+ if (u)
+ *u = '\0';
+ }
+ if (!strcmp(namebuf, "MAX_FILE_SIZE")) {
+ max_file_size = atol(ptr);
+ }
+ if (itype) {
+ if (u)
+ *u = '[';
+ }
+ rem -= (loc - ptr);
+ ptr = loc;
+ state = 0;
+ break;
+
+ case 3: /* Handle file */
+ loc = memchr(ptr, *boundary, rem);
+ u = ptr;
+ while (loc) {
+ if (!strncmp(loc, boundary, len)
+#if NEW_BOUNDARY_CHECK
+ && (loc-2>buf && *(loc-2)=='-' && *(loc-1)=='-') /* ensure boundary is prefixed with -- */
+ && (loc-2==buf || *(loc-3)=='\n') /* ensure beginning of line */
+#endif
+ ) {
+ break;
+ }
+ u = loc + 1;
+ urem = rem - (loc - ptr) - 1;
+ loc = memchr(u, *boundary, urem);
+ }
+ if (!loc) {
+ php3_error(E_WARNING, "File Upload Error - No Mime boundary found after start of file header");
+ SAFE_RETURN;
+ }
+ fn = tempnam(PG(upload_tmp_dir), "php");
+ if ((loc - ptr - 4) > PG(upload_max_filesize)) {
+ php3_error(E_WARNING, "Max file size of %ld bytes exceeded - file [%s] not saved", PG(upload_max_filesize),namebuf);
+ bytes=0;
+ SET_VAR_STRING(namebuf, estrdup("none"));
+ } else if (max_file_size && ((loc - ptr - 4) > max_file_size)) {
+ php3_error(E_WARNING, "Max file size exceeded - file [%s] not saved", namebuf);
+ bytes = 0;
+ SET_VAR_STRING(namebuf, estrdup("none"));
+ } else if ((loc - ptr - 4) <= 0) {
+ bytes = 0;
+ SET_VAR_STRING(namebuf, estrdup("none"));
+ } else {
+ fp = fopen(fn, "w");
+ if (!fp) {
+ php3_error(E_WARNING, "File Upload Error - Unable to open temporary file [%s]", fn);
+ SAFE_RETURN;
+ }
+ bytes = fwrite(ptr, 1, loc - ptr - 4, fp);
+ fclose(fp);
+ php3_list_insert(fn,GLOBAL(le_uploads)); /* Tell PHP about the file so the destructor can unlink it later */
+ if (bytes < (loc - ptr - 4)) {
+ php3_error(E_WARNING, "Only %d bytes were written, expected to write %ld", bytes, loc - ptr - 4);
+ }
+ SET_VAR_STRING(namebuf, estrdup(fn));
+ }
+ sprintf(lbuf, "%s_size", namebuf);
+ SET_VAR_LONG(lbuf, bytes);
+ state = 0;
+ rem -= (loc - ptr);
+ ptr = loc;
+ break;
+ }
+ }
+ SAFE_RETURN;
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/standard/mime.h b/ext/standard/mime.h
new file mode 100644
index 0000000000..df5d78799f
--- /dev/null
+++ b/ext/standard/mime.h
@@ -0,0 +1,8 @@
+#ifndef _MIME_H
+#define _MIME_H
+
+#include "php_globals.h"
+
+extern void php3_mime_split(char *buf, int cnt, char *boundary, pval *http_post_vars PLS_DC);
+
+#endif
diff --git a/ext/standard/php3_standard.h b/ext/standard/php3_standard.h
index 77ccafb40f..a3920e30e7 100644
--- a/ext/standard/php3_standard.h
+++ b/ext/standard/php3_standard.h
@@ -62,6 +62,9 @@
#include "type.h"
#include "dl.h"
#include "php3_crypt.h"
+#include "head.h"
+#include "post.h"
+#include "mime.h"
#define standard_module_ptr basic_functions_module_ptr
diff --git a/ext/standard/post.c b/ext/standard/post.c
new file mode 100644
index 0000000000..224450990d
--- /dev/null
+++ b/ext/standard/post.c
@@ -0,0 +1,498 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
+ +----------------------------------------------------------------------+
+ */
+/* $Id: */
+#ifdef THREAD_SAFE
+#include "tls.h"
+#endif
+#include <stdio.h>
+#include "php.h"
+#include "php3_standard.h"
+#include "php_globals.h"
+
+#include "zend_globals.h"
+
+/*
+ * php3_getpost()
+ *
+ * This reads the post form data into a string.
+ * Remember to free this pointer when done with it.
+ */
+static char *php3_getpost(pval *http_post_vars PLS_DC)
+{
+ char *buf = NULL;
+ const char *ctype;
+#if MODULE_MAGIC_NUMBER > 19961007
+ char argsbuffer[HUGE_STRING_LEN];
+#else
+ int bytes;
+#endif
+ int length, cnt;
+ int file_upload = 0;
+ char *mb;
+ char boundary[100];
+ TLS_VARS;
+
+ ctype = GLOBAL(request_info).content_type;
+ if (!ctype) {
+ php3_error(E_WARNING, "POST Error: content-type missing");
+ return NULL;
+ }
+ if (strncasecmp(ctype, "application/x-www-form-urlencoded", 33) && strncasecmp(ctype, "multipart/form-data", 19)
+#if HAVE_FDFLIB
+ && strncasecmp(ctype, "application/vnd.fdf", 19)
+#endif
+ ) {
+ php3_error(E_WARNING, "Unsupported content-type: %s", ctype);
+ return NULL;
+ }
+ if (!strncasecmp(ctype, "multipart/form-data", 19)) {
+ file_upload = 1;
+ mb = strchr(ctype, '=');
+ if (mb) {
+ strncpy(boundary, mb + 1, sizeof(boundary));
+ } else {
+ php3_error(E_WARNING, "File Upload Error: No MIME boundary found");
+ php3_error(E_WARNING, "There should have been a \"boundary=something\" in the Content-Type string");
+ php3_error(E_WARNING, "The Content-Type string was: \"%s\"", ctype);
+ return NULL;
+ }
+ }
+ length = GLOBAL(request_info).content_length;
+ cnt = length;
+ buf = (char *) emalloc((length + 1) * sizeof(char));
+ if (!buf) {
+ php3_error(E_WARNING, "Unable to allocate memory in php3_getpost()");
+ return NULL;
+ }
+#if FHTTPD
+ memcpy(buf,req->databuffer,length);
+ buf[length]=0;
+#else
+#if MODULE_MAGIC_NUMBER > 19961007
+ if (should_client_block(GLOBAL(php3_rqst))) {
+ void (*handler) (int);
+ int dbsize, len_read, dbpos = 0;
+
+ hard_timeout("copy script args", GLOBAL(php3_rqst)); /* start timeout timer */
+ handler = signal(SIGPIPE, SIG_IGN); /* Ignore sigpipes for now */
+ while ((len_read = get_client_block(GLOBAL(php3_rqst), argsbuffer, HUGE_STRING_LEN)) > 0) {
+ if ((dbpos + len_read) > length)
+ dbsize = length - dbpos;
+ else
+ dbsize = len_read;
+ reset_timeout(GLOBAL(php3_rqst)); /* Make sure we don't timeout */
+ memcpy(buf + dbpos, argsbuffer, dbsize);
+ dbpos += dbsize;
+ }
+ signal(SIGPIPE, handler); /* restore normal sigpipe handling */
+ kill_timeout(GLOBAL(php3_rqst)); /* stop timeout timer */
+ }
+#else
+ cnt = 0;
+ do {
+#if APACHE
+ bytes = read_client_block(php3_rqst, buf + cnt, length - cnt);
+#endif
+#if CGI_BINARY
+ bytes = fread(buf + cnt, 1, length - cnt, stdin);
+#endif
+#if USE_SAPI
+ bytes = GLOBAL(sapi_rqst)->readclient(GLOBAL(sapi_rqst)->scid,buf + cnt, 1, length - cnt);
+#endif
+ cnt += bytes;
+ } while (bytes && cnt < length);
+#endif
+#endif
+ if (file_upload) {
+ php3_mime_split(buf, cnt, boundary, http_post_vars PLS_CC);
+ efree(buf);
+ return NULL;
+ }
+ buf[cnt] = '\0';
+
+#if HAVE_FDFLIB
+ if (!strncasecmp(ctype, "application/vnd.fdf", 19)) {
+ pval *postdata_ptr = (pval *) emalloc(sizeof(pval));
+
+ postdata_ptr->type = IS_STRING;
+ postdata_ptr->value.str.val = (char *) estrdup(buf);
+ postdata_ptr->value.str.len = cnt;
+ postdata_ptr->refcount=1;
+ postdata_ptr->is_ref=0;
+ _php3_hash_add(&GLOBAL(symbol_table), "HTTP_FDF_DATA", sizeof("HTTP_FDF_DATA"), postdata_ptr, sizeof(pval *),NULL);
+ }
+#endif
+ return (buf);
+}
+
+
+/*
+ * parse Get/Post/Cookie string and create appropriate variable
+ *
+ * This is a tad ugly because it was yanked out of the middle of
+ * the old TreatData function. This is a temporary measure filling
+ * the gap until a more flexible parser can be built to do this.
+ */
+void _php3_parse_gpc_data(char *val, char *var, pval *track_vars_array)
+{
+ int var_type;
+ char *ind, *tmp = NULL, *ret = NULL;
+ int var_len;
+ pval *entry;
+ ELS_FETCH();
+ PLS_FETCH();
+
+ var_type = php3_check_ident_type(var);
+ if (var_type == GPC_INDEXED_ARRAY) {
+ ind = php3_get_ident_index(var);
+ if (PG(magic_quotes_gpc)) {
+ ret = _php3_addslashes(ind, 0, NULL, 1);
+ } else {
+ ret = ind;
+ }
+ }
+ if (var_type & GPC_ARRAY) { /* array (indexed or not */
+ tmp = strchr(var, '[');
+ if (tmp) {
+ *tmp = '\0';
+ }
+ }
+ /* ignore leading spaces in the variable name */
+ while (*var && *var==' ') {
+ var++;
+ }
+ var_len = strlen(var);
+ if (var_len==0) { /* empty variable name, or variable name with a space in it */
+ return;
+ }
+
+ /* ensure that we don't have spaces or dots in the variable name (not binary safe) */
+ for (tmp=var; *tmp; tmp++) {
+ switch(*tmp) {
+ case ' ':
+ case '.':
+ *tmp='_';
+ break;
+ }
+ }
+
+ tmp = estrdup(val);
+ if (var_type & GPC_ARRAY) {
+ pval *arr1, *arr2;
+ pval **arr_ptr;
+
+ /* If the array doesn't exist, create it */
+ if (_php3_hash_find(EG(active_symbol_table), var, var_len+1, (void **) &arr_ptr) == FAILURE) {
+ arr1 = (pval *) emalloc(sizeof(pval));
+ arr1->refcount=1;
+ arr1->is_ref=0;
+ if (array_init(arr1)==FAILURE) {
+ return;
+ }
+ _php3_hash_update(EG(active_symbol_table), var, var_len+1, &arr1, sizeof(pval *), NULL);
+ if (track_vars_array) {
+ arr2 = (pval *) emalloc(sizeof(pval));
+ arr2->refcount=1;
+ arr2->is_ref=0;
+ if (array_init(arr2)==FAILURE) {
+ return;
+ }
+ _php3_hash_update(track_vars_array->value.ht, var, var_len+1, (void *) &arr2, sizeof(pval *),NULL);
+ }
+ } else {
+ if ((*arr_ptr)->type!=IS_ARRAY) {
+ if (--(*arr_ptr) > 0) {
+ *arr_ptr = (pval *) emalloc(sizeof(pval));
+ (*arr_ptr)->refcount=1;
+ (*arr_ptr)->is_ref=0;
+ } else {
+ pval_destructor(*arr_ptr);
+ }
+ if (array_init(*arr_ptr)==FAILURE) {
+ return;
+ }
+ if (track_vars_array) {
+ arr2 = (pval *) emalloc(sizeof(pval));
+ arr2->refcount=1;
+ arr2->is_ref=0;
+ if (array_init(arr2)==FAILURE) {
+ return;
+ }
+ _php3_hash_update(track_vars_array->value.ht, var, var_len+1, (void *) &arr2, sizeof(pval *),NULL);
+ }
+ }
+ arr1 = *arr_ptr;
+ if (track_vars_array && _php3_hash_find(track_vars_array->value.ht, var, var_len+1, (void **) &arr_ptr) == FAILURE) {
+ return;
+ }
+ arr2 = *arr_ptr;
+ }
+ /* Now create the element */
+ entry = (pval *) emalloc(sizeof(pval));
+ entry->refcount=1;
+ entry->is_ref=0;
+ if (PG(magic_quotes_gpc)) {
+ entry->value.str.val = _php3_addslashes(tmp, 0, &entry->value.str.len, 0);
+ } else {
+ entry->value.str.len = strlen(tmp);
+ entry->value.str.val = estrndup(tmp,entry->value.str.len);
+ }
+ entry->type = IS_STRING;
+
+ /* And then insert it */
+ if (ret) { /* indexed array */
+ if (php3_check_type(ret) == IS_LONG) {
+ _php3_hash_index_update(arr1->value.ht, atol(ret), &entry, sizeof(pval *),NULL); /* s[ret]=tmp */
+ if (track_vars_array) {
+ _php3_hash_index_update(arr2->value.ht, atol(ret), &entry, sizeof(pval *),NULL);
+ entry->refcount++;
+ }
+ } else {
+ _php3_hash_update(arr1->value.ht, ret, strlen(ret)+1, &entry, sizeof(pval *),NULL); /* s["ret"]=tmp */
+ if (track_vars_array) {
+ _php3_hash_update(arr2->value.ht, ret, strlen(ret)+1, &entry, sizeof(pval *),NULL);
+ entry->refcount++;
+ }
+ }
+ efree(ret);
+ ret = NULL;
+ } else { /* non-indexed array */
+ _php3_hash_next_index_insert(arr1->value.ht, &entry, sizeof(pval *),NULL);
+ if (track_vars_array) {
+ _php3_hash_next_index_insert(arr2->value.ht, &entry, sizeof(pval *),NULL);
+ entry->refcount++;
+ }
+ }
+ } else { /* we have a normal variable */
+ pval *entry = (pval *) emalloc(sizeof(pval));
+
+ if (PG(magic_quotes_gpc)) {
+ entry->value.str.val = _php3_addslashes(tmp, 0, &entry->value.str.len, 0);
+ } else {
+ entry->value.str.len = strlen(tmp);
+ entry->value.str.val = estrndup(tmp,entry->value.str.len);
+ }
+ entry->type = IS_STRING;
+ entry->refcount=1;
+ entry->is_ref=0;
+ _php3_hash_update(EG(active_symbol_table), var, var_len+1, (void *) &entry, sizeof(pval *),NULL);
+ if (track_vars_array) {
+ pval_copy_constructor(entry);
+ _php3_hash_update(track_vars_array->value.ht, var, var_len+1, (void *) &entry, sizeof(pval *),NULL);
+ }
+ }
+
+ if (tmp) efree(tmp);
+}
+
+
+void php3_treat_data(int arg, char *str)
+{
+ char *res = NULL, *var, *val;
+ pval *array_ptr;
+ ELS_FETCH();
+ PLS_FETCH();
+
+ switch (arg) {
+ case PARSE_POST:
+ case PARSE_GET:
+ case PARSE_COOKIE:
+ if (PG(track_vars)) {
+ array_ptr = (pval *) emalloc(sizeof(pval));
+ array_init(array_ptr);
+ array_ptr->refcount=1;
+ array_ptr->is_ref=0;
+ switch (arg) {
+ case PARSE_POST:
+ _php3_hash_add(&EG(symbol_table), "HTTP_POST_VARS", sizeof("HTTP_POST_VARS"), &array_ptr, sizeof(pval *),NULL);
+ break;
+ case PARSE_GET:
+ _php3_hash_add(&EG(symbol_table), "HTTP_GET_VARS", sizeof("HTTP_GET_VARS"), &array_ptr, sizeof(pval *),NULL);
+ break;
+ case PARSE_COOKIE:
+ _php3_hash_add(&EG(symbol_table), "HTTP_COOKIE_VARS", sizeof("HTTP_COOKIE_VARS"), &array_ptr, sizeof(pval *),NULL);
+ break;
+ }
+ } else {
+ array_ptr=NULL;
+ }
+ break;
+ default:
+ array_ptr=NULL;
+ break;
+ }
+
+ if (arg == PARSE_POST) {
+ res = php3_getpost(array_ptr PLS_CC);
+ } else if (arg == PARSE_GET) { /* Get data */
+ var = GLOBAL(request_info).query_string;
+ if (var && *var) {
+ res = (char *) estrdup(var);
+ }
+ } else if (arg == PARSE_COOKIE) { /* Cookie data */
+ var = (char *)GLOBAL(request_info).cookies;
+ if (var && *var) {
+ res = (char *) estrdup(var);
+ }
+ } else if (arg == PARSE_STRING) { /* String data */
+ res = str;
+ }
+ if (!res) {
+ return;
+ }
+
+ if (arg == PARSE_COOKIE) {
+ var = strtok(res, ";");
+ } else if (arg == PARSE_POST) {
+ var = strtok(res, "&");
+ } else {
+ var = strtok(res, PG(arg_separator));
+ }
+
+ while (var) {
+ val = strchr(var, '=');
+ if (val) { /* have a value */
+ *val++ = '\0';
+ /* FIXME: XXX: not binary safe, discards returned length */
+ _php3_urldecode(var, strlen(var));
+ _php3_urldecode(val, strlen(val));
+ _php3_parse_gpc_data(val,var,array_ptr);
+ }
+ if (arg == PARSE_COOKIE) {
+ var = strtok(NULL, ";");
+ } else if (arg == PARSE_POST) {
+ var = strtok(NULL, "&");
+ } else {
+ var = strtok(NULL, PG(arg_separator));
+ }
+ }
+ efree(res);
+}
+
+
+void php3_TreatHeaders(void)
+{
+#if APACHE
+#if MODULE_MAGIC_NUMBER > 19961007
+ const char *s = NULL;
+#else
+ char *s = NULL;
+#endif
+ char *t;
+ char *user, *type;
+ int len;
+ char *escaped_str;
+ PLS_FETCH();
+
+ if (GLOBAL(php3_rqst)->headers_in)
+ s = table_get(GLOBAL(php3_rqst)->headers_in, "Authorization");
+ if (!s)
+ return;
+
+ /* Check to make sure that this URL isn't authenticated
+ using a traditional auth module mechanism */
+ if (auth_type(GLOBAL(php3_rqst))) {
+ /*php3_error(E_WARNING, "Authentication done by server module\n");*/
+ return;
+ }
+ if (strcmp(t=getword(GLOBAL(php3_rqst)->pool, &s, ' '), "Basic")) {
+ /* Client tried to authenticate using wrong auth scheme */
+ php3_error(E_WARNING, "client used wrong authentication scheme (%s)", t);
+ return;
+ }
+ t = uudecode(GLOBAL(php3_rqst)->pool, s);
+#if MODULE_MAGIC_NUMBER > 19961007
+ user = getword_nulls_nc(GLOBAL(php3_rqst)->pool, &t, ':');
+#else
+ user = getword(GLOBAL(php3_rqst)->pool, &t, ':');
+#endif
+ type = "Basic";
+
+ if (user) {
+ if (PG(magic_quotes_gpc)) {
+ escaped_str = _php3_addslashes(user, 0, &len, 0);
+ SET_VAR_STRINGL("PHP_AUTH_USER", escaped_str, len);
+ } else {
+ SET_VAR_STRING("PHP_AUTH_USER", estrdup(user));
+ }
+ }
+ if (t) {
+ if (PG(magic_quotes_gpc)) {
+ escaped_str = _php3_addslashes(t, 0, &len, 0);
+ SET_VAR_STRINGL("PHP_AUTH_PW", escaped_str, len);
+ } else {
+ SET_VAR_STRING("PHP_AUTH_PW", estrdup(t));
+ }
+ }
+ if (type) {
+ if (PG(magic_quotes_gpc)) {
+ escaped_str = _php3_addslashes(type, 0, &len, 0);
+ SET_VAR_STRINGL("PHP_AUTH_TYPE", escaped_str, len);
+ } else {
+ SET_VAR_STRING("PHP_AUTH_TYPE", estrdup(type));
+ }
+ }
+#endif
+#if FHTTPD
+ int i,len;
+ struct rline *l;
+ char *type;
+ char *escaped_str;
+
+ if(req && req->remote_user){
+ for(i=0; i < req->nlines; i++){
+ l=req->lines+i;
+ if((l->paramc > 1)&&!strcasecmp(l->params[0], "REMOTE_PW")){
+ type = "Basic";
+ if (PG(magic_quotes_gpc)) {
+ escaped_str = _php3_addslashes(type, 0, &len, 0);
+ SET_VAR_STRINGL("PHP_AUTH_TYPE", escaped_str, len);
+ escaped_str = _php3_addslashes(l->params[1], 0, &len, 0);
+ SET_VAR_STRINGL("PHP_AUTH_PW", escaped_str, len);
+ escaped_str = _php3_addslashes(req->remote_user, 0, &len, 0);
+ SET_VAR_STRINGL("PHP_AUTH_USER", escaped_str, len);
+
+ } else {
+ SET_VAR_STRING("PHP_AUTH_TYPE", estrdup(type));
+ SET_VAR_STRING("PHP_AUTH_PW", estrdup(l->params[1]));
+ SET_VAR_STRING("PHP_AUTH_USER", estrdup(req->remote_user));
+ }
+ i=req->nlines;
+ }
+ }
+ }
+#endif
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/standard/post.h b/ext/standard/post.h
new file mode 100644
index 0000000000..37920a8978
--- /dev/null
+++ b/ext/standard/post.h
@@ -0,0 +1,43 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
+ +----------------------------------------------------------------------+
+ */
+/* $Id$ */
+
+#ifndef _POST_H
+#define _POST_H
+
+#define PARSE_POST 0
+#define PARSE_GET 1
+#define PARSE_COOKIE 2
+#define PARSE_STRING 3
+
+extern void php3_treat_data(int arg, char *str);
+extern void php3_TreatHeaders(void);
+extern void _php3_parse_gpc_data(char *, char *, pval *track_vars_array);
+
+#endif
diff --git a/ext/standard/string.c b/ext/standard/string.c
index 43457ba44a..b05605275c 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -37,7 +37,7 @@
#include <stdio.h>
#include "php.h"
#include "reg.h"
-#include "functions/post.h"
+#include "post.h"
#include "php3_string.h"
#if HAVE_SETLOCALE
#include <locale.h>
diff --git a/ext/standard/var.c b/ext/standard/var.c
index a602ee0eb7..feb277c4c3 100644
--- a/ext/standard/var.c
+++ b/ext/standard/var.c
@@ -36,7 +36,7 @@
#include "php.h"
#include "fopen-wrappers.h"
#include "reg.h"
-#include "functions/post.h"
+#include "post.h"
#include "php3_string.h"
#if HAVE_SETLOCALE
#include <locale.h>
diff --git a/ext/sybase/Makefile.am b/ext/sybase/Makefile.am
new file mode 100644
index 0000000000..97c3e06f8f
--- /dev/null
+++ b/ext/sybase/Makefile.am
@@ -0,0 +1,6 @@
+# $Id$
+
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_sybase.a
+libphpext_sybase_a_SOURCES=sybase.c sybase-ct.c
+
diff --git a/ext/sybase/Makefile.in b/ext/sybase/Makefile.in
new file mode 100644
index 0000000000..224e6b570d
--- /dev/null
+++ b/ext/sybase/Makefile.in
@@ -0,0 +1,270 @@
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# $Id$
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+APACHE_INCLUDE = @APACHE_INCLUDE@
+APACHE_TARGET = @APACHE_TARGET@
+APXS = @APXS@
+APXS_LDFLAGS = @APXS_LDFLAGS@
+BINNAME = @BINNAME@
+CC = @CC@
+CFLAGS = @CFLAGS@
+CFLAGS_SHLIB = @CFLAGS_SHLIB@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+EXTINFO_DEPS = @EXTINFO_DEPS@
+EXTRA_LIBS = @EXTRA_LIBS@
+EXT_LIBS = @EXT_LIBS@
+EXT_SUBDIRS = @EXT_SUBDIRS@
+FHTTPD_LIB = @FHTTPD_LIB@
+FHTTPD_TARGET = @FHTTPD_TARGET@
+HSREGEX = @HSREGEX@
+INSTALL_IT = @INSTALL_IT@
+LDFLAGS_SHLIB = @LDFLAGS_SHLIB@
+LDFLAGS_SHLIB_EXPORT = @LDFLAGS_SHLIB_EXPORT@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+PERL_PATH = @PERL_PATH@
+PHP_BUILD_DATE = @PHP_BUILD_DATE@
+PHP_DEBUG = @PHP_DEBUG@
+PHP_LIBS = @PHP_LIBS@
+PHP_VERSION = @PHP_VERSION@
+PROG_SENDMAIL = @PROG_SENDMAIL@
+RANLIB = @RANLIB@
+RDYNAMIC_LFLAGS = @RDYNAMIC_LFLAGS@
+REGEX_LIB = @REGEX_LIB@
+STRONGHOLD = @STRONGHOLD@
+VERSION = @VERSION@
+WARNING_LEVEL = @WARNING_LEVEL@
+YACC = @YACC@
+
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_sybase.a
+libphpext_sybase_a_SOURCES=sybase.c sybase-ct.c
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libphpext_sybase_a_LIBADD =
+libphpext_sybase_a_OBJECTS = sybase.o sybase-ct.o
+AR = ar
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+SOURCES = $(libphpext_sybase_a_SOURCES)
+OBJECTS = $(libphpext_sybase_a_OBJECTS)
+
+all: Makefile $(LIBRARIES)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps ext/sybase/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+ $(COMPILE) -c $<
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libphpext_sybase.a: $(libphpext_sybase_a_OBJECTS) $(libphpext_sybase_a_DEPENDENCIES)
+ -rm -f libphpext_sybase.a
+ $(AR) cru libphpext_sybase.a $(libphpext_sybase_a_OBJECTS) $(libphpext_sybase_a_LIBADD)
+ $(RANLIB) libphpext_sybase.a
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = ext/sybase
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
+ done
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
+install-strip:
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+
+
+mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -rm -f Makefile $(DISTCLEANFILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-tags mostlyclean-generic
+
+clean: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+ mostlyclean
+
+distclean: distclean-noinstLIBRARIES distclean-compile distclean-tags \
+ distclean-generic clean
+ -rm -f config.status
+
+maintainer-clean: maintainer-clean-noinstLIBRARIES \
+ maintainer-clean-compile maintainer-clean-tags \
+ maintainer-clean-generic distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info dvi installcheck \
+install-exec install-data install uninstall all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/ext/sybase/config.h.stub b/ext/sybase/config.h.stub
new file mode 100644
index 0000000000..15ce4496bc
--- /dev/null
+++ b/ext/sybase/config.h.stub
@@ -0,0 +1,6 @@
+/* Define if you have libdnet_stub (used for Sybase support) */
+#define HAVE_LIBDNET_STUB 0
+
+#define HAVE_SYBASE 0
+
+#define HAVE_SYBASE_CT 0
diff --git a/ext/sybase/config.m4 b/ext/sybase/config.m4
new file mode 100644
index 0000000000..34de48373b
--- /dev/null
+++ b/ext/sybase/config.m4
@@ -0,0 +1,73 @@
+dnl $Id$
+
+AC_MSG_CHECKING(for Sybase support)
+AC_ARG_WITH(sybase,
+[ --with-sybase[=DIR] Include Sybase-DB support. DIR is the Sybase home
+ directory, defaults to /home/sybase.],
+[
+ if test "$withval" != "no"; then
+ if test "$withval" = "yes"; then
+ SYBASE_INCDIR=/home/sybase/include
+ SYBASE_LIBDIR=/home/sybase/lib
+ else
+ SYBASE_INCDIR=$withval/include
+ SYBASE_LIBDIR=$withval/lib
+ fi
+ SYBASE_INCLUDE=-I$SYBASE_INCDIR
+ SYBASE_LFLAGS="-L$SYBASE_LIBDIR -L$SYBASE_LIBDIR"
+ SYBASE_LIBS=-lsybdb
+ AC_MSG_RESULT(yes)
+ PHP_EXTENSION(sybase)
+ AC_CHECK_LIB(dnet_stub, dnet_addr,
+ [ SYBASE_LIBS="$SYBASE_LIBS -ldnet_stub"
+ AC_DEFINE(HAVE_LIBDNET_STUB)
+ ])
+ AC_DEFINE(HAVE_SYBASE)
+ EXTRA_LIBS="$EXTRA_LIBS $SYBASE_LFLAGS $SYBASE_LIBS"
+ INCLUDES="$INCLUDES $SYBASE_INCLUDE"
+ else
+ AC_MSG_RESULT(no)
+ fi
+],[
+ AC_MSG_RESULT(no)
+])
+
+
+AC_MSG_CHECKING(for Sybase-CT support)
+AC_ARG_WITH(sybase-ct,
+[ --with-sybase-ct[=DIR] Include Sybase-CT support. DIR is the Sybase home
+ directory, defaults to /home/sybase.],
+[
+ if test "$withval" != "no"; then
+ AC_MSG_RESULT(yes)
+ if test -z "$SYBASE_LIBS"; then
+ PHP_EXTENSION(sybase)
+ fi
+ AC_DEFINE(HAVE_SYBASE_CT)
+ if test "$withval" = "yes"; then
+ SYBASE_CT_INCDIR=/home/sybase/include
+ SYBASE_CT_LIBDIR=/home/sybase/lib
+ else
+ SYBASE_CT_INCDIR=$withval/include
+ SYBASE_CT_LIBDIR=$withval/lib
+ fi
+ SYBASE_CT_INCLUDE=-I$SYBASE_CT_INCDIR
+ SYBASE_CT_LFLAGS="-L$SYBASE_CT_LIBDIR"
+ SYBASE_CT_LIBS="-lcs -lct -lcomn -lintl"
+ old_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -L$SYBASE_CT_LIBDIR"
+ AC_CHECK_LIB(tcl, netg_errstr,
+ [ SYBASE_CT_LIBS="$SYBASE_CT_LIBS -ltcl" ],
+ [ SYBASE_CT_LIBS="$SYBASE_CT_LIBS -lsybtcl" ],
+ [ $SYBASE_CT_LIBS ])
+ AC_CHECK_LIB(insck, insck__getVdate,
+ [ SYBASE_CT_LIBS="$SYBASE_CT_LIBS -linsck" ])
+ LDFLAGS=$old_LDFLAGS
+ EXTRA_LIBS="$EXTRA_LIBS $SYBASE_CT_LFLAGS $SYBASE_CT_LIBS"
+ INCLUDES="$INCLUDES $SYBASE_CT_INCLUDE"
+ else
+ AC_MSG_RESULT(no)
+ fi
+],[
+ AC_MSG_RESULT(no)
+])
diff --git a/ext/sybase/php3_sybase-ct.h b/ext/sybase/php3_sybase-ct.h
new file mode 100644
index 0000000000..1ce0a30f0c
--- /dev/null
+++ b/ext/sybase/php3_sybase-ct.h
@@ -0,0 +1,123 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Zeev Suraski <zeev@zend.com> |
+ +----------------------------------------------------------------------+
+ */
+
+
+/* $Id$ */
+
+#ifndef _PHP3_SYBASE_CT_H
+#define _PHP3_SYBASE_CT_H
+
+#if COMPILE_DL
+#undef HAVE_SYBASE_CT
+#define HAVE_SYBASE_CT 1
+#endif
+
+#if HAVE_SYBASE_CT
+
+#define CTLIB_VERSION CS_VERSION_100
+
+extern php3_module_entry sybct_module_entry;
+#define sybct_module_ptr &sybct_module_entry
+
+extern int php3_minit_sybct(INIT_FUNC_ARGS);
+extern int php3_rinit_sybct(INIT_FUNC_ARGS);
+extern int php3_mshutdown_sybct(SHUTDOWN_FUNC_ARGS);
+extern int php3_rshutdown_sybct(SHUTDOWN_FUNC_ARGS);
+extern void php3_info_sybct(void);
+extern void php3_sybct_connect(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_pconnect(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_close(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_select_db(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_query(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_free_result(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_get_last_message(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_num_rows(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_num_fields(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_fetch_row(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_fetch_array(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_fetch_object(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_data_seek(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_result(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_affected_rows(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_field_seek(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_min_client_severity(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_min_server_severity(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybct_fetch_field(INTERNAL_FUNCTION_PARAMETERS);
+
+
+#include <ctpublic.h>
+
+typedef struct {
+ long default_link;
+ long num_links,num_persistent;
+ long max_links,max_persistent;
+ long allow_persistent;
+ char *appname;
+ char *hostname;
+ char *server_message;
+ int le_link,le_plink,le_result;
+ long min_server_severity, min_client_severity;
+ long cfg_min_server_severity, cfg_min_client_severity;
+} sybct_module;
+
+typedef struct {
+ CS_CONNECTION *connection;
+ CS_COMMAND *cmd;
+ int valid;
+ int deadlock;
+ int dead;
+ long affected_rows;
+} sybct_link;
+
+#define SYBASE_ROWS_BLOCK 128
+
+typedef struct {
+ char *name,*column_source;
+ int max_length, numeric;
+ CS_INT type;
+} sybct_field;
+
+typedef struct {
+ pval **data;
+ sybct_field *fields;
+ sybct_link *sybct_ptr;
+ int cur_row,cur_field;
+ int num_rows,num_fields;
+} sybct_result;
+
+
+extern sybct_module php3_sybct_module;
+
+#else
+
+#define sybct_module_ptr NULL
+
+#endif
+
+#endif /* _PHP3_SYBASE_CT_H */
diff --git a/ext/sybase/php3_sybase.h b/ext/sybase/php3_sybase.h
new file mode 100644
index 0000000000..dbfcdd767a
--- /dev/null
+++ b/ext/sybase/php3_sybase.h
@@ -0,0 +1,141 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Zeev Suraski <zeev@zend.com> |
+ +----------------------------------------------------------------------+
+ */
+
+
+/* $Id$ */
+
+#ifndef _PHP3_SYBASE_H
+#define _PHP3_SYBASE_H
+
+#if COMPILE_DL
+#undef HAVE_SYBASE
+#define HAVE_SYBASE 1
+#endif
+
+#if HAVE_SYBASE
+
+extern php3_module_entry sybase_module_entry;
+#define sybase_module_ptr &sybase_module_entry
+
+extern int php3_minit_sybase(INIT_FUNC_ARGS);
+extern int php3_rinit_sybase(INIT_FUNC_ARGS);
+extern int php3_mshutdown_sybase(SHUTDOWN_FUNC_ARGS);
+extern int php3_rshutdown_sybase(SHUTDOWN_FUNC_ARGS);
+extern void php3_info_sybase(void);
+extern void php3_sybase_connect(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_pconnect(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_close(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_select_db(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_query(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_free_result(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_get_last_message(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_num_rows(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_num_fields(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_fetch_row(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_fetch_array(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_fetch_object(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_data_seek(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_result(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_field_seek(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_min_error_severity(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_min_message_severity(INTERNAL_FUNCTION_PARAMETERS);
+
+extern void php3_sybase_db_query(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_list_fields(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_fetch_lengths(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_fetch_field(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_field_seek(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_free_result(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_field_name(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_field_table(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_field_len(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_field_type(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sybase_field_flags(INTERNAL_FUNCTION_PARAMETERS);
+
+
+
+#include <sybfront.h>
+#include <sybdb.h>
+#include <syberror.h>
+
+#define coltype(j) dbcoltype(sybase_ptr->link,j)
+#define intcol(i) ((int) *(DBINT *) dbdata(sybase_ptr->link,i))
+#define smallintcol(i) ((int) *(DBSMALLINT *) dbdata(sybase_ptr->link,i))
+#define tinyintcol(i) ((int) *(DBTINYINT *) dbdata(sybase_ptr->link,i))
+#define anyintcol(j) (coltype(j)==SYBINT4?intcol(j):(coltype(j)==SYBINT2?smallintcol(j):tinyintcol(j)))
+#define charcol(i) ((DBCHAR *) dbdata(sybase_ptr->link,i))
+#define floatcol(i) ((float) *(DBFLT8 *) dbdata(sybase_ptr->link,i))
+
+typedef struct sybase_link_struct sybase_link;
+
+typedef struct {
+ long default_link;
+ long num_links,num_persistent;
+ long max_links,max_persistent;
+ long allow_persistent;
+ char *appname;
+ char *server_message;
+ int le_link,le_plink,le_result;
+ long min_error_severity,min_message_severity;
+ long cfg_min_error_severity,cfg_min_message_severity;
+ long compatability_mode;
+} sybase_module;
+
+struct sybase_link_struct {
+ LOGINREC *login;
+ DBPROCESS *link;
+ int valid;
+};
+
+#define SYBASE_ROWS_BLOCK 128
+
+typedef struct {
+ char *name,*column_source;
+ int max_length, numeric;
+ int type;
+} sybase_field;
+
+typedef struct {
+ pval **data;
+ sybase_field *fields;
+ sybase_link *sybase_ptr;
+ int cur_row,cur_field;
+ int num_rows,num_fields;
+} sybase_result;
+
+
+extern sybase_module php3_sybase_module;
+
+#else
+
+#define sybase_module_ptr NULL
+
+#endif
+
+#endif /* _PHP3_SYBASE_H */
diff --git a/ext/sybase/setup.stub b/ext/sybase/setup.stub
new file mode 100644
index 0000000000..58e0b789c6
--- /dev/null
+++ b/ext/sybase/setup.stub
@@ -0,0 +1,11 @@
+# $Source$
+# $Id$
+
+define_option with-sybase 'Sybase support?' yesnodir \
+ 'no /home/sybase Sybase install' \
+' Whether to build PHP with Sybase support (DBLib only).\n
+ More info about Sybase can be found at http://www.sybase.com/.'
+
+define_option with-sybase-ct 'Sybase-CT support?' yesnodir \
+ 'no /home/sybase Sybase-CT install' \
+' Whether to build PHP with Sybase-CT support.'
diff --git a/ext/sybase/sybase-ct.c b/ext/sybase/sybase-ct.c
new file mode 100644
index 0000000000..7f45658d6b
--- /dev/null
+++ b/ext/sybase/sybase-ct.c
@@ -0,0 +1,1652 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Zeev Suraski <zeev@zend.com> |
+ | Tom May <tom@go2net.com> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+
+#ifndef MSVC5
+#include "config.h"
+#endif
+#include "php.h"
+#include "php3_sybase-ct.h"
+#include "ext/standard/php3_standard.h"
+#include "php_globals.h"
+
+#if HAVE_SYBASE_CT
+
+
+
+function_entry sybct_functions[] = {
+ {"sybase_connect", php3_sybct_connect, NULL},
+ {"sybase_pconnect", php3_sybct_pconnect, NULL},
+ {"sybase_close", php3_sybct_close, NULL},
+ {"sybase_select_db", php3_sybct_select_db, NULL},
+ {"sybase_query", php3_sybct_query, NULL},
+ {"sybase_free_result", php3_sybct_free_result, NULL},
+ {"sybase_num_rows", php3_sybct_num_rows, NULL},
+ {"sybase_num_fields", php3_sybct_num_fields, NULL},
+ {"sybase_fetch_row", php3_sybct_fetch_row, NULL},
+ {"sybase_fetch_array", php3_sybct_fetch_array, NULL},
+ {"sybase_fetch_object", php3_sybct_fetch_object, NULL},
+ {"sybase_data_seek", php3_sybct_data_seek, NULL},
+ {"sybase_fetch_field", php3_sybct_fetch_field, NULL},
+ {"sybase_field_seek", php3_sybct_field_seek, NULL},
+ {"sybase_result", php3_sybct_result, NULL},
+ {"sybase_affected_rows",php3_sybct_affected_rows, NULL},
+ {"sybase_min_client_severity", php3_sybct_min_client_severity, NULL},
+ {"sybase_min_server_severity", php3_sybct_min_server_severity, NULL},
+ {"mssql_connect", php3_sybct_connect, NULL},
+ {"mssql_pconnect", php3_sybct_pconnect, NULL},
+ {"mssql_close", php3_sybct_close, NULL},
+ {"mssql_select_db", php3_sybct_select_db, NULL},
+ {"mssql_query", php3_sybct_query, NULL},
+ {"mssql_free_result", php3_sybct_free_result, NULL},
+ {"mssql_num_rows", php3_sybct_num_rows, NULL},
+ {"mssql_num_fields", php3_sybct_num_fields, NULL},
+ {"mssql_fetch_row", php3_sybct_fetch_row, NULL},
+ {"mssql_fetch_array", php3_sybct_fetch_array, NULL},
+ {"mssql_fetch_object", php3_sybct_fetch_object, NULL},
+ {"mssql_data_seek", php3_sybct_data_seek, NULL},
+ {"mssql_fetch_field", php3_sybct_fetch_field, NULL},
+ {"mssql_field_seek", php3_sybct_field_seek, NULL},
+ {"mssql_result", php3_sybct_result, NULL},
+ {"mssql_affected_rows", php3_sybct_affected_rows, NULL},
+ {"mssql_min_client_severity", php3_sybct_min_client_severity, NULL},
+ {"mssql_min_server_severity", php3_sybct_min_server_severity, NULL},
+ {NULL, NULL, NULL}
+};
+
+php3_module_entry sybct_module_entry = {
+ "Sybase SQL - CT", sybct_functions, php3_minit_sybct, php3_mshutdown_sybct, php3_rinit_sybct, php3_rshutdown_sybct, php3_info_sybct, STANDARD_MODULE_PROPERTIES
+};
+
+#if COMPILE_DL
+php3_module_entry *get_module() { return &sybct_module_entry; }
+#endif
+
+THREAD_LS sybct_module php3_sybct_module;
+THREAD_LS static CS_CONTEXT *context;
+THREAD_LS static HashTable *resource_list,*resource_plist;
+
+#define CHECK_LINK(link) { if (link==-1) { php3_error(E_WARNING,"Sybase: A link to the server could not be established"); RETURN_FALSE; } }
+
+
+static int _clean_invalid_results(list_entry *le)
+{
+ if (le->type == php3_sybct_module.le_result) {
+ sybct_link *sybct_ptr = ((sybct_result *) le->ptr)->sybct_ptr;
+
+ if (!sybct_ptr->valid) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+static void _free_sybct_result(sybct_result *result)
+{
+ int i,j;
+
+ if (result->data) {
+ for (i=0; i<result->num_rows; i++) {
+ for (j=0; j<result->num_fields; j++) {
+ pval_destructor(&result->data[i][j]);
+ }
+ efree(result->data[i]);
+ }
+ efree(result->data);
+ }
+
+ if (result->fields) {
+ for (i=0; i<result->num_fields; i++) {
+ STR_FREE(result->fields[i].name);
+ STR_FREE(result->fields[i].column_source);
+ }
+ efree(result->fields);
+ }
+
+ efree(result);
+}
+
+
+static void _close_sybct_link(sybct_link *sybct_ptr)
+{
+ CS_INT con_status;
+
+ sybct_ptr->valid = 0;
+ _php3_hash_apply(resource_list,(int (*)(void *))_clean_invalid_results);
+
+ /* Non-persistent connections will always be connected or we wouldn't
+ * get here, but since we want to check the death status anyway
+ * we might as well double-check the connect status.
+ */
+ if (ct_con_props(sybct_ptr->connection, CS_GET, CS_CON_STATUS,
+ &con_status, CS_UNUSED, NULL)!=CS_SUCCEED) {
+ php3_error(E_WARNING,"Sybase: Unable to get connection status on close");
+ /* Assume the worst. */
+ con_status = CS_CONSTAT_CONNECTED | CS_CONSTAT_DEAD;
+ }
+ if (con_status & CS_CONSTAT_CONNECTED) {
+ if ((con_status & CS_CONSTAT_DEAD) || ct_close(sybct_ptr->connection, CS_UNUSED)!=CS_SUCCEED) {
+ ct_close(sybct_ptr->connection, CS_FORCE_CLOSE);
+ }
+ }
+
+ ct_con_drop(sybct_ptr->connection);
+ efree(sybct_ptr);
+ php3_sybct_module.num_links--;
+}
+
+
+static void _close_sybct_plink(sybct_link *sybct_ptr)
+{
+ CS_INT con_status;
+
+ /* Persistent connections may have been closed before a failed
+ * reopen attempt.
+ */
+ if (ct_con_props(sybct_ptr->connection, CS_GET, CS_CON_STATUS,
+ &con_status, CS_UNUSED, NULL)!=CS_SUCCEED) {
+ php3_error(E_WARNING,"Sybase: Unable to get connection status on close");
+ /* Assume the worst. */
+ con_status = CS_CONSTAT_CONNECTED | CS_CONSTAT_DEAD;
+ }
+ if (con_status & CS_CONSTAT_CONNECTED) {
+ if ((con_status & CS_CONSTAT_DEAD) || ct_close(sybct_ptr->connection, CS_UNUSED)!=CS_SUCCEED) {
+ ct_close(sybct_ptr->connection, CS_FORCE_CLOSE);
+ }
+ }
+
+ ct_con_drop(sybct_ptr->connection);
+ free(sybct_ptr);
+ php3_sybct_module.num_persistent--;
+ php3_sybct_module.num_links--;
+}
+
+
+static CS_RETCODE _client_message_handler(CS_CONTEXT *context, CS_CONNECTION *connection, CS_CLIENTMSG *errmsg)
+{
+ if (CS_SEVERITY(errmsg->msgnumber) >= php3_sybct_module.min_client_severity) {
+ php3_error(E_WARNING,"Sybase: Client message: %s (severity %d)",errmsg->msgstring, CS_SEVERITY(errmsg->msgnumber));
+ }
+
+ /* If this is a timeout message, return CS_FAIL to cancel the
+ * operation and mark the connection as dead.
+ */
+ if (CS_SEVERITY(errmsg->msgnumber) == CS_SV_RETRY_FAIL &&
+ CS_NUMBER(errmsg->msgnumber) == 63 &&
+ CS_ORIGIN(errmsg->msgnumber) == 2 &&
+ CS_LAYER(errmsg->msgnumber) == 1)
+ {
+ return CS_FAIL;
+ }
+
+ return CS_SUCCEED;
+}
+
+
+static CS_RETCODE _server_message_handler(CS_CONTEXT *context, CS_CONNECTION *connection, CS_SERVERMSG *srvmsg)
+{
+ if (srvmsg->severity >= php3_sybct_module.min_server_severity) {
+ php3_error(E_WARNING,"Sybase: Server message: %s (severity %d, procedure %s)",
+ srvmsg->text, srvmsg->severity, ((srvmsg->proclen>0) ? srvmsg->proc : "N/A"));
+ }
+
+ /* If this is a deadlock message, set the connection's deadlock flag
+ * so we will retry the request. Sorry about the bare constant here,
+ * but it's not defined anywhere and it's a "well-known" number.
+ */
+ if (srvmsg->msgnumber == 1205) {
+ sybct_link *sybct;
+
+ if (ct_con_props(connection, CS_GET, CS_USERDATA, &sybct, CS_SIZEOF(sybct), NULL)==CS_SUCCEED) {
+ sybct->deadlock = 1;
+ }
+ else {
+ /* oh well */
+ }
+ }
+
+ return CS_SUCCEED;
+}
+
+
+int php3_minit_sybct(INIT_FUNC_ARGS)
+{
+ long timeout;
+
+ if (cs_ctx_alloc(CTLIB_VERSION, &context)!=CS_SUCCEED || ct_init(context,CTLIB_VERSION)!=CS_SUCCEED) {
+ return FAILURE;
+ }
+ /* Initialize message handlers */
+
+ if (ct_callback(context, NULL, CS_SET, CS_SERVERMSG_CB, (CS_VOID *)_server_message_handler)!=CS_SUCCEED) {
+ php3_error(E_WARNING,"Sybase: Unable to set server message handler");
+ }
+ if (ct_callback(context, NULL, CS_SET, CS_CLIENTMSG_CB, (CS_VOID *)_client_message_handler)!=CS_SUCCEED) {
+ php3_error(E_WARNING,"Sybase: Unable to set client message handler");
+ }
+
+ /* Set datetime conversion format to "Nov 3 1998 8:06PM".
+ * This is the default format for the ct-lib that comes with
+ * Sybase ASE 11.5.1 for Solaris, but the Linux libraries that
+ * come with 11.0.3.3 default to "03/11/98" which is singularly
+ * useless. This levels the playing field for all platforms.
+ */
+ {
+ CS_INT dt_convfmt = CS_DATES_SHORT;
+ if (cs_dt_info(context, CS_SET, NULL, CS_DT_CONVFMT, CS_UNUSED, &dt_convfmt, sizeof(dt_convfmt), NULL)!=CS_SUCCEED) {
+ php3_error(E_WARNING,"Sybase: Unable to set datetime conversion format");
+ }
+ }
+
+ /* Set the login and command timeouts. These are per-context and
+ * can't be set with ct_con_props(), so set them globally from
+ * their config values if requested. The defaults are 1 minute
+ * for CS_LOGIN_TIMEOUT and CS_NO_LIMIT for CS_TIMEOUT. The latter
+ * especially is fairly useless for web applications.
+ * Note that depite some noise in the documentation about using
+ * signals to implement timeouts, they are actually implemented
+ * by using poll() or select() on Solaris and Linux.
+ */
+ if (cfg_get_long("sybct.login_timeout",&timeout)==SUCCESS) {
+ CS_INT cs_login_timeout = timeout;
+ if (ct_config(context, CS_SET, CS_LOGIN_TIMEOUT, &cs_login_timeout, CS_UNUSED, NULL)!=CS_SUCCEED) {
+ php3_error(E_WARNING,"Sybase: Unable to set login timeoutt");
+ }
+ }
+ if (cfg_get_long("sybct.timeout",&timeout)==SUCCESS) {
+ CS_INT cs_timeout = timeout;
+ if (ct_config(context, CS_SET, CS_TIMEOUT, &cs_timeout, CS_UNUSED, NULL)!=CS_SUCCEED) {
+ php3_error(E_WARNING,"Sybase: Unable to set timeout");
+ }
+ }
+
+ if (cfg_get_long("sybct.allow_persistent",&php3_sybct_module.allow_persistent)==FAILURE) {
+ php3_sybct_module.allow_persistent=1;
+ }
+ if (cfg_get_long("sybct.max_persistent",&php3_sybct_module.max_persistent)==FAILURE) {
+ php3_sybct_module.max_persistent=-1;
+ }
+ if (cfg_get_long("sybct.max_links",&php3_sybct_module.max_links)==FAILURE) {
+ php3_sybct_module.max_links=-1;
+ }
+ if (cfg_get_long("sybct.min_server_severity",&php3_sybct_module.cfg_min_server_severity)==FAILURE) {
+ php3_sybct_module.cfg_min_server_severity=10;
+ }
+ if (cfg_get_long("sybct.min_client_severity",&php3_sybct_module.cfg_min_client_severity)==FAILURE) {
+ php3_sybct_module.cfg_min_client_severity=10;
+ }
+
+ if (cfg_get_string("sybct.hostname",&php3_sybct_module.hostname)==FAILURE
+ || php3_sybct_module.hostname[0]==0) {
+ php3_sybct_module.hostname=NULL;
+ }
+
+ php3_sybct_module.num_persistent=0;
+ php3_sybct_module.le_link = register_list_destructors(_close_sybct_link,NULL);
+ php3_sybct_module.le_plink = register_list_destructors(NULL,_close_sybct_plink);
+ php3_sybct_module.le_result = register_list_destructors(_free_sybct_result,NULL);
+
+ return SUCCESS;
+}
+
+
+int php3_rinit_sybct(INIT_FUNC_ARGS)
+{
+ php3_sybct_module.default_link=-1;
+ php3_sybct_module.num_links = php3_sybct_module.num_persistent;
+ php3_sybct_module.appname = estrndup("PHP 3.0",7);
+ php3_sybct_module.server_message = NULL;
+ php3_sybct_module.min_server_severity = php3_sybct_module.cfg_min_server_severity;
+ php3_sybct_module.min_client_severity = php3_sybct_module.cfg_min_client_severity;
+ return SUCCESS;
+}
+
+int php3_mshutdown_sybct(SHUTDOWN_FUNC_ARGS)
+{
+/* ct_exit(context,CS_UNUSED);
+ cs_ctx_drop(context); */
+ return SUCCESS;
+}
+
+int php3_rshutdown_sybct(SHUTDOWN_FUNC_ARGS)
+{
+ efree(php3_sybct_module.appname);
+ if (php3_sybct_module.server_message) {
+ efree(php3_sybct_module.server_message);
+ }
+ return SUCCESS;
+}
+
+
+static int _php3_sybct_really_connect(sybct_link *sybct, char *host, char *user, char *passwd)
+{
+ /* set a CS_CONNECTION record */
+ if (ct_con_alloc(context, &sybct->connection)!=CS_SUCCEED) {
+ php3_error(E_WARNING,"Sybase: Unable to allocate connection record");
+ return 0;
+ }
+
+ /* Note - this saves a copy of sybct, not a pointer to it. */
+ if (ct_con_props(sybct->connection, CS_SET, CS_USERDATA, &sybct, CS_SIZEOF(sybct), NULL)!=CS_SUCCEED) {
+ php3_error(E_WARNING,"Sybase: Unable to set userdata");
+ ct_con_drop(sybct->connection);
+ return 0;
+ }
+
+ if (user) {
+ ct_con_props(sybct->connection, CS_SET, CS_USERNAME, user, CS_NULLTERM, NULL);
+ }
+ if (passwd) {
+ ct_con_props(sybct->connection, CS_SET, CS_PASSWORD, passwd, CS_NULLTERM, NULL);
+ }
+ ct_con_props(sybct->connection, CS_SET, CS_APPNAME, php3_sybct_module.appname, CS_NULLTERM, NULL);
+
+ if (php3_sybct_module.hostname) {
+ ct_con_props(sybct->connection, CS_SET, CS_HOSTNAME, php3_sybct_module.hostname, CS_NULLTERM, NULL);
+ }
+
+ sybct->valid = 1;
+ sybct->dead = 0;
+
+ /* create the link */
+ if (ct_connect(sybct->connection, host, CS_NULLTERM)!=CS_SUCCEED) {
+ php3_error(E_WARNING,"Sybase: Unable to connect");
+ ct_con_drop(sybct->connection);
+ return 0;
+ }
+
+ if (ct_cmd_alloc(sybct->connection,&sybct->cmd)!=CS_SUCCEED) {
+ php3_error(E_WARNING,"Sybase: Unable to allocate command record");
+ ct_close(sybct->connection,CS_UNUSED);
+ ct_con_drop(sybct->connection);
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static void php3_sybct_do_connect(INTERNAL_FUNCTION_PARAMETERS,int persistent)
+{
+ char *user,*passwd,*host;
+ char *hashed_details;
+ int hashed_details_length;
+ sybct_link *sybct_ptr;
+
+ resource_list = list;
+ resource_plist = plist;
+
+ switch(ARG_COUNT(ht)) {
+ case 0: /* defaults */
+ host=user=passwd=NULL;
+ hashed_details_length=5+3;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ strcpy(hashed_details,"sybct___");
+ break;
+ case 1: {
+ pval *yyhost;
+
+ if (getParameters(ht, 1, &yyhost)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string(yyhost);
+ host = yyhost->value.str.val;
+ user=passwd=NULL;
+ hashed_details_length = yyhost->value.str.len+5+3;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details,"sybct_%s__",yyhost->value.str.val);
+ }
+ break;
+ case 2: {
+ pval *yyhost,*yyuser;
+
+ if (getParameters(ht, 2, &yyhost, &yyuser)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string(yyhost);
+ convert_to_string(yyuser);
+ host = yyhost->value.str.val;
+ user = yyuser->value.str.val;
+ passwd=NULL;
+ hashed_details_length = yyhost->value.str.len+yyuser->value.str.len+5+3;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details,"sybct_%s_%s_",yyhost->value.str.val,yyuser->value.str.val);
+ }
+ break;
+ case 3: {
+ pval *yyhost,*yyuser,*yypasswd;
+
+ if (getParameters(ht, 3, &yyhost, &yyuser, &yypasswd) == FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string(yyhost);
+ convert_to_string(yyuser);
+ convert_to_string(yypasswd);
+ host = yyhost->value.str.val;
+ user = yyuser->value.str.val;
+ passwd = yypasswd->value.str.val;
+ hashed_details_length = yyhost->value.str.len+yyuser->value.str.len+yypasswd->value.str.len+5+3;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details,"sybct_%s_%s_%s",yyhost->value.str.val,yyuser->value.str.val,yypasswd->value.str.val); /* SAFE */
+ }
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+
+ if (!php3_sybct_module.allow_persistent) {
+ persistent=0;
+ }
+ if (persistent) {
+ list_entry *le;
+
+ /* try to find if we already have this link in our persistent list */
+ if (_php3_hash_find(plist, hashed_details, hashed_details_length+1, (void **) &le)==FAILURE) { /* we don't */
+ list_entry new_le;
+
+ if (php3_sybct_module.max_links!=-1 && php3_sybct_module.num_links>=php3_sybct_module.max_links) {
+ php3_error(E_WARNING,"Sybase: Too many open links (%d)",php3_sybct_module.num_links);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ if (php3_sybct_module.max_persistent!=-1 && php3_sybct_module.num_persistent>=php3_sybct_module.max_persistent) {
+ php3_error(E_WARNING,"Sybase: Too many open persistent links (%d)",php3_sybct_module.num_persistent);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ sybct_ptr = (sybct_link *) malloc(sizeof(sybct_link));
+ if (!_php3_sybct_really_connect(sybct_ptr, host, user, passwd)) {
+ free(sybct_ptr);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ /* hash it up */
+ new_le.type = php3_sybct_module.le_plink;
+ new_le.ptr = sybct_ptr;
+ if (_php3_hash_update(plist, hashed_details, hashed_details_length+1, (void *) &new_le, sizeof(list_entry),NULL)==FAILURE) {
+ ct_close(sybct_ptr->connection, CS_UNUSED);
+ ct_con_drop(sybct_ptr->connection);
+ free(sybct_ptr);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ php3_sybct_module.num_persistent++;
+ php3_sybct_module.num_links++;
+ } else { /* we do */
+ CS_INT con_status;
+
+ if (le->type != php3_sybct_module.le_plink) {
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ sybct_ptr = (sybct_link *) le->ptr;
+
+ /* If the link has died, close it and overwrite it with a new one. */
+
+ if (ct_con_props(sybct_ptr->connection, CS_GET, CS_CON_STATUS,
+ &con_status, CS_UNUSED, NULL)!=CS_SUCCEED) {
+ php3_error(E_WARNING,"Sybase: Unable to get connection status");
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ if (!(con_status & CS_CONSTAT_CONNECTED) || (con_status & CS_CONSTAT_DEAD) || sybct_ptr->dead) {
+ sybct_link sybct;
+
+ if (con_status & CS_CONSTAT_CONNECTED) {
+ ct_close(sybct_ptr->connection, CS_FORCE_CLOSE);
+ }
+ /* Create a new connection, then replace the old
+ * connection. If we fail to create a new connection,
+ * put the old one back so there will be a connection,
+ * even if it is a non-functional one. This is because
+ * code may still be holding an id for this connection
+ * so we can't free the CS_CONNECTION.
+ * (This is actually totally hokey, it would be better
+ * to just ct_con_drop() the connection and set
+ * sybct_ptr->connection to NULL, then test it for
+ * NULL before trying to use it elsewhere . . .)
+ */
+ memcpy(&sybct,sybct_ptr,sizeof(sybct_link));
+ if (!_php3_sybct_really_connect(sybct_ptr, host, user, passwd)) {
+ memcpy(sybct_ptr,&sybct,sizeof(sybct_link));
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ ct_con_drop(sybct.connection); /* drop old connection */
+ }
+ }
+ return_value->value.lval = php3_list_insert(sybct_ptr,php3_sybct_module.le_plink);
+ return_value->type = IS_LONG;
+ } else { /* non persistent */
+ list_entry *index_ptr,new_index_ptr;
+
+ /* first we check the hash for the hashed_details key. if it exists,
+ * it should point us to the right offset where the actual sybct link sits.
+ * if it doesn't, open a new sybct link, add it to the resource list,
+ * and add a pointer to it with hashed_details as the key.
+ */
+ if (_php3_hash_find(list,hashed_details,hashed_details_length+1,(void **) &index_ptr)==SUCCESS) {
+ int type,link;
+ void *ptr;
+
+ if (index_ptr->type != le_index_ptr) {
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ link = (int) index_ptr->ptr;
+ ptr = php3_list_find(link,&type); /* check if the link is still there */
+ if (ptr && (type==php3_sybct_module.le_link || type==php3_sybct_module.le_plink)) {
+ return_value->value.lval = php3_sybct_module.default_link = link;
+ return_value->type = IS_LONG;
+ efree(hashed_details);
+ return;
+ } else {
+ _php3_hash_del(list,hashed_details,hashed_details_length+1);
+ }
+ }
+ if (php3_sybct_module.max_links!=-1 && php3_sybct_module.num_links>=php3_sybct_module.max_links) {
+ php3_error(E_WARNING,"Sybase: Too many open links (%d)",php3_sybct_module.num_links);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ sybct_ptr = (sybct_link *) emalloc(sizeof(sybct_link));
+ if (!_php3_sybct_really_connect(sybct_ptr, host, user, passwd)) {
+ efree(sybct_ptr);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ /* add it to the list */
+ return_value->value.lval = php3_list_insert(sybct_ptr,php3_sybct_module.le_link);
+ return_value->type = IS_LONG;
+
+ /* add it to the hash */
+ new_index_ptr.ptr = (void *) return_value->value.lval;
+ new_index_ptr.type = le_index_ptr;
+ if (_php3_hash_update(list,hashed_details,hashed_details_length+1,(void *) &new_index_ptr, sizeof(list_entry),NULL)==FAILURE) {
+ ct_close(sybct_ptr->connection, CS_UNUSED);
+ ct_con_drop(sybct_ptr->connection);
+ efree(sybct_ptr);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ php3_sybct_module.num_links++;
+ }
+ efree(hashed_details);
+ php3_sybct_module.default_link=return_value->value.lval;
+}
+
+
+static int php3_sybct_get_default_link(INTERNAL_FUNCTION_PARAMETERS)
+{
+ if (php3_sybct_module.default_link==-1) { /* no link opened yet, implicitly open one */
+ HashTable dummy;
+
+ _php3_hash_init(&dummy,0,NULL,NULL,0);
+ php3_sybct_do_connect(&dummy,return_value,list,plist,0);
+ _php3_hash_destroy(&dummy);
+ }
+ return php3_sybct_module.default_link;
+}
+
+
+void php3_sybct_connect(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_sybct_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
+}
+
+void php3_sybct_pconnect(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_sybct_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
+}
+
+
+void php3_sybct_close(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *sybct_link_index;
+ int id,type;
+
+ switch (ARG_COUNT(ht)) {
+ case 0:
+ id = php3_sybct_module.default_link;
+ break;
+ case 1:
+ if (getParameters(ht, 1, &sybct_link_index)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(sybct_link_index);
+ id = sybct_link_index->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ php3_list_find(id,&type);
+ if (type!=php3_sybct_module.le_link && type!=php3_sybct_module.le_plink) {
+ php3_error(E_WARNING,"%d is not a Sybase link index",id);
+ RETURN_FALSE;
+ }
+
+ php3_list_delete(id);
+ RETURN_TRUE;
+}
+
+
+static int exec_cmd(sybct_link *sybct_ptr,char *cmdbuf)
+{
+ CS_RETCODE retcode;
+ CS_INT restype;
+ int failure=0;
+
+ /* Fail if we already marked this connection dead. */
+
+ if (sybct_ptr->dead) {
+ return FAILURE;
+ }
+
+ /*
+ ** Get a command handle, store the command string in it, and
+ ** send it to the server.
+ */
+
+ if (ct_command(sybct_ptr->cmd, CS_LANG_CMD, cmdbuf, CS_NULLTERM, CS_UNUSED)!=CS_SUCCEED) {
+ sybct_ptr->dead = 1;
+ return FAILURE;
+ }
+ if (ct_send(sybct_ptr->cmd)!=CS_SUCCEED) {
+ sybct_ptr->dead = 1;
+ return FAILURE;
+ }
+
+ while ((retcode = ct_results(sybct_ptr->cmd, &restype))==CS_SUCCEED) {
+ switch ((int) restype) {
+ case CS_CMD_SUCCEED:
+ case CS_CMD_DONE:
+ break;
+
+ case CS_CMD_FAIL:
+ failure=1;
+ break;
+
+ case CS_STATUS_RESULT:
+ ct_cancel(NULL, sybct_ptr->cmd, CS_CANCEL_CURRENT);
+ break;
+
+ default:
+ failure=1;
+ break;
+ }
+ if (failure) {
+ ct_cancel(NULL, sybct_ptr->cmd, CS_CANCEL_ALL);
+ return FAILURE;
+ }
+ }
+
+ switch (retcode) {
+ case CS_END_RESULTS:
+ return SUCCESS;
+ break;
+
+ case CS_FAIL:
+ /* Hopefully this either cleans up the connection, or the
+ * connection ends up marked dead so it will be reopened
+ * if it is persistent. We may want to do
+ * ct_close(CS_FORCE_CLOSE) if ct_cancel() fails; see the
+ * doc for ct_results()==CS_FAIL.
+ */
+ ct_cancel(NULL, sybct_ptr->cmd, CS_CANCEL_ALL);
+ /* Don't take chances with the vagaries of ct-lib. Mark it
+ * dead ourselves.
+ */
+ sybct_ptr->dead = 1;
+ return FAILURE;
+
+ default:
+ return FAILURE;
+ }
+}
+
+
+void php3_sybct_select_db(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *db,*sybct_link_index;
+ int id,type;
+ char *cmdbuf;
+ sybct_link *sybct_ptr;
+
+ switch(ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &db)==FAILURE) {
+ RETURN_FALSE;
+ }
+ id = php3_sybct_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ break;
+ case 2:
+ if (getParameters(ht, 2, &db, &sybct_link_index)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(sybct_link_index);
+ id = sybct_link_index->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ CHECK_LINK(id);
+
+ sybct_ptr = (sybct_link *) php3_list_find(id,&type);
+ if (type!=php3_sybct_module.le_link && type!=php3_sybct_module.le_plink) {
+ php3_error(E_WARNING,"%d is not a Sybase link index",id);
+ RETURN_FALSE;
+ }
+
+ convert_to_string(db);
+ cmdbuf = (char *) emalloc(sizeof("use ")+db->value.str.len+1);
+ sprintf(cmdbuf,"use %s",db->value.str.val); /* SAFE */
+
+ if (exec_cmd(sybct_ptr,cmdbuf)==FAILURE) {
+ efree(cmdbuf);
+ RETURN_FALSE;
+ } else {
+ efree(cmdbuf);
+ RETURN_TRUE;
+ }
+}
+
+
+static sybct_result * _php3_sybct_fetch_result_set (sybct_link *sybct_ptr)
+{
+ int num_fields;
+ sybct_result *result;
+ char **tmp_buffer;
+ CS_INT *lengths;
+ CS_SMALLINT *indicators;
+ unsigned char *numerics;
+ CS_INT *types;
+ CS_DATAFMT *datafmt;
+ int i,j,retcode;
+ int blocks_initialized=1;
+
+ /* The following is more or less the equivalent of mysql_store_result().
+ * fetch all rows from the server into the row buffer, thus:
+ * 1) Being able to fire up another query without explicitly reading all rows
+ * 2) Having numrows accessible
+ */
+
+ if (ct_res_info(sybct_ptr->cmd, CS_NUMDATA, &num_fields, CS_UNUSED, NULL)!=CS_SUCCEED) {
+ return NULL;
+ }
+
+ result = (sybct_result *) emalloc(sizeof(sybct_result));
+ result->data = (pval **) emalloc(sizeof(pval *)*SYBASE_ROWS_BLOCK);
+ result->fields = NULL;
+ result->sybct_ptr = sybct_ptr;
+ result->cur_field=result->cur_row=result->num_rows=0;
+ result->num_fields = num_fields;
+
+ tmp_buffer = (char **) emalloc(sizeof(char *)*num_fields);
+ lengths = (CS_INT *) emalloc(sizeof(CS_INT)*num_fields);
+ indicators = (CS_SMALLINT *) emalloc(sizeof(CS_INT)*num_fields);
+ datafmt = (CS_DATAFMT *) emalloc(sizeof(CS_DATAFMT)*num_fields);
+ numerics = (unsigned char *) emalloc(sizeof(unsigned char)*num_fields);
+ types = (CS_INT *) emalloc(sizeof(CS_INT)*num_fields);
+
+
+ for (i=0; i<num_fields; i++) {
+ ct_describe(sybct_ptr->cmd,i+1,&datafmt[i]);
+ types[i] = datafmt[i].datatype;
+ switch (datafmt[i].datatype) {
+ case CS_CHAR_TYPE:
+ case CS_VARCHAR_TYPE:
+ case CS_TEXT_TYPE:
+ case CS_IMAGE_TYPE:
+ datafmt[i].maxlength++;
+ numerics[i] = 0;
+ break;
+ case CS_BINARY_TYPE:
+ case CS_VARBINARY_TYPE:
+ datafmt[i].maxlength *= 2;
+ datafmt[i].maxlength++;
+ numerics[i] = 0;
+ break;
+ case CS_BIT_TYPE:
+ case CS_TINYINT_TYPE:
+ datafmt[i].maxlength = 4;
+ numerics[i] = 1;
+ break;
+ case CS_SMALLINT_TYPE:
+ datafmt[i].maxlength = 7;
+ numerics[i] = 1;
+ break;
+ case CS_INT_TYPE:
+ datafmt[i].maxlength = 12;
+ numerics[i] = 1;
+ break;
+ case CS_REAL_TYPE:
+ case CS_FLOAT_TYPE:
+ datafmt[i].maxlength = 24;
+ numerics[i] = 1;
+ break;
+ case CS_MONEY_TYPE:
+ case CS_MONEY4_TYPE:
+ datafmt[i].maxlength = 24;
+ numerics[i] = 0;
+ break;
+ case CS_DATETIME_TYPE:
+ case CS_DATETIME4_TYPE:
+ datafmt[i].maxlength = 30;
+ numerics[i] = 0;
+ break;
+ case CS_NUMERIC_TYPE:
+ case CS_DECIMAL_TYPE:
+ datafmt[i].maxlength = datafmt[i].precision + 3;
+ numerics[i] = 1;
+ break;
+ default:
+ datafmt[i].maxlength++;
+ numerics[i] = 0;
+ break;
+ }
+ tmp_buffer[i] = (char *)emalloc(datafmt[i].maxlength);
+ datafmt[i].datatype = CS_CHAR_TYPE;
+ datafmt[i].format = CS_FMT_NULLTERM;
+ ct_bind(sybct_ptr->cmd,i+1,&datafmt[i],tmp_buffer[i],&lengths[i],&indicators[i]);
+ }
+
+ while ((retcode=ct_fetch(sybct_ptr->cmd,CS_UNUSED,CS_UNUSED,CS_UNUSED,NULL))==CS_SUCCEED
+ || retcode==CS_ROW_FAIL) {
+ /*
+ if (retcode==CS_ROW_FAIL) {
+ php3_error(E_WARNING,"Sybase: Error reading row %d",result->num_rows);
+ }
+ */
+ i = result->num_rows++;
+ if (result->num_rows > blocks_initialized*SYBASE_ROWS_BLOCK) {
+ result->data = (pval **) erealloc(result->data,sizeof(pval *)*SYBASE_ROWS_BLOCK*(++blocks_initialized));
+ }
+ result->data[i] = (pval *) emalloc(sizeof(pval)*num_fields);
+ for (j=0; j<num_fields; j++) {
+ if (indicators[j] == -1) { /* null value */
+ var_reset(&result->data[i][j]);
+ } else {
+ result->data[i][j].value.str.len = lengths[j]-1; /* we don't need the NULL in the length */
+ result->data[i][j].value.str.val = estrndup(tmp_buffer[j],lengths[j]);
+ result->data[i][j].type = IS_STRING;
+ }
+ }
+ }
+
+ if (retcode != CS_END_DATA) {
+ _free_sybct_result(result);
+ result = NULL;
+ } else {
+ result->fields = (sybct_field *) emalloc(sizeof(sybct_field)*num_fields);
+ j=0;
+ for (i=0; i<num_fields; i++) {
+ char computed_buf[16];
+
+ if (datafmt[i].namelen>0) {
+ result->fields[i].name = estrndup(datafmt[i].name,datafmt[i].namelen);
+ } else {
+ if (j>0) {
+ snprintf(computed_buf,16,"computed%d",j);
+ } else {
+ strcpy(computed_buf,"computed");
+ }
+ result->fields[i].name = estrdup(computed_buf);
+ j++;
+ }
+ result->fields[i].column_source = empty_string;
+ result->fields[i].max_length = datafmt[i].maxlength-1;
+ result->fields[i].numeric = numerics[i];
+ result->fields[i].type = types[i];
+ }
+ }
+
+ efree(datafmt);
+ efree(lengths);
+ efree(indicators);
+ efree(numerics);
+ efree(types);
+ for (i=0; i<num_fields; i++) {
+ efree(tmp_buffer[i]);
+ }
+ efree(tmp_buffer);
+
+ return result;
+}
+
+
+void php3_sybct_query(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *query,*sybct_link_index;
+ int id,type;
+ sybct_link *sybct_ptr;
+ sybct_result *result;
+ CS_INT restype;
+ CS_RETCODE retcode;
+ enum {
+ Q_RESULT, /* Success with results. */
+ Q_SUCCESS, /* Success but no results. */
+ Q_FAILURE, /* Failure, no results. */
+ } status;
+
+ switch(ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &query)==FAILURE) {
+ RETURN_FALSE;
+ }
+ id = php3_sybct_module.default_link;
+ break;
+ case 2:
+ if (getParameters(ht, 2, &query, &sybct_link_index)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(sybct_link_index);
+ id = sybct_link_index->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ sybct_ptr = (sybct_link *) php3_list_find(id,&type);
+ if (type!=php3_sybct_module.le_link && type!=php3_sybct_module.le_plink) {
+ php3_error(E_WARNING,"%d is not a Sybase link index",id);
+ RETURN_FALSE;
+ }
+
+ convert_to_string(query);
+
+ /* Fail if we already marked this connection dead. */
+
+ if (sybct_ptr->dead) {
+ RETURN_FALSE;
+ }
+
+ /* Repeat until we don't deadlock. */
+
+ for (;;) {
+ result = NULL;
+ sybct_ptr->deadlock = 0;
+ sybct_ptr->affected_rows = 0;
+
+ /* On Solaris 11.5, ct_command() can be moved outside the
+ * loop, but not on Linux 11.0.
+ */
+ if (ct_command(sybct_ptr->cmd, CS_LANG_CMD, query->value.str.val, CS_NULLTERM, CS_UNUSED)!=CS_SUCCEED) {
+ /* If this didn't work, the connection is screwed but
+ * ct-lib might not set CS_CONSTAT_DEAD. So set our own
+ * flag. This happens sometimes when the database is restarted
+ * and/or its machine is rebooted, and ct_command() returns
+ * CS_BUSY for some reason.
+ */
+ sybct_ptr->dead = 1;
+ RETURN_FALSE;
+ }
+
+ if (ct_send(sybct_ptr->cmd)!=CS_SUCCEED) {
+ ct_cancel(NULL, sybct_ptr->cmd, CS_CANCEL_ALL);
+ sybct_ptr->dead = 1;
+ RETURN_FALSE;
+ }
+
+ /* Use the first result set or succeed/fail status and discard the
+ * others. Applications really shouldn't be making calls that
+ * return multiple result sets, but if they do then we need to
+ * properly read or cancel them or the connection will become
+ * unusable.
+ */
+ if (ct_results(sybct_ptr->cmd, &restype)!=CS_SUCCEED) {
+ ct_cancel(NULL, sybct_ptr->cmd, CS_CANCEL_ALL);
+ sybct_ptr->dead = 1;
+ RETURN_FALSE;
+ }
+
+ switch ((int) restype) {
+ case CS_CMD_FAIL:
+ default:
+ status = Q_FAILURE;
+ break;
+ case CS_CMD_SUCCEED:
+ case CS_CMD_DONE: {
+ CS_INT row_count;
+ if (ct_res_info(sybct_ptr->cmd, CS_ROW_COUNT, &row_count, CS_UNUSED, NULL)==CS_SUCCEED) {
+ sybct_ptr->affected_rows = (long)row_count;
+ }
+ }
+ /* Fall through */
+ case CS_COMPUTEFMT_RESULT:
+ case CS_ROWFMT_RESULT:
+ case CS_DESCRIBE_RESULT:
+ case CS_MSG_RESULT:
+ status = Q_SUCCESS;
+ break;
+ case CS_COMPUTE_RESULT:
+ case CS_CURSOR_RESULT:
+ case CS_PARAM_RESULT:
+ case CS_ROW_RESULT:
+ case CS_STATUS_RESULT:
+ result = _php3_sybct_fetch_result_set(sybct_ptr);
+ if (result == NULL) {
+ ct_cancel(NULL, sybct_ptr->cmd, CS_CANCEL_ALL);
+ sybct_ptr->dead = 1;
+ RETURN_FALSE;
+ }
+ status = Q_RESULT;
+ break;
+ }
+
+ /* The only restype we should get now is CS_CMD_DONE, possibly
+ * followed by a CS_STATUS_RESULT/CS_CMD_SUCCEED/CS_CMD_DONE
+ * sequence if the command was a stored procedure call. But we
+ * still need to read and discard unexpected results. We might
+ * want to return a failure in this case because the application
+ * won't be getting all the results it asked for.
+ */
+ while ((retcode = ct_results(sybct_ptr->cmd, &restype))==CS_SUCCEED) {
+ switch ((int) restype) {
+ case CS_CMD_SUCCEED:
+ case CS_CMD_DONE:
+ break;
+
+ case CS_CMD_FAIL:
+ status = Q_FAILURE;
+ break;
+
+ case CS_COMPUTE_RESULT:
+ case CS_CURSOR_RESULT:
+ case CS_PARAM_RESULT:
+ case CS_ROW_RESULT:
+ /* Unexpected results, cancel them. */
+ case CS_STATUS_RESULT:
+ ct_cancel(NULL, sybct_ptr->cmd, CS_CANCEL_CURRENT);
+ break;
+
+ default:
+ status = Q_FAILURE;
+ break;
+ }
+ if (status == Q_FAILURE) {
+ ct_cancel(NULL, sybct_ptr->cmd, CS_CANCEL_ALL);
+ }
+ }
+
+ switch (retcode) {
+ case CS_END_RESULTS:
+ /* Normal. */
+ break;
+
+ case CS_FAIL:
+ /* Hopefully this either cleans up the connection, or the
+ * connection ends up marked dead so it will be reopened
+ * if it is persistent. We may want to do
+ * ct_close(CS_FORCE_CLOSE) if ct_cancel() fails; see the
+ * doc for ct_results()==CS_FAIL.
+ */
+ ct_cancel(NULL, sybct_ptr->cmd, CS_CANCEL_ALL);
+ /* Don't take chances with the vagaries of ct-lib. Mark it
+ * dead ourselves.
+ */
+ sybct_ptr->dead = 1;
+ case CS_CANCELED:
+ default:
+ status = Q_FAILURE;
+ break;
+ }
+
+ /* If query completed without deadlock, break out of the loop.
+ * Sometimes deadlock results in failures and sometimes not,
+ * it seems to depend on the server flavor. But we want to
+ * retry all deadlocks.
+ */
+ if (sybct_ptr->dead || sybct_ptr->deadlock == 0) {
+ break;
+ }
+
+ /* Get rid of any results we may have fetched. This happens:
+ * e.g., our result set may be a stored procedure status which
+ * is returned even if the stored procedure deadlocks. As an
+ * optimization, we could try not to fetch results in known
+ * deadlock conditions, but deadlock is (should be) rare.
+ */
+ if (result != NULL) {
+ _free_sybct_result(result);
+ }
+ }
+
+ if (status == Q_SUCCESS) {
+ RETURN_TRUE;
+ }
+
+ if (status == Q_FAILURE) {
+ if (result != NULL) {
+ _free_sybct_result(result);
+ }
+ RETURN_FALSE;
+ }
+
+ return_value->value.lval = php3_list_insert(result,php3_sybct_module.le_result);
+ return_value->type = IS_LONG;
+}
+
+
+void php3_sybct_free_result(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *sybct_result_index;
+ sybct_result *result;
+ int type;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &sybct_result_index)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(sybct_result_index);
+ if (sybct_result_index->value.lval==0) {
+ RETURN_FALSE;
+ }
+ result = (sybct_result *) php3_list_find(sybct_result_index->value.lval,&type);
+
+ if (type!=php3_sybct_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",sybct_result_index->value.lval);
+ RETURN_FALSE;
+ }
+ php3_list_delete(sybct_result_index->value.lval);
+ RETURN_TRUE;
+}
+
+
+#if 0
+void php3_sybct_get_last_message(INTERNAL_FUNCTION_PARAMETERS)
+{
+ if (php3_sybct_module.server_message) {
+ RETURN_STRING(php3_sybct_module.server_message,1);
+ }
+}
+#endif
+
+
+void php3_sybct_num_rows(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *result_index;
+ int type,id;
+ sybct_result *result;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &result_index)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(result_index);
+ id = result_index->value.lval;
+
+ result = (sybct_result *) php3_list_find(id,&type);
+ if (type!=php3_sybct_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",id);
+ RETURN_FALSE;
+ }
+
+ return_value->value.lval = result->num_rows;
+ return_value->type = IS_LONG;
+}
+
+
+void php3_sybct_num_fields(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *result_index;
+ int type,id;
+ sybct_result *result;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &result_index)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(result_index);
+ id = result_index->value.lval;
+
+ result = (sybct_result *) php3_list_find(id,&type);
+ if (type!=php3_sybct_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",id);
+ RETURN_FALSE;
+ }
+
+ return_value->value.lval = result->num_fields;
+ return_value->type = IS_LONG;
+}
+
+
+void php3_sybct_fetch_row(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *sybct_result_index;
+ int type,i,id;
+ sybct_result *result;
+ pval field_content;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &sybct_result_index)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(sybct_result_index);
+ id = sybct_result_index->value.lval;
+
+ result = (sybct_result *) php3_list_find(id,&type);
+ if (type!=php3_sybct_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",id);
+ RETURN_FALSE;
+ }
+
+ if (result->cur_row >= result->num_rows) {
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+ for (i=0; i<result->num_fields; i++) {
+ field_content = result->data[result->cur_row][i];
+ pval_copy_constructor(&field_content);
+ _php3_hash_index_update(return_value->value.ht, i, (void *) &field_content, sizeof(pval),NULL);
+ }
+ result->cur_row++;
+}
+
+
+static void php3_sybct_fetch_hash(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *sybct_result_index;
+ sybct_result *result;
+ int type;
+ int i;
+ pval *pval_ptr,tmp;
+ PLS_FETCH();
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &sybct_result_index)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(sybct_result_index);
+ result = (sybct_result *) php3_list_find(sybct_result_index->value.lval,&type);
+
+ if (type!=php3_sybct_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",sybct_result_index->value.lval);
+ RETURN_FALSE;
+ }
+
+ if (result->cur_row >= result->num_rows) {
+ RETURN_FALSE;
+ }
+
+ if (array_init(return_value)==FAILURE) {
+ RETURN_FALSE;
+ }
+
+ for (i=0; i<result->num_fields; i++) {
+ tmp = result->data[result->cur_row][i];
+ pval_copy_constructor(&tmp);
+ if (PG(magic_quotes_runtime) && tmp.type == IS_STRING) {
+ tmp.value.str.val = _php3_addslashes(tmp.value.str.val,tmp.value.str.len,&tmp.value.str.len,1);
+ }
+ _php3_hash_index_update(return_value->value.ht, i, (void *) &tmp, sizeof(pval), (void **) &pval_ptr);
+ _php3_hash_pointer_update(return_value->value.ht, result->fields[i].name, strlen(result->fields[i].name)+1, pval_ptr);
+ }
+ result->cur_row++;
+}
+
+
+void php3_sybct_fetch_object(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_sybct_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ if (return_value->type==IS_ARRAY) {
+ return_value->type=IS_OBJECT;
+ }
+}
+
+
+void php3_sybct_fetch_array(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_sybct_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+void php3_sybct_data_seek(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *sybct_result_index,*offset;
+ int type,id;
+ sybct_result *result;
+
+ if (ARG_COUNT(ht)!=2 || getParameters(ht, 2, &sybct_result_index, &offset)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(sybct_result_index);
+ id = sybct_result_index->value.lval;
+
+ result = (sybct_result *) php3_list_find(id,&type);
+ if (type!=php3_sybct_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",id);
+ RETURN_FALSE;
+ }
+
+ convert_to_long(offset);
+ if (offset->value.lval<0 || offset->value.lval>=result->num_rows) {
+ php3_error(E_WARNING,"Sybase: Bad row offset");
+ RETURN_FALSE;
+ }
+
+ result->cur_row = offset->value.lval;
+ RETURN_TRUE;
+}
+
+
+static char *php3_sybct_get_field_name(CS_INT type)
+{
+ switch (type) {
+ case CS_CHAR_TYPE:
+ case CS_VARCHAR_TYPE:
+ case CS_TEXT_TYPE:
+ return "string";
+ break;
+ case CS_IMAGE_TYPE:
+ return "image";
+ break;
+ case CS_BINARY_TYPE:
+ case CS_VARBINARY_TYPE:
+ return "blob";
+ break;
+ case CS_BIT_TYPE:
+ return "bit";
+ break;
+ case CS_TINYINT_TYPE:
+ case CS_SMALLINT_TYPE:
+ case CS_INT_TYPE:
+ return "int";
+ break;
+ case CS_REAL_TYPE:
+ case CS_FLOAT_TYPE:
+ case CS_NUMERIC_TYPE:
+ case CS_DECIMAL_TYPE:
+ return "real";
+ break;
+ case CS_MONEY_TYPE:
+ case CS_MONEY4_TYPE:
+ return "money";
+ break;
+ case CS_DATETIME_TYPE:
+ case CS_DATETIME4_TYPE:
+ return "datetime";
+ break;
+ default:
+ return "unknown";
+ break;
+ }
+}
+
+
+void php3_sybct_fetch_field(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *sybct_result_index,*offset;
+ int type,id,field_offset;
+ sybct_result *result;
+
+ switch (ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &sybct_result_index)==FAILURE) {
+ RETURN_FALSE;
+ }
+ field_offset=-1;
+ break;
+ case 2:
+ if (getParameters(ht, 2, &sybct_result_index, &offset)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(offset);
+ field_offset = offset->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ convert_to_long(sybct_result_index);
+ id = sybct_result_index->value.lval;
+
+ result = (sybct_result *) php3_list_find(id,&type);
+ if (type!=php3_sybct_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",id);
+ RETURN_FALSE;
+ }
+
+ if (field_offset==-1) {
+ field_offset = result->cur_field;
+ result->cur_field++;
+ }
+
+ if (field_offset<0 || field_offset >= result->num_fields) {
+ if (ARG_COUNT(ht)==2) { /* field specified explicitly */
+ php3_error(E_WARNING,"Sybase: Bad column offset");
+ }
+ RETURN_FALSE;
+ }
+
+ if (object_init(return_value)==FAILURE) {
+ RETURN_FALSE;
+ }
+ add_property_string(return_value, "name",result->fields[field_offset].name, 1);
+ add_property_long(return_value, "max_length",result->fields[field_offset].max_length);
+ add_property_string(return_value, "column_source",result->fields[field_offset].column_source, 1);
+ add_property_long(return_value, "numeric", result->fields[field_offset].numeric);
+ add_property_string(return_value, "type", php3_sybct_get_field_name(result->fields[field_offset].type), 1);
+}
+
+
+void php3_sybct_field_seek(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *sybct_result_index,*offset;
+ int type,id,field_offset;
+ sybct_result *result;
+
+ if (ARG_COUNT(ht)!=2 || getParameters(ht, 2, &sybct_result_index, &offset)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(sybct_result_index);
+ id = sybct_result_index->value.lval;
+
+ result = (sybct_result *) php3_list_find(id,&type);
+ if (type!=php3_sybct_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",id);
+ RETURN_FALSE;
+ }
+
+ convert_to_long(offset);
+ field_offset = offset->value.lval;
+
+ if (field_offset<0 || field_offset >= result->num_fields) {
+ php3_error(E_WARNING,"Sybase: Bad column offset");
+ RETURN_FALSE;
+ }
+
+ result->cur_field = field_offset;
+ RETURN_TRUE;
+}
+
+
+void php3_sybct_result(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *row, *field, *sybct_result_index;
+ int id,type,field_offset=0;
+ sybct_result *result;
+
+
+ if (ARG_COUNT(ht)!=3 || getParameters(ht, 3, &sybct_result_index, &row, &field)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(sybct_result_index);
+ id = sybct_result_index->value.lval;
+
+ result = (sybct_result *) php3_list_find(id,&type);
+ if (type!=php3_sybct_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",id);
+ RETURN_FALSE;
+ }
+
+ convert_to_long(row);
+ if (row->value.lval<0 || row->value.lval>=result->num_rows) {
+ php3_error(E_WARNING,"Sybase: Bad row offset (%d)",row->value.lval);
+ RETURN_FALSE;
+ }
+
+ switch(field->type) {
+ case IS_STRING: {
+ int i;
+
+ for (i=0; i<result->num_fields; i++) {
+ if (!strcasecmp(result->fields[i].name,field->value.str.val)) {
+ field_offset = i;
+ break;
+ }
+ }
+ if (i>=result->num_fields) { /* no match found */
+ php3_error(E_WARNING,"Sybase: %s field not found in result",field->value.str.val);
+ RETURN_FALSE;
+ }
+ break;
+ }
+ default:
+ convert_to_long(field);
+ field_offset = field->value.lval;
+ if (field_offset<0 || field_offset>=result->num_fields) {
+ php3_error(E_WARNING,"Sybase: Bad column offset specified");
+ RETURN_FALSE;
+ }
+ break;
+ }
+
+ *return_value = result->data[row->value.lval][field_offset];
+ pval_copy_constructor(return_value);
+}
+
+
+void php3_sybct_affected_rows(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *sybct_link_index;
+ int id,type;
+ sybct_link *sybct_ptr;
+ CS_INT row_count;
+
+ switch(ARG_COUNT(ht)) {
+ case 0:
+ id = php3_sybct_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ break;
+ case 1:
+ if (getParameters(ht, 1, &sybct_link_index)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(sybct_link_index);
+ id = sybct_link_index->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ sybct_ptr = (sybct_link *) php3_list_find(id,&type);
+ if (type!=php3_sybct_module.le_link && type!=php3_sybct_module.le_plink) {
+ php3_error(E_WARNING,"%d is not a Sybase link index",id);
+ RETURN_FALSE;
+ }
+
+ return_value->value.lval = sybct_ptr->affected_rows;
+ return_value->type = IS_LONG;
+}
+
+
+void php3_info_sybct(void)
+{
+ char maxp[16],maxl[16];
+
+ if (php3_sybct_module.max_persistent==-1) {
+ strcpy(maxp,"Unlimited");
+ } else {
+ snprintf(maxp,15,"%ld",php3_sybct_module.max_persistent);
+ maxp[15]=0;
+ }
+ if (php3_sybct_module.max_links==-1) {
+ strcpy(maxl,"Unlimited");
+ } else {
+ snprintf(maxl,15,"%ld",php3_sybct_module.max_links);
+ maxl[15]=0;
+ }
+ php3_printf("<table cellpadding=5>"
+ "<tr><td>Allow persistent links:</td><td>%s</td></tr>\n"
+ "<tr><td>Persistent links:</td><td>%d/%s</td></tr>\n"
+ "<tr><td>Total links:</td><td>%d/%s</td></tr>\n"
+ "<tr><td>Application name:</td><td>%s</td></tr>\n"
+ "</table>\n",
+ (php3_sybct_module.allow_persistent?"Yes":"No"),
+ php3_sybct_module.num_persistent,maxp,
+ php3_sybct_module.num_links,maxl,
+ php3_sybct_module.appname);
+}
+
+
+void php3_sybct_min_client_severity(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *severity;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &severity)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(severity);
+ php3_sybct_module.min_client_severity = severity->value.lval;
+}
+
+
+void php3_sybct_min_server_severity(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *severity;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &severity)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(severity);
+ php3_sybct_module.min_server_severity = severity->value.lval;
+}
+
+
+#endif
diff --git a/ext/sybase/sybase.c b/ext/sybase/sybase.c
new file mode 100644
index 0000000000..11d5fcd768
--- /dev/null
+++ b/ext/sybase/sybase.c
@@ -0,0 +1,1258 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Zeev Suraski <zeev@zend.com> |
+ +----------------------------------------------------------------------+
+ | php3_sybase_get_column_content_with_type() based on code by: |
+ | Muhammad A Muquit <MA_Muquit@fccc.edu> |
+ | Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+
+#ifndef MSVC5
+#include "config.h"
+#endif
+#include "php.h"
+#include "php3_sybase.h"
+#include "ext/standard/php3_standard.h"
+#include "php_globals.h"
+
+#if HAVE_SYBASE
+
+#include <sybfront.h>
+#include <sybdb.h>
+#include <syberror.h>
+
+#if BROKEN_SYBASE_PCONNECTS
+#include "http_log.h"
+#endif
+
+function_entry sybase_functions[] = {
+ {"sybase_connect", php3_sybase_connect, NULL},
+ {"sybase_pconnect", php3_sybase_pconnect, NULL},
+ {"sybase_close", php3_sybase_close, NULL},
+ {"sybase_select_db", php3_sybase_select_db, NULL},
+ {"sybase_query", php3_sybase_query, NULL},
+ {"sybase_free_result", php3_sybase_free_result, NULL},
+ {"sybase_get_last_message", php3_sybase_get_last_message, NULL},
+ {"sybase_num_rows", php3_sybase_num_rows, NULL},
+ {"sybase_num_fields", php3_sybase_num_fields, NULL},
+ {"sybase_fetch_row", php3_sybase_fetch_row, NULL},
+ {"sybase_fetch_array", php3_sybase_fetch_array, NULL},
+ {"sybase_fetch_object", php3_sybase_fetch_object, NULL},
+ {"sybase_data_seek", php3_sybase_data_seek, NULL},
+ {"sybase_fetch_field", php3_sybase_fetch_field, NULL},
+ {"sybase_field_seek", php3_sybase_field_seek, NULL},
+ {"sybase_result", php3_sybase_result, NULL},
+ {"sybase_min_error_severity", php3_sybase_min_error_severity, NULL},
+ {"sybase_min_message_severity", php3_sybase_min_message_severity, NULL},
+ {"mssql_connect", php3_sybase_connect, NULL},
+ {"mssql_pconnect", php3_sybase_pconnect, NULL},
+ {"mssql_close", php3_sybase_close, NULL},
+ {"mssql_select_db", php3_sybase_select_db, NULL},
+ {"mssql_query", php3_sybase_query, NULL},
+ {"mssql_free_result", php3_sybase_free_result, NULL},
+ {"mssql_get_last_message", php3_sybase_get_last_message, NULL},
+ {"mssql_num_rows", php3_sybase_num_rows, NULL},
+ {"mssql_num_fields", php3_sybase_num_fields, NULL},
+ {"mssql_fetch_row", php3_sybase_fetch_row, NULL},
+ {"mssql_fetch_array", php3_sybase_fetch_array, NULL},
+ {"mssql_fetch_object", php3_sybase_fetch_object, NULL},
+ {"mssql_data_seek", php3_sybase_data_seek, NULL},
+ {"mssql_fetch_field", php3_sybase_fetch_field, NULL},
+ {"mssql_field_seek", php3_sybase_field_seek, NULL},
+ {"mssql_result", php3_sybase_result, NULL},
+ {"mssql_min_error_severity", php3_sybase_min_error_severity, NULL},
+ {"mssql_min_message_severity", php3_sybase_min_message_severity, NULL},
+ {NULL, NULL, NULL}
+};
+
+php3_module_entry sybase_module_entry = {
+ "Sybase SQL", sybase_functions, php3_minit_sybase, php3_mshutdown_sybase, php3_rinit_sybase, php3_rshutdown_sybase, php3_info_sybase, STANDARD_MODULE_PROPERTIES
+};
+
+#if COMPILE_DL
+php3_module_entry *get_module() { return &sybase_module_entry; }
+#endif
+
+THREAD_LS sybase_module php3_sybase_module;
+THREAD_LS static HashTable *resource_list, *resource_plist;
+
+
+#define CHECK_LINK(link) { if (link==-1) { php3_error(E_WARNING,"Sybase: A link to the server could not be established"); RETURN_FALSE; } }
+
+
+static void php3_sybase_get_column_content(sybase_link *sybase_ptr,int offset,pval *result, int column_type);
+
+/* error handler */
+static int php3_sybase_error_handler(DBPROCESS *dbproc,int severity,int dberr,
+ int oserr,char *dberrstr,char *oserrstr)
+{
+ if (severity >= php3_sybase_module.min_error_severity) {
+ php3_error(E_WARNING,"Sybase error: %s (severity %d)",dberrstr,severity);
+ }
+ return INT_CANCEL;
+}
+
+/* message handler */
+static int php3_sybase_message_handler(DBPROCESS *dbproc,DBINT msgno,int msgstate,
+ int severity,char *msgtext,char *srvname,
+ char *procname,DBUSMALLINT line)
+{
+ if (severity >= php3_sybase_module.min_message_severity) {
+ php3_error(E_WARNING,"Sybase message: %s (severity %d)",msgtext,severity);
+ }
+ STR_FREE(php3_sybase_module.server_message);
+ php3_sybase_module.server_message = estrdup(msgtext);
+ return 0;
+}
+
+
+static int _clean_invalid_results(list_entry *le)
+{
+ if (le->type == php3_sybase_module.le_result) {
+ sybase_link *sybase_ptr = ((sybase_result *) le->ptr)->sybase_ptr;
+
+ if (!sybase_ptr->valid) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+static void _free_sybase_result(sybase_result *result)
+{
+ int i,j;
+
+ if (result->data) {
+ for (i=0; i<result->num_rows; i++) {
+ for (j=0; j<result->num_fields; j++) {
+ pval_destructor(&result->data[i][j]);
+ }
+ efree(result->data[i]);
+ }
+ efree(result->data);
+ }
+
+ if (result->fields) {
+ for (i=0; i<result->num_fields; i++) {
+ STR_FREE(result->fields[i].name);
+ STR_FREE(result->fields[i].column_source);
+ }
+ efree(result->fields);
+ }
+ efree(result);
+}
+
+
+static void _close_sybase_link(sybase_link *sybase_ptr)
+{
+ sybase_ptr->valid = 0;
+ _php3_hash_apply(resource_list,(int (*)(void *))_clean_invalid_results);
+ dbclose(sybase_ptr->link);
+ dbloginfree(sybase_ptr->login);
+ efree(sybase_ptr);
+ php3_sybase_module.num_links--;
+}
+
+
+static void _close_sybase_plink(sybase_link *sybase_ptr)
+{
+ dbclose(sybase_ptr->link);
+ dbloginfree(sybase_ptr->login);
+ free(sybase_ptr);
+ php3_sybase_module.num_persistent--;
+ php3_sybase_module.num_links--;
+}
+
+
+int php3_minit_sybase(INIT_FUNC_ARGS)
+{
+ char *interface_file;
+
+ if (dbinit()==FAIL) {
+ return FAILURE;
+ }
+ dberrhandle((EHANDLEFUNC) php3_sybase_error_handler);
+ dbmsghandle((MHANDLEFUNC) php3_sybase_message_handler);
+
+ if (cfg_get_string("sybase.interface_file",&interface_file)==SUCCESS) {
+ dbsetifile(interface_file);
+ }
+ if (cfg_get_long("sybase.allow_persistent",&php3_sybase_module.allow_persistent)==FAILURE) {
+ php3_sybase_module.allow_persistent=1;
+ }
+ if (cfg_get_long("sybase.max_persistent",&php3_sybase_module.max_persistent)==FAILURE) {
+ php3_sybase_module.max_persistent=-1;
+ }
+ if (cfg_get_long("sybase.max_links",&php3_sybase_module.max_links)==FAILURE) {
+ php3_sybase_module.max_links=-1;
+ }
+ if (cfg_get_long("sybase.min_error_severity",&php3_sybase_module.cfg_min_error_severity)==FAILURE) {
+ php3_sybase_module.cfg_min_error_severity=10;
+ }
+ if (cfg_get_long("sybase.min_message_severity",&php3_sybase_module.cfg_min_message_severity)==FAILURE) {
+ php3_sybase_module.cfg_min_message_severity=10;
+ }
+ if (cfg_get_long("sybase.compatability_mode",&php3_sybase_module.compatability_mode)==FAILURE) {
+ php3_sybase_module.compatability_mode = 0;
+ }
+
+ php3_sybase_module.num_persistent=0;
+ php3_sybase_module.le_link = register_list_destructors(_close_sybase_link,NULL);
+ php3_sybase_module.le_plink = register_list_destructors(NULL,_close_sybase_plink);
+ php3_sybase_module.le_result = register_list_destructors(_free_sybase_result,NULL);
+
+ return SUCCESS;
+}
+
+
+int php3_rinit_sybase(INIT_FUNC_ARGS)
+{
+ php3_sybase_module.default_link=-1;
+ php3_sybase_module.num_links = php3_sybase_module.num_persistent;
+ php3_sybase_module.appname = estrndup("PHP 3.0",7);
+ php3_sybase_module.server_message = empty_string;
+ php3_sybase_module.min_error_severity = php3_sybase_module.cfg_min_error_severity;
+ php3_sybase_module.min_message_severity = php3_sybase_module.cfg_min_message_severity;
+ return SUCCESS;
+}
+
+int php3_mshutdown_sybase(SHUTDOWN_FUNC_ARGS)
+{
+ dbexit();
+ return SUCCESS;
+}
+
+int php3_rshutdown_sybase(SHUTDOWN_FUNC_ARGS)
+{
+ efree(php3_sybase_module.appname);
+ STR_FREE(php3_sybase_module.server_message);
+ return SUCCESS;
+}
+
+static void php3_sybase_do_connect(INTERNAL_FUNCTION_PARAMETERS,int persistent)
+{
+ char *user,*passwd,*host;
+ char *hashed_details;
+ int hashed_details_length;
+ sybase_link sybase,*sybase_ptr;
+
+ resource_list = list;
+ resource_plist = plist;
+
+ switch(ARG_COUNT(ht)) {
+ case 0: /* defaults */
+ host=user=passwd=NULL;
+ hashed_details_length=6+3;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ strcpy(hashed_details,"sybase___");
+ break;
+ case 1: {
+ pval *yyhost;
+
+ if (getParameters(ht, 1, &yyhost)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string(yyhost);
+ host = yyhost->value.str.val;
+ user=passwd=NULL;
+ hashed_details_length = yyhost->value.str.len+6+3;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details,"sybase_%s__",yyhost->value.str.val);
+ }
+ break;
+ case 2: {
+ pval *yyhost,*yyuser;
+
+ if (getParameters(ht, 2, &yyhost, &yyuser)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string(yyhost);
+ convert_to_string(yyuser);
+ host = yyhost->value.str.val;
+ user = yyuser->value.str.val;
+ passwd=NULL;
+ hashed_details_length = yyhost->value.str.len+yyuser->value.str.len+6+3;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details,"sybase_%s_%s_",yyhost->value.str.val,yyuser->value.str.val);
+ }
+ break;
+ case 3: {
+ pval *yyhost,*yyuser,*yypasswd;
+
+ if (getParameters(ht, 3, &yyhost, &yyuser, &yypasswd) == FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string(yyhost);
+ convert_to_string(yyuser);
+ convert_to_string(yypasswd);
+ host = yyhost->value.str.val;
+ user = yyuser->value.str.val;
+ passwd = yypasswd->value.str.val;
+ hashed_details_length = yyhost->value.str.len+yyuser->value.str.len+yypasswd->value.str.len+6+3;
+ hashed_details = (char *) emalloc(hashed_details_length+1);
+ sprintf(hashed_details,"sybase_%s_%s_%s",yyhost->value.str.val,yyuser->value.str.val,yypasswd->value.str.val); /* SAFE */
+ }
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+
+ /* set a DBLOGIN record */
+ if ((sybase.login=dblogin())==NULL) {
+ php3_error(E_WARNING,"Sybase: Unable to allocate login record");
+ RETURN_FALSE;
+ }
+
+ if (user) {
+ DBSETLUSER(sybase.login,user);
+ }
+ if (passwd) {
+ DBSETLPWD(sybase.login,passwd);
+ }
+ DBSETLAPP(sybase.login,php3_sybase_module.appname);
+ sybase.valid = 1;
+
+ if (!php3_sybase_module.allow_persistent) {
+ persistent=0;
+ }
+ if (persistent) {
+ list_entry *le;
+
+ /* try to find if we already have this link in our persistent list */
+ if (_php3_hash_find(plist, hashed_details, hashed_details_length+1, (void **) &le)==FAILURE) { /* we don't */
+ list_entry new_le;
+
+ if (php3_sybase_module.max_links!=-1 && php3_sybase_module.num_links>=php3_sybase_module.max_links) {
+ php3_error(E_WARNING,"Sybase: Too many open links (%d)",php3_sybase_module.num_links);
+ efree(hashed_details);
+ dbloginfree(sybase.login);
+ RETURN_FALSE;
+ }
+ if (php3_sybase_module.max_persistent!=-1 && php3_sybase_module.num_persistent>=php3_sybase_module.max_persistent) {
+ php3_error(E_WARNING,"Sybase: Too many open persistent links (%d)",php3_sybase_module.num_persistent);
+ efree(hashed_details);
+ dbloginfree(sybase.login);
+ RETURN_FALSE;
+ }
+ /* create the link */
+ if ((sybase.link=dbopen(sybase.login,host))==FAIL) {
+ /*php3_error(E_WARNING,"Sybase: Unable to connect to server: %s",sybase_error(sybase));*/
+ efree(hashed_details);
+ dbloginfree(sybase.login);
+ RETURN_FALSE;
+ }
+
+ if (dbsetopt(sybase.link,DBBUFFER,"2",-1)==FAIL) {
+ efree(hashed_details);
+ dbloginfree(sybase.login);
+ dbclose(sybase.link);
+ RETURN_FALSE;
+ }
+
+ /* hash it up */
+ sybase_ptr = (sybase_link *) malloc(sizeof(sybase_link));
+ memcpy(sybase_ptr,&sybase,sizeof(sybase_link));
+ new_le.type = php3_sybase_module.le_plink;
+ new_le.ptr = sybase_ptr;
+ if (_php3_hash_update(plist, hashed_details, hashed_details_length+1, (void *) &new_le, sizeof(list_entry),NULL)==FAILURE) {
+ free(sybase_ptr);
+ efree(hashed_details);
+ dbloginfree(sybase.login);
+ RETURN_FALSE;
+ }
+ php3_sybase_module.num_persistent++;
+ php3_sybase_module.num_links++;
+ } else { /* we do */
+ if (le->type != php3_sybase_module.le_plink) {
+#if BROKEN_SYBASE_PCONNECTS
+ log_error("PHP/Sybase: Hashed persistent link is not a Sybase link!",php3_rqst->server);
+#endif
+ php3_error(E_WARNING,"Sybase: Hashed persistent link is not a Sybase link!");
+ RETURN_FALSE;
+ }
+
+ sybase_ptr = (sybase_link *) le->ptr;
+ /* test that the link hasn't died */
+ if (DBDEAD(sybase_ptr->link)==TRUE) {
+#if BROKEN_SYBASE_PCONNECTS
+ log_error("PHP/Sybase: Persistent link died, trying to reconnect...",php3_rqst->server);
+#endif
+ if ((sybase_ptr->link=dbopen(sybase_ptr->login,host))==FAIL) {
+#if BROKEN_SYBASE_PCONNECTS
+ log_error("PHP/Sybase: Unable to reconnect!",php3_rqst->server);
+#endif
+ /*php3_error(E_WARNING,"Sybase: Link to server lost, unable to reconnect");*/
+ _php3_hash_del(plist, hashed_details, hashed_details_length+1);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+#if BROKEN_SYBASE_PCONNECTS
+ log_error("PHP/Sybase: Reconnect successful!",php3_rqst->server);
+#endif
+ if (dbsetopt(sybase_ptr->link,DBBUFFER,"2",-1)==FAIL) {
+#if BROKEN_SYBASE_PCONNECTS
+ log_error("PHP/Sybase: Unable to set required options",php3_rqst->server);
+#endif
+ _php3_hash_del(plist, hashed_details, hashed_details_length+1);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ }
+ }
+ return_value->value.lval = php3_list_insert(sybase_ptr,php3_sybase_module.le_plink);
+ return_value->type = IS_LONG;
+ } else { /* non persistent */
+ list_entry *index_ptr,new_index_ptr;
+
+ /* first we check the hash for the hashed_details key. if it exists,
+ * it should point us to the right offset where the actual sybase link sits.
+ * if it doesn't, open a new sybase link, add it to the resource list,
+ * and add a pointer to it with hashed_details as the key.
+ */
+ if (_php3_hash_find(list,hashed_details,hashed_details_length+1,(void **) &index_ptr)==SUCCESS) {
+ int type,link;
+ void *ptr;
+
+ if (index_ptr->type != le_index_ptr) {
+ RETURN_FALSE;
+ }
+ link = (int) index_ptr->ptr;
+ ptr = php3_list_find(link,&type); /* check if the link is still there */
+ if (ptr && (type==php3_sybase_module.le_link || type==php3_sybase_module.le_plink)) {
+ return_value->value.lval = php3_sybase_module.default_link = link;
+ return_value->type = IS_LONG;
+ efree(hashed_details);
+ return;
+ } else {
+ _php3_hash_del(list,hashed_details,hashed_details_length+1);
+ }
+ }
+ if (php3_sybase_module.max_links!=-1 && php3_sybase_module.num_links>=php3_sybase_module.max_links) {
+ php3_error(E_WARNING,"Sybase: Too many open links (%d)",php3_sybase_module.num_links);
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ if ((sybase.link=dbopen(sybase.login,host))==NULL) {
+ /*php3_error(E_WARNING,"Sybase: Unable to connect to server: %s",sybase_error(sybase));*/
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+
+ if (dbsetopt(sybase.link,DBBUFFER,"2",-1)==FAIL) {
+ efree(hashed_details);
+ dbloginfree(sybase.login);
+ dbclose(sybase.link);
+ RETURN_FALSE;
+ }
+
+ /* add it to the list */
+ sybase_ptr = (sybase_link *) emalloc(sizeof(sybase_link));
+ memcpy(sybase_ptr,&sybase,sizeof(sybase_link));
+ return_value->value.lval = php3_list_insert(sybase_ptr,php3_sybase_module.le_link);
+ return_value->type = IS_LONG;
+
+ /* add it to the hash */
+ new_index_ptr.ptr = (void *) return_value->value.lval;
+ new_index_ptr.type = le_index_ptr;
+ if (_php3_hash_update(list,hashed_details,hashed_details_length+1,(void *) &new_index_ptr, sizeof(list_entry),NULL)==FAILURE) {
+ efree(hashed_details);
+ RETURN_FALSE;
+ }
+ php3_sybase_module.num_links++;
+ }
+ efree(hashed_details);
+ php3_sybase_module.default_link=return_value->value.lval;
+}
+
+
+static int php3_sybase_get_default_link(INTERNAL_FUNCTION_PARAMETERS)
+{
+ if (php3_sybase_module.default_link==-1) { /* no link opened yet, implicitly open one */
+ HashTable dummy;
+
+ _php3_hash_init(&dummy,0,NULL,NULL,0);
+ php3_sybase_do_connect(&dummy,return_value,list,plist,0);
+ _php3_hash_destroy(&dummy);
+ }
+ return php3_sybase_module.default_link;
+}
+
+
+void php3_sybase_connect(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_sybase_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
+}
+
+void php3_sybase_pconnect(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_sybase_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
+}
+
+
+void php3_sybase_close(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *sybase_link_index;
+ int id,type;
+
+ switch (ARG_COUNT(ht)) {
+ case 0:
+ id = php3_sybase_module.default_link;
+ break;
+ case 1:
+ if (getParameters(ht, 1, &sybase_link_index)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(sybase_link_index);
+ id = sybase_link_index->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ php3_list_find(id,&type);
+ if (type!=php3_sybase_module.le_link && type!=php3_sybase_module.le_plink) {
+ php3_error(E_WARNING,"%d is not a Sybase link index",id);
+ RETURN_FALSE;
+ }
+
+ php3_list_delete(id);
+ RETURN_TRUE;
+}
+
+
+void php3_sybase_select_db(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *db,*sybase_link_index;
+ int id,type;
+ sybase_link *sybase_ptr;
+
+ switch(ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &db)==FAILURE) {
+ RETURN_FALSE;
+ }
+ id = php3_sybase_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ break;
+ case 2:
+ if (getParameters(ht, 2, &db, &sybase_link_index)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(sybase_link_index);
+ id = sybase_link_index->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ CHECK_LINK(id);
+
+ sybase_ptr = (sybase_link *) php3_list_find(id,&type);
+ if (type!=php3_sybase_module.le_link && type!=php3_sybase_module.le_plink) {
+ php3_error(E_WARNING,"%d is not a Sybase link index",id);
+ RETURN_FALSE;
+ }
+
+ convert_to_string(db);
+
+ if (dbuse(sybase_ptr->link,db->value.str.val)==FAIL) {
+ /*php3_error(E_WARNING,"Sybase: Unable to select database: %s",sybase_error(sybase));*/
+ RETURN_FALSE;
+ } else {
+ RETURN_TRUE;
+ }
+}
+
+
+static void php3_sybase_get_column_content(sybase_link *sybase_ptr,int offset,pval *result, int column_type)
+{
+ if (dbdatlen(sybase_ptr->link,offset) == 0) {
+ var_reset(result);
+ return;
+ }
+
+ switch (column_type)
+ {
+ case SYBINT2:
+ case SYBINT4: {
+ result->value.lval = (long) anyintcol(offset);
+ result->type = IS_LONG;
+ break;
+ }
+ case SYBCHAR:
+ case SYBTEXT: {
+ int length;
+ char *data = charcol(offset);
+
+ length=dbdatlen(sybase_ptr->link,offset);
+ while (length>0 && charcol(offset)[length-1] == ' ') { /* nuke trailing whitespace */
+ length--;
+ }
+ result->value.str.val = estrndup(data,length);
+ result->value.str.len = length;
+ result->type = IS_STRING;
+ break;
+ }
+ /*case SYBFLT8:*/
+ case SYBREAL: {
+ result->value.dval = (double) floatcol(offset);
+ result->type = IS_DOUBLE;
+ break;
+ }
+ default: {
+ if (dbwillconvert(coltype(offset),SYBCHAR)) {
+ char *res_buf;
+ int res_length = dbdatlen(sybase_ptr->link,offset);
+ register char *p;
+
+ switch (coltype(offset)) {
+ case SYBBINARY:
+ case SYBVARBINARY:
+ case SYBCHAR:
+ case SYBVARCHAR:
+ case SYBTEXT:
+ case SYBIMAGE:
+ break;
+ default:
+ /* take no chances, no telling how big the result would really be */
+ res_length += 20;
+ break;
+ }
+
+ res_buf = (char *) emalloc(res_length+1);
+ dbconvert(NULL,coltype(offset),dbdata(sybase_ptr->link,offset), res_length,SYBCHAR,res_buf,-1);
+
+ /* get rid of trailing spaces */
+ p = res_buf + res_length;
+ while (*p == ' ') {
+ p--;
+ res_length--;
+ }
+ *(++p) = 0; /* put a trailing NULL */
+
+ result->value.str.len = res_length;
+ result->value.str.val = res_buf;
+ result->type = IS_STRING;
+ } else {
+ php3_error(E_WARNING,"Sybase: column %d has unknown data type (%d)", offset, coltype(offset));
+ var_reset(result);
+ }
+ }
+ }
+}
+
+
+void php3_sybase_query(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *query,*sybase_link_index;
+ int id,type,retvalue;
+ sybase_link *sybase_ptr;
+ sybase_result *result;
+ int num_fields;
+ int blocks_initialized=1;
+ int i,j;
+ int *column_types;
+
+ switch(ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &query)==FAILURE) {
+ RETURN_FALSE;
+ }
+ id = php3_sybase_module.default_link;
+ break;
+ case 2:
+ if (getParameters(ht, 2, &query, &sybase_link_index)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(sybase_link_index);
+ id = sybase_link_index->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ sybase_ptr = (sybase_link *) php3_list_find(id,&type);
+ if (type!=php3_sybase_module.le_link && type!=php3_sybase_module.le_plink) {
+ php3_error(E_WARNING,"%d is not a Sybase link index",id);
+ RETURN_FALSE;
+ }
+
+ convert_to_string(query);
+ if (dbcmd(sybase_ptr->link,query->value.str.val)==FAIL) {
+ /*php3_error(E_WARNING,"Sybase: Unable to set query");*/
+ RETURN_FALSE;
+ }
+ if (dbsqlexec(sybase_ptr->link)==FAIL || dbresults(sybase_ptr->link)==FAIL) {
+ /*php3_error(E_WARNING,"Sybase: Query failed");*/
+ RETURN_FALSE;
+ }
+
+ /* The following is more or less the equivalent of mysql_store_result().
+ * fetch all rows from the server into the row buffer, thus:
+ * 1) Being able to fire up another query without explicitly reading all rows
+ * 2) Having numrows accessible
+ */
+
+ retvalue=dbnextrow(sybase_ptr->link);
+
+ if (retvalue==FAIL) {
+ RETURN_FALSE;
+ }
+
+ num_fields = dbnumcols(sybase_ptr->link);
+ if (num_fields<=0) {
+ RETURN_TRUE;
+ }
+
+ column_types = (int *) emalloc(sizeof(int) * num_fields);
+ for (i=0; i<num_fields; i++) {
+ column_types[i] = coltype(i+1);
+ }
+
+ result = (sybase_result *) emalloc(sizeof(sybase_result));
+ result->data = (pval **) emalloc(sizeof(pval *)*SYBASE_ROWS_BLOCK);
+ result->sybase_ptr = sybase_ptr;
+ result->cur_field=result->cur_row=result->num_rows=0;
+ result->num_fields = num_fields;
+
+ i=0;
+ while (retvalue!=FAIL && retvalue!=NO_MORE_ROWS) {
+ result->num_rows++;
+ if (result->num_rows > blocks_initialized*SYBASE_ROWS_BLOCK) {
+ result->data = (pval **) erealloc(result->data,sizeof(pval *)*SYBASE_ROWS_BLOCK*(++blocks_initialized));
+ }
+ result->data[i] = (pval *) emalloc(sizeof(pval)*num_fields);
+ for (j=1; j<=num_fields; j++) {
+ php3_sybase_get_column_content(sybase_ptr, j, &result->data[i][j-1], column_types[j-1]);
+ if (!php3_sybase_module.compatability_mode) {
+ convert_to_string(&result->data[i][j-1]);
+ }
+ }
+ retvalue=dbnextrow(sybase_ptr->link);
+ dbclrbuf(sybase_ptr->link,DBLASTROW(sybase_ptr->link)-1);
+ i++;
+ }
+ result->num_rows = DBCOUNT(sybase_ptr->link);
+
+ result->fields = (sybase_field *) emalloc(sizeof(sybase_field)*num_fields);
+ j=0;
+ for (i=0; i<num_fields; i++) {
+ char *fname = dbcolname(sybase_ptr->link,i+1);
+ char computed_buf[16];
+
+ if (*fname) {
+ result->fields[i].name = estrdup(fname);
+ } else {
+ if (j>0) {
+ snprintf(computed_buf,16,"computed%d",j);
+ } else {
+ strcpy(computed_buf,"computed");
+ }
+ result->fields[i].name = estrdup(computed_buf);
+ j++;
+ }
+ result->fields[i].max_length = dbcollen(sybase_ptr->link,i+1);
+ result->fields[i].column_source = estrdup(dbcolsource(sybase_ptr->link,i+1));
+ if (!result->fields[i].column_source) {
+ result->fields[i].column_source = empty_string;
+ }
+ result->fields[i].type = column_types[i];
+ /* set numeric flag */
+ switch (column_types[i]) {
+ case SYBINT2:
+ case SYBINT4:
+ case SYBFLT8:
+ case SYBREAL:
+ result->fields[i].numeric = 1;
+ break;
+ case SYBCHAR:
+ case SYBTEXT:
+ default:
+ result->fields[i].numeric = 0;
+ break;
+ }
+ }
+ efree(column_types);
+ return_value->value.lval = php3_list_insert(result,php3_sybase_module.le_result);
+ return_value->type = IS_LONG;
+}
+
+
+void php3_sybase_free_result(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *sybase_result_index;
+ sybase_result *result;
+ int type;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &sybase_result_index)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(sybase_result_index);
+ if (sybase_result_index->value.lval==0) {
+ RETURN_FALSE;
+ }
+ result = (sybase_result *) php3_list_find(sybase_result_index->value.lval,&type);
+
+ if (type!=php3_sybase_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",sybase_result_index->value.lval);
+ RETURN_FALSE;
+ }
+ php3_list_delete(sybase_result_index->value.lval);
+ RETURN_TRUE;
+}
+
+
+void php3_sybase_get_last_message(INTERNAL_FUNCTION_PARAMETERS)
+{
+ RETURN_STRING(php3_sybase_module.server_message,1);
+}
+
+
+void php3_sybase_num_rows(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *result_index;
+ int type,id;
+ sybase_result *result;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &result_index)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(result_index);
+ id = result_index->value.lval;
+
+ result = (sybase_result *) php3_list_find(id,&type);
+ if (type!=php3_sybase_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",id);
+ RETURN_FALSE;
+ }
+
+ return_value->value.lval = result->num_rows;
+ return_value->type = IS_LONG;
+}
+
+
+void php3_sybase_num_fields(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *result_index;
+ int type,id;
+ sybase_result *result;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &result_index)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(result_index);
+ id = result_index->value.lval;
+
+ result = (sybase_result *) php3_list_find(id,&type);
+ if (type!=php3_sybase_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",id);
+ RETURN_FALSE;
+ }
+
+ return_value->value.lval = result->num_fields;
+ return_value->type = IS_LONG;
+}
+
+
+void php3_sybase_fetch_row(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *sybase_result_index;
+ int type,i,id;
+ sybase_result *result;
+ pval field_content;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &sybase_result_index)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(sybase_result_index);
+ id = sybase_result_index->value.lval;
+
+ result = (sybase_result *) php3_list_find(id,&type);
+ if (type!=php3_sybase_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",id);
+ RETURN_FALSE;
+ }
+
+ if (result->cur_row >= result->num_rows) {
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+ for (i=0; i<result->num_fields; i++) {
+ field_content = result->data[result->cur_row][i];
+ pval_copy_constructor(&field_content);
+ _php3_hash_index_update(return_value->value.ht, i, (void *) &field_content, sizeof(pval),NULL);
+ }
+ result->cur_row++;
+}
+
+
+static void php3_sybase_fetch_hash(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *sybase_result_index;
+ sybase_result *result;
+ int type;
+ int i;
+ pval *pval_ptr,tmp;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &sybase_result_index)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(sybase_result_index);
+ result = (sybase_result *) php3_list_find(sybase_result_index->value.lval,&type);
+
+ if (type!=php3_sybase_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",sybase_result_index->value.lval);
+ RETURN_FALSE;
+ }
+
+ if (result->cur_row >= result->num_rows) {
+ RETURN_FALSE;
+ }
+
+ if (array_init(return_value)==FAILURE) {
+ RETURN_FALSE;
+ }
+
+ for (i=0; i<result->num_fields; i++) {
+ tmp = result->data[result->cur_row][i];
+ pval_copy_constructor(&tmp);
+ if (PG(magic_quotes_runtime) && tmp.type == IS_STRING) {
+ tmp.value.str.val = _php3_addslashes(tmp.value.str.val,tmp.value.str.len,&tmp.value.str.len,1);
+ }
+ _php3_hash_index_update(return_value->value.ht, i, (void *) &tmp, sizeof(pval), (void **) &pval_ptr);
+ _php3_hash_pointer_update(return_value->value.ht, result->fields[i].name, strlen(result->fields[i].name)+1, pval_ptr);
+ }
+ result->cur_row++;
+}
+
+
+void php3_sybase_fetch_object(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_sybase_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ if (return_value->type==IS_ARRAY) {
+ return_value->type=IS_OBJECT;
+ }
+}
+
+
+void php3_sybase_fetch_array(INTERNAL_FUNCTION_PARAMETERS)
+{
+ php3_sybase_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+void php3_sybase_data_seek(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *sybase_result_index,*offset;
+ int type,id;
+ sybase_result *result;
+
+ if (ARG_COUNT(ht)!=2 || getParameters(ht, 2, &sybase_result_index, &offset)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(sybase_result_index);
+ id = sybase_result_index->value.lval;
+
+ result = (sybase_result *) php3_list_find(id,&type);
+ if (type!=php3_sybase_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",id);
+ RETURN_FALSE;
+ }
+
+ convert_to_long(offset);
+ if (offset->value.lval<0 || offset->value.lval>=result->num_rows) {
+ php3_error(E_WARNING,"Sybase: Bad row offset");
+ RETURN_FALSE;
+ }
+
+ result->cur_row = offset->value.lval;
+ RETURN_TRUE;
+}
+
+
+static char *php3_sybase_get_field_name(int type)
+{
+ switch (type) {
+ case SYBBINARY:
+ case SYBVARBINARY:
+ return "blob";
+ break;
+ case SYBCHAR:
+ case SYBVARCHAR:
+ case SYBTEXT:
+ return "string";
+ case SYBDATETIME:
+ case SYBDATETIME4:
+ case SYBDATETIMN:
+ return "datetime";
+ break;
+ case SYBDECIMAL:
+ case SYBFLT8:
+ case SYBFLTN:
+ case SYBREAL:
+ case SYBNUMERIC:
+ return "real";
+ break;
+ case SYBINT1:
+ case SYBINT2:
+ case SYBINT4:
+ case SYBINTN:
+ return "int";
+ break;
+ case SYBMONEY:
+ case SYBMONEY4:
+ case SYBMONEYN:
+ return "money";
+ break;
+ case SYBBIT:
+ return "bit";
+ break;
+ case SYBIMAGE:
+ return "image";
+ break;
+ default:
+ return "unknown";
+ break;
+ }
+}
+
+
+void php3_sybase_fetch_field(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *sybase_result_index,*offset;
+ int type,id,field_offset;
+ sybase_result *result;
+
+ switch (ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &sybase_result_index)==FAILURE) {
+ RETURN_FALSE;
+ }
+ field_offset=-1;
+ break;
+ case 2:
+ if (getParameters(ht, 2, &sybase_result_index, &offset)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(offset);
+ field_offset = offset->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ convert_to_long(sybase_result_index);
+ id = sybase_result_index->value.lval;
+
+ result = (sybase_result *) php3_list_find(id,&type);
+ if (type!=php3_sybase_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",id);
+ RETURN_FALSE;
+ }
+
+ if (field_offset==-1) {
+ field_offset = result->cur_field;
+ result->cur_field++;
+ }
+
+ if (field_offset<0 || field_offset >= result->num_fields) {
+ if (ARG_COUNT(ht)==2) { /* field specified explicitly */
+ php3_error(E_WARNING,"Sybase: Bad column offset");
+ }
+ RETURN_FALSE;
+ }
+
+ if (object_init(return_value)==FAILURE) {
+ RETURN_FALSE;
+ }
+ add_property_string(return_value, "name",result->fields[field_offset].name, 1);
+ add_property_long(return_value, "max_length",result->fields[field_offset].max_length);
+ add_property_string(return_value, "column_source",result->fields[field_offset].column_source, 1);
+ add_property_long(return_value, "numeric", result->fields[field_offset].numeric);
+ add_property_string(return_value, "type", php3_sybase_get_field_name(result->fields[field_offset].type), 1);
+}
+
+void php3_sybase_field_seek(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *sybase_result_index,*offset;
+ int type,id,field_offset;
+ sybase_result *result;
+
+ if (ARG_COUNT(ht)!=2 || getParameters(ht, 2, &sybase_result_index, &offset)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(sybase_result_index);
+ id = sybase_result_index->value.lval;
+
+ result = (sybase_result *) php3_list_find(id,&type);
+ if (type!=php3_sybase_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",id);
+ RETURN_FALSE;
+ }
+
+ convert_to_long(offset);
+ field_offset = offset->value.lval;
+
+ if (field_offset<0 || field_offset >= result->num_fields) {
+ php3_error(E_WARNING,"Sybase: Bad column offset");
+ RETURN_FALSE;
+ }
+
+ result->cur_field = field_offset;
+ RETURN_TRUE;
+}
+
+
+void php3_sybase_result(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *row, *field, *sybase_result_index;
+ int id,type,field_offset=0;
+ sybase_result *result;
+
+
+ if (ARG_COUNT(ht)!=3 || getParameters(ht, 3, &sybase_result_index, &row, &field)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(sybase_result_index);
+ id = sybase_result_index->value.lval;
+
+ result = (sybase_result *) php3_list_find(id,&type);
+ if (type!=php3_sybase_module.le_result) {
+ php3_error(E_WARNING,"%d is not a Sybase result index",id);
+ RETURN_FALSE;
+ }
+
+ convert_to_long(row);
+ if (row->value.lval<0 || row->value.lval>=result->num_rows) {
+ php3_error(E_WARNING,"Sybase: Bad row offset (%d)",row->value.lval);
+ RETURN_FALSE;
+ }
+
+ switch(field->type) {
+ case IS_STRING: {
+ int i;
+
+ for (i=0; i<result->num_fields; i++) {
+ if (!strcasecmp(result->fields[i].name,field->value.str.val)) {
+ field_offset = i;
+ break;
+ }
+ }
+ if (i>=result->num_fields) { /* no match found */
+ php3_error(E_WARNING,"Sybase: %s field not found in result",field->value.str.val);
+ RETURN_FALSE;
+ }
+ break;
+ }
+ default:
+ convert_to_long(field);
+ field_offset = field->value.lval;
+ if (field_offset<0 || field_offset>=result->num_fields) {
+ php3_error(E_WARNING,"Sybase: Bad column offset specified");
+ RETURN_FALSE;
+ }
+ break;
+ }
+
+ *return_value = result->data[row->value.lval][field_offset];
+ pval_copy_constructor(return_value);
+}
+
+
+void php3_info_sybase(void)
+{
+ char maxp[16],maxl[16];
+
+ if (php3_sybase_module.max_persistent==-1) {
+ strcpy(maxp,"Unlimited");
+ } else {
+ snprintf(maxp,15,"%ld",php3_sybase_module.max_persistent);
+ maxp[15]=0;
+ }
+ if (php3_sybase_module.max_links==-1) {
+ strcpy(maxl,"Unlimited");
+ } else {
+ snprintf(maxl,15,"%ld",php3_sybase_module.max_links);
+ maxl[15]=0;
+ }
+ php3_printf("<table cellpadding=5>"
+ "<tr><td>Allow persistent links:</td><td>%s</td></tr>\n"
+ "<tr><td>Persistent links:</td><td>%d/%s</td></tr>\n"
+ "<tr><td>Total links:</td><td>%d/%s</td></tr>\n"
+ "<tr><td>Application name:</td><td>%s</td></tr>\n"
+ "<tr><td valign=\"top\" width=\"20%%\">Client API information:</td><td><pre>%s</pre></td></tr>\n"
+ "</table>\n",
+ (php3_sybase_module.allow_persistent?"Yes":"No"),
+ php3_sybase_module.num_persistent,maxp,
+ php3_sybase_module.num_links,maxl,
+ php3_sybase_module.appname,
+ dbversion());
+}
+
+
+void php3_sybase_min_error_severity(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *severity;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &severity)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(severity);
+ php3_sybase_module.min_error_severity = severity->value.lval;
+}
+
+
+void php3_sybase_min_message_severity(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *severity;
+
+ if (ARG_COUNT(ht)!=1 || getParameters(ht, 1, &severity)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(severity);
+ php3_sybase_module.min_message_severity = severity->value.lval;
+}
+
+#endif
diff --git a/ext/sysvsem/Makefile.am b/ext/sysvsem/Makefile.am
new file mode 100644
index 0000000000..7ed09a0337
--- /dev/null
+++ b/ext/sysvsem/Makefile.am
@@ -0,0 +1,6 @@
+# $Id$
+
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_sysvsem.a
+libphpext_sysvsem_a_SOURCES=sysvsem.c
+
diff --git a/ext/sysvsem/Makefile.in b/ext/sysvsem/Makefile.in
new file mode 100644
index 0000000000..8563cb6e78
--- /dev/null
+++ b/ext/sysvsem/Makefile.in
@@ -0,0 +1,270 @@
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# $Id$
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+APACHE_INCLUDE = @APACHE_INCLUDE@
+APACHE_TARGET = @APACHE_TARGET@
+APXS = @APXS@
+APXS_LDFLAGS = @APXS_LDFLAGS@
+BINNAME = @BINNAME@
+CC = @CC@
+CFLAGS = @CFLAGS@
+CFLAGS_SHLIB = @CFLAGS_SHLIB@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+EXTINFO_DEPS = @EXTINFO_DEPS@
+EXTRA_LIBS = @EXTRA_LIBS@
+EXT_LIBS = @EXT_LIBS@
+EXT_SUBDIRS = @EXT_SUBDIRS@
+FHTTPD_LIB = @FHTTPD_LIB@
+FHTTPD_TARGET = @FHTTPD_TARGET@
+HSREGEX = @HSREGEX@
+INSTALL_IT = @INSTALL_IT@
+LDFLAGS_SHLIB = @LDFLAGS_SHLIB@
+LDFLAGS_SHLIB_EXPORT = @LDFLAGS_SHLIB_EXPORT@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+PERL_PATH = @PERL_PATH@
+PHP_BUILD_DATE = @PHP_BUILD_DATE@
+PHP_DEBUG = @PHP_DEBUG@
+PHP_LIBS = @PHP_LIBS@
+PHP_VERSION = @PHP_VERSION@
+PROG_SENDMAIL = @PROG_SENDMAIL@
+RANLIB = @RANLIB@
+RDYNAMIC_LFLAGS = @RDYNAMIC_LFLAGS@
+REGEX_LIB = @REGEX_LIB@
+STRONGHOLD = @STRONGHOLD@
+VERSION = @VERSION@
+WARNING_LEVEL = @WARNING_LEVEL@
+YACC = @YACC@
+
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_sysvsem.a
+libphpext_sysvsem_a_SOURCES=sysvsem.c
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libphpext_sysvsem_a_LIBADD =
+libphpext_sysvsem_a_OBJECTS = sysvsem.o
+AR = ar
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+SOURCES = $(libphpext_sysvsem_a_SOURCES)
+OBJECTS = $(libphpext_sysvsem_a_OBJECTS)
+
+all: Makefile $(LIBRARIES)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps ext/sysvsem/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+ $(COMPILE) -c $<
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libphpext_sysvsem.a: $(libphpext_sysvsem_a_OBJECTS) $(libphpext_sysvsem_a_DEPENDENCIES)
+ -rm -f libphpext_sysvsem.a
+ $(AR) cru libphpext_sysvsem.a $(libphpext_sysvsem_a_OBJECTS) $(libphpext_sysvsem_a_LIBADD)
+ $(RANLIB) libphpext_sysvsem.a
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = ext/sysvsem
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
+ done
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
+install-strip:
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+
+
+mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -rm -f Makefile $(DISTCLEANFILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-tags mostlyclean-generic
+
+clean: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+ mostlyclean
+
+distclean: distclean-noinstLIBRARIES distclean-compile distclean-tags \
+ distclean-generic clean
+ -rm -f config.status
+
+maintainer-clean: maintainer-clean-noinstLIBRARIES \
+ maintainer-clean-compile maintainer-clean-tags \
+ maintainer-clean-generic distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info dvi installcheck \
+install-exec install-data install uninstall all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/ext/sysvsem/config.h.stub b/ext/sysvsem/config.h.stub
new file mode 100644
index 0000000000..09634a8cfd
--- /dev/null
+++ b/ext/sysvsem/config.h.stub
@@ -0,0 +1,7 @@
+/* Define if you want System V semaphore support.
+ */
+#define HAVE_SYSVSEM 0
+
+/* Define if you have union semun.
+ */
+#define HAVE_SEMUN 0
diff --git a/ext/sysvsem/config.m4 b/ext/sysvsem/config.m4
new file mode 100644
index 0000000000..afdd602e30
--- /dev/null
+++ b/ext/sysvsem/config.m4
@@ -0,0 +1,37 @@
+dnl $Id$
+
+AC_MSG_CHECKING(whether to enable System V semaphore support)
+AC_ARG_ENABLE(sysvsem,
+[ --enable-sysvsem Enable System V semaphore support.],
+[
+ if test "$enableval" = "yes"; then
+ AC_MSG_RESULT(yes)
+ PHP_EXTENSION(sysvsem)
+ AC_DEFINE(HAVE_SYSVSEM, 1)
+ AC_CACHE_CHECK(for union semun,php_cv_semun,
+ AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+ ],
+ [union semun x;],
+ [
+ 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
+ else
+ AC_MSG_RESULT(no)
+ AC_DEFINE(HAVE_SYSVSEM, 0)
+ fi
+],[
+ AC_MSG_RESULT(no)
+ AC_DEFINE(HAVE_SYSVSEM, 0)
+])
+
diff --git a/ext/sysvsem/php3_sysvsem.h b/ext/sysvsem/php3_sysvsem.h
new file mode 100644
index 0000000000..fcb971dc96
--- /dev/null
+++ b/ext/sysvsem/php3_sysvsem.h
@@ -0,0 +1,74 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Tom May <tom@go2net.com> |
+ +----------------------------------------------------------------------+
+ */
+
+
+/* $Id$ */
+
+#ifndef _PHP3_SYSVSEM_H
+#define _PHP3_SYSVSEM_H
+
+#if COMPILE_DL
+#undef HAVE_SYSVSEM
+#define HAVE_SYSVSEM 1
+#endif
+
+#if HAVE_SYSVSEM
+
+extern php3_module_entry sysvsem_module_entry;
+#define sysvsem_module_ptr &sysvsem_module_entry
+
+extern int php3_minit_sysvsem(INIT_FUNC_ARGS);
+extern int php3_rinit_sysvsem(INIT_FUNC_ARGS);
+extern int php3_mshutdown_sysvsem(SHUTDOWN_FUNC_ARGS);
+extern int php3_rshutdown_sysvsem(SHUTDOWN_FUNC_ARGS);
+extern void php3_info_sysvsem(void);
+extern void php3_sysvsem_get(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sysvsem_acquire(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sysvsem_release(INTERNAL_FUNCTION_PARAMETERS);
+
+typedef struct {
+ int le_sem;
+} sysvsem_module;
+
+typedef struct {
+ int id; /* For error reporting. */
+ int key; /* For error reporting. */
+ int semid; /* Returned by semget(). */
+ int count; /* Acquire count for auto-release. */
+} sysvsem_sem;
+
+extern sysvsem_module php3_sysvsem_module;
+
+#else
+
+#define sysvsem_module_ptr NULL
+
+#endif
+
+#endif /* _PHP3_SYSVSEM_H */
diff --git a/ext/sysvsem/setup.stub b/ext/sysvsem/setup.stub
new file mode 100644
index 0000000000..cad1279592
--- /dev/null
+++ b/ext/sysvsem/setup.stub
@@ -0,0 +1,5 @@
+# $Source$
+# $Id$
+
+define_option enable-sysvsem 'System V semaphores support? ' yesno no \
+' Whether to use the System V semaphores (currently only solaris and linux).'
diff --git a/ext/sysvsem/sysvsem.c b/ext/sysvsem/sysvsem.c
new file mode 100644
index 0000000000..2c2a9ccbc0
--- /dev/null
+++ b/ext/sysvsem/sysvsem.c
@@ -0,0 +1,343 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Tom May <tom@go2net.com> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+/* This has been built and tested on Solaris 2.6 and Linux 2.1.122.
+ * It may not compile or execute correctly on other systems.
+ *
+ * sas: Works for me on Linux 2.0.36 and FreeBSD 3.0-current
+ */
+
+#ifndef MSVC5
+#include "config.h"
+#endif
+
+#if HAVE_SYSVSEM
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <errno.h>
+
+#include "php.h"
+#include "php3_sysvsem.h"
+
+
+function_entry sysvsem_functions[] = {
+ {"sem_get", php3_sysvsem_get, NULL},
+ {"sem_acquire", php3_sysvsem_acquire, NULL},
+ {"sem_release", php3_sysvsem_release, NULL},
+ {NULL, NULL, NULL}
+};
+
+php3_module_entry sysvsem_module_entry = {
+ "System V semaphores", sysvsem_functions, php3_minit_sysvsem, NULL, NULL, NULL, NULL, STANDARD_MODULE_PROPERTIES
+};
+
+#if COMPILE_DL
+php3_module_entry *get_module() { return &sysvsem_module_entry; }
+#endif
+
+
+THREAD_LS sysvsem_module php3_sysvsem_module;
+
+/* Semaphore functions using System V semaphores. Each semaphore
+ * actually consists of three semaphores allocated as a unit under the
+ * same key. Semaphore 0 (SYSVSEM_SEM) is the actual semaphore, it is
+ * initialized to max_acquire and decremented as processes acquire it.
+ * The value of semaphore 1 (SYSVSEM_USAGE) is a count of the number
+ * of processes using the semaphore. After calling semget(), if a
+ * process finds that the usage count is 1, it will set the value of
+ * SYSVSEM_SEM to max_acquire. This allows max_acquire to be set and
+ * track the PHP code without having a global init routine or external
+ * semaphore init code. Except see the bug regarding a race condition
+ * php3_sysvsem_get(). Semaphore 2 (SYSVSEM_SETVAL) serializes the
+ * calls to GETVAL SYSVSEM_USAGE and SETVAL SYSVSEM_SEM. It can be
+ * acquired only when it is zero.
+ */
+
+#define SYSVSEM_SEM 0
+#define SYSVSEM_USAGE 1
+#define SYSVSEM_SETVAL 2
+
+
+static void release_sysvsem_sem(sysvsem_sem *sem_ptr)
+{
+ struct sembuf sop[2];
+
+ /* Decrement the usage count. */
+
+ sop[0].sem_num = SYSVSEM_USAGE;
+ sop[0].sem_op = -1;
+ sop[0].sem_flg = SEM_UNDO;
+
+ /* Release the semaphore if it has been acquired but not released. */
+
+ if (sem_ptr->count) {
+ php3_error(E_WARNING, "Releasing SysV semaphore id %d key 0x%x in request cleanup", sem_ptr->id, sem_ptr->key);
+
+ sop[1].sem_num = SYSVSEM_SEM;
+ sop[1].sem_op = sem_ptr->count;
+ sop[1].sem_flg = SEM_UNDO;
+ }
+ if (semop(sem_ptr->semid, sop, sem_ptr->count ? 2 : 1) == -1) {
+ php3_error(E_WARNING, "semop() failed in release_sysvsem_sem for key 0x%x: %s", sem_ptr->key, strerror(errno));
+ }
+
+ efree(sem_ptr);
+}
+
+
+int php3_minit_sysvsem(INIT_FUNC_ARGS)
+{
+ php3_sysvsem_module.le_sem = register_list_destructors(release_sysvsem_sem, NULL);
+
+ return SUCCESS;
+}
+
+
+/* {{{ proto int sem_get(int key [, int max_acquire [, int perm]])
+ Return an id for the semaphore with the given key, and allow max_acquire (default 1) processes to acquire it simultaneously. */
+void php3_sysvsem_get(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *arg_key, *arg_max_acquire, *arg_perm;
+ int key, max_acquire, perm;
+ int semid;
+ struct sembuf sop[3];
+ int count;
+ sysvsem_sem *sem_ptr;
+#if HAVE_SEMUN
+ union semun un;
+#endif
+
+ max_acquire = 1;
+ perm = 0666;
+
+ switch (ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &arg_key)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(arg_key);
+ key = (int)arg_key->value.lval;
+ break;
+ case 2:
+ if (getParameters(ht, 2, &arg_key, &arg_max_acquire)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(arg_key);
+ key = (int)arg_key->value.lval;
+ convert_to_long(arg_max_acquire);
+ max_acquire = (int)arg_max_acquire->value.lval;
+ break;
+ case 3:
+ if (getParameters(ht, 3, &arg_key, &arg_max_acquire, &arg_perm)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(arg_key);
+ key = (int)arg_key->value.lval;
+ convert_to_long(arg_max_acquire);
+ max_acquire = (int)arg_max_acquire->value.lval;
+ convert_to_long(arg_perm);
+ perm = (int)arg_perm->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ /* Get/create the semaphore. Note that we rely on the semaphores
+ * being zeroed when they are created. Despite the fact that
+ * the(?) Linux semget() man page says they are not initialized,
+ * the kernel versions 2.0.x and 2.1.z do in fact zero them.
+ */
+
+ semid = semget(key, 3, perm|IPC_CREAT);
+ if (semid == -1) {
+ php3_error(E_WARNING, "semget() failed for key 0x%x: %s", key, strerror(errno));
+ RETURN_FALSE;
+ }
+
+ /* Find out how many processes are using this semaphore. Note
+ * that on Linux (at least) there is a race condition here because
+ * semaphore undo on process exit is not atomic, so we could
+ * acquire SYSVSEM_SETVAL before a crashed process has decremented
+ * SYSVSEM_USAGE in which case count will be greater than it
+ * should be and we won't set max_acquire. Fortunately this
+ * doesn't actually matter in practice.
+ */
+
+ /* Wait for sem 1 to be zero . . . */
+
+ sop[0].sem_num = SYSVSEM_SETVAL;
+ sop[0].sem_op = 0;
+ sop[0].sem_flg = 0;
+
+ /* . . . and increment it so it becomes non-zero . . . */
+
+ sop[1].sem_num = SYSVSEM_SETVAL;
+ sop[1].sem_op = 1;
+ sop[1].sem_flg = SEM_UNDO;
+
+ /* . . . and increment the usage count. */
+
+ sop[2].sem_num = SYSVSEM_USAGE;
+ sop[2].sem_op = 1;
+ sop[2].sem_flg = SEM_UNDO;
+ while (semop(semid, sop, 3) == -1) {
+ if (errno != EINTR) {
+ php3_error(E_WARNING, "semop() failed acquiring SYSVSEM_SETVAL for key 0x%x: %s", key, strerror(errno));
+ break;
+ }
+ }
+
+ /* Get the usage count. */
+#if HAVE_SEMUN
+ count = semctl(semid, SYSVSEM_USAGE, GETVAL, un);
+#else
+ count = semctl(semid, SYSVSEM_USAGE, GETVAL, NULL);
+#endif
+ if (count == -1) {
+ php3_error(E_WARNING, "semctl(GETVAL) failed for key 0x%x: %s", key, strerror(errno));
+ }
+
+ /* If we are the only user, then take this opportunity to set the max. */
+
+ if (count == 1) {
+#if HAVE_SEMUN
+ /* This is correct for Linux which has union semun. */
+ union semun semarg;
+ semarg.val = max_acquire;
+ if (semctl(semid, SYSVSEM_SEM, SETVAL, semarg) == -1) {
+ php3_error(E_WARNING, "semctl(SETVAL) failed for key 0x%x: %s", key, strerror(errno));
+ }
+#else
+ /* This is correct for Solaris 2.6 which does not have union semun. */
+ if (semctl(semid, SYSVSEM_SEM, SETVAL, &max_acquire) == -1) {
+ php3_error(E_WARNING, "semctl(SETVAL) failed for key 0x%x: %s", key, strerror(errno));
+ }
+#endif
+ }
+
+ /* Set semaphore 1 back to zero. */
+
+ sop[0].sem_num = SYSVSEM_SETVAL;
+ sop[0].sem_op = -1;
+ sop[0].sem_flg = SEM_UNDO;
+ while (semop(semid, sop, 1) == -1) {
+ if (errno != EINTR) {
+ php3_error(E_WARNING, "semop() failed releasing SYSVSEM_SETVAL for key 0x%x: %s", key, strerror(errno));
+ break;
+ }
+ }
+
+ sem_ptr = (sysvsem_sem *) emalloc(sizeof(sysvsem_sem));
+ sem_ptr->key = key;
+ sem_ptr->semid = semid;
+ sem_ptr->count = 0;
+
+ return_value->value.lval = php3_list_insert(sem_ptr, php3_sysvsem_module.le_sem);
+ return_value->type = IS_LONG;
+
+ sem_ptr->id = (int)return_value->value.lval;
+}
+/* }}} */
+
+static void _php3_sysvsem_semop(INTERNAL_FUNCTION_PARAMETERS, int acquire)
+{
+ pval *arg_id;
+ int id, type;
+ sysvsem_sem *sem_ptr;
+ struct sembuf sop;
+
+ switch(ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &arg_id)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(arg_id);
+ id = (int)arg_id->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ sem_ptr = (sysvsem_sem *) php3_list_find(id, &type);
+ if (type!=php3_sysvsem_module.le_sem) {
+ php3_error(E_WARNING, "%d is not a SysV semaphore index", id);
+ RETURN_FALSE;
+ }
+
+ if (!acquire && sem_ptr->count == 0) {
+ php3_error(E_WARNING, "SysV semaphore index %d (key 0x%x) is not currently acquired", id, sem_ptr->key);
+ RETURN_FALSE;
+ }
+
+ sop.sem_num = SYSVSEM_SEM;
+ sop.sem_op = acquire ? -1 : 1;
+ sop.sem_flg = SEM_UNDO;
+
+ while (semop(sem_ptr->semid, &sop, 1) == -1) {
+ if (errno != EINTR) {
+ php3_error(E_WARNING, "semop(%s) failed for key 0x%x: %s",
+ acquire ? "acquire" : "release", sem_ptr->key, strerror(errno));
+ RETURN_FALSE;
+ }
+ }
+
+ sem_ptr->count -= acquire ? -1 : 1;
+ RETURN_TRUE;
+}
+
+
+/* {{{ proto int sem_acquire(int id)
+ Acquires the semaphore with the given id, blocking if necessary. */
+void php3_sysvsem_acquire(INTERNAL_FUNCTION_PARAMETERS)
+{
+ _php3_sysvsem_semop(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ proto int sem_release(int id)
+ Releases the semaphore with the given id. */
+void php3_sysvsem_release(INTERNAL_FUNCTION_PARAMETERS)
+{
+ _php3_sysvsem_semop(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+#endif /* HAVE_SYSVSEM */
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/sysvshm/Makefile.am b/ext/sysvshm/Makefile.am
new file mode 100644
index 0000000000..9c759a02bb
--- /dev/null
+++ b/ext/sysvshm/Makefile.am
@@ -0,0 +1,6 @@
+# $Id$
+
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_sysvshm.a
+libphpext_sysvshm_a_SOURCES=sysvshm.c
+
diff --git a/ext/sysvshm/Makefile.in b/ext/sysvshm/Makefile.in
new file mode 100644
index 0000000000..27a168ca22
--- /dev/null
+++ b/ext/sysvshm/Makefile.in
@@ -0,0 +1,270 @@
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# $Id$
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+APACHE_INCLUDE = @APACHE_INCLUDE@
+APACHE_TARGET = @APACHE_TARGET@
+APXS = @APXS@
+APXS_LDFLAGS = @APXS_LDFLAGS@
+BINNAME = @BINNAME@
+CC = @CC@
+CFLAGS = @CFLAGS@
+CFLAGS_SHLIB = @CFLAGS_SHLIB@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+EXTINFO_DEPS = @EXTINFO_DEPS@
+EXTRA_LIBS = @EXTRA_LIBS@
+EXT_LIBS = @EXT_LIBS@
+EXT_SUBDIRS = @EXT_SUBDIRS@
+FHTTPD_LIB = @FHTTPD_LIB@
+FHTTPD_TARGET = @FHTTPD_TARGET@
+HSREGEX = @HSREGEX@
+INSTALL_IT = @INSTALL_IT@
+LDFLAGS_SHLIB = @LDFLAGS_SHLIB@
+LDFLAGS_SHLIB_EXPORT = @LDFLAGS_SHLIB_EXPORT@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+PERL_PATH = @PERL_PATH@
+PHP_BUILD_DATE = @PHP_BUILD_DATE@
+PHP_DEBUG = @PHP_DEBUG@
+PHP_LIBS = @PHP_LIBS@
+PHP_VERSION = @PHP_VERSION@
+PROG_SENDMAIL = @PROG_SENDMAIL@
+RANLIB = @RANLIB@
+RDYNAMIC_LFLAGS = @RDYNAMIC_LFLAGS@
+REGEX_LIB = @REGEX_LIB@
+STRONGHOLD = @STRONGHOLD@
+VERSION = @VERSION@
+WARNING_LEVEL = @WARNING_LEVEL@
+YACC = @YACC@
+
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_sysvshm.a
+libphpext_sysvshm_a_SOURCES=sysvshm.c
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libphpext_sysvshm_a_LIBADD =
+libphpext_sysvshm_a_OBJECTS = sysvshm.o
+AR = ar
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+SOURCES = $(libphpext_sysvshm_a_SOURCES)
+OBJECTS = $(libphpext_sysvshm_a_OBJECTS)
+
+all: Makefile $(LIBRARIES)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps ext/sysvshm/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+ $(COMPILE) -c $<
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libphpext_sysvshm.a: $(libphpext_sysvshm_a_OBJECTS) $(libphpext_sysvshm_a_DEPENDENCIES)
+ -rm -f libphpext_sysvshm.a
+ $(AR) cru libphpext_sysvshm.a $(libphpext_sysvshm_a_OBJECTS) $(libphpext_sysvshm_a_LIBADD)
+ $(RANLIB) libphpext_sysvshm.a
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = ext/sysvshm
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
+ done
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
+install-strip:
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+
+
+mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -rm -f Makefile $(DISTCLEANFILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-tags mostlyclean-generic
+
+clean: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+ mostlyclean
+
+distclean: distclean-noinstLIBRARIES distclean-compile distclean-tags \
+ distclean-generic clean
+ -rm -f config.status
+
+maintainer-clean: maintainer-clean-noinstLIBRARIES \
+ maintainer-clean-compile maintainer-clean-tags \
+ maintainer-clean-generic distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info dvi installcheck \
+install-exec install-data install uninstall all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/ext/sysvshm/config.h.stub b/ext/sysvshm/config.h.stub
new file mode 100644
index 0000000000..9b5f5e35cb
--- /dev/null
+++ b/ext/sysvshm/config.h.stub
@@ -0,0 +1,3 @@
+/* Define if you want System V shared memory support.
+ */
+#define HAVE_SYSVSHM 0
diff --git a/ext/sysvshm/config.m4 b/ext/sysvshm/config.m4
new file mode 100644
index 0000000000..287841f26d
--- /dev/null
+++ b/ext/sysvshm/config.m4
@@ -0,0 +1,17 @@
+dnl $Id$
+
+AC_MSG_CHECKING(whether to enable System V shared memory support)
+AC_ARG_ENABLE(sysvshm,
+[ --enable-sysvshm Enable the System V shared memory support],[
+ if test "$enableval" = "yes"; then
+ AC_DEFINE(HAVE_SYSVSHM, 1)
+ AC_MSG_RESULT(yes)
+ PHP_EXTENSION(sysvshm)
+ else
+ AC_DEFINE(HAVE_SYSVSHM, 0)
+ AC_MSG_RESULT(no)
+ fi
+],[
+ AC_DEFINE(HAVE_SYSVSHM, 0)
+ AC_MSG_RESULT(no)
+])
diff --git a/ext/sysvshm/php3_sysvshm.h b/ext/sysvshm/php3_sysvshm.h
new file mode 100644
index 0000000000..c47e561d2c
--- /dev/null
+++ b/ext/sysvshm/php3_sysvshm.h
@@ -0,0 +1,101 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Christian Cartus <chc@idgruppe.de> |
+ +----------------------------------------------------------------------+
+ */
+
+
+/* $Id$ */
+
+#ifndef _PHP3_SYSVSHM_H
+#define _PHP3_SYSVSHM_H
+
+#if COMPILE_DL
+#undef HAVE_SYSVSHM
+#define HAVE_SYSVSHM 1
+#endif
+
+
+#if HAVE_SYSVSHM
+
+extern php3_module_entry sysvshm_module_entry;
+#define sysvshm_module_ptr &sysvshm_module_entry
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+typedef struct {
+ int le_shm;
+ long init_mem;
+} sysvshm_module;
+
+
+typedef struct {
+ long key;
+ long length;
+ long next;
+ char mem;
+} sysvshm_chunk;
+
+
+typedef struct {
+ char magic[8];
+ long start;
+ long end;
+ long free;
+ long total;
+} sysvshm_chunk_head;
+
+
+typedef struct {
+ key_t key; /* Key set by user */
+ long id; /* Returned by shmget. */
+ sysvshm_chunk_head *ptr; /* memoryaddress of shared memory */
+} sysvshm_shm;
+
+
+
+extern int php3_minit_sysvshm(INIT_FUNC_ARGS);
+extern void php3_sysvshm_attach(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sysvshm_detach(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sysvshm_remove(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sysvshm_put_var(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sysvshm_get_var(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_sysvshm_remove_var(INTERNAL_FUNCTION_PARAMETERS);
+extern int php3int_put_shmdata(sysvshm_chunk_head *ptr,long key,char *data, long len);
+extern long php3int_check_shmdata(sysvshm_chunk_head *ptr, long key);
+extern int php3int_remove_shmdata(sysvshm_chunk_head *ptr, long shm_varpos);
+
+extern sysvshm_module php3_sysvshm_module;
+
+#else
+
+#define sysvshm_module_ptr NULL
+
+#endif
+
+#endif /* _PHP3_SYSVSHM_H */
diff --git a/ext/sysvshm/setup.stub b/ext/sysvshm/setup.stub
new file mode 100644
index 0000000000..4a9e894b4e
--- /dev/null
+++ b/ext/sysvshm/setup.stub
@@ -0,0 +1,5 @@
+# $Source$
+# $Id$
+
+define_option enable-sysvshm 'System V shared memory support? ' yesno no \
+' Whether to use the System V shared memory (currently only Solaris and Linux).'
diff --git a/ext/sysvshm/sysvshm.c b/ext/sysvshm/sysvshm.c
new file mode 100644
index 0000000000..68547281c5
--- /dev/null
+++ b/ext/sysvshm/sysvshm.c
@@ -0,0 +1,485 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Christian Cartus <chc@idgruppe.de> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+/* This has been built and tested on Solaris 2.6.
+ * It may not compile or execute correctly on other systems.
+ */
+
+#ifndef MSVC5
+#include "config.h"
+#endif
+
+
+#if HAVE_SYSVSHM
+
+#include <errno.h>
+
+#include "php.h"
+#include "php3_var.h"
+#include "php3_sysvshm.h"
+
+
+function_entry sysvshm_functions[] = {
+ {"shm_attach", php3_sysvshm_attach, NULL},
+ {"shm_detach", php3_sysvshm_detach, NULL},
+ {"shm_remove", php3_sysvshm_remove, NULL},
+ {"shm_put_var", php3_sysvshm_put_var, NULL},
+ {"shm_get_var", php3_sysvshm_get_var, NULL},
+ {"shm_remove_var", php3_sysvshm_remove_var, NULL},
+ {NULL, NULL, NULL}
+};
+
+php3_module_entry sysvshm_module_entry = {
+ "System V Shared-Memory", sysvshm_functions, php3_minit_sysvshm, NULL, NULL, NULL, NULL, STANDARD_MODULE_PROPERTIES
+};
+
+
+#if COMPILE_DL
+php3_module_entry *get_module() { return &sysvshm_module_entry; }
+#endif
+
+
+THREAD_LS sysvshm_module php3_sysvshm_module;
+
+
+
+static void php3i_release_sysvshm(sysvshm_shm *shm_ptr) {
+
+ shmdt((void*)shm_ptr->ptr);
+}
+
+
+
+int php3_minit_sysvshm(INIT_FUNC_ARGS)
+{
+ php3_sysvshm_module.le_shm = register_list_destructors(php3i_release_sysvshm, NULL);
+ if (cfg_get_long("sysvshm.init_mem",
+ &php3_sysvshm_module.init_mem)==FAILURE) {
+ php3_sysvshm_module.init_mem=10000;
+ }
+ return SUCCESS;
+}
+
+
+/* {{{ proto int shm_attach(int key, int size, int flag)
+ Return an id for the shared memory with the given key. */
+void php3_sysvshm_attach(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *arg_key,*arg_size,*arg_flag;
+ long shm_size,shm_flag;
+ sysvshm_shm *shm_list_ptr;
+ char *shm_ptr;
+ sysvshm_chunk_head *chunk_ptr;
+ key_t shm_key;
+ long shm_id,list_id;
+
+ shm_flag = 0666;
+ shm_size = php3_sysvshm_module.init_mem;
+
+ switch (ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &arg_key)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(arg_key);
+ shm_key = arg_key->value.lval;
+ break;
+ case 2:
+ if (getParameters(ht, 2, &arg_key, &arg_size)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(arg_key);
+ shm_key = arg_key->value.lval;
+ convert_to_long(arg_size);
+ shm_size=arg_size->value.lval;
+ break;
+ case 3:
+ if (getParameters(ht, 3, &arg_key, &arg_size, &arg_flag)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(arg_key);
+ shm_key = arg_key->value.lval;
+ convert_to_long(arg_size);
+ shm_size=arg_size->value.lval;
+ convert_to_long(arg_flag);
+ shm_flag = arg_flag->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+
+ if((shm_list_ptr = (sysvshm_shm *) emalloc(sizeof(sysvshm_shm)))==NULL) {
+ php3_error(E_WARNING, "shm_attach() failed for key 0x%x: cannot allocate internal listelement", shm_key);
+ RETURN_FALSE;
+ }
+
+ /* get the id from a specified key or create new shared memory */
+ if((shm_id=shmget(shm_key,0,0))<0) {
+ if(shm_size<sizeof(sysvshm_chunk_head)) {
+ php3_error(E_WARNING, "shm_attach() failed for key 0x%x: memorysize too small", shm_key);
+ RETURN_FALSE;
+ }
+ if((shm_id=shmget(shm_key,shm_size,shm_flag|IPC_CREAT|IPC_EXCL))<0) {
+ php3_error(E_WARNING, "shmget() failed for key 0x%x: %s", shm_key, strerror(errno));
+ RETURN_FALSE;
+ }
+ }
+
+ if((shm_ptr = shmat(shm_id,NULL,0))==NULL) {
+ php3_error(E_WARNING, "shmget() failed for key 0x%x: %s", shm_key, strerror(errno));
+ RETURN_FALSE;
+ }
+
+ /* check if shm is already initialized */
+ chunk_ptr= (sysvshm_chunk_head*) shm_ptr;
+ if(strcmp((char*)&(chunk_ptr->magic),"PHP3SM")!=0) {
+ strcpy((char*)&(chunk_ptr->magic),"PHP3SM");
+ chunk_ptr->start=sizeof(sysvshm_chunk_head);
+ chunk_ptr->end=chunk_ptr->start;
+ chunk_ptr->total=shm_size;
+ chunk_ptr->free=shm_size-chunk_ptr->end;
+ }
+
+
+ shm_list_ptr->key = shm_key;
+ shm_list_ptr->id = shm_id;
+ shm_list_ptr->ptr = chunk_ptr;
+ list_id = php3_list_insert(shm_list_ptr, php3_sysvshm_module.le_shm);
+ RETURN_LONG(list_id);
+}
+/* }}} */
+
+
+
+/* {{{ proto int shm_detach(int id)
+ releases the shared memory attachment with the given id. */
+void php3_sysvshm_detach(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *arg_id;
+ long id;
+ sysvshm_shm *shm_list_ptr;
+ int type;
+
+
+ switch (ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &arg_id)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(arg_id);
+ id = arg_id->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ shm_list_ptr = (sysvshm_shm *) php3_list_find(id, &type);
+ if (type!=php3_sysvshm_module.le_shm) {
+ php3_error(E_WARNING, "%d is not a SysV shared memory index", id);
+ RETURN_FALSE;
+ }
+
+ if(shmdt((void*)shm_list_ptr->ptr)<0) {
+ php3_error(E_WARNING, "shm_detach() failed for id 0x%x: %s", id, strerror(errno));
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+
+
+
+
+/* {{{ proto int shm_remove(int key)
+ removes the shared memory with the given key. */
+void php3_sysvshm_remove(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *arg_key;
+ long id;
+ key_t key;
+
+
+ switch (ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht, 1, &arg_key)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(arg_key);
+ key = arg_key->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+
+ if((id=shmget(key,0,0))<0) {
+ php3_error(E_WARNING, "%d is not a existing SysV shared memory key", key);
+ RETURN_FALSE;
+ }
+ if(shmctl(id,IPC_RMID,NULL)<0) {
+ php3_error(E_WARNING, "shm_remove() failed for key 0x%x: %s", key, strerror(errno));
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+
+
+/* {{{ proto int shm_put(int id, int key, object *variable)
+ insert a variable into shared memory. */
+void php3_sysvshm_put_var(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *arg_id, *arg_key, *arg_var;
+ long key, id;
+ sysvshm_shm *shm_list_ptr;
+ int type;
+ pval shm_var;
+ int ret;
+
+ switch (ARG_COUNT(ht)) {
+ case 3:
+ if (getParameters(ht, 3, &arg_id, &arg_key,&arg_var)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(arg_id);
+ id = arg_id->value.lval;
+ convert_to_long(arg_key);
+ key = arg_key->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ shm_list_ptr = (sysvshm_shm *) php3_list_find(id, &type);
+ if (type!=php3_sysvshm_module.le_shm) {
+ php3_error(E_WARNING, "%d is not a SysV shared memory index", id);
+ RETURN_FALSE;
+ }
+
+ /* setup string-variable and serialize */
+ shm_var.type=IS_STRING;
+ shm_var.value.str.len=0;
+ shm_var.value.str.val=emalloc(1);
+ shm_var.value.str.val[0]=0;
+ php3api_var_serialize(&shm_var,arg_var);
+ /* insert serialized variable into shared memory */
+ ret=php3int_put_shmdata(shm_list_ptr->ptr,key,shm_var.value.str.val,shm_var.value.str.len);
+
+ /* free string */
+ efree(shm_var.value.str.val);
+
+ if(ret==-1) {
+ php3_error(E_WARNING, "not enough shared memory left");
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+
+
+
+/* {{{ proto string/float/int/array shm_get_var(int id, int key)
+ returns a variable into shared memory. */
+void php3_sysvshm_get_var(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *arg_id, *arg_key;
+ long key, id;
+ sysvshm_shm *shm_list_ptr;
+ int type;
+ char *shm_data;
+ long shm_varpos;
+ sysvshm_chunk *shm_var;
+
+ switch (ARG_COUNT(ht)) {
+ case 2:
+ if (getParameters(ht, 2, &arg_id, &arg_key)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(arg_id);
+ id = arg_id->value.lval;
+ convert_to_long(arg_key);
+ key = arg_key->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ shm_list_ptr = (sysvshm_shm *) php3_list_find(id, &type);
+ if (type!=php3_sysvshm_module.le_shm) {
+ php3_error(E_WARNING, "%d is not a SysV shared memory index", id);
+ RETURN_FALSE;
+ }
+
+ /* setup string-variable and serialize */
+ /* get serialized variable from shared memory */
+ shm_varpos=php3int_check_shmdata((shm_list_ptr->ptr),key);
+
+ if(shm_varpos<0) {
+ php3_error(E_WARNING, "variable key %d doesn't exist", key);
+ RETURN_FALSE;
+ }
+ shm_var=(sysvshm_chunk*)((char*)shm_list_ptr->ptr+shm_varpos);
+ shm_data=&shm_var->mem;
+
+ if(php3api_var_unserialize(return_value, &shm_data, shm_data+shm_var->length)!=1) {
+ php3_error(E_WARNING, "variable data in shared memory is corruped");
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto int shm_remove_var(int id, int key)
+ removes variable from shared memory. */
+void php3_sysvshm_remove_var(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *arg_id, *arg_key;
+ long key, id;
+ sysvshm_shm *shm_list_ptr;
+ int type;
+ long shm_varpos;
+
+ switch (ARG_COUNT(ht)) {
+ case 2:
+ if (getParameters(ht, 2, &arg_id, &arg_key)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_long(arg_id);
+ id = arg_id->value.lval;
+ convert_to_long(arg_key);
+ key = arg_key->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ shm_list_ptr = (sysvshm_shm *) php3_list_find(id, &type);
+ if (type!=php3_sysvshm_module.le_shm) {
+ php3_error(E_WARNING, "%d is not a SysV shared memory index", id);
+ RETURN_FALSE;
+ }
+
+ shm_varpos=php3int_check_shmdata((shm_list_ptr->ptr),key);
+
+ if(shm_varpos<0) {
+ php3_error(E_WARNING, "variable key %d doesn't exist", key);
+ RETURN_FALSE;
+ }
+ php3int_remove_shmdata((shm_list_ptr->ptr),shm_varpos);
+ RETURN_TRUE;
+}
+/* }}} */
+
+
+
+
+
+
+
+/* inserts an ascii-string into shared memory */
+int php3int_put_shmdata(sysvshm_chunk_head *ptr,long key,char *data, long len) {
+ sysvshm_chunk* shm_var;
+ long total_size;
+ long shm_varpos;
+
+ total_size=((long)(len+sizeof(sysvshm_chunk)-1)/4)*4+4; /* 4-byte alligment */
+
+ if(ptr->free<total_size) {
+ return -1; /* not enough memeory */
+ }
+
+ if((shm_varpos=php3int_check_shmdata(ptr,key))>0) {
+ php3int_remove_shmdata(ptr, shm_varpos);
+ }
+ shm_var=(sysvshm_chunk*)((char *)ptr+ptr->end);
+ shm_var->key=key;
+ shm_var->length=len;
+ shm_var->next=total_size;
+ memcpy(&(shm_var->mem),data,len);
+ ptr->end+=total_size;
+ ptr->free-=total_size;
+ return 0;
+}
+
+
+long php3int_check_shmdata(sysvshm_chunk_head *ptr, long key) {
+ long pos;
+ sysvshm_chunk *shm_var;
+
+ pos=ptr->start;
+
+ for(;;) {
+ if(pos>=ptr->end) {
+ return -1;
+ }
+ shm_var=(sysvshm_chunk*)((char*)ptr+pos);
+ if(shm_var->key==key) {
+ return pos;
+ }
+ pos+=shm_var->next;
+ }
+ return -1;
+}
+
+
+int php3int_remove_shmdata(sysvshm_chunk_head *ptr, long shm_varpos) {
+ sysvshm_chunk *chunk_ptr, *next_chunk_ptr;
+ long memcpy_len;
+
+ chunk_ptr=(sysvshm_chunk*)((char*)ptr+shm_varpos);
+ next_chunk_ptr=(sysvshm_chunk*)((char*)ptr+shm_varpos+chunk_ptr->next);
+
+ memcpy_len=ptr->end-shm_varpos-chunk_ptr->next;
+ ptr->free+=chunk_ptr->next;
+ ptr->end-=chunk_ptr->next;
+ if(memcpy_len>0)
+ memcpy(chunk_ptr,next_chunk_ptr,memcpy_len);
+ return 0;
+}
+
+
+
+#endif /* HAVE_SYSVSHM */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/xml/Makefile.am b/ext/xml/Makefile.am
new file mode 100644
index 0000000000..c4f9f526f3
--- /dev/null
+++ b/ext/xml/Makefile.am
@@ -0,0 +1,6 @@
+# $Id$
+
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_xml.a
+libphpext_xml_a_SOURCES=xml.c
+
diff --git a/ext/xml/Makefile.in b/ext/xml/Makefile.in
new file mode 100644
index 0000000000..8ba8f5f22c
--- /dev/null
+++ b/ext/xml/Makefile.in
@@ -0,0 +1,270 @@
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# $Id$
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+APACHE_INCLUDE = @APACHE_INCLUDE@
+APACHE_TARGET = @APACHE_TARGET@
+APXS = @APXS@
+APXS_LDFLAGS = @APXS_LDFLAGS@
+BINNAME = @BINNAME@
+CC = @CC@
+CFLAGS = @CFLAGS@
+CFLAGS_SHLIB = @CFLAGS_SHLIB@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+EXTINFO_DEPS = @EXTINFO_DEPS@
+EXTRA_LIBS = @EXTRA_LIBS@
+EXT_LIBS = @EXT_LIBS@
+EXT_SUBDIRS = @EXT_SUBDIRS@
+FHTTPD_LIB = @FHTTPD_LIB@
+FHTTPD_TARGET = @FHTTPD_TARGET@
+HSREGEX = @HSREGEX@
+INSTALL_IT = @INSTALL_IT@
+LDFLAGS_SHLIB = @LDFLAGS_SHLIB@
+LDFLAGS_SHLIB_EXPORT = @LDFLAGS_SHLIB_EXPORT@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+PERL_PATH = @PERL_PATH@
+PHP_BUILD_DATE = @PHP_BUILD_DATE@
+PHP_DEBUG = @PHP_DEBUG@
+PHP_LIBS = @PHP_LIBS@
+PHP_VERSION = @PHP_VERSION@
+PROG_SENDMAIL = @PROG_SENDMAIL@
+RANLIB = @RANLIB@
+RDYNAMIC_LFLAGS = @RDYNAMIC_LFLAGS@
+REGEX_LIB = @REGEX_LIB@
+STRONGHOLD = @STRONGHOLD@
+VERSION = @VERSION@
+WARNING_LEVEL = @WARNING_LEVEL@
+YACC = @YACC@
+
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_xml.a
+libphpext_xml_a_SOURCES=xml.c
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libphpext_xml_a_LIBADD =
+libphpext_xml_a_OBJECTS = xml.o
+AR = ar
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+SOURCES = $(libphpext_xml_a_SOURCES)
+OBJECTS = $(libphpext_xml_a_OBJECTS)
+
+all: Makefile $(LIBRARIES)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps ext/xml/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+ $(COMPILE) -c $<
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libphpext_xml.a: $(libphpext_xml_a_OBJECTS) $(libphpext_xml_a_DEPENDENCIES)
+ -rm -f libphpext_xml.a
+ $(AR) cru libphpext_xml.a $(libphpext_xml_a_OBJECTS) $(libphpext_xml_a_LIBADD)
+ $(RANLIB) libphpext_xml.a
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = ext/xml
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
+ done
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
+install-strip:
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+
+
+mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -rm -f Makefile $(DISTCLEANFILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-tags mostlyclean-generic
+
+clean: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+ mostlyclean
+
+distclean: distclean-noinstLIBRARIES distclean-compile distclean-tags \
+ distclean-generic clean
+ -rm -f config.status
+
+maintainer-clean: maintainer-clean-noinstLIBRARIES \
+ maintainer-clean-compile maintainer-clean-tags \
+ maintainer-clean-generic distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info dvi installcheck \
+install-exec install-data install uninstall all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/ext/xml/config.h.stub b/ext/xml/config.h.stub
new file mode 100644
index 0000000000..a4abe9b584
--- /dev/null
+++ b/ext/xml/config.h.stub
@@ -0,0 +1,4 @@
+/* define if you want to use the xml extension */
+
+/* Define if you have the expat (XML Parser Toolkit) library */
+#define HAVE_LIBEXPAT 0
diff --git a/ext/xml/config.m4 b/ext/xml/config.m4
new file mode 100644
index 0000000000..c4b871107d
--- /dev/null
+++ b/ext/xml/config.m4
@@ -0,0 +1,24 @@
+dnl $Id$
+
+AC_MSG_CHECKING(for XML support)
+AC_ARG_WITH(xml,
+[ --with-xml Include XML support],[
+ if test "$withval" != "no"; then
+ if test "$withval" = "yes"; then
+ XML_LIBS="-lexpat"
+ XML_INCLUDE=""
+ else
+ XML_LIBS="-L$withval/lib -lexpat"
+ XML_INCLUDE="-I$withval/include"
+ fi
+ AC_DEFINE(HAVE_LIBEXPAT, 1)
+ AC_MSG_RESULT(yes)
+ PHP_EXTENSION(xml)
+ EXTRA_LIBS="$EXTRA_LIBS $XML_LIBS"
+ INCLUDES="$INCLUDES $XML_INCLUDE"
+ else
+ AC_MSG_RESULT(no)
+ fi
+],[
+ AC_MSG_RESULT(no)
+])
diff --git a/ext/xml/php3_xml.h b/ext/xml/php3_xml.h
new file mode 100644
index 0000000000..7daba59b88
--- /dev/null
+++ b/ext/xml/php3_xml.h
@@ -0,0 +1,117 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Stig Sæther Bakken <ssb@guardian.no> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id */
+
+#if HAVE_LIBEXPAT
+# ifndef _PHP_XML_H
+# define _PHP_XML_H
+# endif
+
+#include <xml/xmltok.h>
+#include <xml/xmlparse.h>
+
+#ifdef XML_UNICODE
+# error "UTF-16 Unicode support not implemented!"
+#endif
+
+typedef struct {
+ int le_xml_parser;
+ XML_Char *default_encoding;
+} xml_module;
+
+typedef struct {
+ int index;
+ int case_folding;
+ XML_Parser parser;
+ XML_Char *target_encoding;
+ char *startElementHandler;
+ char *endElementHandler;
+ char *characterDataHandler;
+ char *processingInstructionHandler;
+ char *defaultHandler;
+ char *unparsedEntityDeclHandler;
+ char *notationDeclHandler;
+ char *externalEntityRefHandler;
+ char *unknownEncodingHandler;
+ XML_Char *baseURI;
+} xml_parser;
+
+
+typedef struct {
+ XML_Char *name;
+ char (*decoding_function)(unsigned short);
+ unsigned short (*encoding_function)(char);
+} xml_encoding;
+
+
+extern php3_module_entry xml_module_entry;
+# define xml_module_ptr &xml_module_entry
+
+enum php3_xml_option {
+ PHP3_XML_OPTION_CASE_FOLDING,
+ PHP3_XML_OPTION_TARGET_ENCODING
+};
+
+# define RETURN_OUT_OF_MEMORY \
+ php3_error(E_WARNING, "Out of memory");\
+ RETURN_FALSE
+
+PHP_FUNCTION(xml_parser_create);
+PHP_FUNCTION(xml_set_element_handler);
+PHP_FUNCTION(xml_set_character_data_handler);
+PHP_FUNCTION(xml_set_processing_instruction_handler);
+PHP_FUNCTION(xml_set_default_handler);
+PHP_FUNCTION(xml_set_unparsed_entity_decl_handler);
+PHP_FUNCTION(xml_set_notation_decl_handler);
+PHP_FUNCTION(xml_set_external_entity_ref_handler);
+PHP_FUNCTION(xml_parse);
+PHP_FUNCTION(xml_get_error_code);
+PHP_FUNCTION(xml_error_string);
+PHP_FUNCTION(xml_get_current_line_number);
+PHP_FUNCTION(xml_get_current_column_number);
+PHP_FUNCTION(xml_get_current_byte_index);
+PHP_FUNCTION(xml_parser_free);
+PHP_FUNCTION(xml_parser_set_option);
+PHP_FUNCTION(xml_parser_get_option);
+PHP_FUNCTION(utf8_encode);
+PHP_FUNCTION(utf8_decode);
+
+#else /* !HAVE_LIBEXPAT */
+
+# define xml_module_ptr NULL
+
+#endif /* HAVE_LIBEXPAT */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/xml/xml.c b/ext/xml/xml.c
new file mode 100644
index 0000000000..eed6a3f6e0
--- /dev/null
+++ b/ext/xml/xml.c
@@ -0,0 +1,1307 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of one of the following licenses: |
+ | |
+ | A) the GNU General Public License as published by the Free Software |
+ | Foundation; either version 2 of the License, or (at your option) |
+ | any later version. |
+ | |
+ | B) the PHP License as published by the PHP Development Team and |
+ | included in the distribution in the file: LICENSE |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of both licenses referred to here. |
+ | If you did not, or have any questions about PHP licensing, please |
+ | contact core@php.net. |
+ +----------------------------------------------------------------------+
+ | Authors: Stig Sæther Bakken <ssb@guardian.no> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+#define IS_EXT_MODULE
+#if COMPILE_DL
+# if PHP_31
+# include "../phpdl.h"
+# else
+# include "dl/phpdl.h"
+# endif
+#endif
+#include "php.h"
+#include "php3_xml.h"
+#include "zend_variables.h"
+
+#if defined(THREAD_SAFE) && !PHP_31
+#undef THREAD_SAFE
+#endif
+
+#if HAVE_LIBEXPAT
+
+# if !(WIN32|WINNT)
+# include "build-defs.h"
+# endif
+# include "snprintf.h"
+# include "ext/standard/head.h"
+# include "php3_string.h"
+
+/* Short-term TODO list:
+ * - Implement XML_ExternalEntityParserCreate()
+ */
+
+/* Long-term TODO list:
+ * - Fix the expat library so you can install your own memory manager
+ * functions
+ */
+
+/* Known bugs:
+ * - Weird things happen with <![CDATA[]]> sections.
+ */
+
+/* {{{ thread safety stuff */
+
+# ifdef THREAD_SAFE
+# define XML_GLOBAL(a) xml_globals->a
+# define XML_TLS_VARS xml_global_struct *xml_globals = TlsGetValue(XMLTls);
+
+void *xml_mutex;
+DWORD XMLTls;
+static int numthreads=0;
+
+typedef struct xml_global_struct {
+ xml_module php3_xml_module;
+} xml_global_struct;
+
+# else /* !defined(THREAD_SAFE) */
+# define XML_GLOBAL(a) a
+# define XML_TLS_VARS
+
+xml_module php3_xml_module;
+
+# endif /* defined(THREAD_SAFE) */
+
+/* }}} */
+/* {{{ dynamically loadable module stuff */
+
+# if COMPILE_DL
+DLEXPORT php3_module_entry *get_module() { return &xml_module_entry; };
+# endif /* COMPILE_DL */
+
+/* }}} */
+/* {{{ function prototypes */
+
+int php3_minit_xml(INIT_FUNC_ARGS);
+int php3_rinit_xml(INIT_FUNC_ARGS);
+int php3_mshutdown_xml(SHUTDOWN_FUNC_ARGS);
+int php3_rshutdown_xml(SHUTDOWN_FUNC_ARGS);
+void php3_info_xml(void);
+
+static xml_parser *xml_get_parser(int, const char *, HashTable *);
+static void xml_destroy_parser(xml_parser *);
+static void xml_set_handler(char **, pval *);
+inline static unsigned short xml_encode_iso_8859_1(unsigned char);
+inline static char xml_decode_iso_8859_1(unsigned short);
+inline static unsigned short xml_encode_us_ascii(char);
+inline static char xml_decode_us_ascii(unsigned short);
+static XML_Char *xml_utf8_encode(const char *, int, int *, const XML_Char *);
+static char *xml_utf8_decode(const XML_Char *, int, int *, const XML_Char *);
+static pval *xml_call_handler(xml_parser *, char *, int, pval **);
+static pval *php3i_xmlcharpval(const XML_Char *, int, const XML_Char *);
+static int php3i_xmlcharlen(const XML_Char *);
+
+void php3i_xml_startElementHandler(void *, const char *, const char **);
+void php3i_xml_endElementHandler(void *, const char *);
+void php3i_xml_characterDataHandler(void *, const XML_Char *, int);
+void php3i_xml_processingInstructionHandler(void *, const XML_Char *, const XML_Char *);
+void php3i_xml_defaultHandler(void *, const XML_Char *, int);
+void php3i_xml_unparsedEntityDeclHandler(void *, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *);
+void php3i_xml_notationDeclHandler(void *, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *);
+int php3i_xml_externalEntityRefHandler(XML_Parser, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *);
+
+/* }}} */
+/* {{{ extension definition structures */
+
+function_entry xml_functions[] = {
+ PHP_FE(xml_parser_create, NULL)
+ PHP_FE(xml_set_element_handler, NULL)
+ PHP_FE(xml_set_character_data_handler, NULL)
+ PHP_FE(xml_set_processing_instruction_handler, NULL)
+ PHP_FE(xml_set_default_handler, NULL)
+ PHP_FE(xml_set_unparsed_entity_decl_handler, NULL)
+ PHP_FE(xml_set_notation_decl_handler, NULL)
+ PHP_FE(xml_set_external_entity_ref_handler, NULL)
+ PHP_FE(xml_parse, NULL)
+ PHP_FE(xml_get_error_code, NULL)
+ PHP_FE(xml_error_string, NULL)
+ PHP_FE(xml_get_current_line_number, NULL)
+ PHP_FE(xml_get_current_column_number, NULL)
+ PHP_FE(xml_get_current_byte_index, NULL)
+ PHP_FE(xml_parser_free, NULL)
+ PHP_FE(xml_parser_set_option, NULL)
+ PHP_FE(xml_parser_get_option, NULL)
+ PHP_FE(utf8_encode, NULL)
+ PHP_FE(utf8_decode, NULL)
+ {NULL, NULL, NULL}
+};
+
+php3_module_entry xml_module_entry = {
+ "XML", /* extension name */
+ xml_functions, /* extension function list */
+ php3_minit_xml, /* extension-wide startup function */
+ php3_mshutdown_xml, /* extension-wide shutdown function */
+ php3_rinit_xml, /* per-request startup function */
+ php3_rshutdown_xml, /* per-request shutdown function */
+ php3_info_xml, /* information function */
+ STANDARD_MODULE_PROPERTIES
+};
+
+/* All the encoding functions are set to NULL right now, since all
+ * the encoding is currently done internally by expat/xmltok.
+ */
+xml_encoding xml_encodings[] = {
+ { "ISO-8859-1", xml_decode_iso_8859_1, xml_encode_iso_8859_1 },
+ { "US-ASCII", xml_decode_us_ascii, xml_encode_us_ascii },
+ { "UTF-8", NULL, NULL },
+ { NULL, NULL, NULL }
+};
+
+/* }}} */
+/* {{{ startup, shutdown and info functions */
+
+ /* {{{ php3_minit_xml */
+
+int php3_minit_xml(INIT_FUNC_ARGS)
+{
+#if defined(THREAD_SAFE)
+ xml_global_struct *xml_globals;
+ PHP3_MUTEX_ALLOC(xml_mutex);
+ PHP3_MUTEX_LOCK(xml_mutex);
+ numthreads++;
+ if (numthreads==1){
+ if (!PHP3_TLS_PROC_STARTUP(XMLTls)){
+ PHP3_MUTEX_UNLOCK(xml_mutex);
+ PHP3_MUTEX_FREE(xml_mutex);
+ return FAILURE;
+ }
+ }
+ PHP3_MUTEX_UNLOCK(xml_mutex);
+ if(!PHP3_TLS_THREAD_INIT(XMLTls,xml_globals,xml_global_struct)){
+ PHP3_MUTEX_FREE(xml_mutex);
+ return FAILURE;
+ }
+#endif
+
+ XML_GLOBAL(php3_xml_module).le_xml_parser =
+ register_list_destructors(xml_destroy_parser, NULL);
+
+ XML_GLOBAL(php3_xml_module).default_encoding = "ISO-8859-1";
+
+ REGISTER_LONG_CONSTANT("XML_ERROR_NONE", XML_ERROR_NONE, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_NO_MEMORY", XML_ERROR_NO_MEMORY, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_SYNTAX", XML_ERROR_SYNTAX, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_NO_ELEMENTS", XML_ERROR_NO_ELEMENTS, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_INVALID_TOKEN", XML_ERROR_INVALID_TOKEN, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_UNCLOSED_TOKEN", XML_ERROR_UNCLOSED_TOKEN, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_PARTIAL_CHAR", XML_ERROR_PARTIAL_CHAR, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_TAG_MISMATCH", XML_ERROR_TAG_MISMATCH, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_DUPLICATE_ATTRIBUTE", XML_ERROR_DUPLICATE_ATTRIBUTE, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_JUNK_AFTER_DOC_ELEMENT", XML_ERROR_JUNK_AFTER_DOC_ELEMENT, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_PARAM_ENTITY_REF", XML_ERROR_PARAM_ENTITY_REF, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_UNDEFINED_ENTITY", XML_ERROR_UNDEFINED_ENTITY, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_RECURSIVE_ENTITY_REF", XML_ERROR_RECURSIVE_ENTITY_REF, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_ASYNC_ENTITY", XML_ERROR_ASYNC_ENTITY, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_BAD_CHAR_REF", XML_ERROR_BAD_CHAR_REF, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_BINARY_ENTITY_REF", XML_ERROR_BINARY_ENTITY_REF, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF", XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_MISPLACED_XML_PI", XML_ERROR_MISPLACED_XML_PI, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_UNKNOWN_ENCODING", XML_ERROR_UNKNOWN_ENCODING, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_INCORRECT_ENCODING", XML_ERROR_INCORRECT_ENCODING, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_UNCLOSED_CDATA_SECTION", XML_ERROR_UNCLOSED_CDATA_SECTION, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_ERROR_EXTERNAL_ENTITY_HANDLING", XML_ERROR_EXTERNAL_ENTITY_HANDLING, CONST_CS|CONST_PERSISTENT);
+
+ REGISTER_LONG_CONSTANT("XML_OPTION_CASE_FOLDING", PHP3_XML_OPTION_CASE_FOLDING, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("XML_OPTION_TARGET_ENCODING", PHP3_XML_OPTION_TARGET_ENCODING, CONST_CS|CONST_PERSISTENT);
+
+ return SUCCESS;
+}
+
+/* }}} */
+ /* {{{ php3_rinit_xml */
+
+int php3_rinit_xml(INIT_FUNC_ARGS)
+{
+ return SUCCESS;
+}
+
+/* }}} */
+ /* {{{ php3_mshutdown_xml() */
+
+int php3_mshutdown_xml(SHUTDOWN_FUNC_ARGS)
+{
+ XML_TLS_VARS;
+#ifdef THREAD_SAFE
+ PHP3_TLS_THREAD_FREE(xml_globals);
+ PHP3_MUTEX_LOCK(xml_mutex);
+ numthreads--;
+ if (numthreads<1) {
+ PHP3_TLS_PROC_SHUTDOWN(XMLTls);
+ PHP3_MUTEX_UNLOCK(xml_mutex);
+ PHP3_MUTEX_FREE(xml_mutex);
+ return SUCCESS;
+ }
+ PHP3_MUTEX_UNLOCK(xml_mutex);
+#endif
+ return SUCCESS;
+}
+
+/* }}} */
+ /* {{{ php3_rshutdown_xml() */
+
+int php3_rshutdown_xml(SHUTDOWN_FUNC_ARGS)
+{
+ return SUCCESS;
+}
+
+/* }}} */
+ /* {{{ php3_info_xml() */
+
+void php3_info_xml()
+{
+ PUTS("XML support active");
+}
+
+/* }}} */
+
+/* }}} */
+/* {{{ extension-internal functions */
+
+ /* {{{ xml_get_parser() */
+
+static xml_parser *
+xml_get_parser(int parser_ind, const char *func, HashTable *list)
+{
+ int type;
+ xml_parser *parser;
+ XML_TLS_VARS;
+
+ parser = (xml_parser *)php3_list_find(parser_ind, &type);
+ if (!parser || type != XML_GLOBAL(php3_xml_module).le_xml_parser) {
+ php3_error(E_WARNING, "%s: invalid XML parser %d", func, parser_ind);
+ return (xml_parser *)NULL;
+ }
+ return parser;
+}
+
+/* }}} */
+ /* {{{ xml_destroy_parser() */
+
+static void
+xml_destroy_parser(xml_parser *parser)
+{
+ XML_TLS_VARS;
+
+ if (parser->parser) {
+ XML_ParserFree(parser->parser);
+ }
+ if (parser->startElementHandler) {
+ efree(parser->startElementHandler);
+ }
+ if (parser->endElementHandler) {
+ efree(parser->endElementHandler);
+ }
+ if (parser->characterDataHandler) {
+ efree(parser->characterDataHandler);
+ }
+ if (parser->processingInstructionHandler) {
+ efree(parser->processingInstructionHandler);
+ }
+ if (parser->defaultHandler) {
+ efree(parser->defaultHandler);
+ }
+ if (parser->unparsedEntityDeclHandler) {
+ efree(parser->unparsedEntityDeclHandler);
+ }
+ if (parser->notationDeclHandler) {
+ efree(parser->notationDeclHandler);
+ }
+ if (parser->externalEntityRefHandler) {
+ efree(parser->externalEntityRefHandler);
+ }
+ if (parser->unknownEncodingHandler) {
+ efree(parser->unknownEncodingHandler);
+ }
+ if (parser->baseURI) {
+ efree(parser->baseURI);
+ }
+
+ efree(parser);
+}
+
+/* }}} */
+ /* {{{ xml_set_handler() */
+
+static void
+xml_set_handler(char **nameBufp, pval *data)
+{
+ if (data->value.str.len > 0) {
+ if (*nameBufp != NULL) {
+ efree(*nameBufp);
+ }
+ *nameBufp = php3i_pval_strdup(data);
+ } else {
+ if (*nameBufp != NULL) {
+ efree(*nameBufp);
+ }
+ *nameBufp = NULL;
+ }
+}
+
+/* }}} */
+ /* {{{ xml_call_handler() */
+
+static pval *
+xml_call_handler(xml_parser *parser, char *funcName, int argc, pval **argv)
+{
+ if (parser && funcName) {
+ pval *retval, *func;
+ int i;
+ HashTable *function_table;
+
+ func = php3i_string_pval(funcName);
+ retval = emalloc(sizeof(pval));
+ /* We cannot call internal variables from a function module as
+ it breaks any chance of compiling it as a module on windows.
+ Instead, we create a callback function. */
+ function_table=php3i_get_function_table();
+ if (call_user_function(function_table, NULL, func, retval, argc, argv) == FAILURE) {
+ php3tls_pval_destructor(retval);
+ efree(retval);
+ return NULL;
+ }
+ php3tls_pval_destructor(func);
+ efree(func);
+ for (i = 0; i < argc; i++) {
+ php3tls_pval_destructor(argv[i]);
+ efree(argv[i]);
+ }
+ return retval;
+ }
+ return NULL;
+}
+
+/* }}} */
+ /* {{{ xml_encode_iso_8859_1() */
+
+inline static unsigned short
+xml_encode_iso_8859_1(unsigned char c)
+{
+ php3_printf("c=%d ", c);
+ return (unsigned short)c;
+}
+
+/* }}} */
+ /* {{{ xml_decode_iso_8859_1() */
+
+inline static char
+xml_decode_iso_8859_1(unsigned short c)
+{
+ return (char)(c > 0xff ? '?' : c);
+}
+
+/* }}} */
+ /* {{{ xml_encode_us_ascii() */
+
+inline static unsigned short
+xml_encode_us_ascii(char c)
+{
+ return (unsigned short)c;
+}
+
+/* }}} */
+ /* {{{ xml_decode_us_ascii() */
+
+inline static char
+xml_decode_us_ascii(unsigned short c)
+{
+ return (char)(c > 0x7f ? '?' : c);
+}
+
+/* }}} */
+ /* {{{ xml_get_encoding() */
+
+static xml_encoding *
+xml_get_encoding(const XML_Char *name)
+{
+ xml_encoding *enc = &xml_encodings[0];
+
+ while (enc && enc->name) {
+ if (strcasecmp(name, enc->name) == 0) {
+ return enc;
+ }
+ enc++;
+ }
+ return NULL;
+}
+
+/* }}} */
+ /* {{{ xml_utf8_encode */
+static XML_Char *
+xml_utf8_encode(const char *s, int len, int *newlen, const XML_Char *encoding)
+{
+ int pos = len;
+ char *newbuf;
+ unsigned short c;
+ unsigned short (*encoder)(char) = NULL;
+ xml_encoding *enc = xml_get_encoding(encoding);
+
+ *newlen = 0;
+ if (enc) {
+ encoder = enc->encoding_function;
+ } else {
+ /* If the target encoding was unknown, fail */
+ return NULL;
+ }
+ if (encoder == NULL) {
+ /* If no encoder function was specified, return the data as-is.
+ */
+ newbuf = emalloc(len);
+ memcpy(newbuf, s, len);
+ *newlen = len;
+ return newbuf;
+ }
+ /* This is the theoretical max (will never get beyond len * 2 as long
+ * as we are converting from single-byte characters, though) */
+ newbuf = emalloc(len * 4);
+ while (pos > 0) {
+ c = encoder ? encoder((unsigned char)(*s)) : (unsigned short)(*s);
+ if (c < 0x80) {
+ newbuf[(*newlen)++] = c;
+ } else if (c < 0x800) {
+ newbuf[(*newlen)++] = (0xc0 | (c >> 6));
+ newbuf[(*newlen)++] = (0x80 | (c & 0x3f));
+ } else if (c < 0x10000) {
+ newbuf[(*newlen)++] = (0xe0 | (c >> 12));
+ newbuf[(*newlen)++] = (0xc0 | ((c >> 6) & 0x3f));
+ newbuf[(*newlen)++] = (0x80 | (c & 0x3f));
+ } else if (c < 0x200000) {
+ newbuf[(*newlen)++] = (0xf0 | (c >> 18));
+ newbuf[(*newlen)++] = (0xe0 | ((c >> 12) & 0x3f));
+ newbuf[(*newlen)++] = (0xc0 | ((c >> 6) & 0x3f));
+ newbuf[(*newlen)++] = (0x80 | (c & 0x3f));
+ }
+ pos--;
+ s++;
+ }
+ if (*newlen < len * 4) {
+ newbuf = erealloc(newbuf, *newlen);
+ }
+ return newbuf;
+}
+/* }}} */
+ /* {{{ xml_utf8_decode */
+static char *
+xml_utf8_decode(const XML_Char *s, int len, int *newlen, const XML_Char *encoding)
+{
+ int pos = len;
+ char *newbuf = emalloc(len);
+ unsigned short c;
+ char (*decoder)(unsigned short) = NULL;
+ xml_encoding *enc = xml_get_encoding(encoding);
+
+ *newlen = 0;
+ if (enc) {
+ decoder = enc->decoding_function;
+ }
+ if (decoder == NULL) {
+ /* If the target encoding was unknown, or no decoder function
+ * was specified, return the UTF-8-encoded data as-is.
+ */
+ memcpy(newbuf, s, len);
+ *newlen = len;
+ return newbuf;
+ }
+ while (pos > 0) {
+ c = (unsigned char)(*s);
+ if (c >= 0xf0) { /* four bytes encoded, 21 bits */
+ c = ((s[0]&7)<<18) | ((s[1]&63)<<12) | ((s[2]&63)<<6) | (s[3]&63);
+ s += 4;
+ pos -= 4;
+ } else if (c >= 0xe0) { /* three bytes encoded, 16 bits */
+ c = ((s[0]&63)<<12) | ((s[1]&63)<<6) | (s[2]&63);
+ s += 3;
+ pos -= 3;
+ } else if (c >= 0xc0) { /* two bytes encoded, 11 bits */
+ c = ((s[0]&63)<<6) | (s[1]&63);
+ s += 2;
+ pos -= 2;
+ } else {
+ s++;
+ pos--;
+ }
+ newbuf[*newlen] = decoder ? decoder(c) : c;
+ ++*newlen;
+ }
+ if (*newlen < len) {
+ newbuf = erealloc(newbuf, *newlen);
+ }
+ return newbuf;
+}
+/* }}} */
+ /* {{{ php3i_xmlcharpval() */
+
+static pval *php3i_xmlcharpval(const XML_Char *s, int len, const XML_Char *encoding)
+{
+ pval *ret = emalloc(sizeof(pval));
+
+ if (s == NULL) {
+ var_reset(ret);
+ return ret;
+ }
+ if (len == 0) {
+ len = php3i_xmlcharlen(s);
+ }
+ ret->type = IS_STRING;
+ ret->value.str.val = xml_utf8_decode(s, len, &ret->value.str.len, encoding);
+ return ret;
+}
+
+/* }}} */
+ /* {{{ php3i_xmlcharlen() */
+
+static int php3i_xmlcharlen(const XML_Char *s)
+{
+ int len = 0;
+
+ while (*s) {
+ len++;
+ s++;
+ }
+ return len;
+}
+
+/* }}} */
+ /* {{{ php3i_xml_startElementHandler() */
+
+void php3i_xml_startElementHandler(void *userData, const char *name,
+ const char **attributes)
+{
+ xml_parser *parser = (xml_parser *)userData;
+ XML_TLS_VARS;
+
+ if (parser && parser->startElementHandler) {
+ pval *retval, *args[3];
+
+ if (parser->case_folding) {
+ name = _php3_strtoupper(estrdup(name));
+ }
+ args[0] = php3i_long_pval(parser->index);
+ args[1] = php3i_string_pval(name);
+ args[2] = emalloc(sizeof(pval));
+ array_init(args[2]);
+ while (attributes && *attributes) {
+ char *key = (char *)attributes[0];
+ char *value = (char *)attributes[1];
+ if (parser->case_folding) {
+ key = _php3_strtoupper(estrdup(key));
+ }
+ add_assoc_string(args[2], key, value, 1);
+ if (parser->case_folding) {
+ efree(key);
+ }
+ attributes += 2;
+ }
+ if ((retval = xml_call_handler(parser, parser->startElementHandler, 3, args))) {
+ php3tls_pval_destructor(retval);
+ efree(retval);
+ }
+ if (parser->case_folding) {
+ efree((char *)name);
+ }
+ }
+}
+
+/* }}} */
+ /* {{{ php3i_xml_endElementHandler() */
+
+void php3i_xml_endElementHandler(void *userData, const char *name)
+{
+ xml_parser *parser = (xml_parser *)userData;
+ XML_TLS_VARS;
+
+ if (parser && parser->endElementHandler) {
+ pval *retval, *args[2];
+
+ if (parser->case_folding) {
+ name = _php3_strtoupper(estrdup(name));
+ }
+ args[0] = php3i_long_pval(parser->index);
+ args[1] = php3i_string_pval(name);
+ if ((retval = xml_call_handler(parser, parser->endElementHandler, 2, args))) {
+ php3tls_pval_destructor(retval);
+ efree(retval);
+ }
+ if (parser->case_folding) {
+ efree((char *)name);
+ }
+ }
+}
+
+/* }}} */
+ /* {{{ php3i_xml_characterDataHandler() */
+
+void php3i_xml_characterDataHandler(void *userData, const XML_Char *s, int len)
+{
+ xml_parser *parser = (xml_parser *)userData;
+ XML_TLS_VARS;
+
+ if (parser && parser->characterDataHandler) {
+ pval *retval, *args[2];
+
+ args[0] = php3i_long_pval(parser->index);
+ args[1] = php3i_xmlcharpval(s, len, parser->target_encoding);
+ if ((retval = xml_call_handler(parser, parser->characterDataHandler, 2, args))) {
+ php3tls_pval_destructor(retval);
+ efree(retval);
+ }
+ }
+}
+
+/* }}} */
+ /* {{{ php3i_xml_processingInstructionHandler() */
+
+void php3i_xml_processingInstructionHandler(void *userData,
+ const XML_Char *target,
+ const XML_Char *data)
+{
+ xml_parser *parser = (xml_parser *)userData;
+ XML_TLS_VARS;
+
+ if (parser && parser->processingInstructionHandler) {
+ pval *retval, *args[3];
+
+ args[0] = php3i_long_pval(parser->index);
+ args[1] = php3i_xmlcharpval(target, 0, parser->target_encoding);
+ args[2] = php3i_xmlcharpval(data, 0, parser->target_encoding);
+ if ((retval = xml_call_handler(parser, parser->processingInstructionHandler, 3, args))) {
+ php3tls_pval_destructor(retval);
+ efree(retval);
+ }
+ }
+}
+
+/* }}} */
+ /* {{{ php3i_xml_defaultHandler() */
+
+void php3i_xml_defaultHandler(void *userData, const XML_Char *s, int len)
+{
+ xml_parser *parser = (xml_parser *)userData;
+ XML_TLS_VARS;
+
+ if (parser && parser->defaultHandler) {
+ pval *retval, *args[2];
+
+ args[0] = php3i_long_pval(parser->index);
+ args[1] = php3i_xmlcharpval(s, len, parser->target_encoding);
+ if ((retval = xml_call_handler(parser, parser->defaultHandler, 2, args))) {
+ php3tls_pval_destructor(retval);
+ efree(retval);
+ }
+ }
+}
+
+/* }}} */
+ /* {{{ php3i_xml_unparsedEntityDeclHandler() */
+
+void php3i_xml_unparsedEntityDeclHandler(void *userData,
+ const XML_Char *entityName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId,
+ const XML_Char *notationName)
+{
+ xml_parser *parser = (xml_parser *)userData;
+ XML_TLS_VARS;
+
+ if (parser && parser->unparsedEntityDeclHandler) {
+ pval *retval, *args[5];
+
+ args[0] = php3i_long_pval(parser->index);
+ args[1] = php3i_xmlcharpval(entityName, 0, parser->target_encoding);
+ args[2] = php3i_xmlcharpval(base, 0, parser->target_encoding);
+ args[3] = php3i_xmlcharpval(systemId, 0, parser->target_encoding);
+ args[4] = php3i_xmlcharpval(publicId, 0, parser->target_encoding);
+ args[5] = php3i_xmlcharpval(notationName, 0, parser->target_encoding);
+ if ((retval = xml_call_handler(parser, parser->unparsedEntityDeclHandler, 6, args))) {
+ php3tls_pval_destructor(retval);
+ efree(retval);
+ }
+ }
+}
+
+/* }}} */
+ /* {{{ php3i_xml_notationDeclHandler() */
+
+void
+php3i_xml_notationDeclHandler(void *userData,
+ const XML_Char *notationName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId)
+{
+ xml_parser *parser = (xml_parser *)userData;
+ XML_TLS_VARS;
+
+ if (parser && parser->notationDeclHandler) {
+ pval *retval, *args[5];
+
+ args[0] = php3i_long_pval(parser->index);
+ args[1] = php3i_xmlcharpval(notationName, 0, parser->target_encoding);
+ args[2] = php3i_xmlcharpval(base, 0, parser->target_encoding);
+ args[3] = php3i_xmlcharpval(systemId, 0, parser->target_encoding);
+ args[4] = php3i_xmlcharpval(publicId, 0, parser->target_encoding);
+ if ((retval = xml_call_handler(parser, parser->notationDeclHandler, 5, args))) {
+ php3tls_pval_destructor(retval);
+ efree(retval);
+ }
+ }
+}
+
+/* }}} */
+ /* {{{ php3i_xml_externalEntityRefHandler() */
+
+int
+php3i_xml_externalEntityRefHandler(XML_Parser parserPtr,
+ const XML_Char *openEntityNames,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId)
+{
+ xml_parser *parser = XML_GetUserData(parserPtr);
+ int ret = 0; /* abort if no handler is set (should be configurable?) */
+ XML_TLS_VARS;
+
+ if (parser && parser->externalEntityRefHandler) {
+ pval *retval, *args[5];
+
+ args[0] = php3i_long_pval(parser->index);
+ args[1] = php3i_xmlcharpval(openEntityNames, 0, parser->target_encoding);
+ args[2] = php3i_xmlcharpval(base, 0, parser->target_encoding);
+ args[3] = php3i_xmlcharpval(systemId, 0, parser->target_encoding);
+ args[4] = php3i_xmlcharpval(publicId, 0, parser->target_encoding);
+ if ((retval = xml_call_handler(parser, parser->externalEntityRefHandler, 5, args))) {
+ convert_to_long(retval);
+ ret = retval->value.lval;
+ efree(retval);
+ } else {
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+/* }}} */
+
+/* }}} */
+
+/************************* EXTENSION FUNCTIONS *************************/
+
+/* {{{ int xml_parser_create() */
+
+PHP_FUNCTION(xml_parser_create)
+{
+ xml_parser *parser;
+ int id, argc;
+ pval *encodingArg = NULL;
+ XML_Char *encoding;
+ char thisfunc[] = "xml_parser_create";
+ XML_TLS_VARS;
+
+ argc = ARG_COUNT(ht);
+
+ if (argc > 1 || getParameters(ht, argc, &encodingArg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if (argc == 1) {
+ convert_to_string(encodingArg);
+ /* The supported encoding types are hardcoded here because
+ * we are limited to the encodings supported by expat/xmltok.
+ */
+ if (strncasecmp(encodingArg->value.str.val, "ISO-8859-1",
+ encodingArg->value.str.len) == 0) {
+ encoding = "ISO-8859-1";
+ } else if (strncasecmp(encodingArg->value.str.val, "UTF-8",
+ encodingArg->value.str.len) == 0) {
+ encoding = "UTF-8";
+ } else if (strncasecmp(encodingArg->value.str.val, "US-ASCII",
+ encodingArg->value.str.len) == 0) {
+ encoding = "US-ASCII";
+ } else { /* UTF-16 not supported */
+ php3_error(E_WARNING, "%s: unsupported source encoding \"%s\"",
+ thisfunc, encodingArg->value.str.val);
+ RETURN_FALSE;
+ }
+ } else {
+ encoding = XML_GLOBAL(php3_xml_module).default_encoding;
+ }
+
+ parser = ecalloc(sizeof(xml_parser), 1);
+ parser->parser = XML_ParserCreate(encoding);
+ parser->target_encoding = encoding;
+ XML_SetUserData(parser->parser, parser);
+ XML_SetElementHandler(parser->parser, php3i_xml_startElementHandler, php3i_xml_endElementHandler);
+ XML_SetCharacterDataHandler(parser->parser, php3i_xml_characterDataHandler);
+ XML_SetProcessingInstructionHandler(parser->parser, php3i_xml_processingInstructionHandler);
+ XML_SetDefaultHandler(parser->parser, php3i_xml_defaultHandler);
+ XML_SetUnparsedEntityDeclHandler(parser->parser, php3i_xml_unparsedEntityDeclHandler);
+ XML_SetNotationDeclHandler(parser->parser, php3i_xml_notationDeclHandler);
+ XML_SetExternalEntityRefHandler(parser->parser, php3i_xml_externalEntityRefHandler);
+ id = php3_list_insert(parser, XML_GLOBAL(php3_xml_module).le_xml_parser);
+ parser = xml_get_parser(id, thisfunc, list);
+ parser->index = id;
+ parser->case_folding = 1;
+
+ RETVAL_LONG(id);
+}
+
+/* }}} */
+/* {{{ int xml_set_element_handler(int pind, string shdl, string ehdl) */
+
+PHP_FUNCTION(xml_set_element_handler)
+{
+ xml_parser *parser;
+ pval *pind, *shdl, *ehdl;
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 3 ||
+ getParameters(ht, 3, &pind, &shdl, &ehdl) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(pind);
+ convert_to_string(shdl);
+ convert_to_string(ehdl);
+ parser = xml_get_parser(pind->value.lval, "xml_set_element_handler", list);
+ if (parser == NULL) {
+ RETURN_FALSE;
+ }
+ xml_set_handler(&parser->startElementHandler, shdl);
+ xml_set_handler(&parser->endElementHandler, ehdl);
+ RETVAL_TRUE;
+}
+
+/* }}} */
+/* {{{ int xml_set_character_data_handler(int pind, string hdl) */
+
+PHP_FUNCTION(xml_set_character_data_handler)
+{
+ xml_parser *parser;
+ pval *pind, *hdl;
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &pind, &hdl) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(pind);
+ convert_to_string(hdl);
+ parser = xml_get_parser(pind->value.lval, "xml_set_character_data_handler", list);
+ if (parser == NULL) {
+ RETURN_FALSE;
+ }
+ xml_set_handler(&parser->characterDataHandler, hdl);
+ RETVAL_TRUE;
+}
+
+/* }}} */
+/* {{{ int xml_set_processing_instruction_handler(int pind, string hdl) */
+
+PHP_FUNCTION(xml_set_processing_instruction_handler)
+{
+ xml_parser *parser;
+ pval *pind, *hdl;
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &pind, &hdl) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(pind);
+ convert_to_string(hdl);
+ parser = xml_get_parser(pind->value.lval, "xml_set_processing_instruction_handler", list);
+ if (parser == NULL) {
+ RETURN_FALSE;
+ }
+ xml_set_handler(&parser->processingInstructionHandler, hdl);
+ RETVAL_TRUE;
+}
+
+/* }}} */
+/* {{{ int xml_set_default_handler(int pind, string hdl) */
+
+PHP_FUNCTION(xml_set_default_handler)
+{
+ xml_parser *parser;
+ pval *pind, *hdl;
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &pind, &hdl) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(pind);
+ convert_to_string(hdl);
+ parser = xml_get_parser(pind->value.lval, "xml_set_default_handler", list);
+ if (parser == NULL) {
+ RETURN_FALSE;
+ }
+ xml_set_handler(&parser->defaultHandler, hdl);
+ RETVAL_TRUE;
+}
+
+/* }}} */
+/* {{{ int xml_set_unparsed_entity_decl_handler(int pind, string hdl) */
+
+PHP_FUNCTION(xml_set_unparsed_entity_decl_handler)
+{
+ xml_parser *parser;
+ pval *pind, *hdl;
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &pind, &hdl) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(pind);
+ convert_to_string(hdl);
+ parser = xml_get_parser(pind->value.lval, "xml_set_unparsed_entity_decl_handler", list);
+ if (parser == NULL) {
+ RETURN_FALSE;
+ }
+ xml_set_handler(&parser->unparsedEntityDeclHandler, hdl);
+ RETVAL_TRUE;
+}
+
+/* }}} */
+/* {{{ int xml_set_notation_decl_handler(int pind, string hdl) */
+
+PHP_FUNCTION(xml_set_notation_decl_handler)
+{
+ xml_parser *parser;
+ pval *pind, *hdl;
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &pind, &hdl) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(pind);
+ convert_to_string(hdl);
+ parser = xml_get_parser(pind->value.lval, "xml_set_notation_decl_handler", list);
+ if (parser == NULL) {
+ RETURN_FALSE;
+ }
+ xml_set_handler(&parser->notationDeclHandler, hdl);
+ RETVAL_TRUE;
+}
+
+/* }}} */
+/* {{{ int xml_set_external_entity_ref_handler(int pind, string hdl) */
+
+PHP_FUNCTION(xml_set_external_entity_ref_handler)
+{
+ xml_parser *parser;
+ pval *pind, *hdl;
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &pind, &hdl) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(pind);
+ convert_to_string(hdl);
+ parser = xml_get_parser(pind->value.lval, "xml_set_external_entity_ref_handler", list);
+ if (parser == NULL) {
+ RETURN_FALSE;
+ }
+ xml_set_handler(&parser->externalEntityRefHandler, hdl);
+ RETVAL_TRUE;
+}
+
+/* }}} */
+/* {{{ int xml_parse(int pind, string data[, int isFinal]) */
+
+PHP_FUNCTION(xml_parse)
+{
+ xml_parser *parser;
+ pval *pind, *data, *final;
+ int argc, isFinal, ret;
+ XML_TLS_VARS;
+
+ argc = ARG_COUNT(ht);
+ if (argc < 2 || argc > 3 || getParameters(ht, argc, &pind, &data, &final) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(pind);
+ convert_to_string(data);
+ if (argc == 3) {
+ convert_to_long(final);
+ isFinal = final->value.lval;
+ } else {
+ isFinal = 0;
+ }
+ parser = xml_get_parser(pind->value.lval, "XML_Parse", list);
+ if (parser == NULL) {
+ RETURN_FALSE;
+ }
+ fflush(stdout);
+ ret = XML_Parse(parser->parser, data->value.str.val, data->value.str.len, isFinal);
+ RETVAL_LONG(ret);
+}
+
+/* }}} */
+/* {{{ int xml_get_error_code(int pind) */
+
+PHP_FUNCTION(xml_get_error_code)
+{
+ xml_parser *parser;
+ pval *pind;
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &pind) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(pind);
+ parser = xml_get_parser(pind->value.lval, "xml_get_error_code", list);
+ if (parser == NULL) {
+ RETURN_FALSE;
+ }
+ RETVAL_LONG((long)XML_GetErrorCode(parser->parser));
+}
+
+/* }}} */
+/* {{{ string xml_error_string(int code) */
+
+PHP_FUNCTION(xml_error_string)
+{
+ pval *code;
+ char *str;
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &code) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(code);
+ str = (char *)XML_ErrorString((int)code->value.lval);
+ if (str) {
+ RETVAL_STRING(str, 1);
+ }
+}
+
+/* }}} */
+/* {{{ int xml_get_current_line_number(int pind) */
+
+PHP_FUNCTION(xml_get_current_line_number)
+{
+ xml_parser *parser;
+ pval *pind;
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &pind) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(pind);
+ parser = xml_get_parser(pind->value.lval, "xml_get_current_line_number", list);
+ if (parser == NULL) {
+ RETURN_FALSE;
+ }
+ RETVAL_LONG(XML_GetCurrentLineNumber(parser->parser));
+}
+
+/* }}} */
+/* {{{ int xml_get_current_column_number(int pind) */
+
+PHP_FUNCTION(xml_get_current_column_number)
+{
+ xml_parser *parser;
+ pval *pind;
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &pind) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(pind);
+ parser = xml_get_parser(pind->value.lval, "xml_get_current_column_number", list);
+ if (parser == NULL) {
+ RETURN_FALSE;
+ }
+ RETVAL_LONG(XML_GetCurrentColumnNumber(parser->parser));
+}
+
+/* }}} */
+/* {{{ int xml_get_current_byte_index(int pind) */
+
+PHP_FUNCTION(xml_get_current_byte_index)
+{
+ xml_parser *parser;
+ pval *pind;
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &pind) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(pind);
+ parser = xml_get_parser(pind->value.lval, "xml_get_current_byte_index", list);
+ if (parser == NULL) {
+ RETURN_FALSE;
+ }
+ RETVAL_LONG(XML_GetCurrentByteIndex(parser->parser));
+}
+
+/* }}} */
+/* {{{ int xml_parser_free(int pind) */
+
+PHP_FUNCTION(xml_parser_free)
+{
+ pval *pind;
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &pind) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(pind);
+ if (php3_list_delete(pind->value.lval) == FAILURE) {
+ RETURN_FALSE;
+ }
+ RETVAL_TRUE;
+}
+
+/* }}} */
+/* {{{ int xml_parser_set_option(int pind, int option, mixed value) */
+
+PHP_FUNCTION(xml_parser_set_option)
+{
+ xml_parser *parser;
+ pval *pind, *opt, *val;
+ char thisfunc[] = "xml_parser_set_option";
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &pind, &opt, &val) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(pind);
+ convert_to_long(opt);
+ parser = xml_get_parser(pind->value.lval, thisfunc, list);
+ if (parser == NULL) {
+ RETURN_FALSE;
+ }
+ switch (opt->value.lval) {
+ case PHP3_XML_OPTION_CASE_FOLDING:
+ convert_to_long(val);
+ parser->case_folding = val->value.lval;
+ break;
+ case PHP3_XML_OPTION_TARGET_ENCODING: {
+ xml_encoding *enc = xml_get_encoding(val->value.str.val);
+ if (enc == NULL) {
+ php3_error(E_WARNING, "%s: unsupported target encoding \"%s\"",
+ thisfunc, val->value.str.val);
+ RETURN_FALSE;
+ }
+ parser->target_encoding = enc->name;
+ break;
+ }
+ default:
+ php3_error(E_WARNING, "%s: unknown option", thisfunc);
+ RETURN_FALSE;
+ break;
+ }
+ RETVAL_TRUE;
+}
+
+/* }}} */
+/* {{{ int xml_parser_get_option(int pind, int option) */
+
+PHP_FUNCTION(xml_parser_get_option)
+{
+ xml_parser *parser;
+ pval *pind, *opt;
+ char thisfunc[] = "xml_parser_get_option";
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &pind, &opt) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(pind);
+ convert_to_long(opt);
+ parser = xml_get_parser(pind->value.lval, thisfunc, list);
+ if (parser == NULL) {
+ RETURN_FALSE;
+ }
+ switch (opt->value.lval) {
+ case PHP3_XML_OPTION_CASE_FOLDING:
+ RETURN_LONG(parser->case_folding);
+ break;
+ case PHP3_XML_OPTION_TARGET_ENCODING:
+ RETURN_STRING(parser->target_encoding, 1);
+ break;
+ default:
+ php3_error(E_WARNING, "%s: unknown option", thisfunc);
+ RETURN_FALSE;
+ break;
+ }
+ RETVAL_FALSE;
+}
+
+/* }}} */
+/* {{{ string utf8_encode(string data) */
+
+PHP_FUNCTION(utf8_encode)
+{
+ pval *arg;
+ XML_Char *encoded;
+ int len;
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string(arg);
+ encoded = xml_utf8_encode(arg->value.str.val, arg->value.str.len, &len, "ISO-8859-1");
+ if (encoded == NULL) {
+ RETURN_FALSE;
+ }
+ RETVAL_STRINGL(encoded, len, 0);
+}
+
+/* }}} */
+/* {{{ string utf8_decode(string data) */
+
+PHP_FUNCTION(utf8_decode)
+{
+ pval *arg;
+ XML_Char *decoded;
+ int len;
+ XML_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string(arg);
+ decoded = xml_utf8_decode(arg->value.str.val, arg->value.str.len, &len, "ISO-8859-1");
+ if (decoded == NULL) {
+ RETURN_FALSE;
+ }
+ RETVAL_STRINGL(decoded, len, 0);
+}
+
+/* }}} */
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/ext/zlib/Makefile.am b/ext/zlib/Makefile.am
new file mode 100644
index 0000000000..ef7d3ea49c
--- /dev/null
+++ b/ext/zlib/Makefile.am
@@ -0,0 +1,6 @@
+# $Id$
+
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_zlib.a
+libphpext_zlib_a_SOURCES=zlib.c
+
diff --git a/ext/zlib/Makefile.in b/ext/zlib/Makefile.in
new file mode 100644
index 0000000000..24bf631fea
--- /dev/null
+++ b/ext/zlib/Makefile.in
@@ -0,0 +1,270 @@
+# Makefile.in generated automatically by automake 1.3 from Makefile.am
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# $Id$
+
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DISTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+APACHE_INCLUDE = @APACHE_INCLUDE@
+APACHE_TARGET = @APACHE_TARGET@
+APXS = @APXS@
+APXS_LDFLAGS = @APXS_LDFLAGS@
+BINNAME = @BINNAME@
+CC = @CC@
+CFLAGS = @CFLAGS@
+CFLAGS_SHLIB = @CFLAGS_SHLIB@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+EXTINFO_DEPS = @EXTINFO_DEPS@
+EXTRA_LIBS = @EXTRA_LIBS@
+EXT_LIBS = @EXT_LIBS@
+EXT_SUBDIRS = @EXT_SUBDIRS@
+FHTTPD_LIB = @FHTTPD_LIB@
+FHTTPD_TARGET = @FHTTPD_TARGET@
+HSREGEX = @HSREGEX@
+INSTALL_IT = @INSTALL_IT@
+LDFLAGS_SHLIB = @LDFLAGS_SHLIB@
+LDFLAGS_SHLIB_EXPORT = @LDFLAGS_SHLIB_EXPORT@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+PERL_PATH = @PERL_PATH@
+PHP_BUILD_DATE = @PHP_BUILD_DATE@
+PHP_DEBUG = @PHP_DEBUG@
+PHP_LIBS = @PHP_LIBS@
+PHP_VERSION = @PHP_VERSION@
+PROG_SENDMAIL = @PROG_SENDMAIL@
+RANLIB = @RANLIB@
+RDYNAMIC_LFLAGS = @RDYNAMIC_LFLAGS@
+REGEX_LIB = @REGEX_LIB@
+STRONGHOLD = @STRONGHOLD@
+VERSION = @VERSION@
+WARNING_LEVEL = @WARNING_LEVEL@
+YACC = @YACC@
+
+INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend
+noinst_LIBRARIES=libphpext_zlib.a
+libphpext_zlib_a_SOURCES=zlib.c
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+libphpext_zlib_a_LIBADD =
+libphpext_zlib_a_OBJECTS = zlib.o
+AR = ar
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP = --best
+SOURCES = $(libphpext_zlib_a_SOURCES)
+OBJECTS = $(libphpext_zlib_a_OBJECTS)
+
+all: Makefile $(LIBRARIES)
+
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s
+$(srcdir)/Makefile.in: @MAINT@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps ext/zlib/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+ $(COMPILE) -c $<
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libphpext_zlib.a: $(libphpext_zlib_a_OBJECTS) $(libphpext_zlib_a_DEPENDENCIES)
+ -rm -f libphpext_zlib.a
+ $(AR) cru libphpext_zlib.a $(libphpext_zlib_a_OBJECTS) $(libphpext_zlib_a_LIBADD)
+ $(RANLIB) libphpext_zlib.a
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = ext/zlib
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file; \
+ done
+info:
+dvi:
+check: all
+ $(MAKE)
+installcheck:
+install-exec:
+ @$(NORMAL_INSTALL)
+
+install-data:
+ @$(NORMAL_INSTALL)
+
+install: install-exec install-data all
+ @:
+
+uninstall:
+
+install-strip:
+ $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
+installdirs:
+
+
+mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -rm -f Makefile $(DISTCLEANFILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-tags mostlyclean-generic
+
+clean: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
+ mostlyclean
+
+distclean: distclean-noinstLIBRARIES distclean-compile distclean-tags \
+ distclean-generic clean
+ -rm -f config.status
+
+maintainer-clean: maintainer-clean-noinstLIBRARIES \
+ maintainer-clean-compile maintainer-clean-tags \
+ maintainer-clean-generic distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info dvi installcheck \
+install-exec install-data install uninstall all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/ext/zlib/config.h.stub b/ext/zlib/config.h.stub
new file mode 100644
index 0000000000..5d6dcad205
--- /dev/null
+++ b/ext/zlib/config.h.stub
@@ -0,0 +1,2 @@
+/* Define if you have the zlib library */
+#define HAVE_ZLIB 0
diff --git a/ext/zlib/config.m4 b/ext/zlib/config.m4
new file mode 100644
index 0000000000..d9d3d75554
--- /dev/null
+++ b/ext/zlib/config.m4
@@ -0,0 +1,38 @@
+dnl $Id$
+
+AC_MSG_CHECKING(whether to include zlib support)
+AC_ARG_WITH(zlib,
+[ --with-zlib[=DIR] Include zlib support (requires zlib >= 1.0.9).
+ DIR is the zlib install directory,
+ defaults to /usr.],
+[
+ case "$withval" in
+ no)
+ AC_MSG_RESULT(no) ;;
+ yes)
+ AC_MSG_RESULT(yes)
+ PHP_EXTENSION(zlib)
+ AC_CHECK_LIB(z, gzgets, [AC_DEFINE(HAVE_ZLIB) ZLIB_LIBS="-lz"],
+ [AC_MSG_ERROR(Zlib module requires zlib >= 1.0.9.)])
+ EXTRA_LIBS="$EXTRA_LIBS $ZLIB_LIBS"
+ ;;
+ *)
+ test -f $withval/include/zlib/zlib.h && ZLIB_INCLUDE="-I$withval/include/zlib"
+ test -f $withval/include/zlib.h && ZLIB_INCLUDE="-I$withval/include"
+ if test -n "$ZLIB_INCLUDE" ; then
+ AC_MSG_RESULT(yes)
+ PHP_EXTENSION(zlib)
+ old_LIBS=$LIBS
+ LIBS="$LIBS -L$withval/lib"
+ AC_CHECK_LIB(z, gzgets, [AC_DEFINE(HAVE_ZLIB) ZLIB_LIBS="-L$withval/lib -lz"],
+ [AC_MSG_ERROR(Zlib module requires zlib >= 1.0.9.)])
+ LIBS=$old_LIBS
+ EXTRA_LIBS="$EXTRA_LIBS $ZLIB_LIBS"
+ INCLUDES="$INCLUDES $ZLIB_INCLUDE"
+ else
+ AC_MSG_RESULT(no)
+ fi ;;
+ esac
+],[
+ AC_MSG_RESULT(no)
+])
diff --git a/ext/zlib/php3_zlib.h b/ext/zlib/php3_zlib.h
new file mode 100644
index 0000000000..22052fbab4
--- /dev/null
+++ b/ext/zlib/php3_zlib.h
@@ -0,0 +1,63 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU General Public License as published by |
+ | the Free Software Foundation; either version 2 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU General Public License |
+ | along with this program; if not, write to the Free Software |
+ | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
+ +----------------------------------------------------------------------+
+ | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
+ | Stefan Röhrich <sr@linux.de> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifndef _PHP3_ZLIB_H
+#define _PHP3_ZLIB_H
+
+#if COMPILE_DL
+#undef HAVE_ZLIB
+#define HAVE_ZLIB 1
+#endif
+
+#if HAVE_ZLIB
+
+extern php3_module_entry php3_zlib_module_entry;
+#define php3_zlib_module_ptr &php3_zlib_module_entry
+
+extern int php3_minit_zlib(INIT_FUNC_ARGS);
+extern int php3_mshutdown_zlib(SHUTDOWN_FUNC_ARGS);
+extern void php3_info_zlib(void);
+extern void php3_gzopen(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_gzclose(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_gzeof(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_gzread(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_gzgetc(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_gzgets(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_gzgetss(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_gzwrite(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_gzrewind(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_gztell(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_gzseek(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_gzpassthru(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_readgzfile(INTERNAL_FUNCTION_PARAMETERS);
+extern void php3_gzfile(INTERNAL_FUNCTION_PARAMETERS);
+
+#else
+#define php3_zlib_module_ptr NULL
+#endif /* HAVE_ZLIB */
+
+#endif /* _PHP3_ZLIB_H */
diff --git a/ext/zlib/setup.stub b/ext/zlib/setup.stub
new file mode 100644
index 0000000000..158978766c
--- /dev/null
+++ b/ext/zlib/setup.stub
@@ -0,0 +1,7 @@
+# $Source$
+# $Id$
+
+define_option with-zlib 'zlib (>= 1.0.9) support? ' yesnodir \
+ 'no /usr zlib install' \
+' Whether to use the zlib support to read/write .gz-files.\n
+ Requires zlib version >= 1.0.9!'
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
new file mode 100644
index 0000000000..e8f80c4450
--- /dev/null
+++ b/ext/zlib/zlib.c
@@ -0,0 +1,926 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP HTML Embedded Scripting Language Version 3.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997,1998 PHP Development Team (See Credits file) |
+ +----------------------------------------------------------------------+
+ | This program is free software; you can redistribute it and/or modify |
+ | it under the terms of the GNU General Public License as published by |
+ | the Free Software Foundation; either version 2 of the License, or |
+ | (at your option) any later version. |
+ | |
+ | This program is distributed in the hope that it will be useful, |
+ | but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ | GNU General Public License for more details. |
+ | |
+ | You should have received a copy of the GNU General Public License |
+ | along with this program; if not, write to the Free Software |
+ | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
+ +----------------------------------------------------------------------+
+ | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> |
+ | Stefan Röhrich <sr@linux.de> |
+ +----------------------------------------------------------------------+
+ */
+/* $Id$ */
+#if !PHP_31 && defined(THREAD_SAFE)
+#undef THREAD_SAFE
+#endif
+#define IS_EXT_MODULE
+
+#ifdef THREAD_SAFE
+#include "tls.h"
+#endif
+#include "php.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#if (WIN32|WINNT)
+#include <windows.h>
+#include <winsock.h>
+#define O_RDONLY _O_RDONLY
+#if PHP_31
+#include "os/nt/param.h"
+#else
+#include "win32/param.h"
+#endif
+#else
+#include <sys/param.h>
+/* #include <sys/uio.h> */
+#endif
+#include "ext/standard/head.h"
+#include "safe_mode.h"
+#include "ext/standard/php3_standard.h"
+#include "php3_zlib.h"
+#include "fopen-wrappers.h"
+#if HAVE_PWD_H
+#if WIN32|WINNT
+#include "win32/pwd.h"
+#else
+#include <pwd.h>
+#endif
+#endif
+#include "snprintf.h"
+#if HAVE_ZLIB
+#if defined(HAVE_UNISTD_H) && (WIN32|WINNT)
+#undef HAVE_UNISTD_H
+#endif
+
+#include <zlib.h>
+
+#if COMPILE_DL
+#if PHP_31
+#include "ext/phpdl.h"
+#else
+#include "dl/phpdl.h"
+#endif
+#ifndef PUTS
+#define PUTS(a) php3_printf("%s",a)
+#endif
+#ifndef PUTC
+#define PUTC(a) PUTS(a)
+#endif
+#ifndef PHPWRITE
+#define PHPWRITE(a,n) php3_write((a),(n))
+#endif
+#endif
+
+
+
+#if defined(THREAD_SAFE)
+typedef struct zlib_global_struct{
+#endif
+ int gzgetss_state;
+ int le_zp;
+#if PHP_31
+ int magic_quotes_runtime;
+ int safe_mode;
+ char *include_path;
+ char *doc_root;
+#endif
+#if defined(THREAD_SAFE)
+}zlib_global_struct;
+#endif
+
+#if defined(THREAD_SAFE)
+DWORD ZLIBtls;
+static int numthreads=0;
+void *zlib_mutex;
+
+#define ZLIB_GLOBAL(a) zlib_globals->a
+
+#define ZLIB_TLS_VARS zlib_global_struct *PHP3_TLS_GET(ZLIBtls,zlib_globals);
+
+#else
+#define ZLIB_GLOBAL(a) a
+#define ZLIB_TLS_VARS
+#endif
+
+#if PHP_31
+# define ZLIB_INI(a) ZLIB_GLOBAL(a)
+#else
+# define ZLIB_INI(a) php3_ini.a
+#endif
+
+function_entry php3_zlib_functions[] = {
+ {"readgzfile", php3_readgzfile, NULL},
+ {"gzrewind", php3_gzrewind, NULL},
+ {"gzclose", php3_gzclose, NULL},
+ {"gzeof", php3_gzeof, NULL},
+ {"gzgetc", php3_gzgetc, NULL},
+ {"gzgets", php3_gzgets, NULL},
+ {"gzgetss", php3_gzgetss, NULL},
+ {"gzread", php3_gzread, NULL},
+ {"gzopen", php3_gzopen, NULL},
+ {"gzpassthru", php3_gzpassthru, NULL},
+ {"gzseek", php3_gzseek, NULL},
+ {"gztell", php3_gztell, NULL},
+ {"gzwrite", php3_gzwrite, NULL},
+ {"gzputs", php3_gzwrite, NULL},
+ {"gzfile", php3_gzfile, NULL},
+ {NULL, NULL, NULL}
+};
+
+php3_module_entry php3_zlib_module_entry = {
+ "zlib", php3_zlib_functions, php3_minit_zlib, php3_mshutdown_zlib, NULL, NULL, php3_info_zlib, STANDARD_MODULE_PROPERTIES
+};
+
+#if defined(COMPILE_DL)
+DLEXPORT php3_module_entry *get_module(void) { return &php3_zlib_module_entry; }
+#endif
+
+int php3_minit_zlib(INIT_FUNC_ARGS)
+{
+#ifdef THREAD_SAFE
+ zlib_global_struct *zlib_globals;
+ PHP3_MUTEX_ALLOC(zlib_mutex);
+ PHP3_MUTEX_LOCK(zlib_mutex);
+ numthreads++;
+ if (numthreads==1){
+ if (!PHP3_TLS_PROC_STARTUP(ZLIBtls)){
+ PHP3_MUTEX_UNLOCK(zlib_mutex);
+ PHP3_MUTEX_FREE(zlib_mutex);
+ return FAILURE;
+ }
+ }
+ PHP3_MUTEX_UNLOCK(zlib_mutex);
+ if(!PHP3_TLS_THREAD_INIT(ZLIBtls,zlib_globals,zlib_global_struct)){
+ PHP3_MUTEX_FREE(zlib_mutex);
+ return FAILURE;
+ }
+#endif
+ /* get our ini variables here */
+ cfg_get_long("safe_mode",&ZLIB_INI(safe_mode));
+ cfg_get_long("magic_quotes_runtime",&ZLIB_INI(magic_quotes_runtime));
+ cfg_get_string("doc_root",&ZLIB_INI(doc_root));
+ cfg_get_string("include_path",&ZLIB_INI(include_path));
+
+ ZLIB_GLOBAL(le_zp) = register_list_destructors(gzclose,NULL);
+ return SUCCESS;
+}
+
+int php3_mshutdown_zlib(SHUTDOWN_FUNC_ARGS){
+#if defined(THREAD_SAFE)
+ ZLIB_TLS_VARS;
+ PHP3_TLS_THREAD_FREE(zlib_globals);
+ PHP3_MUTEX_LOCK(zlib_mutex);
+ numthreads--;
+ if (numthreads<1){
+ PHP3_TLS_PROC_SHUTDOWN(ZLIBtls);
+ PHP3_MUTEX_UNLOCK(zlib_mutex);
+ PHP3_MUTEX_FREE(zlib_mutex);
+ return SUCCESS;
+ }
+ PHP3_MUTEX_UNLOCK(zlib_mutex);
+#endif
+ return SUCCESS;
+}
+
+void php3_info_zlib(void)
+{
+ PUTS("Zlib support active (compiled with ");
+ PUTS(ZLIB_VERSION);
+ PUTS(", linked with ");
+ PUTS((char *)zlibVersion());
+ PUTS(").");
+}
+
+static gzFile *php3_gzopen_with_path(char *filename, char *mode, char *path, char **opened_path);
+
+static gzFile php3_gzopen_wrapper(char *path, char *mode, int options)
+{
+ ZLIB_TLS_VARS;
+ if (options & USE_PATH && ZLIB_INI(include_path) != NULL) {
+ return php3_gzopen_with_path(path, mode, ZLIB_INI(include_path), NULL);
+ }
+ else {
+ if (options & ENFORCE_SAFE_MODE && ZLIB_INI(safe_mode) && (!_php3_checkuid(path,1))) {
+ return NULL;
+ }
+ if (_php3_check_open_basedir(path)) return NULL;
+ return gzopen(path, mode);
+ }
+}
+
+/*
+ * Tries to open a .gz-file with a PATH-style list of directories.
+ * If the filename starts with "." or "/", the path is ignored.
+ */
+static gzFile *php3_gzopen_with_path(char *filename, char *mode, char *path, char **opened_path)
+{
+ char *pathbuf, *ptr, *end;
+ char trypath[MAXPATHLEN + 1];
+ struct stat sb;
+ gzFile *zp;
+ ZLIB_TLS_VARS;
+
+ if (opened_path) {
+ *opened_path = NULL;
+ }
+
+ /* Relative path open */
+ if (*filename == '.') {
+ if (ZLIB_INI(safe_mode) &&(!_php3_checkuid(filename,2))) {
+ return(NULL);
+ }
+ if (_php3_check_open_basedir(filename)) return NULL;
+ zp = gzopen(filename, mode);
+ if (zp && opened_path) {
+ *opened_path = expand_filepath(filename);
+ }
+ return zp;
+ }
+
+ /* Absolute path open - prepend document_root in safe mode */
+#if WIN32|WINNT
+ if ((*filename == '\\')||(*filename == '/')||(filename[1] == ':')) {
+#else
+ if (*filename == '/') {
+#endif
+ if (ZLIB_INI(safe_mode)) {
+ snprintf(trypath,MAXPATHLEN,"%s%s",ZLIB_INI(doc_root),filename);
+ if (!_php3_checkuid(trypath,2)) {
+ return(NULL);
+ }
+ if (_php3_check_open_basedir(trypath)) return NULL;
+ zp = gzopen(trypath, mode);
+ if (zp && opened_path) {
+ *opened_path = expand_filepath(trypath);
+ }
+ return zp;
+ } else {
+ if (_php3_check_open_basedir(filename)) return NULL;
+ return gzopen(filename, mode);
+ }
+ }
+
+ if (!path || (path && !*path)) {
+ if (ZLIB_INI(safe_mode) &&(!_php3_checkuid(filename,2))) {
+ return(NULL);
+ }
+ if (_php3_check_open_basedir(filename)) return NULL;
+ zp = gzopen(filename, mode);
+ if (zp && opened_path) {
+ *opened_path = strdup(filename);
+ }
+ return zp;
+ }
+
+ pathbuf = estrdup(path);
+
+ ptr = pathbuf;
+
+ while (ptr && *ptr) {
+#if WIN32|WINNT
+ end = strchr(ptr, ';');
+#else
+ end = strchr(ptr, ':');
+#endif
+ if (end != NULL) {
+ *end = '\0';
+ end++;
+ }
+ snprintf(trypath, MAXPATHLEN, "%s/%s", ptr, filename);
+ if (ZLIB_INI(safe_mode)) {
+ if (stat(trypath,&sb) == 0 &&(!_php3_checkuid(trypath,2))) {
+ efree(pathbuf);
+ return(NULL);
+ }
+ }
+ if ((zp = gzopen(trypath, mode)) != NULL) {
+ if (_php3_check_open_basedir(trypath)) {
+ gzclose(zp);
+ efree(pathbuf);
+ return NULL;
+ }
+ if (opened_path) {
+ *opened_path = expand_filepath(trypath);
+ }
+ efree(pathbuf);
+ return zp;
+ }
+ ptr = end;
+ }
+ efree(pathbuf);
+ return NULL;
+}
+
+/* {{{ proto array gzfile(string filename)
+Read und uncompress entire .gz-file into an array */
+void php3_gzfile(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *filename, *arg2;
+ gzFile zp;
+ char *slashed, buf[8192];
+ register int i=0;
+ int use_include_path = 0;
+ ZLIB_TLS_VARS;
+
+ /* check args */
+ switch (ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht,1,&filename) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ break;
+ case 2:
+ if (getParameters(ht,2,&filename,&arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg2);
+ use_include_path = arg2->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string(filename);
+
+ zp = php3_gzopen_wrapper(filename->value.str.val,"r", use_include_path|ENFORCE_SAFE_MODE);
+ if (!zp) {
+ php3_error(E_WARNING,"gzFile(\"%s\") - %s",filename->value.str.val,strerror(errno));
+ RETURN_FALSE;
+ }
+
+ /* Initialize return array */
+ if (array_init(return_value) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ /* Now loop through the file and do the magic quotes thing if needed */
+ memset(buf,0,8191);
+ while((int)gzgets(zp, buf, 8191)) {
+ if (ZLIB_INI(magic_quotes_runtime)) {
+ int len;
+
+ slashed = _php3_addslashes(buf,0,&len,0); /* 0 = don't free source string */
+ add_index_stringl(return_value, i++, slashed, len, 0);
+ } else {
+ add_index_string(return_value, i++, buf, 1);
+ }
+ }
+ gzclose(zp);
+}
+/* }}} */
+
+/* {{{ proto int gzopen(string filename, string mode [, int use_include_path])
+Open a .gz-file and return a .gz-file pointer */
+void php3_gzopen(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3;
+ gzFile *zp;
+ char *p;
+ int id;
+ int use_include_path = 0;
+ ZLIB_TLS_VARS;
+
+ switch(ARG_COUNT(ht)) {
+ case 2:
+ if (getParameters(ht,2,&arg1,&arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ break;
+ case 3:
+ if (getParameters(ht,3,&arg1,&arg2,&arg3) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg3);
+ use_include_path = arg3->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string(arg1);
+ convert_to_string(arg2);
+ p = estrndup(arg2->value.str.val,arg2->value.str.len);
+
+ /*
+ * We need a better way of returning error messages from
+ * php3_gzopen_wrapper().
+ */
+ zp = php3_gzopen_wrapper(arg1->value.str.val, p, use_include_path|ENFORCE_SAFE_MODE);
+ if (!zp) {
+ php3_error(E_WARNING,"gzopen(\"%s\",\"%s\") - %s",
+ arg1->value.str.val, p, strerror(errno));
+ efree(p);
+ RETURN_FALSE;
+ }
+ ZLIB_GLOBAL(gzgetss_state)=0;
+ id = php3_list_insert(zp,ZLIB_GLOBAL(le_zp));
+ efree(p);
+ RETURN_LONG(id);
+}
+/* }}} */
+
+/* {{{ proto int gzclose(int zp)
+Close an open .gz-file pointer */
+void php3_gzclose(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ int id, type;
+ gzFile *zp;
+ ZLIB_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg1);
+ id=arg1->value.lval;
+ zp = php3_list_find(id,&type);
+ if (!zp || (type!=ZLIB_GLOBAL(le_zp))) {
+ php3_error(E_WARNING,"Unable to find gz-file identifier %d",id);
+ RETURN_FALSE;
+ }
+ php3_list_delete(id);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int gzeof(int zp)
+Test for end-of-file on a .gz-file pointer */
+void php3_gzeof(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ gzFile *zp;
+ int id, type;
+ ZLIB_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg1);
+ id = arg1->value.lval;
+ zp = php3_list_find(id,&type);
+ if ((!zp || (type!=ZLIB_GLOBAL(le_zp)))) {
+ php3_error(E_WARNING,"Unable to find gz-file identifier %d",id);
+ /* we're at the eof if the file doesn't exist */
+ RETURN_TRUE;
+ }
+ if ((gzeof(zp))) {
+ RETURN_TRUE;
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto string gzgets(int zp, int length)
+Get a line from .gz-file pointer */
+void php3_gzgets(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ gzFile *zp;
+ int id, len, type;
+ char *buf;
+ ZLIB_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg1);
+ convert_to_long(arg2);
+ id = arg1->value.lval;
+ len = arg2->value.lval;
+
+ zp = php3_list_find(id,&type);
+ if (!zp || (type!=ZLIB_GLOBAL(le_zp))) {
+ php3_error(E_WARNING,"Unable to find gz-file identifier %d",id);
+ RETURN_FALSE;
+ }
+ buf = emalloc(sizeof(char) * (len + 1));
+ /* needed because recv doesnt put a null at the end*/
+ memset(buf,0,len+1);
+ if (!((int)gzgets(zp, buf, len))) {
+ efree(buf);
+ RETVAL_FALSE;
+ } else {
+ if (ZLIB_INI(magic_quotes_runtime)) {
+ return_value->value.str.val = _php3_addslashes(buf,0,&return_value->value.str.len,1);
+ } else {
+ return_value->value.str.val = buf;
+ return_value->value.str.len = strlen(return_value->value.str.val);
+ }
+ return_value->type = IS_STRING;
+ }
+ return;
+}
+/* }}} */
+
+/* {{{ proto string gzgetc(int zp)
+Get a character from .gz-file pointer */
+void php3_gzgetc(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ gzFile *zp;
+ int id, type, c;
+ char *buf;
+ ZLIB_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg1);
+ id = arg1->value.lval;
+
+ zp = php3_list_find(id,&type);
+ if (!zp || (type!=ZLIB_GLOBAL(le_zp))) {
+ php3_error(E_WARNING,"Unable to find gz-file identifier %d",id);
+ RETURN_FALSE;
+ }
+ buf = emalloc(sizeof(char) * 2);
+ if ((c=gzgetc(zp)) == (-1)) {
+ efree(buf);
+ RETVAL_FALSE;
+ } else {
+ buf[0]=(char)c;
+ buf[1]='\0';
+ return_value->value.str.val = buf;
+ return_value->value.str.len = 1;
+ return_value->type = IS_STRING;
+ }
+ return;
+}
+/* }}} */
+
+/* Strip any HTML tags while reading */
+/* {{{ proto string gzgetss(int zp, int length)
+Get a line from file pointer and strip HTML tags */
+void php3_gzgetss(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *fd, *bytes;
+ gzFile *zp;
+ int id, len, br, type;
+ char *buf, *p, *rbuf, *rp, c, lc;
+ ZLIB_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &fd, &bytes) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_long(fd);
+ convert_to_long(bytes);
+
+ id = fd->value.lval;
+ len = bytes->value.lval;
+
+ zp = php3_list_find(id,&type);
+ if (!zp || (type!=ZLIB_GLOBAL(le_zp))) {
+ php3_error(E_WARNING, "Unable to find gz-file identifier %d", id);
+ RETURN_FALSE;
+ }
+
+ buf = emalloc(sizeof(char) * (len + 1));
+ /*needed because recv doesnt set null char at end*/
+ memset(buf,0,len+1);
+ if (!((int)gzgets(zp, buf, len))) {
+ efree(buf);
+ RETURN_FALSE;
+ }
+
+ rbuf = estrdup(buf);
+ c = *buf;
+ lc = '\0';
+ p = buf;
+ rp = rbuf;
+ br = 0;
+
+ while (c) {
+ switch (c) {
+ case '<':
+ if (ZLIB_GLOBAL(gzgetss_state) == 0) {
+ lc = '<';
+ ZLIB_GLOBAL(gzgetss_state) = 1;
+ }
+ break;
+
+ case '(':
+ if (ZLIB_GLOBAL(gzgetss_state) == 2) {
+ if (lc != '\"') {
+ lc = '(';
+ br++;
+ }
+ } else if (ZLIB_GLOBAL(gzgetss_state) == 0) {
+ *(rp++) = c;
+ }
+ break;
+
+ case ')':
+ if (ZLIB_GLOBAL(gzgetss_state) == 2) {
+ if (lc != '\"') {
+ lc = ')';
+ br--;
+ }
+ } else if (ZLIB_GLOBAL(gzgetss_state) == 0) {
+ *(rp++) = c;
+ }
+ break;
+
+ case '>':
+ if (ZLIB_GLOBAL(gzgetss_state) == 1) {
+ lc = '>';
+ ZLIB_GLOBAL(gzgetss_state) = 0;
+ } else if (ZLIB_GLOBAL(gzgetss_state) == 2) {
+ if (!br && lc != '\"') {
+ ZLIB_GLOBAL(gzgetss_state) = 0;
+ }
+ }
+ break;
+
+ case '\"':
+ if (ZLIB_GLOBAL(gzgetss_state) == 2) {
+ if (lc == '\"') {
+ lc = '\0';
+ } else if (lc != '\\') {
+ lc = '\"';
+ }
+ } else if (ZLIB_GLOBAL(gzgetss_state) == 0) {
+ *(rp++) = c;
+ }
+ break;
+
+ case '?':
+ if (ZLIB_GLOBAL(gzgetss_state)==1) {
+ br=0;
+ ZLIB_GLOBAL(gzgetss_state)=2;
+ break;
+ }
+ /* fall-through */
+
+ default:
+ if (ZLIB_GLOBAL(gzgetss_state) == 0) {
+ *(rp++) = c;
+ }
+ }
+ c = *(++p);
+ }
+ *rp = '\0';
+ efree(buf);
+ RETVAL_STRING(rbuf,1);
+ efree(rbuf);
+}
+/* }}} */
+
+/* {{{ proto int gzwrite(int zp, string str [, int length])
+Binary-safe .gz-file write */
+void php3_gzwrite(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2, *arg3=NULL;
+ gzFile *zp;
+ int ret,id,type;
+ int num_bytes;
+ ZLIB_TLS_VARS;
+
+ switch (ARG_COUNT(ht)) {
+ case 2:
+ if (getParameters(ht, 2, &arg1, &arg2)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string(arg2);
+ num_bytes = arg2->value.str.len;
+ break;
+ case 3:
+ if (getParameters(ht, 3, &arg1, &arg2, &arg3)==FAILURE) {
+ RETURN_FALSE;
+ }
+ convert_to_string(arg2);
+ convert_to_long(arg3);
+ num_bytes = MIN(arg3->value.lval, arg2->value.str.len);
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ /* NOTREACHED */
+ break;
+ }
+ convert_to_long(arg1);
+ id = arg1->value.lval;
+
+ zp = php3_list_find(id,&type);
+ if (!zp || (type!=ZLIB_GLOBAL(le_zp))) {
+ php3_error(E_WARNING,"Unable to find gz-file identifier %d",id);
+ RETURN_FALSE;
+ }
+
+ /* strip slashes only if the length wasn't specified explicitly */
+ if (!arg3 && ZLIB_INI(magic_quotes_runtime)) {
+ _php3_stripslashes(arg2->value.str.val,&num_bytes);
+ }
+
+ ret = gzwrite(zp, arg2->value.str.val,num_bytes);
+ RETURN_LONG(ret);
+}
+/* }}} */
+
+/* {{{ proto int gzrewind(int zp)
+Rewind the position of a .gz-file pointer */
+void php3_gzrewind(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ int id,type;
+ gzFile *zp;
+ ZLIB_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg1);
+ id = arg1->value.lval;
+ zp = php3_list_find(id,&type);
+ if (!zp || (type!=ZLIB_GLOBAL(le_zp))) {
+ php3_error(E_WARNING,"Unable to find gz-file identifier %d",id);
+ RETURN_FALSE;
+ }
+ gzrewind(zp);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int gztell(int zp)
+Get .gz-file pointer's read/write position */
+void php3_gztell(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ int id, type;
+ long pos;
+ gzFile *zp;
+ ZLIB_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg1);
+ id = arg1->value.lval;
+ zp = php3_list_find(id,&type);
+ if (!zp || (type!=ZLIB_GLOBAL(le_zp))) {
+ php3_error(E_WARNING,"Unable to find gz-file identifier %d",id);
+ RETURN_FALSE;
+ }
+ pos = gztell(zp);
+ RETURN_LONG(pos);
+}
+/* }}} */
+
+/* {{{ proto int gzseek(int zp, int offset)
+Seek on a file pointer */
+void php3_gzseek(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ int ret,id,type;
+ long pos;
+ gzFile *zp;
+ ZLIB_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg1);
+ convert_to_long(arg2);
+ pos = arg2->value.lval;
+ id = arg1->value.lval;
+ zp = php3_list_find(id,&type);
+ if (!zp || (type!=ZLIB_GLOBAL(le_zp))) {
+ php3_error(E_WARNING,"Unable to find gz-file identifier %d",id);
+ RETURN_FALSE;
+ }
+ ret = gzseek(zp,pos,SEEK_SET);
+ RETURN_LONG(ret);
+}
+/* }}} */
+
+/*
+ * Read a file and write the ouput to stdout
+ */
+/* {{{ proto int readgzfile(string filename [, int use_include_path])
+Output a .gz-file */
+void php3_readgzfile(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1, *arg2;
+ char buf[8192];
+ gzFile *zp;
+ int b, size;
+ int use_include_path = 0;
+
+
+ /* check args */
+ switch (ARG_COUNT(ht)) {
+ case 1:
+ if (getParameters(ht,1,&arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ break;
+ case 2:
+ if (getParameters(ht,2,&arg1,&arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg2);
+ use_include_path = arg2->value.lval;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string(arg1);
+
+ /*
+ * We need a better way of returning error messages from
+ * php3_gzopen_wrapper().
+ */
+ zp = php3_gzopen_wrapper(arg1->value.str.val,"r", use_include_path|ENFORCE_SAFE_MODE);
+ if (!zp){
+ php3_error(E_WARNING,"ReadGzFile(\"%s\") - %s",arg1->value.str.val,strerror(errno));
+ RETURN_FALSE;
+ }
+ size= 0;
+ while((b = gzread(zp, buf, sizeof(buf))) > 0) {
+ PHPWRITE(buf,b);
+ size += b ;
+ }
+ gzclose(zp);
+ RETURN_LONG(size);
+}
+/* }}} */
+
+/*
+ * Read to EOF on a file descriptor and write the output to stdout.
+ */
+/* {{{ proto int gzpassthru(int zp)
+Output all remaining data from a .gz-file pointer */
+void php3_gzpassthru(INTERNAL_FUNCTION_PARAMETERS) {
+ pval *arg1;
+ gzFile *zp;
+ char buf[8192];
+ int id, size, b, type;
+ ZLIB_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg1);
+ id = arg1->value.lval;
+ zp = php3_list_find(id,&type);
+ if (!zp || (type!=ZLIB_GLOBAL(le_zp))) {
+ php3_error(E_WARNING,"Unable to find gz-file identifier %d",id);
+ RETURN_FALSE;
+ }
+ size = 0;
+ while((b = gzread(zp, buf, sizeof(buf))) > 0) {
+ PHPWRITE(buf,b);
+ size += b ;
+ }
+/* gzclose(zp); */
+ php3_list_delete(id);
+ RETURN_LONG(size);
+}
+/* }}} */
+
+/* {{{ proto int gzread(int zp, int length)
+Binary-safe file read */
+void php3_gzread(INTERNAL_FUNCTION_PARAMETERS)
+{
+ pval *arg1, *arg2;
+ gzFile *zp;
+ int id, len, type;
+ ZLIB_TLS_VARS;
+
+ if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(arg1);
+ convert_to_long(arg2);
+ id = arg1->value.lval;
+ len = arg2->value.lval;
+
+ zp = php3_list_find(id,&type);
+ if (!zp || (type!=ZLIB_GLOBAL(le_zp))) {
+ php3_error(E_WARNING,"Unable to find gz-file identifier %d",id);
+ RETURN_FALSE;
+ }
+ return_value->value.str.val = emalloc(sizeof(char) * (len + 1));
+ /* needed because recv doesnt put a null at the end*/
+
+ return_value->value.str.len = gzread(zp, return_value->value.str.val, len);
+ return_value->value.str.val[return_value->value.str.len] = 0;
+
+ if (ZLIB_INI(magic_quotes_runtime)) {
+ return_value->value.str.val = _php3_addslashes(return_value->value.str.val,return_value->value.str.len,&return_value->value.str.len,1);
+ }
+ return_value->type = IS_STRING;
+}
+/* }}} */
+
+#endif /* HAVE_ZLIB */
+/*
+ * Local variables:
+ * tab-width: 4
+ * End:
+ */