From: Stig Bakken Date: Wed, 21 Apr 1999 23:11:20 +0000 (+0000) Subject: moved apache, com and hyperwave into ext/ X-Git-Tag: BEFORE_PHP4_APACHE_MODULE_CHANGE~224 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a297b95c9da1b6138523f9b707a0fafe60e0d327;p=php moved apache, com and hyperwave into ext/ --- diff --git a/Makefile.in b/Makefile.in index 8542f082fc..60bb0e4046 100644 --- a/Makefile.in +++ b/Makefile.in @@ -68,18 +68,18 @@ OBJS = main.o internal_functions.o snprintf.o php3_sprintf.o \ safe_mode.o fopen-wrappers.o php3_realpath.o alloca.o output.o \ php_ini.o -FUNCTIONS_SOURCE = functions/apache.c functions/fhttpd.c \ +FUNCTIONS_SOURCE = functions/fhttpd.c \ functions/crypt.c functions/db.c functions/dl.c \ functions/head.c functions/imap.c functions/mime.c \ functions/pgsql.c functions/post.c functions/sybase.c \ functions/sybase-ct.c @BCMATH_SRC@ functions/xml.c \ - functions/ldap.c functions/zlib.c functions/COM.c functions/ifx.c \ - functions/pdf.c functions/hw.c functions/hg_comm.c functions/dlist.c \ + functions/ldap.c functions/zlib.c functions/ifx.c \ + functions/pdf.c \ functions/fdf.c functions/snmp.c functions/interbase.c \ functions/sysvsem.c functions/sysvshm.c FUNCTIONS = $(FUNCTIONS_SOURCE:.c=.o) -PHPLIBS = -L@top_srcdir@/libzend -lzend -Lext -lphpext +PHPLIBS = -L@top_srcdir@/libzend -lzend -L@top_srcdir@/ext -lphpext LIBS = $(PHPLIBS) $(EXTRA_LIBS) @SYBASE_CT_LFLAGS@ @SYBASE_CT_LIBS@ @FHTTPD_LIB@ @REGEX_LIB@ @DBM_LIB@ @SYBASE_LFLAGS@ @SYBASE_LIBS@ @SYBASE_CT_LFLAGS@ @SYBASE_CT_LIBS@ @MYSQL_LFLAGS@ @MYSQL_LIBS@ @PGSQL_LFLAGS@ @PGSQL_LIBS@ @LDAP_LFLAGS@ @LDAP_LIBS@ @IMAP_LIBS@ @ZLIB_LIBS@ @PDFLIB_LIBS@ @FDFLIB_LIBS@ @IFX_LFLAGS@ @IFX_LIBS@ @SNMP_LFLAGS@ @SNMP_LIBS@ @IBASE_LFLAGS@ @IBASE_LIBS@ @XML_LIBS@ @LIBS@ all: $(BINNAME) diff --git a/acconfig.h.in b/acconfig.h.in index f1ece7cefb..5799877b47 100644 --- a/acconfig.h.in +++ b/acconfig.h.in @@ -64,9 +64,6 @@ #define REGEX 0 #define HSREGEX 0 -/* Define if you want Hyperwave support */ -#define HYPERWAVE 0 - /* Define if you have the crypt() function */ #define HAVE_CRYPT 1 diff --git a/configure.in.in b/configure.in.in index b226b6bdf7..a47ef5cf58 100644 --- a/configure.in.in +++ b/configure.in.in @@ -1152,23 +1152,6 @@ dnl## AC_SUBST(IBASE_INCLUDE) INCLUDES="$INCLUDES $IBASE_INCLUDE" -AC_MSG_CHECKING(for Hyperwave support) -AC_ARG_WITH(hyperwave, -[ --with-hyperwave Include Hyperwave support], -[ - if test "$withval" != "no"; then - AC_DEFINE(HYPERWAVE,1) - AC_MSG_RESULT(yes) - else - AC_DEFINE(HYPERWAVE,0) - AC_MSG_RESULT(no) - fi -],[ - AC_DEFINE(HYPERWAVE,0) - AC_MSG_RESULT(no) -]) - - AC_MSG_CHECKING(for XML support) AC_ARG_WITH(xml, [ --with-xml Include XML support],[ diff --git a/ext/apache/Makefile.am b/ext/apache/Makefile.am new file mode 100644 index 0000000000..c9006e13bb --- /dev/null +++ b/ext/apache/Makefile.am @@ -0,0 +1,6 @@ +# $Id$ + +INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend +noinst_LIBRARIES=libphpext_apache.a +libphpext_apache_a_SOURCES=apache.c + diff --git a/ext/apache/apache.c b/ext/apache/apache.c new file mode 100644 index 0000000000..614268d4be --- /dev/null +++ b/ext/apache/apache.c @@ -0,0 +1,386 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + | Stig Sæther Bakken | + | David Sklar | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ +#ifdef THREAD_SAFE +#include "tls.h" +#endif +#include "php.h" +#include "functions/head.h" +#include "php_globals.h" +#include "php_ini.h" +#include "mod_php3.h" + +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include + +#if APACHE +#include "http_request.h" +#include "build-defs.h" + +extern module *top_module; + +void php3_virtual(INTERNAL_FUNCTION_PARAMETERS); +void php3_getallheaders(INTERNAL_FUNCTION_PARAMETERS); +void php3_apachelog(INTERNAL_FUNCTION_PARAMETERS); +void php3_info_apache(void); +void php3_apache_note(INTERNAL_FUNCTION_PARAMETERS); +void php3_apache_lookup_uri(INTERNAL_FUNCTION_PARAMETERS); + +function_entry apache_functions[] = { + {"virtual", php3_virtual, NULL}, + {"getallheaders", php3_getallheaders, NULL}, + {"apache_note", php3_apache_note,NULL}, + {"apache_lookup_uri", php3_apache_lookup_uri,NULL}, + {NULL, NULL, NULL} +}; + + +static PHP_INI_MH(OnChangeApacheInt) +{ + long *p; + char *base = (char *) &php_apache_info; + + p = (long *) (base+(size_t) mh_arg); + + if (new_value) { + *p = atoi(new_value); + return SUCCESS; + } else { + return FAILURE; + } +} + + +static PHP_INI_MH(OnChangeApacheString) +{ + char **p; + char *base = (char *) &php_apache_info; + + p = (char **) (base+(size_t) mh_arg); + + if (new_value) { + *p = new_value; + return SUCCESS; + } else { + return FAILURE; + } +} + +PHP_INI_BEGIN() + PHP_INI_ENTRY("xbithack", "0", PHP_INI_ALL, OnChangeApacheInt, (void *) XtOffsetOf(php_apache_info_struct, xbithack)) + PHP_INI_ENTRY("engine", "1", PHP_INI_ALL, OnChangeApacheInt, (void *) XtOffsetOf(php_apache_info_struct, engine)) + PHP_INI_ENTRY("last_modified", "0", PHP_INI_ALL, OnChangeApacheInt, (void *) XtOffsetOf(php_apache_info_struct, last_modified)) + PHP_INI_ENTRY("dav_script", NULL, PHP_INI_ALL, OnChangeApacheString, (void *) XtOffsetOf(php_apache_info_struct, dav_script)) +PHP_INI_END() + + +static int php_apache_minit(INIT_FUNC_ARGS) +{ + REGISTER_INI_ENTRIES(); + return SUCCESS; +} + + +static int php_apache_mshutdown(SHUTDOWN_FUNC_ARGS) +{ + UNREGISTER_INI_ENTRIES(); + return SUCCESS; +} + + +php3_module_entry apache_module_entry = { + "Apache", apache_functions, php_apache_minit, php_apache_mshutdown, NULL, NULL, php3_info_apache, STANDARD_MODULE_PROPERTIES +}; + +/* {{{ proto string apache_note(string note_name [, string note_value]) + Get and set Apache request notes */ +void php3_apache_note(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *arg_name,*arg_val; + char *note_val; + int arg_count = ARG_COUNT(ht); +TLS_VARS; + + if (arg_count<1 || arg_count>2 || + getParameters(ht,arg_count,&arg_name,&arg_val) == FAILURE ) { + WRONG_PARAM_COUNT; + } + + convert_to_string(arg_name); + note_val = (char *) table_get(GLOBAL(php3_rqst)->notes,arg_name->value.str.val); + + if (arg_count == 2) { + convert_to_string(arg_val); + table_set(GLOBAL(php3_rqst)->notes,arg_name->value.str.val,arg_val->value.str.val); + } + + if (note_val) { + RETURN_STRING(note_val,1); + } else { + RETURN_FALSE; + } +} +/* }}} */ + +void php3_info_apache(void) { + module *modp = NULL; +#if !defined(WIN32) && !defined(WINNT) + char name[64]; + char *p; +#endif + server_rec *serv = GLOBAL(php3_rqst)->server; + extern char server_root[MAX_STRING_LEN]; + extern uid_t user_id; + extern char *user_name; + extern gid_t group_id; + extern int max_requests_per_child; + +#if WIN32|WINNT + PUTS("Apache for Windows 95/NT
"); +#else + php3_printf("APACHE_INCLUDE=%s
\n", PHP_APACHE_INCLUDE); + php3_printf("APACHE_TARGET=%s
\n", PHP_APACHE_TARGET); +#endif + php3_printf("Apache Version: %s
",SERVER_VERSION); +#ifdef APACHE_RELEASE + php3_printf("Apache Release: %d
",APACHE_RELEASE); +#endif + php3_printf("Apache API Version: %d
",MODULE_MAGIC_NUMBER); + php3_printf("Hostname/port: %s:%u
\n",serv->server_hostname,serv->port); +#if !defined(WIN32) && !defined(WINNT) + php3_printf("User/Group: %s(%d)/%d
\n",user_name,(int)user_id,(int)group_id); + php3_printf("Max Requests: per child: %d    keep alive: %s    max per connection: %d
\n",max_requests_per_child,serv->keep_alive ? "on":"off", serv->keep_alive_max); +#endif + php3_printf("Timeouts: connection: %d    keep-alive: %d
",serv->timeout,serv->keep_alive_timeout); +#if !defined(WIN32) && !defined(WINNT) + php3_printf("Server Root: %s
\n",server_root); + + PUTS("Loaded modules: "); + for(modp = top_module; modp; modp = modp->next) { + strncpy(name, modp->name, sizeof(name) - 1); + if ((p = strrchr(name, '.'))) { + *p='\0'; /* Cut off ugly .c extensions on module names */ + } + PUTS(name); + if (modp->next) { + PUTS(", "); + } + } +#endif + PUTS("
\n"); +} + +/* This function is equivalent to + * in mod_include. It does an Apache sub-request. It is useful + * for including CGI scripts or .shtml files, or anything else + * that you'd parse through Apache (for .phtml files, you'd probably + * want to use . This only works when PHP is compiled + * as an Apache module, since it uses the Apache API for doing + * sub requests. + */ +/* {{{ proto int virtual(string filename) + Perform an Apache sub-request */ +void php3_virtual(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *filename; + request_rec *rr = NULL; +TLS_VARS; + + if (ARG_COUNT(ht) != 1 || getParameters(ht,1,&filename) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string(filename); + + if (!(rr = sub_req_lookup_uri (filename->value.str.val, GLOBAL(php3_rqst)))) { + php3_error(E_WARNING, "Unable to include '%s' - URI lookup failed", filename->value.str.val); + if (rr) destroy_sub_req (rr); + RETURN_FALSE; + } + + if (rr->status != 200) { + php3_error(E_WARNING, "Unable to include '%s' - error finding URI", filename->value.str.val); + if (rr) destroy_sub_req (rr); + RETURN_FALSE; + } + + /* Cannot include another PHP file because of global conflicts */ + if (rr->content_type && + !strcmp(rr->content_type, PHP3_MIME_TYPE)) { + php3_error(E_WARNING, "Cannot include a PHP file " + "(use <?include \"%s\"> instead)", filename->value.str.val); + if (rr) destroy_sub_req (rr); + RETURN_FALSE; + } + + if (run_sub_req(rr)) { + php3_error(E_WARNING, "Unable to include '%s' - request execution failed", filename->value.str.val); + if (rr) destroy_sub_req (rr); + RETURN_FALSE; + } else { + if (rr) destroy_sub_req (rr); + RETURN_TRUE; + } +} +/* }}} */ + +/* {{{ proto array getallheaders(void) + Fetch all HTTP request headers */ +void php3_getallheaders(INTERNAL_FUNCTION_PARAMETERS) +{ + array_header *env_arr; + table_entry *tenv; + int i; + + if (array_init(return_value) == FAILURE) { + RETURN_FALSE; + } + env_arr = table_elts(php3_rqst->headers_in); + tenv = (table_entry *)env_arr->elts; + for (i = 0; i < env_arr->nelts; ++i) { + if (!tenv[i].key || + (PG(safe_mode) && + !strncasecmp(tenv[i].key, "authorization", 13))) { + continue; + } + if (add_assoc_string(return_value, tenv[i].key,(tenv[i].val==NULL) ? "" : tenv[i].val, 1)==FAILURE) { + RETURN_FALSE; + } + } +} +/* }}} */ + +/* {{{ proto class apache_lookup_uri(string URI) + Perform a partial request of the given URI to obtain information about it */ +void php3_apache_lookup_uri(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *filename; + request_rec *rr=NULL; + + if (ARG_COUNT(ht) != 1 || getParameters(ht,1,&filename) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string(filename); + + if(!(rr = sub_req_lookup_uri(filename->value.str.val, GLOBAL(php3_rqst)))) { + php3_error(E_WARNING, "URI lookup failed", filename->value.str.val); + RETURN_FALSE; + } + object_init(return_value); + add_property_long(return_value,"status",rr->status); + if (rr->the_request) { + add_property_string(return_value,"the_request",rr->the_request,1); + } + if (rr->status_line) { + add_property_string(return_value,"status_line",rr->status_line,1); + } + if (rr->method) { + add_property_string(return_value,"method",rr->method,1); + } + if (rr->content_type) { + add_property_string(return_value,"content_type",(char *)rr->content_type,1); + } + if (rr->handler) { + add_property_string(return_value,"handler",(char *)rr->handler,1); + } + if (rr->uri) { + add_property_string(return_value,"uri",rr->uri,1); + } + if (rr->filename) { + add_property_string(return_value,"filename",rr->filename,1); + } + if (rr->path_info) { + add_property_string(return_value,"path_info",rr->path_info,1); + } + if (rr->args) { + add_property_string(return_value,"args",rr->args,1); + } + if (rr->boundary) { + add_property_string(return_value,"boundary",rr->boundary,1); + } + add_property_long(return_value,"no_cache",rr->no_cache); + add_property_long(return_value,"no_local_copy",rr->no_local_copy); + add_property_long(return_value,"allowed",rr->allowed); + add_property_long(return_value,"sent_bodyct",rr->sent_bodyct); + add_property_long(return_value,"bytes_sent",rr->bytes_sent); + add_property_long(return_value,"byterange",rr->byterange); + add_property_long(return_value,"clength",rr->clength); + +#if MODULE_MAGIC_NUMBER >= 19980324 + if (rr->unparsed_uri) { + add_property_string(return_value,"unparsed_uri",rr->unparsed_uri,1); + } + if(rr->mtime) { + add_property_long(return_value,"mtime",rr->mtime); + } +#endif + if(rr->request_time) { + add_property_long(return_value,"request_time",rr->request_time); + } + + destroy_sub_req(rr); +} +/* }}} */ + +#if 0 +This function is most likely a bad idea. Just playing with it for now. + +void php3_apache_exec_uri(INTERNAL_FUNCTION_PARAMETERS) { + pval *filename; + request_rec *rr=NULL; + + if (ARG_COUNT(ht) != 1 || getParameters(ht,1,&filename) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string(filename); + + if(!(rr = ap_sub_req_lookup_uri(filename->value.str.val, GLOBAL(php3_rqst)))) { + php3_error(E_WARNING, "URI lookup failed", filename->value.str.val); + RETURN_FALSE; + } + RETVAL_LONG(ap_run_sub_req(rr)); + ap_destroy_sub_req(rr); +} +#endif + +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/ext/apache/config.m4 b/ext/apache/config.m4 new file mode 100644 index 0000000000..e878cdbb8b --- /dev/null +++ b/ext/apache/config.m4 @@ -0,0 +1,5 @@ +dnl $Id$ + +if test -n "$APACHE_INCLUDE"; then + PHP_EXTENSION(apache) +fi diff --git a/ext/com/php3_COM.h b/ext/com/php3_COM.h new file mode 100644 index 0000000000..ed9cc4f526 --- /dev/null +++ b/ext/com/php3_COM.h @@ -0,0 +1,22 @@ +#ifndef _PHP3_COM_H +#define _PHP3_COM_H + +#if WIN32|WINNT + +extern int php3_minit_COM(INIT_FUNC_ARGS); +extern int php3_mshutdown_COM(SHUTDOWN_FUNC_ARGS); +extern void php3_COM_load(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_COM_invoke(INTERNAL_FUNCTION_PARAMETERS); + +PHP_FUNCTION(com_propget); +PHP_FUNCTION(com_propput); +extern php3_module_entry COM_module_entry; +#define COM_module_ptr &COM_module_entry + +#else + +#define COM_module_ptr NULL + +#endif /* Win32|WINNT */ + +#endif /* _PHP3_COM_H */ diff --git a/ext/hyperwave/DList.h b/ext/hyperwave/DList.h new file mode 100644 index 0000000000..e574638e18 --- /dev/null +++ b/ext/hyperwave/DList.h @@ -0,0 +1,128 @@ +/**************************************************************************** +* +* Copyright (C) 1991 Kendall Bennett. +* All rights reserved. +* +* Filename: $RCSfile$ +* Version: $Revision$ +* +* Language: ANSI C +* Environment: any +* +* Description: Header file for doubly linked list routines. +* +* $Id$ +* +* Revision History: +* ----------------- +* +* $Log$ +* Revision 1.1.1.1 1999/04/07 21:03:20 zeev +* PHP 4.0 +* +* Revision 1.1.1.1 1999/03/17 04:29:11 andi +* PHP4 +* +* Revision 1.1.1.1 1998/12/21 07:56:22 andi +* Trying to start the zend CVS tree +* +* Revision 1.2 1998/08/14 15:51:12 shane +* Some work on getting hyperwave to work on windows. hg_comm needs a lot of work. +* +* Mainly, signals, fnctl, bzero, bcopy, etc are not portable functions. Most of this +* will have to be rewriten for windows. +* +* Revision 1.1 1998/08/12 09:29:16 steinm +* First version of Hyperwave module. +* +* Revision 1.5 91/12/31 19:40:54 kjb +* +* Modified include files directories. +* +* Revision 1.4 91/09/27 03:10:41 kjb +* Added compatibility with C++. +* +* Revision 1.3 91/09/26 10:07:16 kjb +* Took out extern references +* +* Revision 1.2 91/09/01 19:37:20 ROOT_DOS +* Changed DLST_TAIL macro so that it returns a pointer to the REAL last +* node of the list, not the dummy last node (l->z). +* +* Revision 1.1 91/09/01 18:38:23 ROOT_DOS +* Initial revision +* +****************************************************************************/ + +#ifndef __DLIST_H +#define __DLIST_H + +#ifndef __DEBUG_H +/*#include "debug.h"*/ +#endif + +/*---------------------- Macros and type definitions ----------------------*/ + +typedef struct DLST_BUCKET { + struct DLST_BUCKET *next; + struct DLST_BUCKET *prev; + } DLST_BUCKET; + +typedef struct { + int count; /* Number of elements currently in list */ + DLST_BUCKET *head; /* Pointer to head element of list */ + DLST_BUCKET *z; /* Pointer to last node of list */ + DLST_BUCKET hz[2]; /* Space for head and z nodes */ + } DLIST; + +/* Return a pointer to the user space given the address of the header of + * a node. + */ + +#define DLST_USERSPACE(h) ((void*)((DLST_BUCKET*)(h) + 1)) + +/* Return a pointer to the header of a node, given the address of the + * user space. + */ + +#define DLST_HEADER(n) ((DLST_BUCKET*)(n) - 1) + +/* Return a pointer to the user space of the list's head node. This user + * space does not actually exist, but it is useful to be able to address + * it to enable insertion at the start of the list. + */ + +#define DLST_HEAD(l) DLST_USERSPACE((l)->head) + +/* Return a pointer to the user space of the last node in list. */ + +#define DLST_TAIL(l) DLST_USERSPACE((l)->z->prev) + +/* Determine if a list is empty + */ + +#define DLST_EMPTY(l) ((l)->count == 0) + +/*-------------------------- Function Prototypes --------------------------*/ + +#ifdef __cplusplus +extern "C" { +#endif + +void *dlst_newnode(int size); +void dlst_freenode(void *node); +DLIST *dlst_init(void); +void dlst_kill(DLIST *l,void (*freeNode)(void *node)); +void dlst_insertafter(DLIST *l,void *node,void *after); +void *dlst_deletenext(DLIST *l,void *node); +void *dlst_first(DLIST *l); +void *dlst_last(DLIST *l); +void *dlst_next(void *prev); +void *dlst_prev(void *next); +void dlst_mergesort(DLIST *l,int (*cmp_func)(void*,void*)); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/hyperwave/Makefile.am b/ext/hyperwave/Makefile.am new file mode 100644 index 0000000000..c5be33e128 --- /dev/null +++ b/ext/hyperwave/Makefile.am @@ -0,0 +1,6 @@ +# $Id$ + +INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend +noinst_LIBRARIES=libphpext_hyperwave.a +libphpext_hyperwave_a_SOURCES=hw.c hg_comm.c + diff --git a/ext/hyperwave/config.h.stub b/ext/hyperwave/config.h.stub new file mode 100644 index 0000000000..d8e8bf43ab --- /dev/null +++ b/ext/hyperwave/config.h.stub @@ -0,0 +1,2 @@ +/* Define if you want Hyperwave support */ +#define HYPERWAVE 0 diff --git a/ext/hyperwave/config.m4 b/ext/hyperwave/config.m4 new file mode 100644 index 0000000000..ef48f24954 --- /dev/null +++ b/ext/hyperwave/config.m4 @@ -0,0 +1,18 @@ +dnl $Id$ + +AC_MSG_CHECKING(for Hyperwave support) +AC_ARG_WITH(hyperwave, +[ --with-hyperwave Include Hyperwave support], +[ + if test "$withval" != "no"; then + AC_DEFINE(HYPERWAVE,1) + AC_MSG_RESULT(yes) + PHP_EXTENSION(hyperwave) + else + AC_DEFINE(HYPERWAVE,0) + AC_MSG_RESULT(no) + fi +],[ + AC_DEFINE(HYPERWAVE,0) + AC_MSG_RESULT(no) +]) diff --git a/ext/hyperwave/dlist.c b/ext/hyperwave/dlist.c new file mode 100644 index 0000000000..27c1305664 --- /dev/null +++ b/ext/hyperwave/dlist.c @@ -0,0 +1,410 @@ +/**************************************************************************** +* +* Copyright (C) 1991 Kendall Bennett. +* All rights reserved. +* +* Filename: $RCSfile$ +* Version: $Revision$ +* +* Language: ANSI C +* Environment: any +* +* Description: Module to implement doubly linked lists. Includes a routine +* to peform a mergesort on the doubly linked list. +* +* $Id$ +* +* Revision History: +* ----------------- +* +* $Log$ +* Revision 1.1.1.1 1999/04/07 21:03:31 zeev +* PHP 4.0 +* +* Revision 1.1.1.1 1999/03/17 04:29:11 andi +* PHP4 +* +* Revision 1.1.1.1 1998/12/21 07:56:22 andi +* Trying to start the zend CVS tree +* +* Revision 1.1 1998/08/12 09:29:16 steinm +* First version of Hyperwave module. +* +* Revision 1.5 91/12/31 19:39:49 kjb +* Modified include file directories. +* +* Revision 1.4 91/10/28 03:16:39 kjb +* Ported to the Iris. +* +* Revision 1.3 91/09/27 03:09:18 kjb +* Cosmetic change. +* +* Revision 1.2 91/09/03 18:27:42 ROOT_DOS +* Ported to UNIX. +* +* Revision 1.1 91/09/01 18:35:23 ROOT_DOS +* Initial revision +* +****************************************************************************/ + +#ifndef MSVC5 +#include "config.h" +#endif + +#if HYPERWAVE + +#include +#include +#include +#include "debug.h" +#include "DList.h" + +PUBLIC void *dlst_newnode(int size) +/**************************************************************************** +* +* Function: dlst_newnode +* Parameters: size - Amount of memory to allocate for node +* Returns: Pointer to the allocated node's user space. +* +* Description: Allocates the memory required for a node, adding a small +* header at the start of the node. We return a reference to +* the user space of the node, as if it had been allocated via +* malloc(). +* +****************************************************************************/ +{ + DLST_BUCKET *node; + + if ( !(node = (DLST_BUCKET*)malloc(size + sizeof(DLST_BUCKET))) ) { + fprintf(stderr,"Not enough memory to allocate list node.\n"); +/* raise(SIGABRT);*/ + return NULL; + } + + return DLST_USERSPACE(node); /* Return pointer to user space */ +} + +PUBLIC void dlst_freenode(void *node) +/**************************************************************************** +* +* Function: dlst_freenode +* Parameters: node - Node to free. +* +* Description: Frees a node previously allocated with lst_newnode(). +* +****************************************************************************/ +{ + free(DLST_HEADER(node)); +} + +PUBLIC DLIST *dlst_init(void) +/**************************************************************************** +* +* Function: dlst_init +* Returns: Pointer to a newly created list. +* +* Description: Initialises a list and returns a pointer to it. +* +****************************************************************************/ +{ + DLIST *l; + + if ((l = (DLIST*)malloc(sizeof(DLIST))) != NULL) { + l->count = 0; + l->head = &(l->hz[0]); + l->z = &(l->hz[1]); + l->head->next = l->z->next = l->z; + l->z->prev = l->head->prev = l->head; + } + else { + fprintf(stderr,"Insufficient memory to allocate list\n"); + /*raise(SIGABRT);*/ + return NULL; + } + + return l; +} + +PUBLIC void dlst_kill(DLIST *l,void (*freeNode)(void *node)) +/**************************************************************************** +* +* Function: dlst_kill +* Parameters: l - List to kill +* freeNode - Pointer to user routine to free a node +* +* Description: Kills the list l, by deleting all of the elements contained +* within the list one by one and then deleting the list +* itself. Note that we call the user supplied routine +* (*freeNode)() to free each list node. This allows the user +* program to perform any extra processing needed to kill each +* node (if each node contains pointers to other items on the +* heap for example). If no extra processing is required, just +* pass the address of dlst_freenode(), ie: +* +* dlst_kill(myList,dlst_freenode); +* +****************************************************************************/ +{ + DLST_BUCKET *n,*p; + + n = l->head->next; + while (n != l->z) { /* Free all nodes in list */ + p = n; + n = n->next; + (*freeNode)(DLST_USERSPACE(p)); + } + free(l); /* Free the list itself */ +} + +PUBLIC void dlst_insertafter(DLIST *l,void *node,void *after) +/**************************************************************************** +* +* Function: lst_insertafter +* Parameters: l - List to insert node into +* node - Pointer to user space of node to insert +* after - Pointer to user space of node to insert node after +* +* Description: Inserts a new node into the list after the node 'after'. To +* insert a new node at the beginning of the list, user the +* macro DLST_HEAD in place of 'after'. ie: +* +* dlst_insertafter(mylist,node,DLST_HEAD(mylist)); +* +****************************************************************************/ +{ + DLST_BUCKET *n = DLST_HEADER(node),*a = DLST_HEADER(after); + + n->next = a->next; + a->next = n; + n->prev = a; + n->next->prev = n; + l->count++; +} + +PUBLIC void *dlst_deletenext(DLIST *l,void *node) +/**************************************************************************** +* +* Function: lst_deletenext +* Parameters: l - List to delete node from. +* node - Node to delete the next node from +* Returns: Pointer to the deleted node's userspace. +* +* Description: Removes the node AFTER 'node' from the list l. +* +****************************************************************************/ +{ + DLST_BUCKET *n = DLST_HEADER(node); + + node = DLST_USERSPACE(n->next); + n->next->next->prev = n; + n->next = n->next->next; + l->count--; + return node; +} + +PUBLIC void *dlst_first(DLIST *l) +/**************************************************************************** +* +* Function: dlst_first +* Parameters: l - List to obtain first node from +* Returns: Pointer to first node in list, NULL if list is empty. +* +* Description: Returns a pointer to the user space of the first node in +* the list. If the list is empty, we return NULL. +* +****************************************************************************/ +{ + DLST_BUCKET *n; + + n = l->head->next; + return (n == l->z ? NULL : DLST_USERSPACE(n)); +} + +PUBLIC void *dlst_last(DLIST *l) +/**************************************************************************** +* +* Function: dlst_last +* Parameters: l - List to obtain last node from +* Returns: Pointer to last node in list, NULL if list is empty. +* +* Description: Returns a pointer to the user space of the last node in +* the list. If the list is empty, we return NULL. +* +****************************************************************************/ +{ + DLST_BUCKET *n; + + n = l->z->prev; + return (n == l->head ? NULL : DLST_USERSPACE(n)); +} + +PUBLIC void *dlst_next(void *prev) +/**************************************************************************** +* +* Function: dlst_next +* Parameters: prev - Previous node in list to obtain next node from +* Returns: Pointer to the next node in the list, NULL at end of list. +* +* Description: Returns a pointer to the user space of the next node in the +* list given a pointer to the user space of the previous node. +* If we have reached the end of the list, we return NULL. The +* end of the list is detected when the next pointer of a node +* points back to itself, as does the dummy last node's next +* pointer. This enables us to detect the end of the list +* without needed access to the list data structure itself. +* +* NOTE: We do no checking to ensure that 'prev' is NOT a +* NULL pointer. +* +****************************************************************************/ +{ + DLST_BUCKET *n = DLST_HEADER(prev); + + n = n->next; + return (n == n->next ? NULL : DLST_USERSPACE(n)); +} + +PUBLIC void *dlst_prev(void *next) +/**************************************************************************** +* +* Function: dlst_prev +* Parameters: next - Next node in list to obtain previous node from +* Returns: Pointer to the previous node in the list, NULL at start list. +* +* Description: Returns a pointer to the user space of the prev node in the +* list given a pointer to the user space of the next node. +* If we have reached the start of the list, we return NULL. The +* start of the list is detected when the prev pointer of a node +* points back to itself, as does the dummy head node's prev +* pointer. This enables us to detect the start of the list +* without needed access to the list data structure itself. +* +* NOTE: We do no checking to ensure that 'next' is NOT a +* NULL pointer. +* +****************************************************************************/ +{ + DLST_BUCKET *n = DLST_HEADER(next); + + n = n->prev; + return (n == n->prev ? NULL : DLST_USERSPACE(n)); +} + +/* Static globals required by merge() */ + +static DLST_BUCKET *z; +static int (*cmp)(void*,void*); + +PRIVATE DLST_BUCKET *merge(DLST_BUCKET *a,DLST_BUCKET *b,DLST_BUCKET **end) +/**************************************************************************** +* +* Function: merge +* Parameters: a,b - Sublist's to merge +* Returns: Pointer to the merged sublists. +* +* Description: Merges two sorted lists of nodes together into a single +* sorted list. +* +****************************************************************************/ +{ + DLST_BUCKET *c; + + /* Go through the lists, merging them together in sorted order */ + + c = z; + while (a != z && b != z) { + if ((*cmp)(DLST_USERSPACE(a),DLST_USERSPACE(b)) <= 0) { + c->next = a; c = a; a = a->next; + } + else { + c->next = b; c = b; b = b->next; + } + }; + + /* If one of the lists is not exhausted, then re-attach it to the end + * of the newly merged list + */ + + if (a != z) c->next = a; + if (b != z) c->next = b; + + /* Set *end to point to the end of the newly merged list */ + + while (c->next != z) c = c->next; + *end = c; + + /* Determine the start of the merged lists, and reset z to point to + * itself + */ + + c = z->next; z->next = z; + return c; +} + +PUBLIC void dlst_mergesort(DLIST *l,int (*cmp_func)(void*,void*)) +/**************************************************************************** +* +* Function: dlst_mergesort +* Parameters: l - List to merge sort +* cmp_func - Function to compare two user spaces +* +* Description: Mergesort's all the nodes in the list. 'cmp' must point to +* a comparison function that can compare the user spaces of +* two different nodes. 'cmp' should work the same as +* strcmp(), in terms of the values it returns. Rather than +* waste processing time keeping the previous pointers up to +* date while performing the mergesort, we simply run through +* the list at the end of the sort to fix the previous pointers. +* +****************************************************************************/ +{ + int i,N; + DLST_BUCKET *a,*b; /* Pointers to sublists to merge */ + DLST_BUCKET *c; /* Pointer to end of sorted sublists */ + DLST_BUCKET *head; /* Pointer to dummy head node for list */ + DLST_BUCKET *todo; /* Pointer to sublists yet to be sorted */ + DLST_BUCKET *t; /* Temporary */ + + /* Set up globals required by merge() and pointer to head */ + + z = l->z; cmp = cmp_func; head = l->head; + + for (N = 1,a = z; a != head->next; N = N + N) { + todo = head->next; c = head; + while (todo != z) { + + /* Build first sublist to be merged, and splice from main list + */ + + a = t = todo; + for (i = 1; i < N; i++) t = t->next; + b = t->next; t->next = z; t = b; + + /* Build second sublist to be merged and splice from main list + */ + + for (i = 1; i < N; i++) t = t->next; + todo = t->next; t->next = z; + + /* Merge the two sublists created, and set 'c' to point to the + * end of the newly merged sublists. + */ + + c->next = merge(a,b,&t); c = t; + } + } + + /* Fix the previous pointers for the list */ + + a = b = l->head; + b = b->next; + while (1) { + b->prev = a; + if (b == z) + break; + a = a->next; + b = b->next; + } +} + +#endif diff --git a/ext/hyperwave/hg_comm.c b/ext/hyperwave/hg_comm.c new file mode 100644 index 0000000000..171ea9e778 --- /dev/null +++ b/ext/hyperwave/hg_comm.c @@ -0,0 +1,4701 @@ +/* + +----------------------------------------------------------------------+ + | 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: Uwe Steinmann | + | | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ + +/* #define HW_DEBUG */ + +#include + +#if WIN32|WINNT +#include "win95nt.h" +#else +#include "config.h" +#endif + +#if HYPERWAVE + +#include +#include +#include +#if WIN32|WINNT +# include +# define EWOULDBLOCK WSAEWOULDBLOCK +# define ETIMEDOUT WSAETIMEDOUT +# define bcopy memcpy +# define bzero(a,b) memset(a,0,b) +#else +# include +# include +# include +# include +# include +#endif +#include +#include +#include +#include "hg_comm.h" +#include "DList.h" +#include "php.h" +#include "head.h" + +static int set_nonblocking(int fd); +static int set_blocking(int fd); + +static int hg_read_exact(int sockfd, char *buf, int size); +static int hg_read(int sockfd, char *buf, int size); +static int hg_write(int sockfd, char *buf, int size); + +static int send_hg_msg(int sockfd, hg_msg *msg, int length); +static void build_msg_header(hg_msg *msg, int length, int version_msgid, int msg_type); +static char *build_msg_int(char *buf, int val); +static char *build_msg_str(char *buf, char *str); +static int swap(int val); + + +int version = VERSION; +/* F_DISTRIBUTED has the effect that all object ids are + virtual. This means whenever an object is requested a + new id is generated for this session. Wavemaster and + Harmony set this flag. How do I know? tcpdump tells + a lot if investigate the output. + int version = VERSION | F_DISTRIBUTED; */ +/* int version = VERSION | F_DISTRIBUTED | F_COMPRESSED; */ +static int msgid = 1; +static int sock_flags = -1; +static int non_blocking = 0; +static int swap_on = 0; +static int rtimeout = 40; +static int wtimeout = 40; +static int lowerror = 0; + +/*********************************************************************** +* Function fnInsStr() * +* * +* Insert string in string at position. The old string will be freed * +* with efree!!! The new string is allocated with malloc. * +* Parameter: string *str: string in which insstr is to be inserted * +* int pos: Position where string is to inserted (0=first) * +* string *insstr: string to be inserted * +* Return: pointer to new string or NULL. If NULL is returned the * +* memory for the old string has not been freed. * +***********************************************************************/ +char *fnInsStr(char *str, int pos, char *insstr) +{ + char *newstr, *ptr; + + if((str == NULL) || (insstr == NULL)) + return NULL; + if(pos > (int)strlen(str)) + return NULL; + + if(insstr[0] == '\0') + return str; + + if(NULL == (newstr = malloc(strlen(str) + strlen(insstr) + 1))) { + lowerror = LE_MALLOC; + return NULL; + } + + ptr = newstr; + memcpy(newstr, str, pos); + ptr += pos; + strcpy(ptr, insstr); + ptr += strlen(insstr); + strcpy(ptr, str+pos); + + free(str); + return newstr; +} + +/*********************************************************************** +* Function fnAddAnchor() * +* * +* Inserts new anchor into anchor list. * +* Parameter: DLIST pList: Anchor list * +* int objectID: object ID of Anchor * +* int start: start position * +* int end: end position * +* Return: Pointer to new anchor, NULL if error * +***********************************************************************/ +ANCHOR *fnAddAnchor(DLIST *pAnchorList, + int objectID, + int start, int end) +{ + ANCHOR *cur_ptr; + + if((cur_ptr = (ANCHOR *) dlst_newnode(sizeof(ANCHOR))) == NULL) { + return NULL; + } + + memset(cur_ptr, 0, sizeof(ANCHOR)); + cur_ptr->start = start; + cur_ptr->end = end; + cur_ptr->id = objectID; + cur_ptr->destdocname = NULL; + cur_ptr->nameanchor = NULL; + cur_ptr->link = NULL; + cur_ptr->tagattr = NULL; + cur_ptr->htmlattr = NULL; + cur_ptr->codebase = NULL; + cur_ptr->code = NULL; + cur_ptr->keyword = NULL; + cur_ptr->fragment = NULL; + + dlst_insertafter(pAnchorList, cur_ptr, DLST_HEAD(pAnchorList)); + + return(cur_ptr); +} + +/*********************************************************************** +* Function fnDeleteAnchor() * +* * +* Inserts new anchor into anchor list. * +* Parameter: ptr: pointer to node * +* Return: void * +***********************************************************************/ +void fnDeleteAnchor(ANCHOR *ptr) +{ + + if(ptr->destdocname) efree(ptr->destdocname); + if(ptr->nameanchor) efree(ptr->nameanchor); + if(ptr->link) efree(ptr->link); + if(ptr->tagattr) efree(ptr->tagattr); + if(ptr->htmlattr) efree(ptr->htmlattr); + if(ptr->codebase) efree(ptr->codebase); + if(ptr->code) efree(ptr->code); + if(ptr->keyword) efree(ptr->keyword); + if(ptr->fragment) efree(ptr->fragment); + + dlst_freenode(ptr); +} + +/*********************************************************************** +* Function fnCmpAnchors() * +* * +* Compares to Anchors by its start position * +* Parameter: ANCHOR a1: First Anchor * +* ANCHOR a2: Second Anchor * +* Return: As strcmp * +***********************************************************************/ +int fnCmpAnchors(ANCHOR *a1, ANCHOR *a2) +{ + if(a1->start < a2->start) + return -1; + if(a1->start == a2->start) { + /* It's importent to check this case as well, because a link with + a bigger end has to be inserted first. + */ + if(a1->end < a2->end) + return -1; + /* If both start and end are equal (yes, it is possible) + we will Src Anchor before a Dest anchor. There has been + a case where an IMG was surrounded by a NAME which was + surrounded by a HREF. In such a case the HREF doesn't + work. + */ + if(a1->end == a2->end) { + if(a1->tanchor > a2->tanchor) + return -1; + } + } + + return 1; +} + +/*********************************************************************** +* Function fnCreateAnchorList() * +* * +* Returns a list of Anchors converted from an object record * +* Parameter: char **anchors: object records of anchors * +* char **dest: object records of destinations * +* int ancount: number of anchors * +* Return: List of Anchors, NULL if error * +***********************************************************************/ +DLIST *fnCreateAnchorList(char **anchors, char **docofanchorrec, char **reldestrec, int ancount, int anchormode) +{ + int start, end, i, destid, anchordestid, objectID; + ANCHOR *cur_ptr = NULL; + DLIST *pAnchorList = dlst_init(); + + for(i=ancount-1; i>=0; i--) { + char *object = NULL; + char *docofanchorptr = NULL; + char *reldestptr = NULL; + char *str, *str1, link[200]; + + if(NULL != anchors[i]) { + object = anchors[i]; + docofanchorptr = docofanchorrec[i]; + reldestptr = reldestrec[i]; + + /* Determine Position. Doesn't matter if Src or Dest */ + str = strstr(object, "Position"); + str += 9; + sscanf(str, "0x%X 0x%X", &start, &end); + + /* Determine ObjectID */ + objectID = 0; + if(NULL != (str = strstr(object, "ObjectID"))) { + str += 9; + sscanf(str, "0x%X", &objectID); + } + + cur_ptr = fnAddAnchor(pAnchorList, objectID, start, end); + + /* Determine Type of Anchor */ + str = strstr(object, "TAnchor"); + str += 8; + if(*str == 'S') { + char destdocname[200]; + char nameanchor[200]; + cur_ptr->tanchor = 1; + + cur_ptr->destdocname = NULL; + if(NULL != (str = strstr(object, "Dest"))) { + char *tempptr; + + /* No need to care about the value of Dest, because we take the info + from docofanchorptr. + Since the anchor has a destination there are two possibilities. + 1. The destination is an anchor or + 2. or the destination is a document already. + In both cases docofanchorptr has the proper info because GETDOCBYANCHOR + is such a nice message. + */ + switch(anchormode) { + case 0: + tempptr = docofanchorptr; + break; + default: + tempptr = reldestptr; + } + if(NULL != tempptr) { + /* It's always nice to deal with names, so let's first check + for a name. If there is none we take the ObjectID. + */ + if(NULL != (str = strstr(tempptr, "Name="))) { + str += 5; + } else if(NULL != (str = strstr(tempptr, "ObjectID="))) { + str += 9; + } + if(sscanf(str, "%s\n", destdocname)) { + cur_ptr->destdocname = estrdup(destdocname); + } + destid = 0; + if(NULL != (str = strstr(tempptr, "ObjectID="))) { + str += 9; + sscanf(str, "0x%X", &destid); + } + } + } + + /* Get the Id of the anchor destination and the document id that belongs + to that anchor. We need that soon in order to determine if the anchor + points to a document or a dest anchor in a document. + */ + anchordestid = 0; + if(NULL != (str = strstr(object, "Dest="))) { + str += 5; + sscanf(str, "0x%X", &anchordestid); + } + + /* if anchordestid != destid then the destination is an anchor in a document whose + name (objectID) is already in destdocname. We will have to extend the link + by '#...' + */ + cur_ptr->nameanchor = NULL; + if(anchordestid != destid) { + if(NULL != (str = strstr(object, "Dest="))) { + str += 5; + if(sscanf(str, "%s\n", nameanchor)) + cur_ptr->nameanchor = estrdup(nameanchor); + } + } + + if(!cur_ptr->destdocname) { + cur_ptr->link = NULL; + if(NULL != (str = strstr(object, "Hint=URL:"))) { + str += 9; + if(sscanf(str, "%s\n", link)) + cur_ptr->link = estrdup(link); + } else if(NULL != (str = strstr(object, "Hint="))) { + str += 5; + if(sscanf(str, "%s\n", link)) + cur_ptr->link = estrdup(link); + } + } + + cur_ptr->fragment = NULL; + if(NULL != (str = strstr(object, "Fragment="))) { + str += 9; + if(sscanf(str, "%s\n", link)) + cur_ptr->fragment = estrdup(link); + } + + cur_ptr->htmlattr = NULL; + if(NULL != (str = strstr(object, "HtmlAttr="))) { + str += 9; + str1 = str; + while((*str1 != '\n') && (*str1 != '\0')) + str1++; + cur_ptr->htmlattr = emalloc(str1 - str + 1); + strncpy(cur_ptr->htmlattr, str, str1 - str); + cur_ptr->htmlattr[str1 - str] = '\0'; + } + + if(NULL != (str = strstr(object, "LinkType="))) { + str += 9; + if(strncmp(str, "background", 10) == 0) + cur_ptr->linktype=HW_BACKGROUND_LINK; + else + if(strncmp(str, "intag", 5) == 0) { + cur_ptr->linktype=HW_INTAG_LINK; + cur_ptr->tagattr = NULL; + if(NULL != (str = strstr(object, "TagAttr="))) { + str += 8; + str1 = str; + while((*str1 != '\n') && (*str1 != '\0')) + str1++; + cur_ptr->tagattr = emalloc(str1 - str + 1); + memcpy(cur_ptr->tagattr, str, str1 - str); + cur_ptr->tagattr[str1 - str] = '\0'; + } + } else + if(strncmp(str, "applet", 6) == 0) { + cur_ptr->linktype=HW_APPLET_LINK; + cur_ptr->codebase = NULL; + if(NULL != (str = strstr(object, "CodeBase="))) { + str += 9; + str1 = str; + while((*str1 != '\n') && (*str1 != '\0')) + str1++; + cur_ptr->codebase = emalloc(str1 - str + 1); + memcpy(cur_ptr->codebase, str, str1 - str); + cur_ptr->codebase[str1 - str] = '\0'; + } + cur_ptr->code = NULL; + if(NULL != (str = strstr(object, "Code="))) { + str += 5; + str1 = str; + while((*str1 != '\n') && (*str1 != '\0')) + str1++; + cur_ptr->code = emalloc(str1 - str + 1); + memcpy(cur_ptr->code, str, str1 - str); + cur_ptr->code[str1 - str] = '\0'; + } + } else + cur_ptr->linktype=HW_DEFAULT_LINK; + } else + cur_ptr->linktype=HW_DEFAULT_LINK; + + } else { /* Destination Anchor */ + char nameanchor[200]; + + cur_ptr->tanchor = 2; + cur_ptr->link = NULL; + + /* Here is the only additional info for the name attribute */ + cur_ptr->nameanchor = NULL; + if(NULL != (str = strstr(object, "ObjectID="))) { + str += 9; + if(sscanf(str, "%s\n", nameanchor)) + cur_ptr->nameanchor = estrdup(nameanchor); + } + + cur_ptr->keyword = NULL; + if(NULL != (str = strstr(object, "Keyword="))) { + str += 8; + if(sscanf(str, "%s\n", nameanchor)) + cur_ptr->keyword = estrdup(nameanchor); + } + + } + + efree(anchors[i]); + if(docofanchorrec[i]) efree(docofanchorrec[i]); + if(reldestrec[i]) efree(reldestrec[i]); + } + } + return pAnchorList; +} + +/*********************************************************************** +* Function fnInsAnchorsIntoText() * +* * +* Returns the text document with all anchors inserted form list * +* Parameter: char *text: text without anchors * +* DList *pAnchorList: list of anchors * +* Return: Text with anchors * +***********************************************************************/ +char *fnInsAnchorsIntoText(char *text, DLIST *pAnchorList, char **bodytag) { + ANCHOR *cur_ptr; + char bgstr[100], istr[200]; + char *scriptname; + char *newtext; + int offset = 0; + int laststart=0; + +#if APACHE + { + int j; + array_header *arr = table_elts(GLOBAL(php3_rqst)->subprocess_env); + table_entry *elts = (table_entry *)arr->elts; + + for (j=0; j < arr->nelts; j++) { + if(0 == strcmp(elts[j].key, "SCRIPT_NAME")) + break; + } + scriptname = elts[j].val; + } +#else + scriptname = getenv("SCRIPT_FILENAME"); +#endif + + newtext = text; + bgstr[0] = '\0'; + dlst_mergesort(pAnchorList, fnCmpAnchors); + + cur_ptr = (ANCHOR *) dlst_last(pAnchorList); + while(NULL != cur_ptr) { + istr[0] = '\0'; + if(cur_ptr->tanchor == 1) { /* Src Anchor */ + if(laststart >= cur_ptr->end) + offset = 0; + if((cur_ptr->link != NULL) && (cur_ptr->link[0] != '\0')) { + /* The link is only set if the Link points to an external document */ + switch(cur_ptr->linktype) { + case HW_BACKGROUND_LINK: + sprintf(bgstr, " background='%s'", cur_ptr->link); + break; + case HW_INTAG_LINK: + sprintf(istr, " %s='%s' start=%d", cur_ptr->tagattr, cur_ptr->link, cur_ptr->start); + offset -= 4; /* because there is no closing tag */ +/* laststart = cur_ptr->start; */ + break; + case HW_APPLET_LINK: + if(cur_ptr->codebase) + sprintf(istr, " CODEBASE='%s' CODE='%s'", cur_ptr->codebase, cur_ptr->code); + else + sprintf(istr, " CODEBASE='/' CODE='%s'", cur_ptr->code); + break; + default: + newtext = fnInsStr(newtext, cur_ptr->end+offset, ""); + sprintf(istr, "", cur_ptr->link, cur_ptr->htmlattr == NULL ? "" : cur_ptr->htmlattr, offset); + } + } else { + switch(cur_ptr->linktype) { + case HW_BACKGROUND_LINK: + if(NULL != cur_ptr->destdocname) + sprintf(bgstr, " background='%s/%s'", scriptname == NULL ? "" : scriptname, cur_ptr->destdocname); + else + sprintf(bgstr, ""); + break; + case HW_INTAG_LINK: + if(cur_ptr->fragment) +/* sprintf(istr, " %s='%s/%s#%s'", cur_ptr->tagattr, scriptname == NULL ? "." : scriptname, cur_ptr->destdocname, cur_ptr->fragment);*/ + sprintf(istr, " %s='#%s'", cur_ptr->tagattr, cur_ptr->fragment); + else + sprintf(istr, " %s='%s/%s'", cur_ptr->tagattr, scriptname == NULL ? "." : scriptname, cur_ptr->destdocname); + offset -= 4; /* because there is no closing tag */ +/* laststart = cur_ptr->start; */ + break; + case HW_APPLET_LINK: + if(cur_ptr->codebase) +/* sprintf(istr, " CODEBASE='%s%s' CODE='%s'", scriptname == NULL ? "" : scriptname, cur_ptr->codebase, cur_ptr->code); */ + sprintf(istr, " CODEBASE='%s' CODE='%s'", cur_ptr->codebase, cur_ptr->code); + else + sprintf(istr, " CODEBASE='/' CODE='%s'", cur_ptr->code); + break; + default: + newtext = fnInsStr(newtext, cur_ptr->end+offset, ""); + + if(cur_ptr->nameanchor) + sprintf(istr, "", scriptname == NULL ? "schade" : scriptname, cur_ptr->destdocname, cur_ptr->nameanchor, cur_ptr->htmlattr == NULL ? "" : cur_ptr->htmlattr); + else + if(cur_ptr->fragment) + sprintf(istr, "", scriptname == NULL ? "" : scriptname, cur_ptr->destdocname, cur_ptr->fragment, cur_ptr->htmlattr == NULL ? "" : cur_ptr->htmlattr); + else + sprintf(istr, "", scriptname == NULL ? "" : scriptname, cur_ptr->destdocname, cur_ptr->htmlattr == NULL ? "" : cur_ptr->htmlattr, offset); + } + } + newtext = fnInsStr(newtext, cur_ptr->start, istr); + /* In case there are several TAGS nested, we accumulate the offset + You wonder what the 4 means? It's the length of */ + offset += strlen(istr) + 4; + laststart = cur_ptr->start; + } else { + if(laststart >= cur_ptr->end) + offset = 0; + newtext = fnInsStr(newtext, cur_ptr->end+offset, ""); + + /* If we have a keyword, we assume we had a fragment which has been used + instead of the destdocname + */ + if(cur_ptr->keyword) + sprintf(istr, "", cur_ptr->keyword); + else if(cur_ptr->nameanchor) + sprintf(istr, "", cur_ptr->nameanchor); + newtext = fnInsStr(newtext, cur_ptr->start, istr); + /* In case there are several TAGS nested, we accumulate the offset + You wonder what the 4 means? It's the length of */ + offset += strlen(istr) + 4; + laststart = cur_ptr->start; + } + cur_ptr = (ANCHOR *) dlst_prev(cur_ptr); + } + sprintf(istr, "", bgstr); + *bodytag = estrdup(istr); + return(newtext); +} + +/*********************************************************************** +* Function fnAttributeValue() * +* * +* Returns the value of an attribute * +* Parameter: char *object: object record * +* char *attrname: attribute name * +* Return: char*: attribute value, NULL if name not found * +***********************************************************************/ +char *fnAttributeValue(char *object, char *attrname) +{ + char *str, *str1, *attrvalue; + int len; + + str = strstr(object, attrname); + if(NULL == str) + return(NULL); + str += strlen(attrname); + str++; + str1 = str; + while((*str1 != '\0') && (*str1 != '\n')) + str1++; + len = str1 - str; + if(NULL == (attrvalue = emalloc(len+1))) { + lowerror = LE_MALLOC; + return NULL; + } + memcpy(attrvalue, str, len); + attrvalue[len] = '\0'; + return(attrvalue); +} + +/*********************************************************************** +* Function fnAttributeCompare() * +* * +* Checks if an attribute in an objrec has a certain value * +* Parameter: char *object: object record * +* char *attrname: attribute name * +* char *value: value of attribute * +* Return: char*: as strcmp * +***********************************************************************/ +int fnAttributeCompare(char *object, char *attrname, char *value) +{ + char *str, *str1; + int len; + + if((NULL == object) || (NULL == attrname) || (NULL == value)) + return -2; + + /* Find the attribute Name and make sure it is followed by + a '=' sign and preceded by a '\n'; + */ + str = strstr(object, attrname); + if((NULL == str) || + (str[strlen(attrname)] != '=') || + (str[-1] != '\n')) { + return(-2); + } + str += strlen(attrname); /* skip the attribute name */ + str++; /* skip the equal sign */ + + /* Search for end of attribute value */ + str1 = str; + while((*str1 != '\0') && (*str1 != '\n')) + str1++; + len = str1 - str; + return(strncmp(str, value, len)); +} + +/********************************************************************* +* Function fnCOpenDataCon() * +* * +* Opens data connection on client side. This function is called * +* right after the client has requested any data from the server * +* Parameter: int sockfd: socket of control connection * +* int *port: port of control und data connection * +* Return : sockfd on success, <0 if error * +*********************************************************************/ +static int fnCOpenDataCon(int sockfd, int *port) + { + int fd; + struct sockaddr_in serv_addr; + int len; + int option = 1; + +/* len = sizeof(com_addr); + if(getsockname(sockfd, (struct sockaddr *) &com_addr, &len) < 0) + { + return(-1); + } + + *port = htons(com_addr.sin_port); */ + + /* + ** Open a TCP socket (an Internet stream socket) + */ + if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + return(-1); + } + + /* + ** Make sure that address may be reused + */ +#if defined(SUN) || (WIN32|WINNT) + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option)); +#else + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); +#endif + + /* + ** Open connection aktiv + ** Let bind() select a port number + */ + bzero((char *) &serv_addr, sizeof(serv_addr)); + if(bind(fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) + { + return(-1); + } + + /* + ** Get the port number bind selected + */ + len = sizeof (serv_addr); + if(getsockname(fd, (struct sockaddr *)&serv_addr, &len) < 0) + { + return(-1); + } + *port = ntohs(serv_addr.sin_port); + + listen(fd, 5); + + return(fd); + } + +/*====================================================================== + * + * Read/write routines with timeout detection. + * + * Usage: write_to(fd, buffer, n, timeout) + * read_to(fd, buffer, n, timeout) + * + * David Chavez + * Engineering Services & Software + * 7841 New Salem Street + * San Diego, CA 92126 + * USA + * + * dec@essw.com + * + *====================================================================*/ +#if WIN32|WINNT +#include +#else +#include +#include +#include +#endif +#include +#include + +#if !(WIN32|WINNT) +static sigset_t newmask, oldmask, zeromask; +#endif + +static int set_noblock(int fd) +{ +#if WIN32|WINNT + u_long argp=1; + + return ioctlsocket (fd, FIONBIO , &argp); +#else + + sigemptyset(&zeromask); + sigemptyset(&newmask); + sigaddset(&newmask, SIGHUP); + sigaddset(&newmask, SIGUSR1); + sigaddset(&newmask, SIGUSR2); + if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) return -1; + + return fcntl(fd, F_SETFL, O_NONBLOCK | O_NDELAY /* | FNBIO*/); +#endif +} + +int write_to(int fd, void *buffer, int n, int timeout) +{ + int nrem, nw; + char *bptr; + int error; +#if defined(SYSV) || (WIN32|WINNT) + int width = 20; +#else + int width = getdtablesize(); +#endif + fd_set writefds; + struct timeval select_timeout; + + select_timeout.tv_sec = timeout; +#if WIN32|WINNT + select_timeout.tv_usec = 0; +#else /* is this just a typo? */ + select_timeout.tv_usec = 0.; +#endif + + /* Set fd to non-blocking */ + + if (set_noblock(fd) != 0) return -1; + + /* Write to fd until no more can be written */ + + FD_ZERO(&writefds); + + FD_SET((unsigned int)fd, &writefds); + + for( nrem = n, bptr = buffer; nrem;) + { + if(( error = select(width, + (fd_set *) 0, + &writefds, + (fd_set *) 0, + &select_timeout)) <= 0 && errno != EINTR) break; + + if(errno != EINTR && ( nw = write(fd, bptr, nrem)) <= 0) { + /* + * check for error number - and keep trying to + * write + */ + if(errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR) + { + continue; + } + else + { + error = nw; + break; + } + } else { + nrem -= nw; + bptr += nw; + } + } +#if !(WIN32|WINNT) + if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) return -1; +#endif + if( ! error ) { + errno = ETIMEDOUT; + return(-2); + } else if (error < 0) { + return(error); + } else { + return(n); + } +} + +int read_to(int fd, char *buffer, int n, int timeout) + { + int nrem, nread, nr; + char *bptr; + int error; + +#if defined(SYSV) || (WIN32|WINNT) + int width = 20; +#else + int width = getdtablesize(); +#endif + fd_set readfds; + struct timeval select_timeout; + + select_timeout.tv_sec = timeout; +#if WIN32|WINNT + select_timeout.tv_usec = 0; +#else + select_timeout.tv_usec = 0.; +#endif + + /* Set fd to non-blocking */ + + if (set_noblock(fd) != 0) return -1; + + FD_ZERO(&readfds); + + FD_SET((unsigned int)fd, &readfds); + + for( nrem = n, bptr = buffer, nread = 0; nrem;) + { + if(( error = select(width, + &readfds, + (fd_set *) 0, + (fd_set *) 0, + &select_timeout)) <= 0 && errno != EINTR) break; + + if(errno != EINTR && (nr = read (fd, bptr, nrem)) < 0) + { + /* + * check for error number - and keep trying to + * read + */ + if(errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR) + { + continue; + } + else + { + error = nr; + break; + } + } + else if(nr == 0) + { + break; + } + else + { + nread += nr; + bptr += nr; + nrem -= nr; + } + } + +#if !(WIN32|WINNT) + if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) return -1; +#endif + if( ! error ) + { + errno = ETIMEDOUT; + return(-2); + } + else if ( error < 0) + { + return(-1); + } + else + { + return(nread); + } + } + +void set_swap(int do_swap) +{ + swap_on = do_swap; +} + +/*********************************************************************** +* Function open_hg_connection() * +* * +***********************************************************************/ +int open_hg_connection(char *server_name, int port) +{ + int sockfd; + int option = 1; + struct sockaddr_in server_addr; + struct hostent *hp; + if ( (hp = gethostbyname(server_name)) == NULL ) { + return(-1); + } + + bzero((char *)&server_addr, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + if ( port != 0 ) + server_addr.sin_port = htons(port); + else + server_addr.sin_port = htons(HG_SERVER_PORT); + bcopy(hp->h_addr, (char *) &server_addr.sin_addr, hp->h_length); + + if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { + return(-2); + } + +#if defined(SUN) || (WIN32|WINNT) + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option)); +#else + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); +#endif /* SUN */ + + if (connect(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) { + close(sockfd); + return(-3); + } + +#if !(WIN32|WINNT) + if ( (sock_flags = fcntl(sockfd, F_GETFL, 0)) == -1 ) +#endif + + if ( set_nonblocking(sockfd) == -1 ) { + return(-4); + } + + return(sockfd); +} + + +/*********************************************************************** +* Function initialize_hg_connection() * +* * +***********************************************************************/ +int initialize_hg_connection(int sockfd, int *do_swap, int *version, char **userdata, char **server_string, char *username, char *password) +{ + char buf, c; + char *tmp; + hg_msg *ready_msg, *retmsg, msg; + int i = 0x01; + int length; + + *do_swap = 0; + buf = 'T'; + if ( hg_write(sockfd, &buf, 1) == -1 ) { + return(-2); + } + + if ( hg_read_exact(sockfd, &buf, 1) == -1 ) { + return(-3); + } + if ( buf == 'F' ) { + return(-4); + } + if ( buf != 'T' ) { + return(-5); + } + + buf = c = ( *(char *)&i ) ? 'l' : 'B'; + if ( hg_write(sockfd, &buf, 1) == -1 ) { + return(-6); + } + if ( hg_read_exact(sockfd, &buf, 1) == -1 ) { + return(-7); + } + if ( c != buf ) { + swap_on = 1; + *do_swap = 1; + } else { + swap_on = 0; + *do_swap = 0; + } + + if ( send_ready(sockfd) == -1) { + return(-8); + } + + /* Receive return from Ready message */ + if ( (ready_msg = recv_ready(sockfd)) == NULL ) { + return(-9); + } + + if ((ready_msg->version_msgid & F_VERSION) < VERSION) + return(-8); + *version = ready_msg->version_msgid; + *server_string = strdup(ready_msg->buf+4); + efree(ready_msg->buf); + efree(ready_msg); + + /* If we have a username and password then do the identification. */ + if((NULL != username) && (NULL != password)) { + length = HEADER_LENGTH + sizeof(int) + strlen(username) + 1 + strlen(password) + 1; + + build_msg_header(&msg, length, msgid++, IDENTIFY_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, 0); + tmp = build_msg_str(tmp, username); + tmp = build_msg_str(tmp, password); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-10); + } + efree(msg.buf); + } + + if((NULL != username) && (NULL != password)) { + /* Receive return form identify message */ + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) + return(-11); + + *userdata = retmsg->buf; + efree(retmsg); + } + + return(0); +} + + +static int set_nonblocking(int fd) +{ +#if WIN32|WINNT + unsigned int argp=0; + +/* if ( sock_flags == -1 ) + getsockopt (fd, SOL_SOCKET, optname, optval, optlen); +*/ if(ioctlsocket (fd, FIONBIO , &argp) == -1) + return(-1); +#else + if ( sock_flags == -1 ) + sock_flags = fcntl(fd, F_GETFL, 0); + if ( fcntl(fd, F_SETFL, O_NONBLOCK) == -1 ) + return(-1); +#endif + non_blocking = 1; + return(0); +} + + +static int set_blocking(int fd) +{ +#if WIN32|WINNT + unsigned int argp=1; + + if(ioctlsocket (fd, FIONBIO , &argp) == -1) + return(-1); +#else + if ( fcntl(fd, F_SETFL, sock_flags) == -1 ) + return(-1); +#endif + return(0); +} + + +static int hg_read_exact(int sockfd, char *buf, int size) +{ + int len = 0; + + len = read_to(sockfd, (void *) buf, size, rtimeout); + if ( len < 0 ) + return -1; + return(0); +} + + +static int hg_read(int sockfd, char *buf, int size) +{ + int try = 0; + int len = 0; + + if ( !non_blocking ) + set_nonblocking(sockfd); + while ( len == 0 ) { + len = recv(sockfd, (void *) buf, size, 0); + if ( len == -1 ) { + if ( (errno == EAGAIN) || (errno == EWOULDBLOCK) ) { + if ( ++try > 5 ) + return(-1); + sleep(1); + } + else return(-1); + } + } + return(len); +} + + +static int hg_write(int sockfd, char *buf, int size) +{ + int try = 0; + int len = 0; + + if ( !non_blocking ) + set_nonblocking(sockfd); + while ( size > 0 ) { + len = send(sockfd, (void *) buf, size, 0); + if ( len == -1 ) { + if ( (errno == EAGAIN) || (errno == EWOULDBLOCK) ) { + if ( ++try > 5 ) + return(-1); + sleep(1); + } + else return(-1); + } + else { + size -= len; + buf += len; + try = 0; + } + } + return(0); +} + + +hg_msg *recv_hg_msg(int sockfd) +{ + hg_msg *msg; + + if ( (msg = (hg_msg *)emalloc(sizeof(hg_msg))) == NULL ) { +/* php3_printf("recv_hg_msg"); */ + lowerror = LE_MALLOC; + return(NULL); + } + + if ( hg_read_exact(sockfd, (char *)&(msg->length), 4) == -1 ) { +/* php3_printf("recv_hg_msg: hg_read (1) returned -1\n"); */ + efree(msg); + return(NULL); + } + + if ( hg_read_exact(sockfd, (char *)&(msg->version_msgid), 4) == -1 ) { +/* php3_printf("recv_hg_msg: hg_read (2) returned -1\n"); */ + efree(msg); + return(NULL); + } + + if ( hg_read_exact(sockfd, (char *)&(msg->msg_type), 4) == -1 ) { +/* php3_printf("recv_hg_msg: hg_read (3) returned -1\n"); */ + efree(msg); + return(NULL); + } + + if ( msg->length > HEADER_LENGTH ) { + if ( (msg->buf = (char *) emalloc(msg->length-HEADER_LENGTH)) == NULL ) { +/* php3_printf("recv_hg_msg"); */ + lowerror = LE_MALLOC; + efree(msg); + return(NULL); + } + if ( hg_read_exact(sockfd, msg->buf, msg->length-HEADER_LENGTH) == -1 ) { +/* php3_printf("recv_hg_msg: hg_read (4) returned -1\n"); */ + efree(msg->buf); + efree(msg); + return(NULL); + } + } + else + msg->buf = NULL; + +#ifdef HW_DEBUG + php3_printf(" Recv msg: type = %d -- id = %d
\n", msg->msg_type, msg->version_msgid); +#endif + return(msg); +} + + +hg_msg *recv_ready(int sockfd) +{ + hg_msg *ready_msg; + + if ( (ready_msg = recv_hg_msg(sockfd)) == NULL ) { +/* php3_printf("recv_ready: recv_hg_msg returned NULL\n"); */ + return(NULL); + } + if ( ready_msg->msg_type != READY_MESSAGE ) { +/* php3_printf("recv_ready: recv_hg_msg returned wrong message: %d, %d \n", ready_msg->length, ready_msg->msg_type); */ + efree(ready_msg); + return(NULL); + } + + return(ready_msg); +} + + +hg_msg *recv_command(int sockfd) +{ + hg_msg *comm_msg; + + if ( (comm_msg = recv_hg_msg(sockfd)) == NULL ) { +/* fprintf(stderr, "recv_command: recv_hg_msg returned NULL\n"); */ + return(NULL); + } + if ( comm_msg->msg_type != COMMAND_MESSAGE ) { +/* fprintf(stderr, "recv_command: recv_hg_msg returned wrong message\n"); */ + return(NULL); + } + + return(comm_msg); +} + +int send_dummy(int sockfd, hw_objectID objectID, int msgid, char **attributes) +{ + hg_msg msg, *retmsg; + int length, error; + char *tmp; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, msgid); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + *attributes = NULL; + return(-1); + } + + if(0 == (int) *(retmsg->buf)) { + *attributes = estrdup(retmsg->buf+sizeof(int)); + efree(retmsg->buf); + efree(retmsg); + } else { + error = *((int *) retmsg->buf); + *attributes = NULL; + efree(retmsg->buf); + efree(retmsg); + return error; + } + + return(0); +} + +static int bh_send_deleteobject(int sockfd, hw_objectID objectID) { + hg_msg msg; + int length; + char *tmp; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, DELETEOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + efree(msg.buf); + + return(msgid-1); +} + +static int uh_send_deleteobject(int sockfd) { + hg_msg *retmsg; + int error; + + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + return(-1); + } + + if(NULL == retmsg->buf) { + efree(retmsg); + return -1; + } + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return(error); +} + +int send_deleteobject(int sockfd, hw_objectID objectID) +{ + if(0 > bh_send_deleteobject(sockfd, objectID)) + return -1; + return(uh_send_deleteobject(sockfd)); +} + +static int bh_send_changeobject(int sockfd, hw_objectID objectID, char *mod) { + hg_msg msg; + int length; + char *tmp; + + length = HEADER_LENGTH + sizeof(hw_objectID) + strlen(mod) + 1; + + build_msg_header(&msg, length, msgid++, CHANGEOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + tmp = build_msg_str(tmp, mod); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + efree(msg.buf); + + return(msgid-1); +} + +static int uh_send_changeobject(int sockfd) { + hg_msg *retmsg; + int error; + + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + return(-1); + } + + error = *((int *) retmsg->buf); + return(error); +} + +int send_changeobject(int sockfd, hw_objectID objectID, char *modification) +{ + if(0 > bh_send_changeobject(sockfd, objectID, modification)) + return -1; + return(uh_send_changeobject(sockfd)); +} + +static int bh_send_getobject(int sockfd, hw_objectID objectID) { + hg_msg msg; + int length; + char *tmp; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + efree(msg.buf); + + return(msgid-1); +} + +static int uh_send_getobject(int sockfd, char **attributes) { + hg_msg *retmsg; + int error; + + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + *attributes = NULL; + return(-1); + } + + if(0 == (int) *(retmsg->buf)) { + *attributes = estrdup(retmsg->buf+sizeof(int)); + efree(retmsg->buf); + efree(retmsg); + } else { + error = *((int *) retmsg->buf); + *attributes = NULL; + efree(retmsg->buf); + efree(retmsg); + return error; + } + + return(0); +} + +int send_getobject(int sockfd, hw_objectID objectID, char **attributes) +{ + if(0 > bh_send_getobject(sockfd, objectID)) + return -1; + return(uh_send_getobject(sockfd, attributes)); +} + +int send_getandlock(int sockfd, hw_objectID objectID, char **attributes) +{ + hg_msg msg, *retmsg; + int length, error; + char *tmp; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETANDLOCK_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + *attributes = NULL; + return(-1); + } + + if(0 == (error = (int) *(retmsg->buf))) { + *attributes = estrdup(retmsg->buf+sizeof(int)); + } else { + *attributes = NULL; + } + + efree(retmsg->buf); + efree(retmsg); + return error; +} + +int send_insertobject(int sockfd, char *objrec, char *parms, hw_objectID *objectID) +{ + hg_msg msg, *retmsg; + int length, error; + char *tmp; + int *ptr; + + length = HEADER_LENGTH + strlen(objrec) + 1 + strlen(parms) + 1; + + build_msg_header(&msg, length, msgid++, INSERTOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_str(msg.buf, objrec); + tmp = build_msg_str(tmp, parms); +/*fprintf(stderr,"objrec = %s, parms = %s\n", objrec, parms); */ + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + *objectID = 0; + return(-1); + } + + ptr = (int *) retmsg->buf; + if(0 == (error = *ptr)) { + ptr++; + *objectID = *ptr; + } else { + *objectID = 0; + } + efree(retmsg->buf); + efree(retmsg); + return error; +} + +int send_unlock(int sockfd, hw_objectID objectID) +{ + hg_msg msg, *retmsg; + int length, error; + char *tmp; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, UNLOCK_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + return(-1); + } + + error = (int) *(retmsg->buf); + + efree(retmsg->buf); + efree(retmsg); + return error; +} + +int send_incollections(int sockfd, int retcol, int cobjids, hw_objectID *objectIDs, int ccollids, hw_objectID *collIDs, int *count, hw_objectID **retIDs) +{ + hg_msg msg, *retmsg; + int length, error; + char *tmp; + int *ptr, *ptr1, i; + + length = HEADER_LENGTH + sizeof(hw_objectID) + (cobjids + ccollids) * sizeof(hw_objectID) + 2 * sizeof(int); + + build_msg_header(&msg, length, msgid++, INCOLLECTIONS_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { + lowerror = LE_MALLOC; + return(-3); + } + + tmp = build_msg_int(msg.buf, retcol); + tmp = build_msg_int(tmp, cobjids); + for(i=0; ibuf; + if(ptr == NULL) { + if(retmsg) efree(retmsg); + return -1; + } + if(*ptr++ == 0) { + *count = *ptr; + ptr++; + if(NULL != (*retIDs = emalloc(*count * sizeof(hw_objectID)))) { + ptr1 = *retIDs; + for(i=0; i<*count; ptr++, i++) + ptr1[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + if(retmsg->buf) efree(retmsg->buf); + if(retmsg) efree(retmsg); + return error; + } + return(0); +} + + +int send_inscoll(int sockfd, hw_objectID objectID, char *objrec, hw_objectID *new_objectID) +{ + hg_msg msg, *retmsg; + int length, error; + char *tmp; + int *ptr; + + length = HEADER_LENGTH + sizeof(hw_objectID) + strlen(objrec) + 1; + + build_msg_header(&msg, length, msgid++, INSCOLL_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { + lowerror = LE_MALLOC; + return(-3); + } + + tmp = build_msg_int(msg.buf, objectID); + tmp = build_msg_str(tmp, objrec); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-2); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if(retmsg == NULL) { + return(-1); + } + + ptr = (int *) retmsg->buf; + if(0 != (error = *ptr)) { + efree(retmsg->buf); + efree(retmsg); + *new_objectID = 0; + return error; + } + + ptr++; + *new_objectID = *ptr; + return 0; +} + +int send_insdoc(int sockfd, hw_objectID objectID, char *objrec, char *text, hw_objectID *new_objectID) +{ + hg_msg msg, *retmsg; + int length, error; + char *tmp; + int *ptr; + + length = HEADER_LENGTH + sizeof(hw_objectID) + strlen(objrec) + 1; + if(text) { + length += strlen(text); + length++; + } + + build_msg_header(&msg, length, msgid++, INSDOC_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { + lowerror = LE_MALLOC; + return(-3); + } + + tmp = build_msg_int(msg.buf, objectID); + tmp = build_msg_str(tmp, objrec); + if(text) + tmp = build_msg_str(tmp, text); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-2); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if(retmsg == NULL) { + return(-1); + } + + ptr = (int *) retmsg->buf; + if(0 != (error = *ptr)) { + efree(retmsg->buf); + efree(retmsg); + *new_objectID = 0; + return error; + } + + ptr++; + *new_objectID = *ptr; + return 0; +} + +int send_getdestforanchorsobj(int sockfd, char **anchorrec, char ***destrec, int count); +int send_getreldestforanchorsobj(int sockfd, char **anchorrec, char ***reldestrec, int count, int rootID, int thisID); + +int send_gettext(int sockfd, hw_objectID objectID, int mode, int rootid, char **objattr, char **bodytag, char **text, int *count) +{ + hg_msg msg, *retmsg; + int length, *ptr, ancount, error; + char *tmp, *attributes, *documenttype; + char **anchors; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if(retmsg == NULL) { + attributes = NULL; + return(-1); + } + + ptr = (int *) retmsg->buf; + if(*ptr == 0) { + attributes = estrdup(retmsg->buf+sizeof(int)); + efree(retmsg); + efree(retmsg->buf); + } else { + error = *ptr; + attributes = NULL; + efree(retmsg); + efree(retmsg->buf); + return error; + } + + length = HEADER_LENGTH + strlen(attributes) + 1; + build_msg_header(&msg, length, msgid++, GETTEXT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_str(msg.buf, attributes); + + documenttype = fnAttributeValue(attributes, "DocumentType"); + *objattr = strdup(attributes); + efree(attributes); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if (retmsg == NULL) { + *text = NULL; + return(-1); + } + + ptr = (int *) retmsg->buf; + if(*ptr == 0) { + ptr++; + *count = retmsg->length-HEADER_LENGTH-sizeof(int); + if(NULL != (*text = malloc(*count + 1))) { + memcpy(*text, retmsg->buf+sizeof(int), *count); +/* *text[*count] = 0; */ + } else { + efree(retmsg); + efree(retmsg->buf); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *ptr; + efree(retmsg); + efree(retmsg->buf); + *text = NULL; + return(error); + } + efree(retmsg); + efree(retmsg->buf); + + if((documenttype != NULL) && (strcmp(documenttype, "Image") != 0)) { + if(send_getanchorsobj(sockfd, objectID, &anchors, &ancount) == 0) { + char **destrec, **reldestrec; + DLIST *pAnchorList; + + send_getdestforanchorsobj(sockfd, anchors, &destrec, ancount); + send_getreldestforanchorsobj(sockfd, anchors, &reldestrec, ancount, rootid, objectID); + pAnchorList = fnCreateAnchorList(anchors, destrec, reldestrec, ancount, mode); + /* Free only the array, the objrecs has been freed in fnCreateAnchorList() */ + if(anchors) efree(anchors); + if(destrec) efree(destrec); + if(reldestrec) efree(reldestrec); + + if(pAnchorList != NULL) { + char *newtext; + char *body; + + newtext = fnInsAnchorsIntoText(*text, pAnchorList, &body); + dlst_kill(pAnchorList, fnDeleteAnchor); + *bodytag = strdup(body); + efree(body); + *text = newtext; + *count = strlen(newtext); + } + } + } + + if(documenttype) efree(documenttype); + return(0); +} + +int send_edittext(int sockfd, char *objattr, char *text) +{ + hg_msg msg, *retmsg; + int length, *ptr, error; + char *tmp, *path, *objid; + hw_objectID objectID; + + objid = fnAttributeValue(objattr, "ObjectID="); + if(objid == NULL) + return(-1); + if(!sscanf(objid, "0x%x", &objectID)) + return(-1); + + path = fnAttributeValue(objattr, "Path="); + if(path == NULL) + return(-1); + length = HEADER_LENGTH + sizeof(hw_objectID) + strlen(path) + 1 + 1 + strlen(text) + 1; + + build_msg_header(&msg, length, msgid++, EDITTEXT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + tmp = build_msg_str(tmp, path); + tmp = build_msg_str(tmp, ""); + tmp = build_msg_str(tmp, text); + + if(path) efree(path); + if(objid) efree(objid); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if (retmsg == NULL) { + *text = '\0'; + return(-1); + } + + ptr = (int *) retmsg->buf; + error = *ptr; + efree(retmsg); + efree(retmsg->buf); + return(error); +} + +int send_getcgi(int sockfd, hw_objectID objectID, char *cgi_env_str, char **objattr, char **text, int *count) +{ + hg_msg msg, *retmsg; + int length, *ptr, error, new_attr_len; + char *tmp, *attributes, *new_attr; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if(retmsg == NULL) { + attributes = NULL; + return(-1); + } + + ptr = (int *) retmsg->buf; + if(*ptr == 0) { + attributes = estrdup(retmsg->buf+sizeof(int)); + efree(retmsg); + efree(retmsg->buf); + } else { + error = *ptr; + attributes = NULL; + efree(retmsg); + efree(retmsg->buf); + return error; + } + + new_attr_len = strlen(attributes) + strlen(cgi_env_str) + 2; + new_attr = malloc(new_attr_len); + strcpy(new_attr, attributes); + strcat(new_attr, cgi_env_str); + length = HEADER_LENGTH + strlen(new_attr) + 1 + sizeof(int); + build_msg_header(&msg, length, msgid++, GETCGI_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_str(msg.buf, new_attr); + tmp = build_msg_int(tmp, 0); + + *objattr = strdup(attributes); + efree(attributes); + free(new_attr); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if (retmsg == NULL) { + *text = NULL; + return(-1); + } + + /* Attention: It looks like the documentation is not quite right. + According to the docs the buffer starts with an integer which + is followed by the output of the cgi script. This seems not to + be true. There is another integer right after the error. + The output of the cgi script is also preceded by the 'Content-type' + header. */ + ptr = (int *) retmsg->buf; + if(*ptr++ == 1024) { + *count = *ptr++; + if(NULL != (*text = malloc(*count + 1))) { + memcpy(*text, ptr, *count); + } else { + efree(retmsg); + efree(retmsg->buf); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *ptr + 1024; /* move errors to >2024 */ + efree(retmsg); + efree(retmsg->buf); + *text = NULL; + return(error); + } + efree(retmsg); + efree(retmsg->buf); + + return(0); +} + +int send_getremote(int sockfd, hw_objectID objectID, char **objattr, char **text, int *count) +{ + hg_msg msg, *retmsg; + int length, *ptr, error; + char *tmp, *attributes; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if(retmsg == NULL) { + attributes = NULL; + return(-1); + } + + ptr = (int *) retmsg->buf; + if(*ptr == 0) { + attributes = estrdup(retmsg->buf+sizeof(int)); + efree(retmsg); + efree(retmsg->buf); + } else { + error = *ptr; + attributes = NULL; + efree(retmsg); + efree(retmsg->buf); + return error; + } + + length = HEADER_LENGTH + strlen(attributes) + 1 + sizeof(int); + build_msg_header(&msg, length, msgid++, GETREMOTE_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_str(msg.buf, attributes); + tmp = build_msg_int(tmp, 0); + + *objattr = strdup(attributes); + efree(attributes); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if (retmsg == NULL) { + *text = NULL; + return(-1); + } + + ptr = (int *) retmsg->buf; + if(*ptr == 1024) { + *count = retmsg->length-HEADER_LENGTH-sizeof(int)-sizeof(int); + if(NULL != (*text = malloc(*count + 1))) { + memcpy(*text, ptr+2, *count); +/* *text[*count] = 0; */ + } else { + efree(retmsg); + efree(retmsg->buf); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *ptr + 1024; /* move errors to >2024 */ + efree(retmsg); + efree(retmsg->buf); + *text = NULL; + return(error); + } + efree(retmsg); + efree(retmsg->buf); + + return(0); +} + +int send_getremotechildren(int sockfd, char *attributes, char **text, int **childIDs, int *count) +{ + hg_msg msg, *retmsg; + int length, *ptr, *ptr1, error; + char *tmp; + +/* length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if(retmsg == NULL) { + attributes = NULL; + return(-1); + } + + ptr = (int *) retmsg->buf; + if(*ptr == 0) { + attributes = estrdup(retmsg->buf+sizeof(int)); + efree(retmsg); + efree(retmsg->buf); + } else { + error = *ptr; + attributes = NULL; + efree(retmsg); + efree(retmsg->buf); + return error; + } +*/ + length = HEADER_LENGTH + strlen(attributes) + 1 + sizeof(int); + build_msg_header(&msg, length, msgid++, GETREMOTECHILDREN_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_str(msg.buf, attributes); + tmp = build_msg_int(tmp, 0); + +/* efree(attributes); */ + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if (retmsg == NULL) { + *childIDs = NULL; + return(-1); + } + ptr = (int *) retmsg->buf; + if(*ptr++ == 1024) { + int i, remlen, sum; + *count = *ptr; + ptr++; + if(NULL != (*childIDs = emalloc(*count * sizeof(hw_objectID)))) { + ptr1 = *childIDs; + sum = 0; + for(i=0; i<*count; ptr++, i++) { + ptr1[i] = *ptr; + sum += *ptr; + } + } else { + efree(retmsg); + efree(retmsg->buf); + lowerror = LE_MALLOC; + return(-1); + } + + remlen = retmsg->length - HEADER_LENGTH - *count * sizeof(int) - 2 * sizeof(int); +/*ptr1[i-1] = remlen; */ +/*ptr1[i-2] = sum; */ +/*ptr1[i-3] = *count; */ + if(NULL != (*text = emalloc(remlen + 1))) { + memcpy(*text, ptr, remlen); + } else { + efree(childIDs); + efree(retmsg); + efree(retmsg->buf); + lowerror = LE_MALLOC; + return(-1); + } + efree(retmsg->buf); + efree(retmsg); + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + *childIDs = NULL; + *text = NULL; + return error; + } + return(0); +} + +int send_mvcpdocscollscoll(int sockfd, hw_objectID *objectIDs, int count, int from, int dest, int cpmv, int doccoll) +{ + hg_msg msg, *retmsg; + int length, i, error; + char *tmp; + + if(count <= 0) + return 0; + + /* HEADER_LENGTH + cpmv + from + dest + count + nr of obj */ + length = HEADER_LENGTH + sizeof(hw_objectID) + sizeof(hw_objectID) + sizeof(hw_objectID) + sizeof(hw_objectID) + count * sizeof(hw_objectID); + + switch(doccoll) { + case DOCUMENT: + build_msg_header(&msg, length, msgid++, MVCPDOCSCOLL_MESSAGE); + break; + case COLLECTION: + build_msg_header(&msg, length, msgid++, MVCPCOLLSCOLL_MESSAGE); + break; + } + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, cpmv); + tmp = build_msg_int(tmp, from); + tmp = build_msg_int(tmp, dest); + tmp = build_msg_int(tmp, count); + for(i=0; ibuf); + efree(retmsg->buf); + return(error); +} + +int send_docbyanchor(int sockfd, hw_objectID objectID, hw_objectID *anchorID) +{ + hg_msg msg, *retmsg; + int length, error; + char *tmp; + int *ptr; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETDOCBYANCHOR_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + return(-1); + } + + ptr = (int *) retmsg->buf; + error = *ptr++; + if(error == 0) { + *anchorID = *ptr; + } else { + *anchorID = 0; + } + efree(retmsg->buf); + efree(retmsg); + return error; +} + +int send_docbyanchorobj(int sockfd, hw_objectID objectID, char **objrec) +{ + hg_msg msg, *retmsg; + int length, error; + char *tmp; + int *ptr, anchorID; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETDOCBYANCHOR_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + return(-1); + } + + ptr = (int *) retmsg->buf; + error = *ptr++; + if(error == 0) { + anchorID = *ptr; + } else { + anchorID = 0; + } + efree(retmsg->buf); + efree(retmsg); + + if(0 > bh_send_getobject(sockfd, anchorID)) + return -1; + return(uh_send_getobject(sockfd, objrec)); +} + +int send_children(int sockfd, hw_objectID objectID, hw_objectID **childIDs, int *count) +{ + hg_msg msg, *retmsg; + int length, i, error; + char *tmp; + int *ptr, *ptr1; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, CHILDREN_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if (-1 == send_hg_msg(sockfd, &msg, length)) { + efree(msg.buf); + return(-2); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + return(-3); + } + + ptr = (int *) retmsg->buf; + if(ptr == NULL) { + if(retmsg) efree(retmsg); + return -1; + } + if(*ptr++ == 0) { + *count = *ptr++; + if(NULL != (*childIDs = emalloc(*count * sizeof(hw_objectID)))) { + ptr1 = *childIDs; + for(i=0; i<*count; ptr++, i++) + ptr1[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return error; + } + + return(0); +} + +int send_childrenobj(int sockfd, hw_objectID objectID, char ***childrec, int *count) +{ + hg_msg msg, *retmsg; + int length, i, error; + char *tmp, **objptr; + int *childIDs = NULL; + int *ptr; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, CHILDREN_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) + return(-1); + + ptr = (int *) retmsg->buf; + if(ptr == NULL) { + if(retmsg) efree(retmsg); + return -1; + } + if(*ptr++ == 0) { + *count = *ptr++; + if(NULL != (childIDs = emalloc(*count * sizeof(hw_objectID)))) { + for(i=0; i<*count; ptr++, i++) + childIDs[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return error; + } + + /* Now get for each child collection the object record */ + for(i=0; i<*count; i++) { + + length = HEADER_LENGTH + sizeof(hw_objectID); + build_msg_header(&msg, length, childIDs[i], GETOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { + efree(childIDs); + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, childIDs[i]); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(childIDs); + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + } + efree(childIDs); + + if(NULL == (objptr = (char **) emalloc(*count * sizeof(hw_objrec *)))) { + /* if emalloc fails, get at least all remaining messages from server */ + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + efree(retmsg->buf); + efree(retmsg); + } + *childrec = NULL; + lowerror = LE_MALLOC; + return(-1); + } else { + *childrec = objptr; + + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + if ( retmsg != NULL ) { + if(0 == (int) *(retmsg->buf)) { + *objptr = estrdup(retmsg->buf+sizeof(int)); + objptr++; + efree(retmsg->buf); + efree(retmsg); + } else { + *objptr = NULL; + objptr++; + efree(retmsg->buf); + efree(retmsg); + } + } + } + } + + return(0); +} + +int send_getchildcoll(int sockfd, hw_objectID objectID, hw_objectID **childIDs, int *count) +{ + hg_msg msg, *retmsg; + int length, error; + char *tmp; + int *ptr, i, *ptr1; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETCHILDCOLL_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + return(-1); + } + + ptr = (int *) retmsg->buf; + if(ptr == NULL) { + if(retmsg) efree(retmsg); + return -1; + } + if(*ptr++ == 0) { + *count = *ptr++; + if(NULL != (*childIDs = emalloc(*count * sizeof(hw_objectID)))) { + ptr1 = *childIDs; + for(i=0; i<*count; ptr++, i++) + ptr1[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return error; + } + + return(0); +} + +int send_getchildcollobj(int sockfd, hw_objectID objectID, char ***childrec, int *count) +{ + hg_msg msg, *retmsg; + int length, i, error; + char *tmp, **objptr; + int *childIDs = NULL; + int *ptr; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETCHILDCOLL_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) + return(-1); + + ptr = (int *) retmsg->buf; + if(ptr == NULL) { + if(retmsg) efree(retmsg); + return -1; + } + if(*ptr++ == 0) { + *count = *ptr++; + if(NULL != (childIDs = emalloc(*count * sizeof(hw_objectID)))) { + for(i=0; i<*count; ptr++, i++) + childIDs[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return error; + } + + /* Now get for each child collection the object record */ + for(i=0; i<*count; i++) { + + length = HEADER_LENGTH + sizeof(hw_objectID); + build_msg_header(&msg, length, childIDs[i], GETOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { + efree(childIDs); + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, childIDs[i]); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(childIDs); + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + } + efree(childIDs); + + if(NULL == (objptr = (char **) emalloc(*count * sizeof(hw_objrec *)))) { + /* if emalloc fails, get at least all remaining messages from server */ + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + efree(retmsg->buf); + efree(retmsg); + } + *childrec = NULL; + lowerror = LE_MALLOC; + return(-1); + } else { + *childrec = objptr; + + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + if ( retmsg != NULL ) { + if(0 == (int) *(retmsg->buf)) { + *objptr = estrdup(retmsg->buf+sizeof(int)); + objptr++; + efree(retmsg->buf); + efree(retmsg); + } else { + *objptr = NULL; + objptr++; + efree(retmsg->buf); + efree(retmsg); + } + } + } + } + + return(0); +} + +int send_getchilddoccoll(int sockfd, hw_objectID objectID, hw_objectID **childIDs, int *count) +{ + hg_msg msg, *retmsg; + int length, error; + char *tmp; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETCHILDDOCCOLL_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } else { + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg != NULL ) { + int *ptr, i, *ptr1; + + ptr = (int *) retmsg->buf; + if(ptr == NULL) { + if(retmsg) efree(retmsg); + return -1; + } + if(*ptr++ == 0) { + *count = *ptr++; + if(NULL != (*childIDs = emalloc(*count * sizeof(hw_objectID)))) { + ptr1 = *childIDs; + for(i=0; i<*count; ptr++, i++) + ptr1[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return error; + } + } + } + + return(0); + +} + +int send_getchilddoccollobj(int sockfd, hw_objectID objectID, hw_objrec ***childrec, int *count) +{ + hg_msg msg, *retmsg; + int length, i, error; + char *tmp, **objptr; + int *childIDs = NULL; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETCHILDDOCCOLL_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + efree(msg.buf); + + retmsg = recv_hg_msg(sockfd); + if ( retmsg != NULL ) { + int *ptr, i; + + ptr = (int *) retmsg->buf; + if(ptr == NULL) { + if(retmsg->buf) efree(retmsg->buf); + return -1; + } + if(*ptr++ == 0) { + *count = *ptr++; + if(NULL != (childIDs = emalloc(*count * sizeof(hw_objectID)))) { + for(i=0; i<*count; ptr++, i++) + childIDs[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return error; + } + } + + /* Now get for each child collection the object record */ + for(i=0; i<*count; i++) { + length = HEADER_LENGTH + sizeof(hw_objectID); + build_msg_header(&msg, length, childIDs[i], GETOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, childIDs[i]); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + } + + if(NULL == (objptr = (char **) emalloc(*count * sizeof(hw_objrec *)))) { + /* if emalloc fails, get at least all remaining messages from server */ + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + efree(retmsg->buf); + efree(retmsg); + } + *childrec = NULL; + lowerror = LE_MALLOC; + return(-1); + } else { + *childrec = objptr; + + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + if ( retmsg != NULL ) { + if(0 == (int) *(retmsg->buf)) { + *objptr = estrdup(retmsg->buf+sizeof(int)); + objptr++; + efree(retmsg->buf); + efree(retmsg); + } else { + *objptr = NULL; + objptr++; + efree(retmsg->buf); + efree(retmsg); + } + } + } + } + + return(0); +} + +int send_getanchors(int sockfd, hw_objectID objectID, int **anchorIDs, int *count) +{ + hg_msg msg, *retmsg; + int length, error; + char *tmp; + int *ptr, i, *ptr1; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETANCHORS_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + efree(msg.buf); + + if (NULL == (retmsg = recv_hg_msg(sockfd))) + return(-1); + + ptr = (int *) retmsg->buf; + if(ptr == NULL) { + if(retmsg) efree(retmsg); + return -1; + } + if(*ptr++ == 0) { + *count = *ptr++; + if(NULL != (*anchorIDs = emalloc(*count * sizeof(hw_objectID)))) { + ptr1 = *anchorIDs; + for(i=0; i<*count; ptr++, i++) + ptr1[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return error; + } + + return(0); +} + +int send_getanchorsobj(int sockfd, hw_objectID objectID, char ***childrec, int *count) +{ + hg_msg msg, *retmsg; + int length, error; + char *tmp; + int *ptr, i, *ptr1; + int *anchorIDs = NULL; + char **objptr; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, 50, GETANCHORS_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + efree(msg.buf); + + if (NULL == (retmsg = recv_hg_msg(sockfd))) + return(-1); + + ptr = (int *) retmsg->buf; + if(ptr == NULL) { + if(retmsg) efree(retmsg); + return -1; + } + if(*ptr++ == 0) { + *count = *ptr++; + if(NULL != (anchorIDs = emalloc(*count * sizeof(hw_objectID)))) { + ptr1 = anchorIDs; + for(i=0; i<*count; ptr++, i++) + ptr1[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return error; + } + + /* Now get for each anchor the object record */ + for(i=0; i<*count; i++) { + + length = HEADER_LENGTH + sizeof(hw_objectID); + build_msg_header(&msg, length, anchorIDs[i], GETOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, anchorIDs[i]); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + } + if(anchorIDs) efree(anchorIDs); + + if(NULL == (objptr = (char **) emalloc(*count * sizeof(hw_objrec *)))) { + /* if emalloc fails, get at least all remaining messages from server */ + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + efree(retmsg->buf); + efree(retmsg); + } + *childrec = NULL; + lowerror = LE_MALLOC; + return(-1); + } else { + *childrec = objptr; + + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + if ( retmsg != NULL ) { + if(0 == (int) *(retmsg->buf)) { + *objptr = estrdup(retmsg->buf+sizeof(int)); + objptr++; + efree(retmsg->buf); + efree(retmsg); + } else { + *objptr = NULL; + objptr++; + efree(retmsg->buf); + efree(retmsg); + } + } + } + } + + return(0); +} + +int send_getdestforanchorsobj(int sockfd, char **anchorrec, char ***destrec, int count) +{ + int i; + char *objptr, **destptr; + char *str; + int objectID; + + if(NULL == (destptr = (char **) emalloc(count * sizeof(hw_objrec *)))) { + lowerror = LE_MALLOC; + return -1; + } + + /* Now get for each anchor the object record of its destination */ + for(i=0; i send_docbyanchorobj(sockfd, objectID, &objptr)) { + efree(destptr); + return -1; + } + destptr[i] = objptr; + /* if we can't get the object rec of the dest, than this document + is probably not accessible for us. For later functions simply + set anchorrec[i] to NULL */ + if(destptr[i] == NULL) { + if(anchorrec[i]) efree(anchorrec[i]); + anchorrec[i] = NULL; + } + } else { + destptr[i] = NULL; + } + } + *destrec = destptr; + + return(0); +} + +int send_getreldestforanchorsobj(int sockfd, char **anchorrec, char ***reldestrec, int count, int rootID, int thisID) +{ + int i; + char *docofanchorptr, **reldestptr; + char *str; + int destobjectID; + + if(NULL == (reldestptr = (char **) emalloc(count * sizeof(char *)))) { + lowerror = LE_MALLOC; + return -1; + } + + /* Now get for each anchor the object record of its destination */ + for(i=0; i send_docbyanchorobj(sockfd, destobjectID, &docofanchorptr)) { + efree(reldestptr); + return -1; + } + reldestptr[i] = docofanchorptr; + /* if we can't get the object rec of the dest, than this document + is probably not accessible for us. For later functions simply + set anchorrec[i] to NULL */ + if(reldestptr[i] == NULL) { + if(anchorrec[i]) efree(anchorrec[i]); + anchorrec[i] = NULL; + } else { + int j, k, *retthisIDs, *retdestIDs, equaltill, mincount, countthis, countdest, destdocid; + char destdocname[200]; + char anchorstr[300]; + char temp[200]; + char *strptr; + + if(NULL != (str = strstr(docofanchorptr, "Name="))) { + str += 5; + sscanf(str, "%s\n", destdocname); + } + if(NULL != (str = strstr(docofanchorptr, "ObjectID="))) { + str += 9; + sscanf(str, "0x%X", &destdocid); + } + + send_incollections(sockfd, 1, 1, &thisID, 1, &rootID, &countthis, &retthisIDs); + send_incollections(sockfd, 1, 1, &destdocid, 1, &rootID, &countdest, &retdestIDs); + +fprintf(stderr, "%d: ", thisID); +for(k=0; k= 0) && (pcount != 0) && (parentIDs != NULL) && (pid != 0)) { +/*fprintf(stderr, "Get parents for %d\n", pid); */ + if(0 != send_getparents(sockfd, pid, &parentIDs, &pcount)) { + efree(pathIDs); + return -1; + } + pid = 0; + for(i=0; i 5 -> 4 -> 20 + ** (this means: 20 is child of 4, 4 is child of 5, 5 is child + ** of 1) it will return 1,4,5 instead of 1,5,4 + ** Consequently, we have to create the correct path, by checking + ** for the parents and identifying it in the list. + ** But there is another problem. If the id for which the list of + ** of collection is generated is a colletion itself, it will + ** show up in the list as well. In order to make the algorithmn + ** work proberly it has to be the last member of the list. + */ + for(i=0; ibuf; + efree(retmsg); + + return(0); +} + +int send_getobjbyquery(int sockfd, char *query, int maxhits, hw_objectID **childIDs, int *count) +{ + hg_msg msg, *retmsg; + int length, error; + char *tmp; + int *ptr, i, *ptr1; + + length = HEADER_LENGTH + strlen(query) + 1; + + build_msg_header(&msg, length, msgid++, GETOBJBYQUERY_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_str(msg.buf, query); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) + return(-1); + + ptr = (int *) retmsg->buf; + if(ptr == NULL) { + if(retmsg) efree(retmsg); + return -1; + } + if(*ptr++ == 0) { + *count = (*ptr < maxhits) ? *ptr : maxhits; + ptr++; + if(NULL != (*childIDs = emalloc(*count * sizeof(hw_objectID)))) { + ptr1 = *childIDs; + for(i=0; i<*count; ptr++, i++) + ptr1[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return error; + } + return(0); +} + +int send_getobjbyqueryobj(int sockfd, char *query, int maxhits, char ***childrec, int *count) +{ + hg_msg msg, *retmsg; + int length, i, error; + char *tmp; + int *childIDs = NULL; + char **objptr; + int *ptr, *ptr1; + + length = HEADER_LENGTH + strlen(query) + 1; + + build_msg_header(&msg, length, msgid++, GETOBJBYQUERY_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_str(msg.buf, query); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) + return(-1); + + ptr = (int *) retmsg->buf; + if(ptr == NULL) { + if(retmsg) efree(retmsg); + return -1; + } + if(*ptr++ == 0) { + *count = (*ptr < maxhits) ? *ptr : maxhits; + ptr++; + if(NULL != (childIDs = emalloc(*count * sizeof(hw_objectID)))) { + ptr1 = childIDs; + for(i=0; i<*count; ptr++, i++) + ptr1[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return error; + } + + /* Now get for each child collection the object record */ + for(i=0; i<*count; i++) { + length = HEADER_LENGTH + sizeof(hw_objectID); + build_msg_header(&msg, length, childIDs[i], GETOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + efree(childIDs); + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, childIDs[i]); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + efree(childIDs); + return(-1); + } + + efree(msg.buf); + } + efree(childIDs); + + if(NULL == (objptr = (char **) emalloc(*count * sizeof(hw_objrec *)))) { + /* if emalloc fails, get at least all remaining messages from server */ + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + efree(retmsg->buf); + efree(retmsg); + } + *childrec = NULL; + lowerror = LE_MALLOC; + return(-1); + } else { + *childrec = objptr; + + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + if ( retmsg != NULL ) { + if(0 == (int) *(retmsg->buf)) { + *objptr = estrdup(retmsg->buf+sizeof(int)); + objptr++; + efree(retmsg->buf); + efree(retmsg); + } else { + *objptr = NULL; + objptr++; + efree(retmsg->buf); + efree(retmsg); + } + } + } + } + + return(0); +} + +int send_getobjbyquerycoll(int sockfd, hw_objectID collID, char *query, int maxhits, hw_objectID **childIDs, int *count) +{ + hg_msg msg, *retmsg; + int length, error; + char *tmp; + int *ptr, i, *ptr1; + + length = HEADER_LENGTH + strlen(query) + 1 + sizeof(int) + sizeof(collID); + + build_msg_header(&msg, length, msgid++, GETOBJBYQUERYCOLL_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, 1); + tmp = build_msg_int(tmp, collID); + tmp = build_msg_str(tmp, query); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) + return(-1); + + ptr = (int *) retmsg->buf; + if(ptr == NULL) { + if(retmsg) efree(retmsg); + return -1; + } + if(*ptr++ == 0) { + *count = (*ptr < maxhits) ? *ptr : maxhits; + ptr++; + if(NULL != (*childIDs = emalloc(*count * sizeof(hw_objectID)))) { + ptr1 = *childIDs; + for(i=0; i<*count; ptr++, i++) + ptr1[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return error; + } + return(0); +} + +int send_getobjbyquerycollobj(int sockfd, hw_objectID collID, char *query, int maxhits, char ***childrec, int *count) +{ + hg_msg msg, *retmsg; + int length, i, error; + char *tmp; + hw_objectID *childIDs = NULL; + char **objptr; + int *ptr, *ptr1; + + length = HEADER_LENGTH + strlen(query) + 1 + sizeof(int) + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETOBJBYQUERYCOLL_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, 1); + tmp = build_msg_int(tmp, collID); + tmp = build_msg_str(tmp, query); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) + return -1; + + ptr = (int *) retmsg->buf; + if(ptr == NULL) { + if(retmsg) efree(retmsg); + return -1; + } + if(*ptr++ == 0) { + *count = (*ptr < maxhits) ? *ptr : maxhits; + ptr++; + if(NULL != (childIDs = emalloc(*count * sizeof(hw_objectID)))) { + ptr1 = childIDs; + for(i=0; i<*count; ptr++, i++) + ptr1[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return error; + } + + /* Now get for each child collection the object record */ + for(i=0; i<*count; i++) { + length = HEADER_LENGTH + sizeof(hw_objectID); + build_msg_header(&msg, length, childIDs[i], GETOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + efree(childIDs); + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, childIDs[i]); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + efree(childIDs); + return(-1); + } + + efree(msg.buf); + } + efree(childIDs); + + if(NULL == (objptr = (char **) emalloc(*count * sizeof(hw_objrec *)))) { + /* if emalloc fails, get at least all remaining messages from server */ + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + efree(retmsg->buf); + efree(retmsg); + } + *childrec = NULL; + lowerror = LE_MALLOC; + return(-1); + } else { + *childrec = objptr; + + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + if ( retmsg != NULL ) { + if(0 == (int) *(retmsg->buf)) { + *objptr = estrdup(retmsg->buf+sizeof(int)); + objptr++; + efree(retmsg->buf); + efree(retmsg); + } else { + *objptr = NULL; + objptr++; + efree(retmsg->buf); + efree(retmsg); + } + } + } + } + + return(0); +} + +int send_getparents(int sockfd, hw_objectID objectID, hw_objectID **childIDs, int *count) +{ + hg_msg msg, *retmsg; + int length, i, error; + char *tmp; + int *ptr, *ptr1; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETPARENT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if (-1 == send_hg_msg(sockfd, &msg, length)) { + efree(msg.buf); + return(-2); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + return(-3); + } + + ptr = (int *) retmsg->buf; + if(ptr == NULL) { + if(retmsg) efree(retmsg); + return -1; + } + if(*ptr++ == 0) { + *count = *ptr++; + if(NULL != (*childIDs = emalloc(*count * sizeof(hw_objectID)))) { + ptr1 = *childIDs; + for(i=0; i<*count; ptr++, i++) + ptr1[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return error; + } + + return(0); +} + +int send_getparentsobj(int sockfd, hw_objectID objectID, char ***childrec, int *count) +{ + hg_msg msg, *retmsg; + int length, i, error; + char *tmp; + hw_objectID *childIDs = NULL; + char **objptr; + int *ptr; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETPARENT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if (-1 == send_hg_msg(sockfd, &msg, length)) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + return(-1); + } + + ptr = (int *) retmsg->buf; + if(ptr == NULL) { + if(retmsg) efree(retmsg); + return -1; + } + if(*ptr++ == 0) { + *count = *ptr++; + if(NULL != (childIDs = emalloc(*count * sizeof(hw_objectID)))) { + for(i=0; i<*count; ptr++, i++) + childIDs[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return error; + } + + /* Now get for each parent the object record */ + for(i=0; i<*count; i++) { + length = HEADER_LENGTH + sizeof(hw_objectID); + build_msg_header(&msg, length, childIDs[i], GETOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, childIDs[i]); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + } + efree(childIDs); + + if(NULL == (objptr = (char **) emalloc(*count * sizeof(hw_objrec *)))) { + /* if emalloc fails, get at least all remaining messages from server */ + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + efree(retmsg->buf); + efree(retmsg); + } + *childrec = NULL; + lowerror = LE_MALLOC; + return(-1); + } else { + *childrec = objptr; + + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + if ( retmsg != NULL ) { + if(0 == (int) *(retmsg->buf)) { + *objptr = estrdup(retmsg->buf+sizeof(int)); + objptr++; + efree(retmsg->buf); + efree(retmsg); + } else { + *objptr = NULL; + objptr++; + efree(retmsg->buf); + efree(retmsg); + } + } + } + } + return(0); +} + +int send_pipedocument(int sockfd, char *host, hw_objectID objectID, int mode, int rootid, char **objattr, char **bodytag, char **text, int *count) +{ + hg_msg msg, *retmsg; + int length, len; + char *tmp, header[80], *head_ptr, *sizestr; + struct sockaddr_in serv_addr; + struct hostent *hostptr; + char *hostip = NULL; + char *attributes = NULL; + char *documenttype; + char **anchors; + int newfd, fd, port, size, error, ancount; + int *ptr; + + if(-1 == (fd = fnCOpenDataCon(sockfd, &port))) { + /* not set yet efree(msg.buf); */ + return(-1); + } + + /* + ** Get information about host + */ + if(host) { + if((hostptr = gethostbyname(host)) == NULL) { + php3_error(E_WARNING, "gethostbyname failed for %s", host); + close(fd); + return(-1); + } + } else { + close(fd); + return(-1); + } + + switch(hostptr->h_addrtype) { + struct in_addr *ptr1; + char *ptr; + case AF_INET: + ptr = hostptr->h_addr_list[0]; + ptr1 = (struct in_addr *) ptr; + hostip = inet_ntoa(*ptr1); + break; + default: + close(fd); + return(-1); + break; + } + + /* Bottom half of send_getobject */ + if(0 > bh_send_getobject(sockfd, objectID)) { + close(fd); + return -1; + } + + /* Upper half of send_getobject */ + if(0 > (error = uh_send_getobject(sockfd, &attributes))) { + close(fd); + return error; + } + + length = HEADER_LENGTH + sizeof(hw_objectID) + sizeof(int) + strlen(hostip) + 1 + strlen("Refno=0x12345678") + 1; + build_msg_header(&msg, length, msgid++, PIPEDOCUMENT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + tmp = build_msg_int(tmp, port); + tmp = build_msg_str(tmp, hostip); + tmp = build_msg_str(tmp, "Refno=0x12345678"); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + if(attributes) efree(attributes); + efree(msg.buf); + close(fd); + return(-1); + } + efree(msg.buf); + + /* Just check if the command was understood */ + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + if(attributes) efree(attributes); + close(fd); + return(-1); + } + + ptr = (int *) retmsg->buf; + if((ptr == NULL) || (*ptr != 0)) { + error = *ptr; + efree(retmsg); + if(retmsg->buf) efree(retmsg->buf); + if(attributes) efree(attributes); + close(fd); + return(error); + } + + efree(retmsg); + efree(retmsg->buf); + + /* passively open the data connection. The HG server is probably + already waiting for us. + */ + len = sizeof(serv_addr); + if((newfd = accept(fd, (struct sockaddr *) &serv_addr, &len)) < 0) { +/* php3_printf("client: can't open data connection to server\n"); */ + if(attributes) efree(attributes); + close(fd); + return(-1); + } else { + close(fd); + } + + /* First of all read the header */ + head_ptr = header; + while((read_to(newfd, head_ptr, 1, rtimeout) == 1) && (*head_ptr != '\0')) { + head_ptr++; + } + + /* Let's see how big the document is and read it into var text */ + sizestr = strstr(header, "sz="); + if(sizestr) { + sizestr += 3; + sscanf(sizestr, "%d\n", &size); + *count = size; + if((size != 0) && (NULL != (*text = malloc(size+1)))) { + read_to(newfd, *text, size, rtimeout); + (*text)[size] = '\0'; + } + } else { + *text = NULL; + } + + /* close the data connection */ + close(newfd); + + documenttype = fnAttributeValue(attributes, "DocumentType"); + + /* Make a copy with strdup (not estrdup), because we want to + keep the attributes in hw_document struct. + */ + *objattr = strdup(attributes); + efree(attributes); + + if((documenttype != NULL) && (!strcmp(documenttype, "text") != 0)) { + if(send_getanchorsobj(sockfd, objectID, &anchors, &ancount) == 0) { + char **destrec, **reldestrec; + DLIST *pAnchorList = NULL; + + send_getdestforanchorsobj(sockfd, anchors, &destrec, ancount); + send_getreldestforanchorsobj(sockfd, anchors, &reldestrec, ancount, rootid, objectID); + pAnchorList = fnCreateAnchorList(anchors, destrec, reldestrec, ancount, mode); + /* Free only the array, the objrecs has been freed in fnCreateAnchorList() */ + if(anchors) efree(anchors); + if(destrec) efree(destrec); + if(reldestrec) efree(reldestrec); + + if(pAnchorList != NULL) { + char *newtext; + char *body; + + newtext = fnInsAnchorsIntoText(*text, pAnchorList, &body); + dlst_kill(pAnchorList, fnDeleteAnchor); + *bodytag = strdup(body); + efree(body); + *text = newtext; + *count = strlen(newtext); + } + } + } else { + *bodytag = NULL; + } + + if(documenttype) efree(documenttype); + return(0); +} + +int send_pipecgi(int sockfd, char *host, hw_objectID objectID, char *cgi_env_str, char **objattr, char **text, int *count) +{ + hg_msg msg, *retmsg; + int length, len, new_attr_len; + char *tmp, header[80], *head_ptr, *sizestr; + struct sockaddr_in serv_addr; + struct hostent *hostptr; + char *hostip = NULL; + char *attributes = NULL; + char *documenttype, *new_attr; + int newfd, fd, port, size, error; + int *ptr; + + if(-1 == (fd = fnCOpenDataCon(sockfd, &port))) { + /* not set yet? efree(msg.buf); */ + return(-1); + } + + /* + ** Get information about host + */ + if(host) { + if((hostptr = gethostbyname(host)) == NULL) { + php3_error(E_WARNING, "gethostbyname failed for %s", host); + close(fd); + return(-1); + } + } else { + close(fd); + return(-1); + } + + switch(hostptr->h_addrtype) { + struct in_addr *ptr1; + char *ptr; + case AF_INET: + ptr = hostptr->h_addr_list[0]; + ptr1 = (struct in_addr *) ptr; + hostip = inet_ntoa(*ptr1); + break; + default: +/* php3_printf(stderr, "unknown address type\n"); */ + break; + } + + /* Bottom half of send_getobject */ + if(0 > bh_send_getobject(sockfd, objectID)) { + close(fd); + return -1; + } + + /* Upper half of send_getobject */ + if(0 > (error = uh_send_getobject(sockfd, &attributes))) { + close(fd); + return error; + } + + new_attr_len = strlen(attributes) + strlen(cgi_env_str) + 2; + new_attr = malloc(new_attr_len); + strcpy(new_attr, attributes); + strcat(new_attr, cgi_env_str); + length = HEADER_LENGTH + strlen(new_attr) + 1 + sizeof(int) + strlen(hostip) + 1 + sizeof(int) + sizeof(int); + build_msg_header(&msg, length, msgid++, PIPECGI_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { + if(attributes) efree(attributes); + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_str(msg.buf, hostip); + tmp = build_msg_int(tmp, port); + tmp = build_msg_str(tmp, new_attr); + tmp = build_msg_int(tmp, 1); + tmp = build_msg_int(tmp, 0x12345678); + free(new_attr); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + if(attributes) efree(attributes); + efree(msg.buf); + close(fd); + return(-1); + } + efree(msg.buf); + + /* Just check if the command was understood */ + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + if(attributes) efree(attributes); + close(fd); + return(-1); + } + + ptr = (int *) retmsg->buf; + if((ptr == NULL) || (*ptr != 0)) { + efree(retmsg); + if(retmsg->buf) efree(retmsg->buf); + if(attributes) efree(attributes); + close(fd); + return(-1); + } + + efree(retmsg); + efree(retmsg->buf); + + /* passively open the data connection. The HG server is probably + already waiting for us. + */ + len = sizeof(serv_addr); + if((newfd = accept(fd, (struct sockaddr *) &serv_addr, &len)) < 0) { + if(attributes) efree(attributes); + close(fd); + return(-1); + } else { + close(fd); + } + + /* First of all read the header */ + head_ptr = header; + while((read_to(newfd, head_ptr, 1, rtimeout) == 1) && (*head_ptr != '\0')) { + head_ptr++; + } + + /* Let's see how big the document is and read it into var text */ + sizestr = strstr(header, "sz="); + if(sizestr) { + sizestr += 3; + sscanf(sizestr, "%d\n", &size); + *count = size; + if((size != 0) && (NULL != (*text = malloc(size+1)))) { + read_to(newfd, *text, size, rtimeout); + } + } else { + *text = NULL; + } + + /* close the data connection */ + close(newfd); + + documenttype = fnAttributeValue(attributes, "DocumentType"); + + /* Make a copy with strdup (not estrdup), because we want to + keep the attributes in hw_document struct. + */ + *objattr = strdup(attributes); + efree(attributes); + + if(documenttype) efree(documenttype); + return(0); +} + +int send_putdocument(int sockfd, char *host, hw_objectID parentID, char *objectRec, char *text, int count) +{ + hg_msg msg, *retmsg; + int length, len; + char *tmp, header[80], parms[30], *head_ptr; + struct sockaddr_in serv_addr; + struct hostent *hostptr; + char *hostip = NULL; + int newfd, fd, port, objectID, error; + int *ptr; + + /* First of all we have to insert the document record */ + sprintf(parms, "Parent=0x%x", parentID); + length = HEADER_LENGTH + strlen(objectRec) + 1 + strlen(parms) + 1; + + build_msg_header(&msg, length, msgid++, INSERTOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_str(msg.buf, objectRec); + tmp = build_msg_str(tmp, parms); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + return(-1); + } + + ptr = (int *) retmsg->buf; + if(0 == (error = *ptr)) { + ptr++; + objectID = *ptr; + } else { + efree(retmsg); + if(retmsg->buf) efree(retmsg->buf); + return(error); + } + + efree(retmsg->buf); + efree(retmsg); + + /* + ** Get information about host + */ + if(host) { + if((hostptr = gethostbyname(host)) == NULL) { + php3_error(E_WARNING, "gethostbyname failed for %s", host); + /* close(fd); fd is not set yet */ + return(-1); + } + } else { + /* close(fd); fd is not set yet */ + return(-1); + } + + switch(hostptr->h_addrtype) { + struct in_addr *ptr1; + char *ptr; + case AF_INET: + ptr = hostptr->h_addr_list[0]; + ptr1 = (struct in_addr *) ptr; + hostip = inet_ntoa(*ptr1); + break; + default: +/* fprintf(stderr, "unknown address type\n"); */ + break; + } + + if(-1 == (fd = fnCOpenDataCon(sockfd, &port))) { + efree(msg.buf); + return(-1); + } + + /* Start building the PUTDOCUMENT message. I works even if + the Refno is skipped. I guess the path can be omitted too. */ + length = HEADER_LENGTH + sizeof(hw_objectID) + sizeof(int) + strlen(hostip) + 1 + strlen("Hyperwave") + 1+ strlen("Refno=0x12345678") + 1; + + build_msg_header(&msg, length, msgid++, PUTDOCUMENT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + tmp = build_msg_int(tmp, port); + tmp = build_msg_str(tmp, hostip); + tmp = build_msg_str(tmp, "Hyperwave"); + tmp = build_msg_str(tmp, "Refno=0x12345678"); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + close(fd); + return(-1); + } + efree(msg.buf); + + /* passively open the data connection. The HG server is probably + already waiting for us. + */ + len = sizeof(serv_addr); + if((newfd = accept(fd, (struct sockaddr *) &serv_addr, &len)) < 0) { + close(fd); + return(-1); + } else { + close(fd); + } + + /* First of all write the header. According to the documentation + there should be a header first. Well, after some investigation + with tcpdump I found out, that Harmony and wavemaster don't + sent it. The also do not sent the Refno in the PUTDOCUMENT msg. + Anyway, we sent both. */ + head_ptr = header; + sprintf(header, "HGHDR\nsz=%d\nref=12345678\n", count); + len = strlen(header) + 1; + if(len != write_to(newfd, header, len, wtimeout)) { + close(newfd); + return(-1); + } + + /* And now the document */ + if(count != write_to(newfd, text, count, wtimeout)) { + close(newfd); + return(-1); + } + + /* The data connection has to be close before the return + msg can be read. The server will not sent it before. */ + close(newfd); + + /* Just check if the command was understood */ + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + close(fd); + return(-1); + } + + ptr = (int *) retmsg->buf; + if((ptr == NULL) || (*ptr != 0)) { + efree(retmsg); + if(retmsg->buf) efree(retmsg->buf); + close(fd); + return(-1); + } + + efree(retmsg); + efree(retmsg->buf); + + return(0); +} + +int send_getsrcbydest(int sockfd, hw_objectID objectID, char ***childrec, int *count) +{ + hg_msg msg, *retmsg; + int length, i, error; + char *tmp; + int *childIDs = NULL; + char **objptr; + int *ptr, *ptr1; + + length = HEADER_LENGTH + sizeof(hw_objectID); + + build_msg_header(&msg, length, msgid++, GETSRCBYDEST_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, objectID); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) + return(-1); + + ptr = (int *) retmsg->buf; + if(ptr == NULL) { + if(retmsg) efree(retmsg); + return -1; + } + if(*ptr++ == 0) { + *count = *ptr; + ptr++; + if(NULL != (childIDs = emalloc(*count * sizeof(hw_objectID)))) { + ptr1 = childIDs; + for(i=0; i<*count; ptr++, i++) + ptr1[i] = *ptr; + efree(retmsg->buf); + efree(retmsg); + } else { + efree(retmsg->buf); + efree(retmsg); + lowerror = LE_MALLOC; + return(-1); + } + } else { + error = *((int *) retmsg->buf); + efree(retmsg->buf); + efree(retmsg); + return error; + } + + /* Now get for each source the object record */ + for(i=0; i<*count; i++) { + length = HEADER_LENGTH + sizeof(hw_objectID); + build_msg_header(&msg, length, childIDs[i], GETOBJECT_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, childIDs[i]); + + if ( send_hg_msg(sockfd, &msg, length) == -1 ) { + efree(msg.buf); + return(-1); + } + + efree(msg.buf); + } + + if(NULL == (objptr = (char **) emalloc(*count * sizeof(hw_objrec *)))) { + /* if emalloc fails, get at least all remaining messages from server */ + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + efree(retmsg->buf); + efree(retmsg); + } + *childrec = NULL; + lowerror = LE_MALLOC; + return(-1); + } else { + *childrec = objptr; + + for(i=0; i<*count; i++) { + retmsg = recv_hg_msg(sockfd); + if ( retmsg != NULL ) { + if(0 == (int) *(retmsg->buf)) { + *objptr = estrdup(retmsg->buf+sizeof(int)); + objptr++; + efree(retmsg->buf); + efree(retmsg); + } else { + *objptr = NULL; + objptr++; + efree(retmsg->buf); + efree(retmsg); + } + } + } + } + + return(0); +} + +char *get_hw_info(hw_connection *conn) + { + char temp[200]; + int len; + struct sockaddr_in serv_addr; + + len = sizeof (serv_addr); + if(getsockname(conn->socket, (struct sockaddr *)&serv_addr, &len) < 0) + return(NULL); + + sprintf(temp, "%s, %s, %d, %s, %d, %d", conn->server_string, conn->hostname, + conn->version, conn->username, + serv_addr.sin_port, conn->swap_on); + return(estrdup(temp)); + } + +static int send_hg_msg(int sockfd, hg_msg *msg, int length) +{ + char *buf, *tmp; + +#ifdef HW_DEBUG + php3_printf("Sending msg: type = %d -- id = %d
\n", msg->msg_type, msg->version_msgid); +#endif + if ( length < HEADER_LENGTH ) { +/* fprintf(stderr, "send_hg_msg: bad msg\n"); */ + return(-1); + } + + if ( (tmp = buf = (char *)emalloc(length)) == NULL ) { +/* perror("send_hg_msg"); */ + lowerror = LE_MALLOC; + return(-1); + } + + memcpy(tmp, (char *) &(msg->length), 4); + tmp += 4; + memcpy(tmp, (char *) &(msg->version_msgid), 4); + tmp += 4; + memcpy(tmp, (char *) &(msg->msg_type), 4); + if ( msg->length > HEADER_LENGTH ) { + tmp += 4; + memcpy(tmp, msg->buf, length-HEADER_LENGTH); + } + + if ( hg_write(sockfd, buf, length) == -1 ) { + efree(buf); + return(-1); + } + + efree(buf); + return(0); +} + + +int send_ready(int sockfd) +{ + hg_msg ready_msg; + + build_msg_header(&ready_msg, HEADER_LENGTH, version, READY_MESSAGE); + ready_msg.buf = NULL; + + if ( send_hg_msg(sockfd, &ready_msg, HEADER_LENGTH) == -1 ) { + return(-1); + } + + return(0); +} + + +int send_command(int sockfd, int command, char **answer) +{ + hg_msg comm_msg, *retmsg; + char *comm_str, *tmp; + int respond = 1; + int length; + + if ( command == STAT_COMMAND ) + comm_str = STAT_COMMAND_STR; + else + comm_str = WHO_COMMAND_STR; + length = HEADER_LENGTH + sizeof(respond) + strlen(comm_str) + 1; + + build_msg_header(&comm_msg, length, msgid++, COMMAND_MESSAGE); + + if ( (comm_msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + + tmp = build_msg_int(comm_msg.buf, respond); + tmp = build_msg_str(tmp, comm_str); + + + if ( send_hg_msg(sockfd, &comm_msg, length) == -1 ) { + efree(comm_msg.buf); + return(-1); + } + efree(comm_msg.buf); + + /* Just check if the command was understood */ + retmsg = recv_hg_msg(sockfd); + if ( retmsg == NULL ) { + return(-1); + } + + efree(retmsg); + *answer = retmsg->buf; + + return(0); +} + + +static void build_msg_header(hg_msg *msg, int length, int version_msgid, int msg_type) +{ + if ( swap_on ) { + msg->length = swap(length); + msg->version_msgid = swap(version_msgid); + msg->msg_type = swap(msg_type); + } + else { + msg->length = length; + msg->version_msgid = version_msgid; + msg->msg_type = msg_type; + } +} + + +static char *build_msg_int(char *buf, int val) { + int tmp; + +#ifdef HW_DEBUG + php3_printf(" Added int to header: %d
\n", val); +#endif + tmp = swap_on ? swap(val) : val; + memcpy(buf, (char *)&tmp, 4); + + return(buf+4); +} + + +static char *build_msg_str(char *buf, char *str) +{ + int len = strlen(str)+1; + +#ifdef HW_DEBUG + php3_printf(" Added str to header: %s (%d)
\n", str, strlen(str)); +#endif + + memcpy(buf, str, len); + + return(buf+len); +} + + +static int swap(int val) +{ + int tmp; + + ((char*)&tmp)[0] = ((char*)&val)[3]; + ((char*)&tmp)[1] = ((char*)&val)[2]; + ((char*)&tmp)[2] = ((char*)&val)[1]; + ((char*)&tmp)[3] = ((char*)&val)[0]; + + return(tmp); +} + + +void close_hg_connection(int sockfd) +{ + shutdown(sockfd, 2); + close(sockfd); +} + +#endif + +/* + * Local variables: + * tab-width: 4 + * End: + */ + diff --git a/ext/hyperwave/hg_comm.h b/ext/hyperwave/hg_comm.h new file mode 100644 index 0000000000..d4e1892677 --- /dev/null +++ b/ext/hyperwave/hg_comm.h @@ -0,0 +1,196 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ + */ + + +/* $Id$ */ + +#ifndef _HG_COMM_H +#define _HG_COMM_H + +#if HYPERWAVE + +#include "hw_error.h" +#define HG_SERVER_PORT 418 + +#define F_DISTRIBUTED 0x80000000 +#define F_COMPRESSED 0x40000000 +#define F_VERSION 0x00003fff +#define VERSION 717L /* 7.05 */ + +#define HEADER_LENGTH 12 + +#define STAT_COMMAND_STR "stat" +#define WHO_COMMAND_STR "who" +#define STAT_COMMAND 1 +#define WHO_COMMAND 2 + +#define GETDOCBYANCHOR_MESSAGE 2 +#define GETCHILDCOLL_MESSAGE 3 +#define GETPARENT_MESSAGE 4 +#define GETCHILDDOCCOLL_MESSAGE 5 +#define GETOBJECT_MESSAGE 7 +#define GETANCHORS_MESSAGE 8 +#define GETOBJBYQUERY_MESSAGE 9 +#define GETOBJBYQUERYCOLL_MESSAGE 10 +#define GETTEXT_MESSAGE 12 +#define INSDOC_MESSAGE 14 +#define INSCOLL_MESSAGE 17 +#define GETSRCBYDEST_MESSAGE 19 +#define MVCPDOCSCOLL_MESSAGE 22 +#define MVCPCOLLSCOLL_MESSAGE 23 +#define IDENTIFY_MESSAGE 24 +#define READY_MESSAGE 25 +#define COMMAND_MESSAGE 26 +#define CHANGEOBJECT_MESSAGE 27 +#define EDITTEXT_MESSAGE 28 +#define GETANDLOCK_MESSAGE 29 +#define UNLOCK_MESSAGE 30 +#define INCOLLECTIONS_MESSAGE 31 +#define INSERTOBJECT_MESSAGE 32 +#define PIPEDOCUMENT_MESSAGE 36 +#define DELETEOBJECT_MESSAGE 37 +#define PUTDOCUMENT_MESSAGE 38 +#define GETREMOTE_MESSAGE 39 +#define GETREMOTECHILDREN_MESSAGE 40 +#define CHILDREN_MESSAGE 44 +#define GETCGI_MESSAGE 45 +#define PIPECGI_MESSAGE 46 + +#define HW_DEFAULT_LINK 0 +#define HW_IMAGE_LINK 1 +#define HW_BACKGROUND_LINK 2 +#define HW_INTAG_LINK 3 +#define HW_APPLET_LINK 4 + +#define COPY 0 +#define MOVE 1 +#define DOCUMENT 0 +#define COLLECTION 1 + +/* Low error messages */ +#define LE_MALLOC -1 + +typedef struct { + int id; /* object ID of anchor */ + int tanchor; /* Type of anchor. Can be 1=Src, 2=Dest */ + int start; /* start of anchor */ + int end; /* end of anchor */ + char *nameanchor; /* name tag attribute of destination document */ + /* if anchor is of type Src the following are used as well */ + char *destdocname; /* name of destination document */ + char *link; /* url for external destination */ + int linktype; /* type of link. see above */ + char *tagattr; /* more attributes of tag, like Border=0 */ + char *htmlattr; /* */ + char *codebase; /* codebase of applet */ + char *code; /* code of applet */ + char *fragment; /* name link of Src */ + + /* if anchor is of type Dest the following are used as well */ + char *keyword; /* name link of Dest */ + } ANCHOR; + +typedef struct { + int length; + int version_msgid; + int msg_type; + char *buf; +} hg_msg; + +typedef struct { + int socket; + int swap_on; + int version; + char *server_string; + char *hostname; + char *username; + int lasterror; + int linkroot; +} hw_connection; + +typedef int hw_objectID; +typedef char hw_objrec; + +extern void set_swap(int do_swap); +extern int open_hg_connection(char *server_name, int port); +extern void close_hg_connection(int sockfd); +extern int initialize_hg_connection(int sockfd, int *do_swap, int *version, char **userdata, char **server_string, char *username, char *password); + +extern int send_ready(int sockfd); +extern int send_command(int sockfd, int command, char **answer); + +extern hg_msg *recv_hg_msg(int sockfd); +extern hg_msg *recv_ready(int sockfd); +extern hg_msg *recv_command(int sockfd); + +extern char *fnInsStr(char *str, int pos, char *insstr); +extern int fnAttributeCompare(char *object, char *attrname, char *value); +extern int getrellink(int sockfd, int rootID, int thisID, int destID, char **reldesstr); + +extern int send_deleteobject(int sockfd, hw_objectID objectID); +extern int send_changeobject(int sockfd, hw_objectID objectID, char *mod); +extern int send_getobject(int sockfd, hw_objectID objectID, char **attributes); +extern int send_getandlock(int sockfd, hw_objectID objectID, char **attributes); +extern int send_unlock(int sockfd, hw_objectID objectID); +extern int send_gettext(int sockfd, hw_objectID objectID, int mode, int rootid, char **objattr, char **bodytag, char **text, int *count); +extern int send_edittext(int sockfd, char *objattr, char *text); +extern int send_getcgi(int sockfd, hw_objectID objectID, char *cgi_env_str, char **objattr, char **text, int *count); +extern int send_getremote(int sockfd, hw_objectID objectID, char **objattr, char **text, int *count); +extern int send_getremotechildren(int sockfd, char *attributes, char **text, int **childIDs, int *count); +extern int send_docbyanchor(int sockfd, hw_objectID objectID, hw_objectID *anchorID); +extern int send_docbyanchorobj(int sockfd, hw_objectID objectID, char **objrec); +extern int send_mvcpdocscollscoll(int sockfd, hw_objectID *objectIDs, int count, int from, int dest, int cpmv, int docscoll); +extern int send_childrenobj(int sockfd, hw_objectID objectID, char ***childrec, int *count); +extern int send_getchildcoll(int sockfd, int objectID, hw_objectID **childIDs, int *count); +extern int send_getchildcollobj(int sockfd, hw_objectID objectID, hw_objrec ***childrec, int *count); +extern int send_getchilddoccoll(int sockfd, hw_objectID objectID, hw_objectID **childIDs, int *count); +extern int send_getchilddoccollobj(int sockfd, hw_objectID objectID, hw_objrec ***childrec, int *count); +extern int send_getanchors(int sockfd, hw_objectID objectID, hw_objectID **anchorIDs, int *count); +extern int send_getanchorsobj(int sockfd, hw_objectID objectID, char ***childrec, int *count); +extern int send_getobjbyquery(int sockfd, char *query, int maxhits, hw_objectID **childIDs, int *count); +extern int send_getobjbyqueryobj(int sockfd, char *query, int maxhits, char ***childrec, int *count); +extern int send_getobjbyquerycoll(int sockfd, hw_objectID collID, char *query, int maxhits, hw_objectID **childIDs, int *count); +extern int send_getobjbyquerycollobj(int sockfd, hw_objectID collID, char *query, int maxhits, char ***childrec, int *count); +extern int send_identify(int sockfd, char *name, char *passwd, char **userdata); +extern int send_getparents(int sockfd, hw_objectID objectID, hw_objectID **childIDs, int *count); +extern int send_children(int sockfd, hw_objectID objectID, hw_objectID **childIDs, int *count); +extern int send_getparentsobj(int sockfd, hw_objectID objectID, char ***childrec, int *count); +extern int send_pipedocument(int sockfd, char *hostname, hw_objectID objectID, int mode, int rootid, char** objattr, char **bodytag, char **text, int *count); +extern int send_pipecgi(int sockfd, char *host, hw_objectID objectID, char *cgi_env_str, char **objattr, char **text, int *count); +extern int send_putdocument(int sockfd, char *hostname, hw_objectID objectID, char *objectRec, char *text, int count); +extern int send_inscoll(int sockfd, hw_objectID objectID, char *objrec, hw_objectID *new_objectID); +extern int send_insertobject(int sockfd, char *objrec, char *parms, hw_objectID *objectID); +extern int send_insdoc(int sockfd, hw_objectID objectID, char *objrec, char *text, hw_objectID *new_objectID); +extern int send_incollections(int sockfd, int retcol, int cobjids, hw_objectID *objectIDs, int ccollids, hw_objectID *collIDs, int *count, hw_objectID **retIDs); +extern int send_getsrcbydest(int sockfd, hw_objectID objid, char ***childrec, int *count); +extern int send_dummy(int sockfd, hw_objectID objectID, int msgid, char **attributes); +extern char *get_hw_info(hw_connection *conn); + +#define send_mvcpdocscoll(sockfd,objectIDs,count,from,dest,mvcp) \ + send_mvcpdocscollscoll(sockfd,objectIDs,count,from,dest,mvcp,DOCUMENT) +#define send_mvcpcollscoll(sockfd,objectIDs,count,from,dest,mvcp) \ + send_mvcpdocscollscoll(sockfd,objectIDs,count,from,dest,mvcp,COLLECTION) + +#endif +#endif diff --git a/ext/hyperwave/hw.c b/ext/hyperwave/hw.c new file mode 100644 index 0000000000..db1da999db --- /dev/null +++ b/ext/hyperwave/hw.c @@ -0,0 +1,3062 @@ +/* + +----------------------------------------------------------------------+ + | 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: Uwe Steinmann | + | | + +----------------------------------------------------------------------+ + */ + +/* $Id$ */ +#if COMPILE_DL +#include "dl/phpdl.h" +#endif + +#include + +#if !(WIN32|WINNT) +#include "config.h" +#endif +#include "php.h" +#include "functions/head.h" + +#if HYPERWAVE + + +#include "hw.h" + +#if APACHE +# ifndef DEBUG +# undef palloc +# endif +#endif + +hw_module php3_hw_module; + +function_entry hw_functions[] = { + {"hw_connect", php3_hw_connect, NULL}, + {"hw_pconnect", php3_hw_pconnect, NULL}, + {"hw_close", php3_hw_close, NULL}, + {"hw_root", php3_hw_root, NULL}, + {"hw_info", php3_hw_info, NULL}, + {"hw_connection_info", php3_hw_connection_info, NULL}, + {"hw_error", php3_hw_error, NULL}, + {"hw_errormsg", php3_hw_errormsg, NULL}, + {"hw_getparentsobj", php3_hw_getparentsobj, NULL}, + {"hw_getparents", php3_hw_getparents, NULL}, + {"hw_children", php3_hw_children, NULL}, + {"hw_childrenobj", php3_hw_childrenobj, NULL}, + {"hw_getchildcoll", php3_hw_getchildcoll, NULL}, + {"hw_getchildcollobj", php3_hw_getchildcollobj, NULL}, + {"hw_getobject", php3_hw_getobject, NULL}, + {"hw_getandlock", php3_hw_getandlock, NULL}, + {"hw_unlock", php3_hw_unlock, NULL}, + {"hw_gettext", php3_hw_gettext, NULL}, + {"hw_edittext", php3_hw_edittext, NULL}, + {"hw_getcgi", php3_hw_getcgi, NULL}, + {"hw_getremote", php3_hw_getremote, NULL}, + {"hw_getremotechildren", php3_hw_getremotechildren, NULL}, + {"hw_pipedocument", php3_hw_pipedocument, NULL}, + {"hw_pipecgi", php3_hw_pipecgi, NULL}, + {"hw_insertdocument", php3_hw_insertdocument, NULL}, + {"hw_mv", php3_hw_mv, NULL}, + {"hw_cp", php3_hw_cp, NULL}, + {"hw_deleteobject", php3_hw_deleteobject, NULL}, + {"hw_changeobject", php3_hw_changeobject, NULL}, + {"hw_docbyanchor", php3_hw_docbyanchor, NULL}, + {"hw_docbyanchorobj", php3_hw_docbyanchorobj, NULL}, + {"hw_getobjectbyquery", php3_hw_getobjectbyquery, NULL}, + {"hw_getobjectbyqueryobj", php3_hw_getobjectbyqueryobj, NULL}, + {"hw_getobjectbyquerycoll", php3_hw_getobjectbyquerycoll, NULL}, + {"hw_getobjectbyquerycollobj", php3_hw_getobjectbyquerycollobj,NULL}, + {"hw_getchilddoccoll", php3_hw_getchilddoccoll, NULL}, + {"hw_getchilddoccollobj", php3_hw_getchilddoccollobj, NULL}, + {"hw_getanchors", php3_hw_getanchors, NULL}, + {"hw_getanchorsobj", php3_hw_getanchorsobj, NULL}, + {"hw_getusername", php3_hw_getusername, NULL}, + {"hw_setlinkroot", php3_hw_setlinkroot, NULL}, + {"hw_identify", php3_hw_identify, NULL}, + {"hw_free_document", php3_hw_free_document, NULL}, + {"hw_new_document", php3_hw_new_document, NULL}, + {"hw_output_document", php3_hw_output_document, NULL}, + {"hw_outputdocument", php3_hw_output_document, NULL}, + {"hw_document_size", php3_hw_document_size, NULL}, + {"hw_documentsize", php3_hw_document_size, NULL}, + {"hw_document_attributes", php3_hw_document_attributes, NULL}, + {"hw_documentattributes", php3_hw_document_attributes, NULL}, + {"hw_document_bodytag", php3_hw_document_bodytag, NULL}, + {"hw_documentbodytag", php3_hw_document_bodytag, NULL}, + {"hw_document_content", php3_hw_document_content, NULL}, + {"hw_objrec2array", php3_hw_objrec2array, NULL}, + {"hw_array2objrec", php3_hw_array2objrec, NULL}, + {"hw_incollections", php3_hw_incollections, NULL}, + {"hw_inscoll", php3_hw_inscoll, NULL}, + {"hw_insertobject", php3_hw_insertobject, NULL}, + {"hw_insdoc", php3_hw_insdoc, NULL}, + {"hw_getsrcbydestobj", php3_hw_getsrcbydestobj, NULL}, + {"hw_getrellink", php3_hw_getrellink, NULL}, + {"hw_who", php3_hw_who, NULL}, + {"hw_stat", php3_hw_stat, NULL}, + {"hw_dummy", php3_hw_dummy, NULL}, + {NULL, NULL, NULL} +}; + +php3_module_entry hw_module_entry = { + "HyperWave", hw_functions, php3_minit_hw, NULL, NULL, NULL, php3_info_hw, 0, 0, 0, NULL +}; + +void print_msg(hg_msg *msg, char *str, int txt); + +#if COMPILE_DL +DLEXPORT php3_module_entry *get_module(void) { return &hw_module_entry; } +#endif + +void _close_hw_link(hw_connection *conn) +{ + if(conn->hostname) + free(conn->hostname); + if(conn->username) + free(conn->username); + close(conn->socket); + free(conn); + php3_hw_module.num_links--; +} + +void _close_hw_plink(hw_connection *conn) +{ + if(conn->hostname) + free(conn->hostname); + if(conn->username) + free(conn->username); + close(conn->socket); + free(conn); + php3_hw_module.num_links--; + php3_hw_module.num_persistent--; +} + +void _free_hw_document(hw_document *doc) +{ + if(doc->data) + free(doc->data); + if(doc->attributes) + free(doc->attributes); + if(doc->bodytag) + free(doc->bodytag); + free(doc); +} + +/* creates an array in return value and frees all memory + * Also adds as an assoc. array at the end of the return array with + * statistics. + */ +int make_return_objrec(pval **return_value, char **objrecs, int count) +{ + pval stat_arr; + int i; + int hidden, collhead, fullcollhead, total; + int collheadnr, fullcollheadnr; + + if (array_init(*return_value) == FAILURE) { + /* Ups, failed! Let's at least free the memory */ + for(i=0; i