diff options
author | Stig Bakken <ssb@php.net> | 1999-04-22 02:48:28 +0000 |
---|---|---|
committer | Stig Bakken <ssb@php.net> | 1999-04-22 02:48:28 +0000 |
commit | 2c0ad3ee25cd8e449b02c4668a39f48998507739 (patch) | |
tree | 8064c7ee59309ffed3d9c5b8fd5c329ede193561 /ext | |
parent | 2a78f92804ae6f3e32cd278afbb9aa8ec3d2f52d (diff) | |
download | php-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')
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: + */ |