diff options
author | Stig Bakken <ssb@php.net> | 1999-04-21 23:11:20 +0000 |
---|---|---|
committer | Stig Bakken <ssb@php.net> | 1999-04-21 23:11:20 +0000 |
commit | a297b95c9da1b6138523f9b707a0fafe60e0d327 (patch) | |
tree | a50bc7a551fe793e1e9403092c0ae2ed4907b053 /ext | |
parent | f67a9bdc52c39eed6837aef8a1eca195549b1469 (diff) | |
download | php-git-a297b95c9da1b6138523f9b707a0fafe60e0d327.tar.gz |
moved apache, com and hyperwave into ext/
Diffstat (limited to 'ext')
-rw-r--r-- | ext/apache/Makefile.am | 6 | ||||
-rw-r--r-- | ext/apache/apache.c | 386 | ||||
-rw-r--r-- | ext/apache/config.m4 | 5 | ||||
-rw-r--r-- | ext/com/php3_COM.h | 22 | ||||
-rw-r--r-- | ext/hyperwave/DList.h | 128 | ||||
-rw-r--r-- | ext/hyperwave/Makefile.am | 6 | ||||
-rw-r--r-- | ext/hyperwave/config.h.stub | 2 | ||||
-rw-r--r-- | ext/hyperwave/config.m4 | 18 | ||||
-rw-r--r-- | ext/hyperwave/dlist.c | 410 | ||||
-rw-r--r-- | ext/hyperwave/hg_comm.c | 4701 | ||||
-rw-r--r-- | ext/hyperwave/hg_comm.h | 196 | ||||
-rw-r--r-- | ext/hyperwave/hw.c | 3062 | ||||
-rw-r--r-- | ext/hyperwave/hw.h | 122 | ||||
-rw-r--r-- | ext/hyperwave/hw_error.h | 117 | ||||
-rw-r--r-- | ext/hyperwave/setup.stub | 6 | ||||
-rw-r--r-- | ext/rpc/com/COM.c | 959 | ||||
-rw-r--r-- | ext/rpc/com/php3_COM.h | 22 |
17 files changed, 10168 insertions, 0 deletions
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 <rasmus@lerdorf.on.ca> | + | Stig Sæther Bakken <ssb@guardian.no> | + | David Sklar <sklar@student.net> | + +----------------------------------------------------------------------+ + */ + +/* $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 <stdlib.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <string.h> +#include <errno.h> +#include <ctype.h> + +#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<br>"); +#else + php3_printf("<tt>APACHE_INCLUDE=%s<br>\n", PHP_APACHE_INCLUDE); + php3_printf("APACHE_TARGET=%s<br></tt>\n", PHP_APACHE_TARGET); +#endif + php3_printf("Apache Version: <b>%s</b><br>",SERVER_VERSION); +#ifdef APACHE_RELEASE + php3_printf("Apache Release: <b>%d</b><br>",APACHE_RELEASE); +#endif + php3_printf("Apache API Version: <b>%d</b><br>",MODULE_MAGIC_NUMBER); + php3_printf("Hostname/port: <b>%s:%u</b><br>\n",serv->server_hostname,serv->port); +#if !defined(WIN32) && !defined(WINNT) + php3_printf("User/Group: <b>%s(%d)/%d</b><br>\n",user_name,(int)user_id,(int)group_id); + php3_printf("Max Requests: <b>per child: %d keep alive: %s max per connection: %d</b><br>\n",max_requests_per_child,serv->keep_alive ? "on":"off", serv->keep_alive_max); +#endif + php3_printf("Timeouts: <b>connection: %d keep-alive: %d</b><br>",serv->timeout,serv->keep_alive_timeout); +#if !defined(WIN32) && !defined(WINNT) + php3_printf("Server Root: <b>%s</b><br>\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("<br></td?</tr>\n"); +} + +/* This function is equivalent to <!--#include virtual...--> + * 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 <?Include>. 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 <code><?include \"%s\"></code> 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 <stdio.h> +#include <malloc.h> +#include <signal.h> +#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 <stdlib.h> + +#if WIN32|WINNT +#include "win95nt.h" +#else +#include "config.h" +#endif + +#if HYPERWAVE + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#if WIN32|WINNT +# include <winsock2.h> +# define EWOULDBLOCK WSAEWOULDBLOCK +# define ETIMEDOUT WSAETIMEDOUT +# define bcopy memcpy +# define bzero(a,b) memset(a,0,b) +#else +# include <sys/socket.h> +# include <netinet/in.h> +# include <netdb.h> +# include <unistd.h> +# include <sys/param.h> +#endif +#include <fcntl.h> +#include <errno.h> +#include <alloc.h> +#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 </A> */ +/* 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, "</A>"); + sprintf(istr, "<A HREF='%s' %s offset=%d>", 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 </A> */ +/* 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, "</A>"); + + if(cur_ptr->nameanchor) + sprintf(istr, "<A HREF='%s/%s#%s' %s>", scriptname == NULL ? "schade" : scriptname, cur_ptr->destdocname, cur_ptr->nameanchor, cur_ptr->htmlattr == NULL ? "" : cur_ptr->htmlattr); + else + if(cur_ptr->fragment) + sprintf(istr, "<A HREF='%s/%s#%s' %s>", scriptname == NULL ? "" : scriptname, cur_ptr->destdocname, cur_ptr->fragment, cur_ptr->htmlattr == NULL ? "" : cur_ptr->htmlattr); + else + sprintf(istr, "<A HREF='%s/%s' %s offset=%d>", 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 </A> */ + offset += strlen(istr) + 4; + laststart = cur_ptr->start; + } else { + if(laststart >= cur_ptr->end) + offset = 0; + newtext = fnInsStr(newtext, cur_ptr->end+offset, "</a>"); + + /* 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, "<A NAME='%s'>", cur_ptr->keyword); + else if(cur_ptr->nameanchor) + sprintf(istr, "<A NAME='%s'>", 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 </A> */ + offset += strlen(istr) + 4; + laststart = cur_ptr->start; + } + cur_ptr = (ANCHOR *) dlst_prev(cur_ptr); + } + sprintf(istr, "<BODY %s>", 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 <time.h> +#else +#include <sys/fcntl.h> +#include <sys/time.h> +#include <sys/types.h> +#endif +#include <errno.h> +#include <signal.h> + +#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("<B> Recv msg: </B>type = %d -- id = %d<BR>\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; i<cobjids; i++) + tmp = build_msg_int(tmp, objectIDs[i]); + tmp = build_msg_int(tmp, ccollids); + for(i=0; i<ccollids; i++) + tmp = build_msg_int(tmp, collIDs[i]); + + 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(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; i<count;i++) + tmp = build_msg_int(tmp,objectIDs[i]); + + 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); + } + + efree(retmsg); + error = *((int *) retmsg->buf); + 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<count; i++) { + /* if you retrieve the anchors you sometimes get more than actually accessible. + This happens for the object 0x29a9c. */ + if((NULL != anchorrec[i]) && (NULL != (str = fnAttributeValue(anchorrec[i], "Dest")))) { + sscanf(str, "0x%x", &objectID); + efree(str); + + if(0 > 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<count; i++) { + /* if you retrieve the anchors you sometimes get more than actually accessible. + */ + if((NULL != anchorrec[i]) && (NULL != (str = fnAttributeValue(anchorrec[i], "Dest")))) { + sscanf(str, "0x%x", &destobjectID); + efree(str); + + if(0 > 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<countthis; k++) + fprintf(stderr,"%d, ", retthisIDs[k]); +fprintf(stderr,"\n"); +fprintf(stderr,"%d: ", destdocid); +for(k=0; k<countdest; k++) + fprintf(stderr,"%d: %d, ", destdocid, retdestIDs[k]); +fprintf(stderr,"\n"); + + mincount = (countthis < countdest) ? countthis : countdest; + for(j=0; (j<mincount) && (retthisIDs[j]==retdestIDs[j]); j++) + ; + equaltill = j; + strcpy(anchorstr, "Name="); + for(j=equaltill; j<countthis; j++) + strcat(anchorstr, "../"); + strcat(anchorstr, "./"); + for(j=equaltill; j<countdest; j++) { + char *temprec, tempname[100], objectidstr[100]; + send_getobject(sockfd, retdestIDs[j], &temprec); + if(NULL != (str = strstr(temprec, "Name="))) { + str += 5; + sscanf(str, "%s\n", tempname); + } else if(NULL != (str = strstr(temprec, "ObjectID="))) { + str += 9; + sscanf(str, "%s\n", tempname); + } + + sprintf(temp, "%s", tempname); + strptr = temp; + while(*strptr != '\0') { + if(*strptr == '/') + *strptr = '_'; + strptr++; + } +fprintf(stderr, "Adding '%s' to '%s'\n", temp, anchorstr); + strcat(anchorstr, temp); + strcat(anchorstr, "/"); +fprintf(stderr, "Is now '%s'\n", anchorstr); + efree(temprec); + } + /* if the anchor destination is a collection it may not be added anymore. */ + if(destdocid != retdestIDs[countdest-1]) { + strptr = destdocname; + while(*strptr != '\0') { + if(*strptr == '/') + *strptr = '_'; + strptr++; + } + strcat(anchorstr, destdocname); + } else { + strcat(anchorstr, "index.html"); + } + strcat(anchorstr, "\n"); + sprintf(temp, "ObjectID=0x%x", destdocid); + strcat(anchorstr, temp); +fprintf(stderr, "%s\n", anchorstr); + efree(retthisIDs); + efree(retdestIDs); + reldestptr[i] = estrdup(anchorstr); + } + } else { + reldestptr[i] = NULL; + } + } + *reldestrec = reldestptr; + + return(0); +} + +int fn_findpath(int sockfd, int *retIDs, int count, int id) { + int *pathIDs; + int *parentIDs, pcount, pid; + int u, j, i; + + if(NULL == (pathIDs = emalloc(count * sizeof(int)))) { + lowerror = LE_MALLOC; + return -1; + } + u = count-1; + pid = id; + pcount = 1; + /* FIXME but parentIDs is not set at this point, why checking it? */ + while((u >= 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<pcount; i++) { + for(j=0; j<count; j++) { + if(parentIDs[i] == retIDs[j]) { + pathIDs[u--] = retIDs[j]; + pid = retIDs[j]; + } + } + } + if(pid == 0) + fprintf(stderr, "parent not found in list\n"); + if(parentIDs) efree(parentIDs); + } +/*fprintf(stderr, "sorted path: "); */ + for(i=0; i<count; i++) { + retIDs[i] = pathIDs[i]; +/*fprintf(stderr, "%d, ", retIDs[i]); */ + } +/*fprintf(stderr, "\n"); */ + efree(pathIDs); + return 0; +} + +/******************************************************************** +* function getrellink() * +* * +* Returns the link to point from document with ID sourceID to * +* document with id destID. * +********************************************************************/ +int getrellink(int sockfd, int rootID, int thisID, int destID, char **reldeststr) { + int i, j, k, *retthisIDs, *retdestIDs, equaltill, count, mincount, countthis, countdest, destdocid; + char anchorstr[300]; + char temp[200]; + char *strptr; + + send_incollections(sockfd, 1, 1, &thisID, 1, &rootID, &countthis, &retthisIDs); + send_incollections(sockfd, 1, 1, &destID, 1, &rootID, &countdest, &retdestIDs); + + +fprintf(stderr, "%d: ", thisID); +for(k=0; k<countthis; k++) + fprintf(stderr,"%d, ", retthisIDs[k]); +fprintf(stderr,"\n"); +fprintf(stderr,"%d: ", destID); +for(k=0; k<countdest; k++) + fprintf(stderr,"%d, ", retdestIDs[k]); +fprintf(stderr,"\n"); + + /* + ** The message incollections returned a list of collections + ** in which the destID or thisID is contained. Unfortunately + ** this list ist not the path for the destID or thisID, but + ** a sorted list of collection IDs. If for example you are + ** looking for an ID 20 which has a path 1 -> 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; i<countdest; i++) + if(retdestIDs[i] == destID) { + retdestIDs[i] = retdestIDs[countdest-1]; + retdestIDs[countdest-1] = destID; + } + count = (retdestIDs[countdest-1] == destID) ? countdest-1 : countdest; + if(0 != fn_findpath(sockfd, retdestIDs, count, destID)) { + efree(retthisIDs); + efree(retdestIDs); + return -1; + } + for(i=0; i<countthis; i++) + if(retthisIDs[i] == thisID) { + retthisIDs[i] = retthisIDs[countthis-1]; + retthisIDs[countthis-1] = thisID; + } + count = (retthisIDs[countthis-1] == thisID) ? countthis-1 : countthis; + if(0 != fn_findpath(sockfd, retthisIDs, count, thisID)) { + efree(retthisIDs); + efree(retdestIDs); + return -1; + } + + mincount = (countthis < countdest) ? countthis : countdest; +fprintf(stderr,"mincount = %d\n", mincount); + for(j=0; (j<mincount) && (retthisIDs[j]==retdestIDs[j]); j++) + ; + equaltill = j; +fprintf(stderr, "first unequal = %d\n", j); + strcpy(anchorstr, ""); + for(j=equaltill; j<countthis; j++) + strcat(anchorstr, "../"); + strcat(anchorstr, "./"); + for(j=equaltill; j<countdest; j++) { + char *temprec, *str, tempname[100], objectidstr[100]; + if(0 == send_getobject(sockfd, retdestIDs[j], &temprec)) { + if(NULL != (str = strstr(temprec, "Name="))) { + str += 5; + sscanf(str, "%s\n", tempname); + } else if(NULL != (str = strstr(temprec, "ObjectID="))) { + str += 9; + sscanf(str, "%s\n", tempname); + } + + sprintf(temp, "%s", tempname); + strptr = temp; + while(*strptr != '\0') { + if(*strptr == '/') + *strptr = '_'; + strptr++; + } +fprintf(stderr, "Adding '%s' (%d) to '%s'\n", temp, retdestIDs[j], anchorstr); + strcat(anchorstr, temp); + strcat(anchorstr, "/"); +fprintf(stderr, "Is now '%s'\n", anchorstr); + efree(temprec); + } else { + strcat(anchorstr, "No access/"); + } + } + /* if the anchor destination is a collection it may not be added anymore. */ + if(destID != retdestIDs[countdest-1]) { + char destdocname[100], *str; + send_getobject(sockfd, destID, &str); + if(NULL != (strptr = strstr(str, "Name="))) { + strptr += 5; + sscanf(strptr, "%s\n", destdocname); + } + strptr = destdocname; + while(*strptr != '\0') { + if(*strptr == '/') + *strptr = '_'; + strptr++; + } + strcat(anchorstr, destdocname); + efree(str); + } else { +/* strcat(anchorstr, "index.html"); */ + } +/*fprintf(stderr, "%s\n", anchorstr); */ + efree(retthisIDs); + efree(retdestIDs); + *reldeststr = estrdup(anchorstr); + return 0; +} + +int send_identify(int sockfd, char *name, char *passwd, char **userdata) { + hg_msg msg, *retmsg; + int length; + char *tmp; + + length = HEADER_LENGTH + sizeof(int) + strlen(name) + 1 + strlen(passwd) + 1; + + build_msg_header(&msg, length, msgid++, IDENTIFY_MESSAGE); + + if ( (msg.buf = (char *)emalloc(length-HEADER_LENGTH)) == NULL ) { +/* perror("send_command"); */ + lowerror = LE_MALLOC; + return(-1); + } + + tmp = build_msg_int(msg.buf, 0); + tmp = build_msg_str(tmp, name); + tmp = build_msg_str(tmp, passwd); + + 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); + + *userdata = (char *) retmsg->buf; + 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("<B>Sending msg: </B>type = %d -- id = %d<BR>\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: <B>%d</B><BR>\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: <B>%s</B> (%d)<BR>\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 <rasmus@lerdorf.on.ca> | + +----------------------------------------------------------------------+ + */ + + +/* $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 <stdlib.h> + +#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<count; i++) + efree(objrecs[i]); + efree(objrecs); + return -1; + } + + hidden = collhead = fullcollhead = total = 0; + collheadnr = fullcollheadnr = -1; + for(i=0; i<count; i++) { + /* Fill the array with entries. No need to free objrecs[i], since + * it is not duplicated in add_next_index_string(). + */ + if(NULL != objrecs[i]) { + if(0 == fnAttributeCompare(objrecs[i], "PresentationHints", "Hidden")) + hidden++; + if(0 == fnAttributeCompare(objrecs[i], "PresentationHints", "CollectionHead")) { + collhead++; + collheadnr = total; + } + if(0 == fnAttributeCompare(objrecs[i], "PresentationHints", "FullCollectionHead")) { + fullcollhead++; + fullcollheadnr = total; + } + total++; + add_next_index_string(*return_value, objrecs[i], 0); + } + } + efree(objrecs); + + /* Array for statistics */ + if (array_init(&stat_arr) == FAILURE) { + return -1; + } + + add_assoc_long(&stat_arr, "Hidden", hidden); + add_assoc_long(&stat_arr, "CollectionHead", collhead); + add_assoc_long(&stat_arr, "FullCollectionHead", fullcollhead); + add_assoc_long(&stat_arr, "Total", total); + add_assoc_long(&stat_arr, "CollectionHeadNr", collheadnr); + add_assoc_long(&stat_arr, "FullCollectionHeadNr", fullcollheadnr); + + /* Add the stat array */ + _php3_hash_next_index_insert((*return_value)->value.ht, &stat_arr, sizeof(pval), NULL); + + /* The title array can now be freed, but I don't know how */ + return 0; +} + +/* +** creates an array return value from object record +*/ +int make_return_array_from_objrec(pval **return_value, char *objrec) { + pval title_arr, desc_arr; + char *attrname, *str, *temp, language[3], *title; + int iTitle, iDesc; + int hasTitle = 0; + int hasDescription = 0; + + if (array_init(*return_value) == FAILURE) { + (*return_value)->type = IS_STRING; + (*return_value)->value.str.val = empty_string; + (*return_value)->value.str.len = 0; + return -1; + } + + /* Array for titles. Only if we have at least one title */ +/* if(0 == strncmp(objrec, "Title=", 6)) { */ + if (array_init(&title_arr) == FAILURE) { + return -1; + } + hasTitle = 1; +/* } */ + + /* Array for Descriptions. Only if we have at least one description */ +/* if(0 == strncmp(objrec, "Description=", 12)) { */ + if (array_init(&desc_arr) == FAILURE) { + return -1; + } + hasDescription = 1; +/* } */ + + /* Fill Array of titles and descriptions */ + temp = estrdup(objrec); + attrname = strtok(temp, "\n"); + while(attrname != NULL) { + str = attrname; + iTitle = 0; + iDesc = 0; + if(0 == strncmp(attrname, "Title=", 6)) { + str += 6; + iTitle = 1; + } else if(0 == strncmp(attrname, "Description=", 12)) { + str += 12; + iDesc = 1; + } + if(iTitle || iDesc) { /* Poor error check if end of string */ + if(str[2] == ':') { + str[2] = '\0'; + strcpy(language, str); + str += 3; + } else + strcpy(language, "xx"); + + title = str; +/* while((*str != '=') && (*str != '\0')) + str++; + *str = '\0'; +*/ if(iTitle) + add_assoc_string(&title_arr, language, title, 1); + else + add_assoc_string(&desc_arr, language, title, 1); + } + attrname = strtok(NULL, "\n"); + } + efree(temp); + + /* Add the title array, if we have one */ + if(hasTitle) { + _php3_hash_update((*return_value)->value.ht, "Title", 6, &title_arr, sizeof(pval), NULL); + + /* The title array can now be freed, but I don't know how */ + } + + if(hasDescription) { + /* Add the description array, if we have one */ + _php3_hash_update((*return_value)->value.ht, "Description", 12, &desc_arr, sizeof(pval), NULL); + + /* The description array can now be freed, but I don't know how */ + } + + /* All other attributes. Make a another copy first */ + temp = estrdup(objrec); + attrname = strtok(temp, "\n"); + while(attrname != NULL) { + str = attrname; + /* We don't want to insert titles a second time */ + if((0 != strncmp(attrname, "Title=", 6)) && + (0 != strncmp(attrname, "Description=", 12))) { + while((*str != '=') && (*str != '\0')) + str++; + *str = '\0'; + str++; + add_assoc_string(*return_value, attrname, str, 1); + } + attrname = strtok(NULL, "\n"); + } + efree(temp); + + return(0); +} + +static char * make_objrec_from_array(HashTable *lht) { + int i, count, keytype; + ulong length; + char *key, str[1024], *objrec = NULL; + pval *keydata; + + if(NULL == lht) + return NULL; + + if(0 == (count = _php3_hash_num_elements(lht))) + return NULL; + + _php3_hash_internal_pointer_reset(lht); + objrec = malloc(1); + *objrec = '\0'; + for(i=0; i<count; i++) { + keytype = _php3_hash_get_current_key(lht, &key, &length); + if(HASH_KEY_IS_STRING == keytype) { + _php3_hash_get_current_data(lht, (void **) &keydata); + switch(keydata->type) { + case IS_STRING: + sprintf(str, "%s=%s\n", key, keydata->value.str.val); + break; + case IS_LONG: + sprintf(str, "%s=0x%lX\n", key, keydata->value.lval); + break; + } + efree(key); + objrec = realloc(objrec, strlen(objrec)+strlen(str)+1); + strcat(objrec, str); + } + _php3_hash_move_forward(lht); + } + return objrec; +} + +static int * make_ints_from_array(HashTable *lht) { + int i, count; + int *objrec = NULL; + pval *keydata; + + if(NULL == lht) + return NULL; + + if(0 == (count = _php3_hash_num_elements(lht))) + return NULL; + + _php3_hash_internal_pointer_reset(lht); + if(NULL == (objrec = emalloc(count*sizeof(int)))) + return NULL; + for(i=0; i<count; i++) { + _php3_hash_get_current_data(lht, (void **) &keydata); + switch(keydata->type) { + case IS_LONG: + objrec[i] = keydata->value.lval; + break; + default: + objrec[i] = 0; + } + _php3_hash_move_forward(lht); + } + return objrec; +} + +int php3_minit_hw(INIT_FUNC_ARGS) { + + if (cfg_get_long("hw.allow_persistent",&php3_hw_module.allow_persistent)==FAILURE) { + php3_hw_module.allow_persistent=1; + } + if (cfg_get_long("hw.max_persistent",&php3_hw_module.max_persistent)==FAILURE) { + php3_hw_module.max_persistent=-1; + } + if (cfg_get_long("hw.max_links",&php3_hw_module.max_links)==FAILURE) { + php3_hw_module.max_links=-1; + } + php3_hw_module.num_persistent=0; + php3_hw_module.le_socketp = register_list_destructors(_close_hw_link,NULL); + php3_hw_module.le_psocketp = register_list_destructors(NULL,_close_hw_plink); + php3_hw_module.le_document = register_list_destructors(_free_hw_document,NULL); + + return SUCCESS; +} + +static void php3_hw_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) +{ + pval *argv[4]; + int argc; + int sockfd; + int port = 0; + char *host = NULL; + char *userdata = NULL; + char *server_string = NULL; + char *username = NULL; + char *password = NULL; + char *hashed_details; + char *str = NULL; + char buffer[20]; + int hashed_details_length; + hw_connection *ptr; + int do_swap; + int version = 0; + TLS_VARS; + + argc = ARG_COUNT(ht); + switch(argc) { + case 2: + if (getParametersArray(ht, argc, argv) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + case 4: + if (getParametersArray(ht, argc, argv) == FAILURE) { + WRONG_PARAM_COUNT; + } + break; + default: + WRONG_PARAM_COUNT; + } + + /* Host: */ + convert_to_string(argv[0]); + host = (char *) estrndup(argv[0]->value.str.val,argv[0]->value.str.len); + + /* Port: */ + convert_to_long(argv[1]); + port = argv[1]->value.lval; + + /* Username and Password */ + if(argc > 2) { + /* Username */ + convert_to_string(argv[2]); + username = (char *) estrndup(argv[2]->value.str.val,argv[2]->value.str.len); + /* Password */ + convert_to_string(argv[3]); + password = (char *) estrndup(argv[3]->value.str.val,argv[3]->value.str.len); + } + + /* Create identifier string for connection */ + sprintf(buffer, "%d", port); + hashed_details_length = strlen(host)+strlen(buffer)+8; + if(NULL == (hashed_details = (char *) emalloc(hashed_details_length+1))) { + if(host) efree(host); + if(password) efree(password); + if(username) efree(username); + php3_error(E_ERROR, "Could not get memory for connection details"); + RETURN_FALSE; + } + sprintf(hashed_details,"hw_%s_%d",host,port); + + if (persistent) { + list_entry *le; + + /* try to find if we already have this link in our persistent list */ + if (_php3_hash_find(plist, hashed_details, hashed_details_length+1, (void **) &le)==FAILURE) { + list_entry new_le; + + if (php3_hw_module.max_links!=-1 && php3_hw_module.num_links>=php3_hw_module.max_links) { + php3_error(E_ERROR,"Hyperwave: Too many open links (%d)",php3_hw_module.num_links); + if(host) efree(host); + if(username) efree(username); + if(password) efree(password); + efree(hashed_details); + RETURN_FALSE; + } + if (php3_hw_module.max_persistent!=-1 && php3_hw_module.num_persistent>=php3_hw_module.max_persistent) { + php3_error(E_ERROR,"Hyperwave: Too many open persistent links (%d)",php3_hw_module.num_persistent); + if(host) efree(host); + if(username) efree(username); + if(password) efree(password); + efree(hashed_details); + RETURN_FALSE; + } + + if ( (sockfd = open_hg_connection(host, port)) < 0 ) { + php3_error(E_ERROR, "Could not open connection to %s, Port: %d (retval=%d)", host, port, sockfd); + if(host) efree(host); + if(username) efree(username); + if(password) efree(password); + efree(hashed_details); + RETURN_FALSE; + } + + if(NULL == (ptr = malloc(sizeof(hw_connection)))) { + php3_error(E_ERROR, "Could not get memory for connection structure"); + if(host) efree(host); + if(username) efree(username); + if(password) efree(password); + efree(hashed_details); + RETURN_FALSE; + } + + if(0 != (ptr->lasterror = initialize_hg_connection(sockfd, &do_swap, &version, &userdata, &server_string, username, password))) { + php3_error(E_ERROR, "Could not initalize hyperwave connection"); + if(host) efree(host); + if(username) efree(username); + if(password) efree(password); + if(userdata) efree(userdata); + if(server_string) free(server_string); + efree(hashed_details); + RETURN_FALSE; + } + + if(username) efree(username); + if(password) efree(password); + + ptr->version = version; + ptr->server_string = server_string; + ptr->socket = sockfd; + ptr->swap_on = do_swap; + ptr->linkroot = 0; + ptr->hostname = strdup(host); + ptr->username = strdup("anonymous"); + + new_le.ptr = (void *) ptr; + new_le.type = php3_hw_module.le_psocketp;; + + if (_php3_hash_update(plist,hashed_details,hashed_details_length+1,(void *) &new_le, sizeof(list_entry), NULL)==FAILURE) { + php3_error(E_ERROR, "Could not hash table with connection details"); + if(host) efree(host); + if(username) efree(username); + if(password) efree(password); + if(server_string) free(server_string); + efree(hashed_details); + RETURN_FALSE; + } + + php3_hw_module.num_links++; + php3_hw_module.num_persistent++; + } else { + /*php3_printf("Found already open connection\n"); */ + if (le->type != php3_hw_module.le_psocketp) { + RETURN_FALSE; + } + ptr = le->ptr; + } + + return_value->value.lval = php3_list_insert(ptr,php3_hw_module.le_psocketp); + return_value->type = IS_LONG; + + } else { + list_entry *index_ptr,new_index_ptr; + + /* first we check the hash for the hashed_details key. if it exists, + * it should point us to the right offset where the actual hyperwave link sits. + * if it doesn't, open a new hyperwave link, add it to the resource list, + * and add a pointer to it with hashed_details as the key. + */ + if (_php3_hash_find(list,hashed_details,hashed_details_length+1,(void **) &index_ptr)==SUCCESS) { + int type,link; + void *ptr; + + if (index_ptr->type != le_index_ptr) { + RETURN_FALSE; + } + link = (int) index_ptr->ptr; + ptr = (hw_connection *) php3_list_find(link,&type); /* check if the link is still there */ + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + return_value->value.lval = php3_hw_module.default_link = link; + return_value->type = IS_LONG; + efree(hashed_details); + if(username) efree(username); + if(password) efree(password); + if(host) efree(host); + return; + } else { + _php3_hash_del(list,hashed_details,hashed_details_length+1); + } + } + + if ( (sockfd = open_hg_connection(host, port)) < 0 ) { + php3_error(E_ERROR, "Could not open connection to %s, Port: %d (retval=%d", host, port, sockfd); + if(host) efree(host); + if(username) efree(username); + if(password) efree(password); + efree(hashed_details); + RETURN_FALSE; + } + + if(NULL == (ptr = malloc(sizeof(hw_connection)))) { + if(host) efree(host); + if(username) efree(username); + if(password) efree(password); + efree(hashed_details); + RETURN_FALSE; + } + + if(0 != (ptr->lasterror = initialize_hg_connection(sockfd, &do_swap, &version, &userdata, &server_string, username, password))) { + php3_error(E_ERROR, "Could not initalize hyperwave connection"); + if(host) efree(host); + if(username) efree(username); + if(password) efree(password); + if(userdata) efree(userdata); + if(server_string) free(server_string); + efree(hashed_details); + RETURN_FALSE; + } + + if(username) efree(username); + if(password) efree(password); + + ptr->version = version; + ptr->server_string = server_string; + ptr->socket = sockfd; + ptr->swap_on = do_swap; + ptr->linkroot = 0; + ptr->hostname = strdup(host); + ptr->username = strdup("anonymous"); + + return_value->value.lval = php3_list_insert(ptr,php3_hw_module.le_socketp); + return_value->type = IS_LONG; + + new_index_ptr.ptr = (void *) return_value->value.lval; + new_index_ptr.type = le_index_ptr; + if (_php3_hash_update(list,hashed_details,hashed_details_length+1,(void *) &new_index_ptr, sizeof(list_entry), NULL)==FAILURE) { + php3_error(E_ERROR, "Could not update connection details in hash table"); + if(host) efree(host); + efree(hashed_details); + RETURN_FALSE; + } + + } + + efree(hashed_details); + if(host) efree(host); + php3_hw_module.default_link=return_value->value.lval; + + /* At this point we have a working connection. If userdata was given + we are also indentified. + If there is no userdata because hw_connect was called without username + and password, we don't evaluate userdata. + */ + if(NULL == userdata) + return; + + if(ptr->username) free(ptr->username); + str = userdata; + while((*str != 0) && (*str != ' ')) + str++; + if(*str != '\0') + ptr->username = strdup(++str); + else + ptr->username = NULL; + efree(userdata); +} + +/* Start of user level functions */ +/* ***************************** */ +/* {{{ proto int hw_connect(string host, int port [string username [, string password]]) + Connect to the Hyperwave server */ +void php3_hw_connect(INTERNAL_FUNCTION_PARAMETERS) +{ + php3_hw_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0); +} +/* }}} */ + +/* {{{ proto int hw_pconnect(string host, int port [string username [, string password]]) + Connect to the Hyperwave server persistent */ +void php3_hw_pconnect(INTERNAL_FUNCTION_PARAMETERS) +{ + php3_hw_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1); +} +/* }}} */ + +/* {{{ proto void hw_close(int link) + Close connection to Hyperwave server */ +void php3_hw_close(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1; + int id, type; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + id=arg1->value.lval; + ptr = php3_list_find(id,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + php3_list_delete(id); + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto void hw_info(int link) + Outputs info string */ +void php3_hw_info(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *arg1; + int id, type; + hw_connection *ptr; + char *str; + TLS_VARS; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + id=arg1->value.lval; + ptr = php3_list_find(id,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + if(NULL != (str = get_hw_info(ptr))) { + /* + php3_printf("%s\n", str); + efree(str); + */ + return_value->value.str.len = strlen(str); + return_value->value.str.val = str; + return_value->type = IS_STRING; + return; + } + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto int hw_error(int link) + Returns last error number */ +void php3_hw_error(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *arg1; + int id, type; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + id=arg1->value.lval; + ptr = php3_list_find(id,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + RETURN_LONG(ptr->lasterror); +} +/* }}} */ + +/* {{{ proto string hw_errormsg(int link) + Returns last error message */ +void php3_hw_errormsg(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *arg1; + int id, type; + hw_connection *ptr; + char errstr[100]; + TLS_VARS; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + id=arg1->value.lval; + ptr = php3_list_find(id,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + switch(ptr->lasterror) { + case 0: + sprintf(errstr, "No error"); + break; + case NOACCESS: + sprintf(errstr, "No access"); + break; + case NODOCS: + sprintf(errstr, "No documents"); + break; + case NONAME: + sprintf(errstr, "No collection name"); + break; + case NODOC: + sprintf(errstr, "Object is not a document"); + break; + case NOOBJ: + sprintf(errstr, "No object received"); + break; + case NOCOLLS: + sprintf(errstr, "No collections received"); + break; + case DBSTUBNG: + sprintf(errstr, "Connection to low-level database failed"); + break; + case NOTFOUND: + sprintf(errstr, "Object not found"); + break; + case EXIST: + sprintf(errstr, "Collection already exists"); + break; + case FATHERDEL: + sprintf(errstr, "parent collection disappeared"); + break; + case FATHNOCOLL: + sprintf(errstr, "parent collection not a collection"); + break; + case NOTEMPTY: + sprintf(errstr, "Collection not empty"); + break; + case DESTNOCOLL: + sprintf(errstr, "Destination not a collection"); + break; + case SRCEQDEST: + sprintf(errstr, "Source equals destination"); + break; + case REQPEND: + sprintf(errstr, "Request pending"); + break; + case TIMEOUT: + sprintf(errstr, "Timeout"); + break; + case NAMENOTUNIQUE: + sprintf(errstr, "Name not unique"); + break; + case WRITESTOPPED: + sprintf(errstr, "Database now read-only; try again later"); + break; + case LOCKED: + sprintf(errstr, "Object locked; try again later"); + break; + default: + sprintf(errstr, "Unknown error: %d", ptr->lasterror); + } + RETURN_STRING(errstr, 1); +} +/* }}} */ + +/* {{{ proto hw_root(void) + Returns object id of root collection */ +void php3_hw_root(INTERNAL_FUNCTION_PARAMETERS) +{ + TLS_VARS; + return_value->value.lval = 0; + return_value->type = IS_LONG; +} +/* }}} */ + +char *php3_hw_command(INTERNAL_FUNCTION_PARAMETERS, int comm) { + pval *arg1; + int link, type; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + return NULL; + } + convert_to_long(arg1); + link=arg1->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",link); + return NULL; + } + + set_swap(ptr->swap_on); + { + char *object = NULL; + if (0 != (ptr->lasterror = send_command(ptr->socket, comm, &object))) + return NULL; + + return object; + } +} + +/* {{{ proto string hw_stat(int link) + Returns status string */ +void php3_hw_stat(INTERNAL_FUNCTION_PARAMETERS) { + char *object; + + object = php3_hw_command(INTERNAL_FUNCTION_PARAM_PASSTHRU, STAT_COMMAND); + if(object == NULL) + RETURN_FALSE; + + return_value->value.str.val = object; + return_value->value.str.len = strlen(object); + return_value->type = IS_STRING; +} +/* }}} */ + +/* {{{ proto array hw_who(int link) + Returns names and info of users loged in */ +void php3_hw_who(INTERNAL_FUNCTION_PARAMETERS) { + pval user_arr; + char *object, *ptr, *temp, *attrname; + int i; + + object = php3_hw_command(INTERNAL_FUNCTION_PARAM_PASSTHRU, WHO_COMMAND); + if(object == NULL) + RETURN_FALSE; + + ptr = object; + + while((*ptr != '\0') && (*ptr != '\n')) + ptr++; + while((*ptr != '\0') && (*ptr != '\n')) + ptr++; + if(*ptr == '\0') { + efree(object); + RETURN_FALSE; + } + + if (array_init(return_value) == FAILURE) { + efree(object); + RETURN_FALSE; + } + + temp = estrdup(ptr); + attrname = strtok(temp, "\n"); + i = 0; + while(attrname != NULL) { + char *name; + + if (array_init(&user_arr) == FAILURE) { + efree(object); + RETURN_FALSE; + } + + ptr = attrname; + if(*ptr == '*') + add_assoc_long(&user_arr, "self", 1); + else + add_assoc_long(&user_arr, "self", 0); + + ptr++; + name = ptr; + while((*ptr != '\0') && (*ptr != ' ')) + ptr++; + *ptr = '\0'; + add_assoc_string(&user_arr, "id", name, 1); + + ptr++; + name = ptr; + while((*ptr != '\0') && (*ptr != ' ')) + ptr++; + *ptr = '\0'; + add_assoc_string(&user_arr, "name", name, 1); + + ptr++; + while((*ptr != '\0') && (*ptr == ' ')) + ptr++; + + name = ptr; + while((*ptr != '\0') && (*ptr != ' ')) + ptr++; + *ptr = '\0'; + add_assoc_string(&user_arr, "system", name, 1); + + ptr++; + while((*ptr != '\0') && (*ptr == ' ')) + ptr++; + + name = ptr; + while((*ptr != '\0') && (*ptr != ' ')) + ptr++; + *ptr = '\0'; + add_assoc_string(&user_arr, "onSinceDate", name, 1); + + ptr++; + while((*ptr != '\0') && (*ptr == ' ')) + ptr++; + + name = ptr; + while((*ptr != '\0') && (*ptr != ' ')) + ptr++; + *ptr = '\0'; + add_assoc_string(&user_arr, "onSinceTime", name, 1); + + ptr++; + while((*ptr != '\0') && (*ptr == ' ')) + ptr++; + + name = ptr; + while((*ptr != '\0') && (*ptr != ' ')) + ptr++; + *ptr = '\0'; + add_assoc_string(&user_arr, "TotalTime", name, 1); + + /* Add the user array */ + _php3_hash_index_update(return_value->value.ht, i++, &user_arr, sizeof(pval), NULL); + + /* The user array can now be freed, but I don't know how */ + + attrname = strtok(NULL, "\n"); + } + efree(temp); + efree(object); + +} +/* }}} */ + +void php3_hw_dummy(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2, *arg3; + int link, id, type, msgid; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + convert_to_long(arg3); + link=arg1->value.lval; + id=arg2->value.lval; + msgid=arg3->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + char *object = NULL; + if (0 != (ptr->lasterror = send_dummy(ptr->socket, id, msgid, &object))) + RETURN_FALSE; + +php3_printf("%s", object); + return_value->value.str.val = object; + return_value->value.str.len = strlen(object); + return_value->type = IS_STRING; + } +} + +/* {{{ proto string hw_getobject(int link, int objid) + Returns object record */ +void php3_hw_getobject(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + char *object = NULL; + if (0 != (ptr->lasterror = send_getobject(ptr->socket, id, &object))) + RETURN_FALSE; + + RETURN_STRING(object, 0); + /* + make_return_array_from_objrec(&return_value, object); + efree(object); + */ + } +} +/* }}} */ + +/* {{{ proto int hw_insertobject(int link, string objrec, string parms) + Inserts an object */ +void php3_hw_insertobject(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2, *arg3; + int link, type; + char *objrec, *parms; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_string(arg2); + convert_to_string(arg3); + link=arg1->value.lval; + objrec=arg2->value.str.val; + parms=arg3->value.str.val; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",link); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + int objid; + if (0 != (ptr->lasterror = send_insertobject(ptr->socket, objrec, parms, &objid))) + RETURN_FALSE; + + RETURN_LONG(objid); + } +} +/* }}} */ + +/* {{{ proto string hw_getandlock(int link, int objid) + Returns object record and locks object */ +void php3_hw_getandlock(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + char *object = NULL; + char *attrname, *str; + if (0 != (ptr->lasterror = send_getandlock(ptr->socket, id, &object))) + RETURN_FALSE; + + RETURN_STRING(object, 0); + } +} +/* }}} */ + +/* {{{ proto void hw_unlock(int link, int objid) + Unlocks object */ +void php3_hw_unlock(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + if (0 != (ptr->lasterror = send_unlock(ptr->socket, id))) + RETURN_FALSE; + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto void hw_deleteobject(int link, int objid) + Deletes object */ +void php3_hw_deleteobject(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + if (0 != (ptr->lasterror = send_deleteobject(ptr->socket, id))) + RETURN_FALSE; + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto void hw_changeobject(int link, int objid, array attributes) + Changes attributes of an object */ +void php3_hw_changeobject(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2, *arg3; + int link, id, type, i; + hw_connection *ptr; + char *modification, *oldobjrec, buf[200]; + HashTable *newobjarr; + TLS_VARS; + + if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); /* Connection */ + convert_to_long(arg2); /* object ID */ + convert_to_array(arg3); /* Array with new attributes */ + link=arg1->value.lval; + id=arg2->value.lval; + newobjarr=arg3->value.ht; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + /* get the old object record */ + if(0 != (ptr->lasterror = send_getobject(ptr->socket, id, &oldobjrec))) + RETURN_FALSE; + + _php3_hash_internal_pointer_reset(newobjarr); + modification = strdup(""); + for(i=0; i<_php3_hash_num_elements(newobjarr); i++) { + char *key, *str, *str1, newattribute[200]; + pval *data; + int j, noinsert=1; + ulong ind; + + _php3_hash_get_current_key(newobjarr, &key, &ind); + _php3_hash_get_current_data(newobjarr, (void *) &data); + switch(data->type) { + case IS_STRING: + if(strlen(data->value.str.val) == 0) + noinsert = 0; + else + sprintf(newattribute, "%s=%s", key, data->value.str.val); + break; + default: + sprintf(newattribute, "%s", ""); + } + + if(!noinsert) { + modification = fnInsStr(modification, 0, "\\"); + modification = fnInsStr(modification, 0, newattribute); + modification = fnInsStr(modification, 0, "add "); + + /* Retrieve the old attribute from object record */ + if(NULL != (str = strstr(oldobjrec, key))) { + str1 = str; + j = 0; + while((str1 != NULL) && (*str1 != '\n')) { + buf[j++] = *str1++; + } + buf[j] = '\0'; + modification = fnInsStr(modification, 0, "\\"); + modification = fnInsStr(modification, 0, buf); + modification = fnInsStr(modification, 0, "rem "); + } + } + efree(key); + _php3_hash_move_forward(newobjarr); + } + efree(oldobjrec); + + set_swap(ptr->swap_on); + modification[strlen(modification)-1] = '\0'; +/* php3_printf("0x%X, %s", id, modification); */ + if (0 != (ptr->lasterror = send_changeobject(ptr->socket, id, modification))) + RETURN_FALSE; + free(modification); + RETURN_TRUE; +} +/* }}} */ + +void php3_hw_mvcp(INTERNAL_FUNCTION_PARAMETERS, int mvcp) { + pval *arg1, *arg2, *arg3, *arg4, **objvIDs; + int link, type, dest=0, from=0; + HashTable *src_arr; + hw_connection *ptr; + int collIDcount, docIDcount, i, *docIDs, *collIDs; + TLS_VARS; + + switch(mvcp) { + case MOVE: /* Move also has fromID */ + if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) + WRONG_PARAM_COUNT; + break; + case COPY: + if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) + WRONG_PARAM_COUNT; + break; + } + convert_to_long(arg1); + convert_to_array(arg2); + convert_to_long(arg3); + link=arg1->value.lval; + src_arr=arg2->value.ht; + switch(mvcp) { + case MOVE: /* Move also has fromID, which is arg3 --> arg4 becomes destID */ + convert_to_long(arg4); + from=arg3->value.lval; + dest=arg4->value.lval; + break; + case COPY: /* No fromID for Copy needed --> arg3 is destID */ + dest=arg3->value.lval; + from = 0; + break; + } + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",link); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + + if(NULL == (objvIDs = emalloc(_php3_hash_num_elements(src_arr) * sizeof(pval *)))) { + RETURN_FALSE; + } + + if(getParametersArray(src_arr, _php3_hash_num_elements(src_arr), objvIDs) == FAILURE) { + RETURN_FALSE; + } + + if(NULL == (collIDs = emalloc(_php3_hash_num_elements(src_arr) * sizeof(int)))) { + efree(objvIDs); + RETURN_FALSE; + } + + if(NULL == (docIDs = emalloc(_php3_hash_num_elements(src_arr) * sizeof(int)))) { + efree(objvIDs); + efree(collIDs); + RETURN_FALSE; + } + + collIDcount = docIDcount = 0; + for(i=0; i<_php3_hash_num_elements(src_arr); i++) { + char *objrec; + if(objvIDs[i]->type == IS_LONG) { + if(0 != (ptr->lasterror = send_getobject(ptr->socket, objvIDs[i]->value.lval, &objrec))) { + efree(objvIDs); + efree(collIDs); + efree(docIDs); + RETURN_FALSE; + } + if(0 == fnAttributeCompare(objrec, "DocumentType", "collection")) + collIDs[collIDcount++] = objvIDs[i]->value.lval; + else + docIDs[docIDcount++] = objvIDs[i]->value.lval; + efree(objrec); + } + } + efree(objvIDs); + + if (0 != (ptr->lasterror = send_mvcpdocscoll(ptr->socket, docIDs, docIDcount, from, dest, mvcp))) { + efree(collIDs); + efree(docIDs); + RETURN_FALSE; + } + + if (0 != (ptr->lasterror = send_mvcpcollscoll(ptr->socket, collIDs, collIDcount, from, dest, mvcp))) { + efree(collIDs); + efree(docIDs); + RETURN_FALSE; + } + + efree(collIDs); + efree(docIDs); + + RETURN_LONG(docIDcount + collIDcount); +} + +/* {{{ proto void hw_mv(int link, array objrec, int from, int dest) + Moves object */ +void php3_hw_mv(INTERNAL_FUNCTION_PARAMETERS) { + php3_hw_mvcp(INTERNAL_FUNCTION_PARAM_PASSTHRU, MOVE); +} +/* }}} */ + +/* {{{ proto void hw_cp(int link, array objrec, int dest) + Copies object */ +void php3_hw_cp(INTERNAL_FUNCTION_PARAMETERS) { + php3_hw_mvcp(INTERNAL_FUNCTION_PARAM_PASSTHRU, COPY); +} +/* }}} */ + +/* {{{ proto hwdoc hw_gettext(int link, int objid[, int rootid]) + Returns text document. Links are relative to rootid if given */ +void php3_hw_gettext(INTERNAL_FUNCTION_PARAMETERS) { + pval *argv[3]; + int argc, link, id, type, mode; + int rootid = 0; + hw_document *doc; + hw_connection *ptr; + TLS_VARS; + + argc = ARG_COUNT(ht); + if((argc > 3) || (argc < 2)) + WRONG_PARAM_COUNT; + + if (getParametersArray(ht, argc, argv) == FAILURE) + RETURN_FALSE; + + convert_to_long(argv[0]); + convert_to_long(argv[1]); + if(argc == 3) { + convert_to_long(argv[2]); + rootid = argv[2]->value.lval; + mode = 1; + } else + mode = 0; + link=argv[0]->value.lval; + id=argv[1]->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + char *object = NULL; + char *attributes = NULL; + char *bodytag = NULL; + int count; + /* !!!! memory for object and attributes is allocated with malloc !!!! */ + if (0 != (ptr->lasterror = send_gettext(ptr->socket, id, mode, rootid, &attributes, &bodytag, &object, &count))) + RETURN_FALSE; + doc = malloc(sizeof(hw_document)); + doc->data = object; + doc->attributes = attributes; + doc->bodytag = bodytag; + doc->size = count; + return_value->value.lval = php3_list_insert(doc,php3_hw_module.le_document); + return_value->type = IS_LONG; + } +} +/* }}} */ + +/* {{{ proto void hw_edittext(int link, hwdoc doc) + Modifies text document */ +void php3_hw_edittext(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, doc, type; + hw_connection *ptr; + hw_document *docptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + ptr = php3_list_find(link,&type); + + /* FIXME id is not set anywhere */ + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + doc=arg2->value.lval; + docptr = php3_list_find(doc,&type); + + /* FIXME id is not set anywhere */ + if(!docptr || (type!=php3_hw_module.le_document)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + if (0 != (ptr->lasterror = send_edittext(ptr->socket, docptr->attributes, docptr->data))) { + RETURN_FALSE; + } + } + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto hwdoc hw_getcgi(int link, int objid) + Returns the output of a cgi script */ +void php3_hw_getcgi(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + hw_document *doc; + hw_connection *ptr; + char cgi_env_str[1000]; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + char *object = NULL; + char *attributes = NULL; + int count; + + /* Here is another undocument function of Hyperwave. + If you call a cgi script with getcgi-message, you will + have to provide the complete cgi enviroment, since it is + only known to the webserver (or wavemaster). This is done + by extending the object record with the following incomplete + string. It should contain any enviroment variable a cgi script + requires. + */ +#if (WIN32|WINNT) + sprintf(cgi_env_str, "CGI_REQUEST_METHOD=%s\nCGI_PATH_INFO=%s\nCGI_QUERY_STRING=%s", + getenv("REQUEST_METHOD"), + getenv("PATH_INFO"), + getenv("QUERY_STRING")); +#else + sprintf(cgi_env_str, "CGI_REQUEST_METHOD=%s\nCGI_PATH_INFO=%s\nCGI_QUERY_STRING=%s", + GLOBAL(request_info).request_method, + GLOBAL(request_info).path_info, + GLOBAL(request_info).query_string); +#endif + /* !!!! memory for object and attributes is allocated with malloc !!!! */ + if (0 != (ptr->lasterror = send_getcgi(ptr->socket, id, cgi_env_str, &attributes, &object, &count))) + RETURN_FALSE; + doc = malloc(sizeof(hw_document)); + doc->data = object; + doc->attributes = attributes; + doc->bodytag = NULL; + doc->size = count; + return_value->value.lval = php3_list_insert(doc,php3_hw_module.le_document); + return_value->type = IS_LONG; + } +} +/* }}} */ + +/* {{{ proto hwdoc hw_getremote(int link, int objid) + Returns the output of a remote document */ +void php3_hw_getremote(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + hw_document *doc; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + char *object = NULL; + char *attributes = NULL; + int count; + /* !!!! memory for object and attributes is allocated with malloc !!!! */ + if (0 != (ptr->lasterror = send_getremote(ptr->socket, id, &attributes, &object, &count))) + RETURN_FALSE; + doc = malloc(sizeof(hw_document)); + doc->data = object; + doc->attributes = attributes; + doc->bodytag = NULL; + doc->size = count; + return_value->value.lval = php3_list_insert(doc,php3_hw_module.le_document); + return_value->type = IS_LONG; + } +} +/* }}} */ + +/* {{{ proto [array|hwdoc] hw_getremotechildren(int link, int objid) + Returns the remote document if only one or an array of object records */ +void php3_hw_getremotechildren(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, type, i; + hw_connection *ptr; + char *objrec; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_string(arg2); + link=arg1->value.lval; + objrec=arg2->value.str.val; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d", link); + RETURN_FALSE; + } + set_swap(ptr->swap_on); + { + int count, *offsets; + char *remainder, *ptr1; + if (0 != (ptr->lasterror = send_getremotechildren(ptr->socket, objrec, &remainder, &offsets, &count))) + RETURN_FALSE; + + if(strncmp(remainder, "ObjectID=0 ", 10)) { + hw_document *doc; + remainder[offsets[0]-18] = '\0'; +/*php3_printf("offset = %d, remainder = %s---", offsets[0], remainder);*/ + doc = malloc(sizeof(hw_document)); + doc->data = strdup(remainder); + doc->attributes = strdup(objrec); + doc->bodytag = NULL; + doc->size = offsets[0]-18; + return_value->value.lval = php3_list_insert(doc,php3_hw_module.le_document); + return_value->type = IS_LONG; + } else { + if (array_init(return_value) == FAILURE) { + efree(offsets); + RETURN_FALSE; + } + + ptr1 = remainder; + for(i=0; i<count; i++) { + *(ptr1+offsets[i]-1) = '\0'; + add_index_string(return_value, i, ptr1, 1); + ptr1 += offsets[i]; + } + } + + efree(offsets); + efree(remainder); + } +} +/* }}} */ + +/* {{{ proto void hw_setlinkroot(int link, int rootid) + Set the id to which links are calculated */ +void php3_hw_setlinkroot(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, type, rootid; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link = arg1->value.lval; + rootid = arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",link); + RETURN_FALSE; + } + + ptr->linkroot = rootid; + RETURN_LONG(rootid); +} +/* }}} */ + +/* {{{ proto hwdoc hw_pipedocument(int link, int objid) + Returns document */ +void php3_hw_pipedocument(INTERNAL_FUNCTION_PARAMETERS) { + pval *argv[3]; + int link, id, type, argc, mode; + int rootid = 0; + hw_connection *ptr; + hw_document *doc; +#if APACHE + server_rec *serv = GLOBAL(php3_rqst)->server; +#endif + TLS_VARS; + + argc = ARG_COUNT(ht); + if((argc > 2) || (argc < 2)) + WRONG_PARAM_COUNT; + + if (getParametersArray(ht, argc, argv) == FAILURE) + RETURN_FALSE; + + convert_to_long(argv[0]); + convert_to_long(argv[1]); +/* if(argc == 3) { + convert_to_long(argv[2]); + rootid = argv[2]->value.lval; + if(rootid != 0) + mode = 1; + } +*/ link=argv[0]->value.lval; + id=argv[1]->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d", link); + RETURN_FALSE; + } + + mode = 0; + if(ptr->linkroot > 0) + mode = 1; + rootid = ptr->linkroot; + + set_swap(ptr->swap_on); + { + char *object = NULL; + char *attributes = NULL; + char *bodytag = NULL; + int count; + /* !!!! memory for object, bodytag and attributes is allocated with malloc !!!! */ + if (0 != (ptr->lasterror = send_pipedocument(ptr->socket, +#if APACHE + serv->server_hostname, +#else + getenv("HOST"), +#endif + id, mode, rootid, &attributes, &bodytag, &object, &count))) + RETURN_FALSE; + + doc = malloc(sizeof(hw_document)); + doc->data = object; + doc->attributes = attributes; + doc->bodytag = bodytag; + doc->size = count; +fprintf(stderr, "size = %d\n", count); + return_value->value.lval = php3_list_insert(doc,php3_hw_module.le_document); + return_value->type = IS_LONG; + } +} /* }}} */ + +/* {{{ proto hwdoc hw_pipecgi(int link, int objid) + Returns output of cgi script */ +void php3_hw_pipecgi(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + hw_connection *ptr; + hw_document *doc; + char cgi_env_str[1000]; +#if APACHE + server_rec *serv = GLOBAL(php3_rqst)->server; +#endif + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + char *object = NULL; + char *attributes = NULL; + int count; + +#if (WIN32|WINNT) + sprintf(cgi_env_str, "CGI_REQUEST_METHOD=%s\nCGI_PATH_INFO=%s\nCGI_QUERY_STRING=%s", + getenv("REQUEST_METHOD"), + getenv("PATH_INFO"), + getenv("QUERY_STRING")); +#else + sprintf(cgi_env_str, "CGI_REQUEST_METHOD=%s\nCGI_PATH_INFO=%s\nCGI_QUERY_STRING=%s", + GLOBAL(request_info).request_method, + GLOBAL(request_info).path_info, + GLOBAL(request_info).query_string); +#endif + /* !!!! memory for object, bodytag and attributes is allocated with malloc !!!! */ + if (0 != (ptr->lasterror = send_pipecgi(ptr->socket, +#if APACHE + serv->server_hostname, +#else + getenv("HOST"), +#endif + id, cgi_env_str, &attributes, &object, &count))) + RETURN_FALSE; + + doc = malloc(sizeof(hw_document)); + doc->data = object; + doc->attributes = attributes; + doc->bodytag = NULL; + doc->size = count; + return_value->value.lval = php3_list_insert(doc,php3_hw_module.le_document); + return_value->type = IS_LONG; + } +} /* }}} */ + +/* {{{ proto void hw_insertdocument(int link, int parentid, hwdoc doc) + Insert new document */ +void php3_hw_insertdocument(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2, *arg3; + int link, id, doc, type; + hw_connection *ptr; + hw_document *docptr; +#if APACHE + server_rec *serv = GLOBAL(php3_rqst)->server; +#endif + TLS_VARS; + + if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + convert_to_long(arg3); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find connection identifier %d",link); + RETURN_FALSE; + } + + doc=arg3->value.lval; + docptr = php3_list_find(doc,&type); + if(!docptr || (type!=php3_hw_module.le_document)) { + php3_error(E_WARNING,"Unable to find document identifier %d",doc); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + if (0 != (ptr->lasterror = send_putdocument(ptr->socket, +#if APACHE + serv->server_hostname, +#else + getenv("HOST"), +#endif + id, docptr->attributes, docptr->data, docptr->size))) { + RETURN_FALSE; + } + } + RETURN_TRUE; +} /* }}} */ + +/* {{{ proto hwdoc hw_new_document(int link, string data, string objrec, int size) + Create a new document */ +void php3_hw_new_document(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2, *arg3; + hw_document *doc; + + if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_string(arg1); + convert_to_string(arg2); + convert_to_long(arg3); + + doc = malloc(sizeof(hw_document)); + doc->data = malloc(arg3->value.lval); + memcpy(doc->data, arg2->value.str.val, arg3->value.lval); + doc->attributes = strdup(arg1->value.str.val); + doc->bodytag = NULL; + doc->size = arg3->value.lval; + return_value->value.lval = php3_list_insert(doc,php3_hw_module.le_document); + return_value->type = IS_LONG; +} /* }}} */ + +/* {{{ proto void hw_free_document(hwdoc doc) + Frees memory of document */ +void php3_hw_free_document(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1; + int id, type; + hw_document *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + id=arg1->value.lval; + ptr = php3_list_find(id,&type); + if(!ptr || (type!=php3_hw_module.le_document)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + php3_list_delete(id); + RETURN_TRUE; +} /* }}} */ + +/* {{{ proto void hw_output_document(hwdoc doc) + Prints document */ +void php3_hw_output_document(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1; + int id, type, count; + hw_document *ptr; + char *ptr1; + TLS_VARS; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + id=arg1->value.lval; + ptr = php3_list_find(id,&type); + if(!ptr || (type!=php3_hw_module.le_document)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + ptr1 = ptr->data; + count = 0; + while(count < ptr->size) { + php3_write(ptr1++, 1); + count++; + } + + RETURN_TRUE; +} /* }}} */ + +/* {{{ proto string hw_document_bodytag(hwdoc doc [, string prefix]) + Return bodytag prefixed by prefix */ +void php3_hw_document_bodytag(INTERNAL_FUNCTION_PARAMETERS) { + pval *argv[2]; + int id, type, argc; + hw_document *ptr; + char *temp, *str = NULL; + TLS_VARS; + + argc = ARG_COUNT(ht); + if((argc > 2) || (argc < 1)) + WRONG_PARAM_COUNT; + + if (getParametersArray(ht, argc, argv) == FAILURE) + RETURN_FALSE; + + convert_to_long(argv[0]); + id=argv[0]->value.lval; + ptr = php3_list_find(id,&type); + if(!ptr || (type!=php3_hw_module.le_document)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + if(argc == 2) { + convert_to_string(argv[1]); + str=argv[1]->value.str.val; + } + + if(str != NULL) { + temp = emalloc(argv[1]->value.str.len + strlen(ptr->bodytag) + 2); + strcpy(temp, ptr->bodytag); + strcpy(temp+strlen(ptr->bodytag)-1, str); + strcpy(temp+strlen(ptr->bodytag)-1+argv[1]->value.str.len, ">\n"); + RETURN_STRING(temp, 0); + } else { + RETURN_STRING(ptr->bodytag, 1); + } +} /* }}} */ + +/* {{{ proto string hw_document_content(hwdoc doc) + Returns content of document */ +void php3_hw_document_content(INTERNAL_FUNCTION_PARAMETERS) { + pval *argv[1]; + int id, type, argc; + hw_document *ptr; + TLS_VARS; + + argc = ARG_COUNT(ht); + if(argc != 1) + WRONG_PARAM_COUNT; + + if (getParametersArray(ht, argc, argv) == FAILURE) + RETURN_FALSE; + + convert_to_long(argv[0]); + id=argv[0]->value.lval; + ptr = php3_list_find(id,&type); + if(!ptr || (type!=php3_hw_module.le_document)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + RETURN_STRING(ptr->data, 1); +} /* }}} */ + +/* {{{ proto int hw_document_content(hwdoc doc) + Returns size of document */ +void php3_hw_document_size(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1; + int id, type; + hw_document *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + id=arg1->value.lval; + ptr = php3_list_find(id,&type); + if(!ptr || (type!=php3_hw_module.le_document)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + RETURN_LONG(ptr->size); +} /* }}} */ + +/* {{{ proto string hw_document_content(hwdoc doc) + Returns object record of document */ +void php3_hw_document_attributes(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1; + int id, type; + hw_document *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + id=arg1->value.lval; + ptr = php3_list_find(id,&type); + if(!ptr || (type!=php3_hw_module.le_document)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + RETURN_STRING(ptr->attributes, 1); +/* make_return_array_from_objrec(&return_value, ptr->attributes); */ +} /* }}} */ + +/* {{{ proto array hw_getparentsobj(int link, int objid) + Returns array of parent object records */ +void php3_hw_getparentsobj(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + int count; + char **childObjRecs = NULL; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + + if (0 != (ptr->lasterror = send_getparentsobj(ptr->socket, id, &childObjRecs, &count))) { + php3_error(E_WARNING, "send_command (getparentsobj) returned -1\n"); + RETURN_FALSE; + } + + /* create return value and free all memory */ + if( 0 > make_return_objrec(&return_value, childObjRecs, count)) + RETURN_FALSE; +} /* }}} */ + +/* {{{ proto array hw_getparents(int link, int objid) + Returns array of parent object ids */ +void php3_hw_getparents(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + int count; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + int *childIDs = NULL; + int i; + + if (0 != (ptr->lasterror = send_getparents(ptr->socket, id, &childIDs, &count))) { + php3_error(E_WARNING, "send_command (getparents) returned -1\n"); + RETURN_FALSE; + } + + if (array_init(return_value) == FAILURE) { + efree(childIDs); + RETURN_FALSE; + } + + for(i=0; i<count; i++) { + add_index_long(return_value, i, childIDs[i]); + } + efree(childIDs); + } + +} /* }}} */ + +/* {{{ proto array hw_children(int link, int objid) + Returns array of children object ids */ +void php3_hw_children(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + int count; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + int *childIDs = NULL; + int i; + + if (0 != (ptr->lasterror = send_children(ptr->socket, id, &childIDs, &count))){ + php3_error(E_WARNING, "send_command (getchildcoll) returned -1\n"); + RETURN_FALSE; + } + + if (array_init(return_value) == FAILURE) { + efree(childIDs); + RETURN_FALSE; + } + + for(i=0; i<count; i++) { + add_index_long(return_value, i, childIDs[i]); + } + efree(childIDs); + } + +} /* }}} */ + +/* {{{ proto array hw_children(int link, int objid) + Returns array of children object records */ +void php3_hw_childrenobj(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + int count; + char **childObjRecs = NULL; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + + if (0 != (ptr->lasterror = send_childrenobj(ptr->socket, id, &childObjRecs, &count))) { + php3_error(E_WARNING, "send_command (getchildcollobj) returned -1\n"); + RETURN_FALSE; + } + + /* create return value and free all memory */ + if( 0 > make_return_objrec(&return_value, childObjRecs, count)) + RETURN_FALSE; +} /* }}} */ + +/* {{{ proto array hw_childcoll(int link, int objid) + Returns array of child collection object ids */ +void php3_hw_getchildcoll(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + int count; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + int *childIDs = NULL; + int i; + + if (0 != (ptr->lasterror = send_getchildcoll(ptr->socket, id, &childIDs, &count))){ + php3_error(E_WARNING, "send_command (getchildcoll) returned -1\n"); + RETURN_FALSE; + } + + if (array_init(return_value) == FAILURE) { + efree(childIDs); + RETURN_FALSE; + } + + for(i=0; i<count; i++) { + add_index_long(return_value, i, childIDs[i]); + } + efree(childIDs); + } + +} /* }}} */ + +/* {{{ proto array hw_childcollobj(int link, int objid) + Returns array of child collection object records */ +void php3_hw_getchildcollobj(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + int count; + char **childObjRecs = NULL; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + + if (0 != (ptr->lasterror = send_getchildcollobj(ptr->socket, id, &childObjRecs, &count))) { + php3_error(E_WARNING, "send_command (getchildcollobj) returned -1\n"); + RETURN_FALSE; + } + + /* create return value and free all memory */ + if( 0 > make_return_objrec(&return_value, childObjRecs, count)) + RETURN_FALSE; +} /* }}} */ + +/* {{{ proto int hw_docbyanchor(int link, int anchorid) + Returns objid of document belonging to anchorid */ +void php3_hw_docbyanchor(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + int objectID; + if (0 != (ptr->lasterror = send_docbyanchor(ptr->socket, id, &objectID))) + RETURN_FALSE; + + RETURN_LONG(objectID); + } +} /* }}} */ + +/* {{{ proto array hw_docbyanchorobj(int link, int anchorid) + Returns object record of document belonging to anchorid */ +void php3_hw_docbyanchorobj(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + char *object = NULL; + if (0 != (ptr->lasterror = send_docbyanchorobj(ptr->socket, id, &object))) + RETURN_FALSE; + + RETURN_STRING(object, 0); + /* + make_return_array_from_objrec(&return_value, object); + efree(object); + */ + } +} /* }}} */ + +/* {{{ proto array hw_getobjectbyquery(int link, string query, int maxhits) + Search for query and return maxhits objids */ +void php3_hw_getobjectbyquery(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2, *arg3; + int link, type, maxhits; + char *query; + int count, i; + int *childIDs = NULL; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_string(arg2); + convert_to_long(arg3); + link=arg1->value.lval; + query=arg2->value.str.val; + maxhits=arg3->value.lval; + if (maxhits < 0) maxhits=0x7FFFFFFF; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",link); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + if (0 != (ptr->lasterror = send_getobjbyquery(ptr->socket, query, maxhits, &childIDs, &count))) { + php3_error(E_WARNING, "send_command (getchildcoll) returned -1\n"); + RETURN_FALSE; + } + + if (array_init(return_value) == FAILURE) { + efree(childIDs); + RETURN_FALSE; + } + + for(i=0; i<count; i++) + add_index_long(return_value, i, childIDs[i]); + efree(childIDs); +} /* }}} */ + +/* {{{ proto array hw_getobjectbyqueryobj(int link, string query, int maxhits) + Search for query and return maxhits object records */ +void php3_hw_getobjectbyqueryobj(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2, *arg3; + int link, type, maxhits; + char *query; + int count; + char **childObjRecs = NULL; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_string(arg2); + convert_to_long(arg3); + link=arg1->value.lval; + query=arg2->value.str.val; + maxhits=arg3->value.lval; + if (maxhits < 0) maxhits=0x7FFFFFFF; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",link); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + if (0 != (ptr->lasterror = send_getobjbyqueryobj(ptr->socket, query, maxhits, &childObjRecs, &count))) { + php3_error(E_WARNING, "send_command (getchildcoll) returned -1\n"); + RETURN_FALSE; + } + + /* create return value and free all memory */ + if( 0 > make_return_objrec(&return_value, childObjRecs, count)) + RETURN_FALSE; +} /* }}} */ + +/* {{{ proto array hw_getobjectbyquerycoll(int link, int collid, string query, int maxhits) + Search for query in collection and return maxhits objids */ +void php3_hw_getobjectbyquerycoll(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2, *arg3, *arg4; + int link, id, type, maxhits; + char *query; + int count, i; + hw_connection *ptr; + int *childIDs = NULL; + TLS_VARS; + + if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + convert_to_string(arg3); + convert_to_long(arg4); + link=arg1->value.lval; + id=arg2->value.lval; + query=arg3->value.str.val; + maxhits=arg4->value.lval; + if (maxhits < 0) maxhits=0x7FFFFFFF; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + if (0 != (ptr->lasterror = send_getobjbyquerycoll(ptr->socket, id, query, maxhits, &childIDs, &count))) { + php3_error(E_WARNING, "send_command (getchildcoll) returned -1\n"); + RETURN_FALSE; + } + + if (array_init(return_value) == FAILURE) { + efree(childIDs); + RETURN_FALSE; + } + + for(i=0; i<count; i++) + add_index_long(return_value, i, childIDs[i]); + efree(childIDs); +} /* }}} */ + +/* {{{ proto array hw_getobjectbyquerycollobj(int link, int collid, string query, int maxhits) + Search for query in collection and return maxhits object records */ +void php3_hw_getobjectbyquerycollobj(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2, *arg3, *arg4; + int link, id, type, maxhits; + char *query; + int count; + hw_connection *ptr; + char **childObjRecs = NULL; + TLS_VARS; + + if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + convert_to_string(arg3); + convert_to_long(arg4); + link=arg1->value.lval; + id=arg2->value.lval; + query=arg3->value.str.val; + maxhits=arg4->value.lval; + if (maxhits < 0) maxhits=0x7FFFFFFF; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + if (0 != (ptr->lasterror = send_getobjbyquerycollobj(ptr->socket, id, query, maxhits, &childObjRecs, &count))) { + php3_error(E_WARNING, "send_command (getchildcoll) returned -1\n"); + RETURN_FALSE; + } + + /* create return value and free all memory */ + if( 0 > make_return_objrec(&return_value, childObjRecs, count)) + RETURN_FALSE; +} /* }}} */ + +/* {{{ proto array hw_getchilddoccoll(int link, int objid) + Returns all children ids which are documents */ +void php3_hw_getchilddoccoll(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + int count, i; + int *childIDs = NULL; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + if (0 != (ptr->lasterror = send_getchilddoccoll(ptr->socket, id, &childIDs, &count))) { + php3_error(E_WARNING, "send_command (getchilddoccoll) returned -1\n"); + RETURN_FALSE; + } + + if (array_init(return_value) == FAILURE) { + efree(childIDs); + RETURN_FALSE; + } + + for(i=0; i<count; i++) + add_index_long(return_value, i, childIDs[i]); + efree(childIDs); +} /* }}} */ + +/* {{{ proto array hw_getchilddoccollobj(int link, int objid) + Returns all children object records which are documents */ +void php3_hw_getchilddoccollobj(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + int count; + char **childObjRecs = NULL; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + if (0 != (ptr->lasterror = send_getchilddoccollobj(ptr->socket, id, &childObjRecs, &count))) { + php3_error(E_WARNING, "send_command (getchilddoccollobj) returned -1\n"); + RETURN_FALSE; + } + + /* create return value and free all memory */ + if( 0 > make_return_objrec(&return_value, childObjRecs, count)) + RETURN_FALSE; + +} /* }}} */ + +/* {{{ proto array hw_getanchors(int link, int objid) + Return all anchors of object */ +void php3_hw_getanchors(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + int count, i; + int *anchorIDs = NULL; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + if (0 != (ptr->lasterror = send_getanchors(ptr->socket, id, &anchorIDs, &count))) { + php3_error(E_WARNING, "send_command (getanchors) returned -1\n"); + RETURN_FALSE; + } + + if (array_init(return_value) == FAILURE) { + efree(anchorIDs); + RETURN_FALSE; + } + + for(i=0; i<count; i++) + add_index_long(return_value, i, anchorIDs[i]); + efree(anchorIDs); +} /* }}} */ + +/* {{{ proto array hw_getanchorsobj(int link, int objid) + Return all object records of anchors of object */ +void php3_hw_getanchorsobj(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, id, type; + int count; + char **anchorObjRecs = NULL; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = (hw_connection *) php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",id); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + if (0 != (ptr->lasterror = send_getanchorsobj(ptr->socket, id, &anchorObjRecs, &count))) { + php3_error(E_WARNING, "send_command (getanchors) returned -1\n"); + RETURN_FALSE; + } + + /* create return value and free all memory */ + if( 0 > make_return_objrec(&return_value, anchorObjRecs, count)) + RETURN_FALSE; +} /* }}} */ + +/* {{{ proto string hw_getusername(int link) + Returns the current user name */ +void php3_hw_getusername(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1; + int link, type; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + link = arg1->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",link); + RETURN_FALSE; + } + + return_value->value.str.val = estrdup(ptr->username); + return_value->value.str.len = strlen(ptr->username); + return_value->type = IS_STRING; +} /* }}} */ + + +/* {{{ proto void hw_identify(int link, string username, string password) + Identifies at Hyperwave server */ +void php3_hw_identify(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2, *arg3; + int link, type; + char *name, *passwd, *userdata; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_string(arg2); + convert_to_string(arg3); + link = arg1->value.lval; + name=arg2->value.str.val; + passwd=arg3->value.str.val; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",link); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + { + char *str; + + if (0 != (ptr->lasterror = send_identify(ptr->socket, name, passwd, &userdata))) { + php3_error(E_WARNING, "send_identify returned -1\n"); + if(ptr->username) free(ptr->username); + ptr->username = NULL; + RETURN_FALSE; + } + + return_value->value.str.val = userdata; + return_value->value.str.len = strlen(userdata); + return_value->type = IS_STRING; + if(ptr->username) free(ptr->username); + str = userdata; + while((*str != 0) && (*str != ' ')) + str++; + if(*str != '\0') + ptr->username = strdup(++str); + else + ptr->username = NULL; + } +} +/* }}} */ + +/* {{{ proto array hw_objrec2array(string objrec) + Returns object array of object record*/ +void php3_hw_objrec2array(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1; + TLS_VARS; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string(arg1); + make_return_array_from_objrec(&return_value, arg1->value.str.val); +} +/* }}} */ + +/* {{{ proto string hw_array2objrec(array objarr) + Returns object record of object array */ +void php3_hw_array2objrec(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1; + char *objrec, *retobj; + TLS_VARS; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string(arg1); + objrec = make_objrec_from_array(arg1->value.ht); + if(objrec) { + retobj = estrdup(objrec); + free(objrec); + RETURN_STRING(retobj, 0); + } else + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto array hw_incollections(int link, array objids, array collids, int para) + Returns object ids which are in collections */ +void php3_hw_incollections(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2, *arg3, *arg4; + int type, link, i; + hw_connection *ptr; + int cobjids, ccollids, *objectIDs, *collIDs, cretids, *retIDs, retcoll; + TLS_VARS; + + if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_array(arg2); + convert_to_array(arg3); + convert_to_long(arg4); + link = arg1->value.lval; + retcoll=arg4->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",link); + RETURN_FALSE; + } + + cobjids = _php3_hash_num_elements(arg2->value.ht); + if(NULL == (objectIDs = make_ints_from_array(arg2->value.ht))) { + php3_error(E_WARNING, "Could not create Int Array from Array\n"); + RETURN_FALSE; + } + + ccollids = _php3_hash_num_elements(arg3->value.ht); + if(NULL == (collIDs = make_ints_from_array(arg3->value.ht))) { + php3_error(E_WARNING, "Could not create Int Array from Array\n"); + efree(objectIDs); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + if (0 != (ptr->lasterror = send_incollections(ptr->socket, retcoll, + cobjids, objectIDs, + ccollids, collIDs, + &cretids, &retIDs))) { + if(objectIDs) efree(objectIDs); + if(collIDs) efree(collIDs); + RETURN_FALSE; + } + + if(objectIDs) efree(objectIDs); + if(collIDs) efree(collIDs); + + if (array_init(return_value) == FAILURE) { + efree(retIDs); + RETURN_FALSE; + } + + for(i=0; i<cretids; i++) + add_index_long(return_value, i, retIDs[i]); + efree(retIDs); + +} +/* }}} */ + +/* {{{ proto void hw_inscoll(int link, int parentid, array objarr) + Inserts collection */ +void php3_hw_inscoll(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2, *arg3; + char *objrec; + int id, newid, type, link; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + convert_to_array(arg3); + link = arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",link); + RETURN_FALSE; + } + + if(NULL == (objrec = make_objrec_from_array(arg3->value.ht))) { + php3_error(E_WARNING, "Could not create Object Record from Array\n"); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + if (0 != (ptr->lasterror = send_inscoll(ptr->socket, id, objrec, &newid))) { + if(objrec) free(objrec); + RETURN_FALSE; + } + + if(objrec) free(objrec); + RETURN_LONG(newid); +} +/* }}} */ + +/* {{{ proto void hw_inscoll(int link, int parentid, array objarr [, string text]) + Inserts document */ +void php3_hw_insdoc(INTERNAL_FUNCTION_PARAMETERS) { + pval *argv[4]; + char *objrec, *text; + int id, newid, type, link, argc; + hw_connection *ptr; + TLS_VARS; + + argc = ARG_COUNT(ht); + if((argc < 3) || (argc > 4)) + WRONG_PARAM_COUNT; + + if (getParametersArray(ht, argc, argv) == FAILURE) + WRONG_PARAM_COUNT; + + convert_to_long(argv[0]); + convert_to_long(argv[1]); + convert_to_string(argv[2]); + if(argc == 4) { + convert_to_string(argv[3]); + text = argv[3]->value.str.val; + } else { + text = NULL; + } + link = argv[0]->value.lval; + id = argv[1]->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",link); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + objrec = argv[2]->value.str.val; + if (0 != (ptr->lasterror = send_insdoc(ptr->socket, id, objrec, text, &newid))) { + RETURN_FALSE; + } + + RETURN_LONG(newid); +} +/* }}} */ + +/* {{{ proto int hw_getsrcbydestobj(int link, int destid) + Returns object id of source docuent by destination anchor */ +void php3_hw_getsrcbydestobj(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2; + int link, type, id; + int count; + char **childObjRecs = NULL; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + link=arg1->value.lval; + id=arg2->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",link); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + if (0 != (ptr->lasterror = send_getsrcbydest(ptr->socket, id, &childObjRecs, &count))) { + php3_error(E_WARNING, "send_command (getsrcbydest) returned -1\n"); + RETURN_FALSE; + } + + /* create return value and free all memory */ + if( 0 > make_return_objrec(&return_value, childObjRecs, count)) + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto string hw_getrellink(int link, int rootid, int sourceid, int destid) + Get link form source to dest relative to rootid */ +void php3_hw_getrellink(INTERNAL_FUNCTION_PARAMETERS) { + pval *arg1, *arg2, *arg3, *arg4; + int link, type; + int rootid, destid, sourceid; + char *anchorstr; + hw_connection *ptr; + TLS_VARS; + + if (ARG_COUNT(ht) != 4 || getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + convert_to_long(arg2); + convert_to_long(arg3); + convert_to_long(arg4); + link=arg1->value.lval; + rootid=arg2->value.lval; + sourceid=arg3->value.lval; + destid=arg4->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",link); + RETURN_FALSE; + } + + set_swap(ptr->swap_on); + if (0 != (ptr->lasterror = getrellink(ptr->socket, rootid, sourceid, destid, &anchorstr))) { + php3_error(E_WARNING, "command (getrellink) returned -1\n"); + RETURN_FALSE; + } + + RETURN_STRING(anchorstr, 0); +} +/* }}} */ + + +void php3_info_hw() +{ + php3_printf("HG-CSP Version: 7.17"); +} + +void php3_hw_connection_info(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *arg1; + hw_connection *ptr; + int link, type; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long(arg1); + link=arg1->value.lval; + ptr = php3_list_find(link,&type); + if(!ptr || (type!=php3_hw_module.le_socketp && type!=php3_hw_module.le_psocketp)) { + php3_error(E_WARNING,"Unable to find file identifier %d",link); + RETURN_FALSE; + } + + php3_printf("Hyperwave Info:\nhost=%s,\nserver string=%s\nversion=%d\nswap=%d\n", ptr->hostname, ptr->server_string, ptr->version, ptr->swap_on); +} + +void print_msg(hg_msg *msg, char *str, int txt) +{ + char *ptr; + int i; + + fprintf(stdout, "\nprint_msg: >>%s<<\n", str); + fprintf(stdout, "print_msg: length = %d\n", msg->length); + fprintf(stdout, "print_msg: msgid = %d\n", msg->version_msgid); + fprintf(stdout, "print_msg: msg_type = %d\n", msg->msg_type); + if ( msg->length > HEADER_LENGTH ) { + ptr = msg->buf; + for ( i = 0; i < msg->length-HEADER_LENGTH; i++ ) { + if ( *ptr == '\n' ) + fprintf(stdout, "%c", *ptr++); + else if ( iscntrl(*ptr) ) + {fprintf(stdout, "."); ptr++;} + else + fprintf(stdout, "%c", *ptr++); + } + } + fprintf(stdout, "\n\n"); +} + +#endif + +/* + * Local variables: + * tab-width: 4 + * End: + */ diff --git a/ext/hyperwave/hw.h b/ext/hyperwave/hw.h new file mode 100644 index 0000000000..21c2e6ad07 --- /dev/null +++ b/ext/hyperwave/hw.h @@ -0,0 +1,122 @@ +/* + +----------------------------------------------------------------------+ + | PHP HTML Embedded Scripting Language Version 3.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997,1998 PHP Development Team (See Credits file) | + +----------------------------------------------------------------------+ + | This program is free software; you can redistribute it and/or modify | + | it under the terms of the GNU General Public License as published by | + | the Free Software Foundation; either version 2 of the License, or | + | (at your option) any later version. | + | | + | This program is distributed in the hope that it will be useful, | + | but WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | + | GNU General Public License for more details. | + | | + | You should have received a copy of the GNU General Public License | + | along with this program; if not, write to the Free Software | + | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | + +----------------------------------------------------------------------+ + | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | + +----------------------------------------------------------------------+ + */ + + +/* $Id$ */ + +#ifndef _HW_H +#define _HW_H + +#if HYPERWAVE +#include "hg_comm.h" + +extern php3_module_entry hw_module_entry; +#define hw_module_ptr &hw_module_entry + +typedef struct { + long default_link; + long num_links,num_persistent; + long max_links,max_persistent; + long allow_persistent; + int le_socketp, le_psocketp, le_document; +} hw_module; + +extern hw_module php3_hw_module; + +typedef struct { + int size; + char *data; + char *attributes; + char *bodytag; +} hw_document; + +extern hw_connection php3_hw_connection; + +extern int php3_minit_hw(INIT_FUNC_ARGS); +extern void php3_hw_connect(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_pconnect(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_close(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_root(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_info(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_error(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_errormsg(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_mv(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_cp(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_deleteobject(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_changeobject(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getparents(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getparentsobj(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_children(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_childrenobj(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getchildcoll(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getchildcollobj(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getobject(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getandlock(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_unlock(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_gettext(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_edittext(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getcgi(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getremote(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getremotechildren(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_pipedocument(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_pipecgi(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_insertdocument(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_docbyanchorobj(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_docbyanchor(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getobjectbyquery(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getobjectbyqueryobj(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getobjectbyquerycoll(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getobjectbyquerycollobj(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getchilddoccoll(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getchilddoccollobj(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getanchors(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getanchorsobj(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getusername(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_setlinkroot(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_inscoll(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_incollections(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_insertobject(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_insdoc(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_identify(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_free_document(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_new_document(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_output_document(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_document_size(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_document_attributes(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_document_bodytag(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_document_content(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_objrec2array(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_array2objrec(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_connection_info(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_info_hw(void); +extern void php3_hw_getsrcbydestobj(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_getrellink(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_dummy(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_who(INTERNAL_FUNCTION_PARAMETERS); +extern void php3_hw_stat(INTERNAL_FUNCTION_PARAMETERS); +#else +#define hw_module_ptr NULL +#endif /* HYPERWAVE */ +#endif /* _HW_H */ + diff --git a/ext/hyperwave/hw_error.h b/ext/hyperwave/hw_error.h new file mode 100644 index 0000000000..9730995e31 --- /dev/null +++ b/ext/hyperwave/hw_error.h @@ -0,0 +1,117 @@ +/* + +----------------------------------------------------------------------+ + | PHP HTML Embedded Scripting Language Version 3.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997,1998 PHP Development Team (See Credits file) | + +----------------------------------------------------------------------+ + | This program is free software; you can redistribute it and/or modify | + | it under the terms of the GNU General Public License as published by | + | the Free Software Foundation; either version 2 of the License, or | + | (at your option) any later version. | + | | + | This program is distributed in the hope that it will be useful, | + | but WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | + | GNU General Public License for more details. | + | | + | You should have received a copy of the GNU General Public License | + | along with this program; if not, write to the Free Software | + | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | + +----------------------------------------------------------------------+ + | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | + +----------------------------------------------------------------------+ + */ + + +/* $Id$ */ +#ifndef _HW_ERROR_H +#define _HW_ERROR_H + +#if HYPERWAVE + +#define NOACCESS 1 /* Access denied */ +#define NODOCS 2 /* No documents */ +#define NONAME 3 /* No collection name */ +#define NODOC 4 /* Object is not a document */ +#define NOOBJ 5 /* No object received */ +#define NOCOLLS 6 /* No collections received */ +#define DBSTUBNG 7 /* Connection to low-level database failed */ +#define NOTFOUND 8 /* Object not found */ +#define EXIST 9 /* Collection already exists */ +#define FATHERDEL 10 /* parent collection disappeared */ +#define FATHNOCOLL 11 /* parent collection not a collection */ +#define NOTEMPTY 12 /* Collection not empty */ +#define DESTNOCOLL 13 /* Destination not a collection */ +#define SRCEQDEST 14 /* Source equals destination */ +#define REQPEND 15 /* Request pending */ +#define TIMEOUT 16 /* Timeout */ +#define NAMENOTUNIQUE 17 /* Name not unique */ +#define WRITESTOPPED 18 /* Database now read-only; try again later */ +#define LOCKED 19 /* Object locked; try again later */ +#define CHANGEBASEFLD 20 /* Change of base-attribute */ +#define NOTREMOVED 21 /* Attribute not removed */ +#define FLDEXISTS 22 /* Attribute exists */ +#define CMDSYNTAX 23 /* Syntax error in command */ +#define NOLANGUAGE 24 /* No or unknown language specified */ +#define WRGTYPE 25 /* Wrong type in object */ +#define WRGVERSION 26 /* Client version too old */ +#define CONNECTION 27 /* No connection to other server */ +#define SYNC 28 /* Synchronization error */ +#define NOPATH 29 /* No path entry */ +#define WRGPATH 30 /* Wrong path entry */ +#define PASSWD 31 /* Wrong password (server-to-server server authentication) */ +#define LC_NO_MORE_USERS 32 /* No more users for license */ +#define LC_NO_MORE_DOCS 33 /* No more documents for this session and license */ +#define RSERV_NRESP 34 /* Remote server not responding */ +#define Q_OVERFLOW 35 /* Query overflow */ +#define USR_BREAK 36 /* Break by user */ +#define N_IMPL 37 /* Not implemented */ +#define WRG_VALUE 38 /* Wrong value */ +#define INSUFF_FUNDS 39 /* Insufficient funds */ +#define REORG 40 /* Reorganization in progress */ +#define USER_LIMIT 41 /* Limit of simultaneous users reached */ +#define FTCONNECT 513 /* No connection to fulltext server */ +#define FTTIMEOUT 514 /* Connection timed out */ +#define FTINDEX 515 /* Something wrong with fulltext index */ +#define FTSYNTAX 516 /* Query syntax error */ +#define REQUESTPENDING 1025 /* Request pending */ +#define NOCONNECTION 1026 /* No connection to document server */ +#define WRONGVERSION 1027 /* Wrong protocol version */ +#define NOTINITIALIZED 1028 /* Not initialized */ +#define BADREQUEST 1029 /* Bad request */ +#define BADLRN 1030 /* Bad document number */ +#define OPENSTORE_WRITE 1031 /* Cannot write to local store */ +#define OPENSTORE_READ 1032 /* Cannot read from local store */ +#define READSTORE 1033 /* Store read error */ +#define WRITESTORE 1034 /* Write error */ +#define CLOSESTORE 1035 /* Close error */ +#define BADPATH 1036 /* Bad path */ +#define NOPATHDC 1037 /* No path */ +#define OPENFILE 1038 /* Cannot open file */ +#define READFILE 1039 /* Cannot read from file // same */ +#define WRITEFILE 1040 /* Cannot write to file */ +#define CONNECTCLIENT 1041 /* Could not connect to client */ +#define ACCEPT 1042 /* Could not accept connection */ +#define READSOCKET 1043 /* Could not read from socket */ +#define WRITESOCKET 1044 /* Could not write to socket */ +#define TOOMUCHDATA 1046 /* Received too much data */ +#define TOOFEWDATA 1047 /* Received too few data // ... */ +#define NOTIMPLEMENTED 1049 /* Not implemented */ +#define USERBREAK 1050 /* User break */ +#define INTERNAL 1051 /* Internal error */ +#define INVALIDOBJECT 1052 /* Invalid object */ +#define JOBTIMEOUT 1053 /* Job timed out */ +#define OPENPORT 1054 /* Cannot open port // ... for several resons */ +#define NODATA 1055 /* Received no data */ +#define NOPORT 1056 /* No port to handle this request */ +#define NOTCACHED 1057 /* Document not cached */ +#define BADCACHETYPE 1058 /* Bad cache type */ +#define OPENCACHE_WRITE 1059 /* Cannot write to cache */ +#define OPENCACHE_READ 1060 /* Cannot read from cache // same */ +#define NOSOURCE 1061 /* Do not know what to read */ +#define CLOSECACHE 1062 /* Could not insert into cache */ +#define CONNECTREMOTE 1063 /* Could not connect to remote server */ +#define LOCKREFUSED 1064 /* Lock refused // could not lock the stores */ + +#endif +#endif diff --git a/ext/hyperwave/setup.stub b/ext/hyperwave/setup.stub new file mode 100644 index 0000000000..51099054d1 --- /dev/null +++ b/ext/hyperwave/setup.stub @@ -0,0 +1,6 @@ +# $Source$ +# $Id$ + +define_option with-hyperwave 'Hyperwave support?' yesno no \ +' Whether to build with Hyperwave support. More\n + information about Hyperwave can be found at http://www.hyperwave.com.' diff --git a/ext/rpc/com/COM.c b/ext/rpc/com/COM.c new file mode 100644 index 0000000000..17e4a28f3b --- /dev/null +++ b/ext/rpc/com/COM.c @@ -0,0 +1,959 @@ +/* + +----------------------------------------------------------------------+ + | PHP HTML Embedded Scripting Language Version 4.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. | + +----------------------------------------------------------------------+ + | Author: Zeev Suraski <zeev@zend.com> | + +----------------------------------------------------------------------+ + */ + + +/* + * This module implements support for COM components that support the IDispatch + * interface. Both local (COM) and remote (DCOM) components can be accessed. + * + * Type libraries can be loaded (in order for PHP to recognize automation constants) + * by specifying a typelib_file in the PHP .ini file. That file should contain + * paths to type libraries, one in every line. By default, constants are registered + * as case-sensitive. If you want them to be defined as case-insensitive, add + * #case_insensitive or #cis at the end of the type library path. + * + * This is also the first module to demonstrate Zend's OO syntax overloading + * capabilities. CORBA coders are invited to write a CORBA module as well! + * + * Zeev + */ + +#if WIN32|WINNT + +#define _WIN32_DCOM + +#include "php.h" +#include "php3_COM.h" +#include "zend_compile.h" +#include "php_ini.h" + +#include "objbase.h" +#include "olestd.h" +#include <ctype.h> + + +static int le_idispatch; + +function_entry COM_functions[] = { + {"com_load", php3_COM_load, NULL}, + {"com_invoke", php3_COM_invoke, NULL}, + + PHP_FE(com_propget, NULL) + PHP_FE(com_propput, NULL) + + PHP_NAMED_FE(com_get, php3_com_propget, NULL) + PHP_NAMED_FE(com_propset, php3_com_propput, NULL) + PHP_NAMED_FE(com_set, php3_com_propput, NULL) + + {NULL, NULL, NULL} +}; + +php3_module_entry COM_module_entry = { + "Win32 COM", COM_functions, php3_minit_COM, php3_mshutdown_COM, NULL, NULL, NULL, STANDARD_MODULE_PROPERTIES +}; + +void php_register_COM_class(); + +static int php_COM_load_typelib(char *typelib_name, int mode); + +static char *_php3_COM_error_message(HRESULT hr) +{ + void *pMsgBuf; + + if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, + hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &pMsgBuf, 0, NULL)) { + char error_string[] = "No description available"; + + pMsgBuf = LocalAlloc(LMEM_FIXED, sizeof(error_string)); + memcpy(pMsgBuf, error_string, sizeof(error_string)); + } + + return pMsgBuf; +} + + +static OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen) +{ + OLECHAR *unicode_str = (OLECHAR *) emalloc(sizeof(OLECHAR)*(strlen+1)); + OLECHAR *unicode_ptr = unicode_str; + + while (*C_str) { + *unicode_ptr++ = (unsigned short) *C_str++; + } + *unicode_ptr = 0; + + return unicode_str; +} + + +char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int persistent) +{ + uint length = OLESTRLEN(unicode_str); + char *C_str = (char *) pemalloc(length+1, persistent), *p = C_str; + + while (*unicode_str) { + *p++ = (char) *unicode_str++; + } + *p = 0; + + if (out_length) { + *out_length = length; + } + + return C_str; +} + + +static char *_php3_string_from_clsid(CLSID *clsid) +{ + LPOLESTR ole_clsid; + char *clsid_str; + + StringFromCLSID(clsid, &ole_clsid); + //s_clsid = OLE2A(ole_clsid); + clsid_str = php_OLECHAR_to_char(ole_clsid, NULL, 0); + LocalFree(ole_clsid); + + return clsid_str; +} + + +static void _php3_idispatch_destructor(IDispatch *i_dispatch) +{ + i_dispatch->lpVtbl->Release(i_dispatch); +} + + +static PHP_INI_MH(OnTypelibFileChange) +{ + FILE *typelib_file; + char *typelib_name_buffer; +#if SUPPORT_INTERACTIVE + int interactive; + ELS_FETCH(); + + interactive = EG(interactive); +#endif + + + if (!new_value || (typelib_file=fopen(new_value, "r"))==NULL) { + return FAILURE; + } + +#if SUPPORT_INTERACTIVE + if (interactive) { + printf("Loading type libraries..."); + fflush(stdout); + } +#endif + + typelib_name_buffer = (char *) malloc(sizeof(char)*1024); + + while (fgets(typelib_name_buffer, 1024, typelib_file)) { + char *typelib_name; + char *modifier; + int mode = CONST_PERSISTENT|CONST_CS; + + if (typelib_name_buffer[0]==';') { + continue; + } + typelib_name = strtok(typelib_name_buffer, "\r\n"); /* get rid of newlines */ + typelib_name = strtok(typelib_name, "#"); + modifier = strtok(NULL, "#"); + if (modifier) { + if (!strcmp(modifier, "cis") || !strcmp(modifier, "case_insensitive")) { + mode &= ~CONST_CS; + } + } +#if SUPPORT_INTERACTIVE + if (interactive) { + printf("\rLoading %-60s\r", typelib_name); + } +#endif + php_COM_load_typelib(typelib_name, mode); + } + + free(typelib_name_buffer); + fclose(typelib_file); + +#if SUPPORT_INTERACTIVE + if (interactive) { + printf("\r%70s\r", ""); + } +#endif + + return SUCCESS; +} + + +PHP_INI_BEGIN() + PHP_INI_ENTRY("allow_dcom", "0", PHP_INI_SYSTEM, NULL, NULL) + PHP_INI_ENTRY("typelib_file", NULL, PHP_INI_SYSTEM, OnTypelibFileChange, NULL) +PHP_INI_END() + + +int php3_minit_COM(INIT_FUNC_ARGS) +{ + CoInitialize(NULL); + le_idispatch = register_list_destructors(_php3_idispatch_destructor,NULL); + php_register_COM_class(); + REGISTER_INI_ENTRIES(); + return SUCCESS; +} + + +int php3_mshutdown_COM(SHUTDOWN_FUNC_ARGS) +{ + CoUninitialize(); + UNREGISTER_INI_ENTRIES(); + return SUCCESS; +} + + +void php3_COM_load(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *module_name, *server_name=NULL; + CLSID clsid; + HRESULT hr; + OLECHAR *ProgID; + IDispatch FAR *i_dispatch = NULL; + char *error_message; + char *clsid_str; + + switch (ARG_COUNT(ht)) { + case 1: + getParameters(ht, 1, &module_name); + break; + case 2: + if (!INI_INT("allow_dcom")) { + php3_error(E_WARNING, "DCOM is disabled"); + RETURN_FALSE; + } + getParameters(ht, 2, &module_name, &server_name); + convert_to_string(server_name); + break; + default: + WRONG_PARAM_COUNT; + break; + } + + convert_to_string(module_name); + ProgID = php_char_to_OLECHAR(module_name->value.str.val, module_name->value.str.len); + hr=CLSIDFromProgID(ProgID, &clsid); + efree(ProgID); + + // obtain CLSID + if (FAILED(hr)) { + error_message = _php3_COM_error_message(hr); + php3_error(E_WARNING,"Invalid ProgID: %s\n", error_message); + LocalFree(error_message); + RETURN_FALSE; + } + + // obtain IDispatch + if (!server_name) { + hr=CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (void **) &i_dispatch); + } else { + COSERVERINFO server_info; + MULTI_QI pResults; + + server_info.dwReserved1=0; + server_info.dwReserved2=0; + server_info.pwszName = php_char_to_OLECHAR(server_name->value.str.val, server_name->value.str.len); + server_info.pAuthInfo=NULL; + + pResults.pIID = &IID_IDispatch; + pResults.pItf = NULL; + pResults.hr = S_OK; + hr=CoCreateInstanceEx(&clsid, NULL, CLSCTX_SERVER, &server_info, 1, &pResults); + if (SUCCEEDED(hr)) { + hr = pResults.hr; + i_dispatch = (IDispatch *) pResults.pItf; + } + efree(server_info.pwszName); + } + if (FAILED(hr)) { + error_message = _php3_COM_error_message(hr); + clsid_str = _php3_string_from_clsid(&clsid); + php3_error(E_WARNING,"Unable to obtain IDispatch interface for CLSID %s: %s",clsid_str,error_message); + LocalFree(error_message); + efree(clsid_str); + RETURN_FALSE; + } + + RETURN_LONG(php3_list_insert(i_dispatch,le_idispatch)); +} + + +static void php_variant_to_pval(VARIANTARG *var_arg, pval *pval_arg, int persistent) +{ + switch (var_arg->vt) { + case VT_EMPTY: + var_uninit(pval_arg); + break; + case VT_UI1: + pval_arg->value.lval = (long) var_arg->bVal; + pval_arg->type = IS_LONG; + break; + case VT_I2: + pval_arg->value.lval = (long) var_arg->iVal; + pval_arg->type = IS_LONG; + break; + case VT_I4: + pval_arg->value.lval = var_arg->lVal; + pval_arg->type = IS_LONG; + break; + case VT_R4: + pval_arg->value.dval = (double) var_arg->fltVal; + pval_arg->type = IS_DOUBLE; + break; + case VT_R8: + pval_arg->value.dval = var_arg->dblVal; + pval_arg->type = IS_DOUBLE; + break; + case VT_BOOL: + + if (var_arg->boolVal & 0xFFFF) { + pval_arg->value.lval = 1; + } else { + + pval_arg->value.lval = 0; + } + + pval_arg->type = IS_BOOL; + break; + case VT_BSTR: + pval_arg->value.str.val = php_OLECHAR_to_char(var_arg->bstrVal, &pval_arg->value.str.len, persistent); + pval_arg->type = IS_STRING; + break; + case VT_UNKNOWN: + case VT_DISPATCH: + /* possibly, return IDispatch as a new COM object. right now - just get rid of it */ + var_arg->pdispVal->lpVtbl->Release(var_arg->pdispVal); + var_reset(pval_arg); + break; + default: + php3_error(E_WARNING,"Unsupported variant type"); + var_reset(pval_arg); + break; + } +} + + +static void _php3_pval_to_variant(pval *pval_arg, VARIANTARG *var_arg) +{ + OLECHAR *unicode_str; + + switch (pval_arg->type) { + case IS_OBJECT: + case IS_ARRAY: + var_arg->vt = VT_EMPTY; + break; + case IS_LONG: + case IS_BOOL: + var_arg->vt = VT_I4; // assuming 32-bit platform + var_arg->lVal = pval_arg->value.lval; + break; + case IS_DOUBLE: + var_arg->vt = VT_R8; // assuming 64-bit double precision + var_arg->dblVal = pval_arg->value.dval; + break; + case IS_STRING: + unicode_str = php_char_to_OLECHAR(pval_arg->value.str.val, pval_arg->value.str.len); + var_arg->bstrVal = SysAllocString(unicode_str); + var_arg->vt = VT_BSTR; + efree(unicode_str); + break; + } +} + + + +int do_COM_invoke(IDispatch *i_dispatch, pval *function_name, VARIANTARG *var_result, pval **arguments, int arg_count) +{ + DISPID dispid; + HRESULT hr; + OLECHAR *funcname; + char *error_message; + VARIANTARG *variant_args; + int current_arg, current_variant; + DISPPARAMS dispparams; + + funcname = php_char_to_OLECHAR(function_name->value.str.val, function_name->value.str.len); + + hr = i_dispatch->lpVtbl->GetIDsOfNames(i_dispatch, &IID_NULL, &funcname, + 1, LOCALE_SYSTEM_DEFAULT, &dispid); + + if (FAILED(hr)) { + error_message = _php3_COM_error_message(hr); + php3_error(E_WARNING,"Unable to lookup %s: %s\n", function_name->value.str.val, error_message); + LocalFree(error_message); + efree(funcname); + return FAILURE; + } + + variant_args = (VARIANTARG *) emalloc(sizeof(VARIANTARG)*arg_count); + + for (current_arg=0; current_arg<arg_count; current_arg++) { + current_variant = arg_count - current_arg - 1; + _php3_pval_to_variant(arguments[current_arg], &variant_args[current_variant]); + } + + + dispparams.rgvarg = variant_args; + dispparams.rgdispidNamedArgs = NULL; + dispparams.cArgs = arg_count; + dispparams.cNamedArgs = 0; + + hr = i_dispatch->lpVtbl->Invoke(i_dispatch, dispid, &IID_NULL, + LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, + &dispparams, var_result, NULL, 0); + + if (FAILED(hr)) { + error_message = _php3_COM_error_message(hr); + php3_error(E_WARNING,"Invoke() failed: %s\n", error_message); + LocalFree(error_message); + efree(funcname); + efree(variant_args); + return FAILURE; + } + + efree(variant_args); + efree(funcname); + return SUCCESS; +} + + +void php3_COM_invoke(INTERNAL_FUNCTION_PARAMETERS) +{ + pval **arguments; + pval *object, *function_name; + IDispatch *i_dispatch; + int type; + int arg_count = ARG_COUNT(ht); + VARIANTARG var_result; + + if (arg_count<2) { + WRONG_PARAM_COUNT; + } + arguments = (pval **) emalloc(sizeof(pval *)*arg_count); + if (getParametersArray(ht, arg_count, arguments)==FAILURE) { + RETURN_FALSE; + } + + object = arguments[0]; + function_name = arguments[1]; + + /* obtain i_dispatch interface */ + convert_to_long(object); + i_dispatch = php3_list_find(object->value.lval, &type); + if (!i_dispatch || (type!=le_idispatch)) { + php3_error(E_WARNING,"%d is not a COM object handler", function_name->value.str.val); + RETURN_FALSE; + } + + /* obtain property/method handler */ + convert_to_string(function_name); + + if (do_COM_invoke(i_dispatch, function_name, &var_result, arguments+2, arg_count-2)==FAILURE) { + RETURN_FALSE; + } + efree(arguments); + + php_variant_to_pval(&var_result, return_value, 0); +} + + + +static int do_COM_offget(VARIANTARG *var_result, VARIANTARG *array, pval *arg_property, int cleanup) +{ + switch (array->vt) { + case VT_DISPATCH: { /* a Collection, possibly */ + pval function_name; + IDispatch *i_dispatch = array->pdispVal; + int retval; + + function_name.value.str.val = "Item"; + function_name.value.str.len = 4; + function_name.type = IS_STRING; + retval = do_COM_invoke(i_dispatch, &function_name, var_result, &arg_property, 1); + if (cleanup) { + i_dispatch->lpVtbl->Release(i_dispatch); + } + return retval; + } + } + return FAILURE; +} + + +static int do_COM_propget(VARIANTARG *var_result, IDispatch *i_dispatch, pval *arg_property, int cleanup) +{ + DISPID dispid; + HRESULT hr; + OLECHAR *propname; + char *error_message; + DISPPARAMS dispparams; + + + /* obtain property handler */ + propname = php_char_to_OLECHAR(arg_property->value.str.val, arg_property->value.str.len); + + hr = i_dispatch->lpVtbl->GetIDsOfNames(i_dispatch, &IID_NULL, &propname, + 1, LOCALE_SYSTEM_DEFAULT, &dispid); + + if (FAILED(hr)) { + error_message = _php3_COM_error_message(hr); + php3_error(E_WARNING,"Unable to lookup %s: %s\n", arg_property->value.str.val, error_message); + LocalFree(error_message); + efree(propname); + if (cleanup) { + i_dispatch->lpVtbl->Release(i_dispatch); + } + return FAILURE; + } + + dispparams.cArgs = 0; + dispparams.cNamedArgs = 0; + + hr = i_dispatch->lpVtbl->Invoke(i_dispatch, dispid, &IID_NULL, + LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, + &dispparams, var_result, NULL, 0); + + if (FAILED(hr)) { + error_message = _php3_COM_error_message(hr); + php3_error(E_WARNING,"PropGet() failed: %s\n", error_message); + LocalFree(error_message); + efree(propname); + if (cleanup) { + i_dispatch->lpVtbl->Release(i_dispatch); + } + return FAILURE; + } + + efree(propname); + if (cleanup) { + i_dispatch->lpVtbl->Release(i_dispatch); + } + return SUCCESS; +} + + + +static void do_COM_propput(pval *return_value, IDispatch *i_dispatch, pval *arg_property, pval *value) +{ + DISPID dispid; + HRESULT hr; + OLECHAR *propname; + char *error_message; + VARIANTARG var_result; + DISPPARAMS dispparams; + VARIANTARG new_value; + DISPID mydispid = DISPID_PROPERTYPUT; + + + /* obtain property handler */ + propname = php_char_to_OLECHAR(arg_property->value.str.val, arg_property->value.str.len); + + hr = i_dispatch->lpVtbl->GetIDsOfNames(i_dispatch, &IID_NULL, &propname, + 1, LOCALE_SYSTEM_DEFAULT, &dispid); + + if (FAILED(hr)) { + error_message = _php3_COM_error_message(hr); + php3_error(E_WARNING,"Unable to lookup %s: %s\n", arg_property->value.str.val, error_message); + LocalFree(error_message); + efree(propname); + RETURN_FALSE; + } + + + _php3_pval_to_variant(value, &new_value); + dispparams.rgvarg = &new_value; + dispparams.rgdispidNamedArgs = &mydispid; + dispparams.cArgs = 1; + dispparams.cNamedArgs = 1; + + hr = i_dispatch->lpVtbl->Invoke(i_dispatch, dispid, &IID_NULL, + LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, + &dispparams, NULL, NULL, 0); + + dispparams.cArgs = 0; + dispparams.cNamedArgs = 0; + + hr = i_dispatch->lpVtbl->Invoke(i_dispatch, dispid, &IID_NULL, + LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, + &dispparams, &var_result, NULL, 0); + + if (FAILED(hr)) { + error_message = _php3_COM_error_message(hr); + php3_error(E_WARNING,"PropPut() failed: %s\n", error_message); + LocalFree(error_message); + efree(propname); + RETURN_FALSE; + } + + php_variant_to_pval(&var_result, return_value, 0); + + efree(propname); +} + + +PHP_FUNCTION(com_propget) +{ + pval *arg_idispatch, *arg_property; + int type; + IDispatch *i_dispatch; + VARIANTARG var_result; + + if (ARG_COUNT(ht)!=2 || getParameters(ht, 2, &arg_idispatch, &arg_property)==FAILURE) { + WRONG_PARAM_COUNT; + } + + /* obtain i_dispatch interface */ + convert_to_long(arg_idispatch); + /* obtain i_dispatch interface */ + i_dispatch = php3_list_find(arg_idispatch->value.lval,&type); + if (!i_dispatch || (type!=le_idispatch)) { + php3_error(E_WARNING,"%d is not a COM object handler", arg_idispatch->value.lval); + } + convert_to_string(arg_property); + + if (do_COM_propget(&var_result, i_dispatch, arg_property, 0)==FAILURE) { + RETURN_FALSE; + } + php_variant_to_pval(&var_result, return_value, 0); +} + + +PHP_FUNCTION(com_propput) +{ + pval *arg_idispatch, *arg_property, *arg_value; + int type; + IDispatch *i_dispatch; + + if (ARG_COUNT(ht)!=3 || getParameters(ht, 3, &arg_idispatch, &arg_property, &arg_value)==FAILURE) { + WRONG_PARAM_COUNT; + } + + /* obtain i_dispatch interface */ + convert_to_long(arg_idispatch); + /* obtain i_dispatch interface */ + i_dispatch = php3_list_find(arg_idispatch->value.lval,&type); + if (!i_dispatch || (type!=le_idispatch)) { + php3_error(E_WARNING,"%d is not a COM object handler", arg_idispatch->value.lval); + } + convert_to_string(arg_property); + + do_COM_propput(return_value, i_dispatch, arg_property, arg_value); +} + + +VARIANTARG _php_COM_get_property_handler(zend_property_reference *property_reference) +{ + zend_overloaded_element *overloaded_property; + zend_llist_element *element; + pval **idispatch_handle; + pval *object = *property_reference->object; + IDispatch *i_dispatch; + int type; + VARIANTARG var_result; + + /*printf("Reading a property from a TestClass object:\n");*/ + + + /* fetch the IDispatch interface */ + zend_hash_index_find(object->value.obj.properties, 0, (void **) &idispatch_handle); + i_dispatch = php3_list_find((*idispatch_handle)->value.lval,&type); + if (!i_dispatch || (type!=le_idispatch)) { + /* bail out */ + } + + var_result.vt = VT_DISPATCH; + var_result.pdispVal = i_dispatch; + + for (element=property_reference->elements_list.head; element; element=element->next) { + overloaded_property = (zend_overloaded_element *) element->data; + switch (overloaded_property->type) { + case IS_ARRAY: + if (do_COM_offget(&var_result, &var_result, &overloaded_property->element, element!=property_reference->elements_list.head)==FAILURE) { + /* bail out */ + } + /*printf("Array offset: ");*/ + break; + case IS_OBJECT: + if (var_result.vt != VT_DISPATCH) { + /* bail out */ + } else { + if (do_COM_propget(&var_result, var_result.pdispVal, &overloaded_property->element, element!=property_reference->elements_list.head)==FAILURE) { + /* bail out */ + } + /*printf("Object property: ");*/ + } + break; + case IS_METHOD: + return var_result; + break; + } + /* + switch (overloaded_property->element.type) { + case IS_LONG: + printf("%d (numeric)\n", overloaded_property->element.value.lval); + break; + case IS_STRING: + printf("'%s'\n", overloaded_property->element.value.str.val); + break; + } + */ + pval_destructor(&overloaded_property->element); + } + return var_result; +} + + +pval php_COM_get_property_handler(zend_property_reference *property_reference) +{ + pval result; + VARIANTARG var_result = _php_COM_get_property_handler(property_reference); + + php_variant_to_pval(&var_result, &result, 0); + return result; +} + + +int php_COM_set_property_handler(zend_property_reference *property_reference, pval *value) +{ + pval result; + zend_overloaded_element *overloaded_property; + zend_llist_element *element; + pval **idispatch_handle; + pval *object = *property_reference->object; + IDispatch *i_dispatch; + int type; + VARIANTARG var_result; + + /*printf("Reading a property from a TestClass object:\n");*/ + + + /* fetch the IDispatch interface */ + zend_hash_index_find(object->value.obj.properties, 0, (void **) &idispatch_handle); + i_dispatch = php3_list_find((*idispatch_handle)->value.lval,&type); + if (!i_dispatch || (type!=le_idispatch)) { + /* bail out */ + } + var_result.vt = VT_DISPATCH; + var_result.pdispVal = i_dispatch; + + for (element=property_reference->elements_list.head; element && element!=property_reference->elements_list.tail; element=element->next) { + overloaded_property = (zend_overloaded_element *) element->data; + switch (overloaded_property->type) { + case IS_ARRAY: + /*printf("Array offset: ");*/ + break; + case IS_OBJECT: + if (var_result.vt != VT_DISPATCH) { + /* bail out */ + } else { + do_COM_propget(&var_result, i_dispatch, &overloaded_property->element, element!=property_reference->elements_list.head); + /*printf("Object property: ");*/ + } + break; + case IS_METHOD: + /* this shouldn't happen */ + return FAILURE; + } + /* + switch (overloaded_property->element.type) { + case IS_LONG: + printf("%d (numeric)\n", overloaded_property->element.value.lval); + break; + case IS_STRING: + printf("'%s'\n", overloaded_property->element.value.str.val); + break; + } + */ + pval_destructor(&overloaded_property->element); + } + + if (var_result.vt != VT_DISPATCH) { + return FAILURE; + } + overloaded_property = (zend_overloaded_element *) element->data; + do_COM_propput(&result, var_result.pdispVal, &overloaded_property->element, value); + pval_destructor(&overloaded_property->element); + return SUCCESS; +} + + + +void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference) +{ + zend_overloaded_element *overloaded_property; + pval *object = *property_reference->object; + zend_overloaded_element *function_name = (zend_overloaded_element *) property_reference->elements_list.tail->data; + + if (zend_llist_count(&property_reference->elements_list)==1 + && !strcmp(function_name->element.value.str.val, "com")) { /* constructor */ + pval *object_handle; + + php3_COM_load(INTERNAL_FUNCTION_PARAM_PASSTHRU); + if (!zend_is_true(return_value)) { + var_reset(object); + return; + } + object_handle = (pval *) emalloc(sizeof(pval)); + *object_handle = *return_value; + pval_copy_constructor(object_handle); + object_handle->refcount = 1; + object_handle->is_ref=0; + zend_hash_index_update(object->value.obj.properties, 0, &object_handle, sizeof(pval *), NULL); + pval_destructor(&function_name->element); + } else { + VARIANTARG object_handle = _php_COM_get_property_handler(property_reference); + pval **arguments; + int arg_count = ARG_COUNT(ht); + VARIANTARG var_result; + + if (object_handle.vt != VT_DISPATCH) { + /* that shouldn't happen */ + return; + } + arguments = (pval **) emalloc(sizeof(pval *)*arg_count); + getParametersArray(ht, arg_count, arguments); + + if (do_COM_invoke((IDispatch *) object_handle.pdispVal, &function_name->element, &var_result, arguments, arg_count)==FAILURE) { + RETVAL_FALSE; + } + pval_destructor(&function_name->element); + efree(arguments); + php_variant_to_pval(&var_result, return_value, 0); + } + + for (overloaded_property = (zend_overloaded_element *) zend_llist_get_first(&property_reference->elements_list); + overloaded_property; + overloaded_property = (zend_overloaded_element *) zend_llist_get_next(&property_reference->elements_list)) { + switch (overloaded_property->type) { + case IS_ARRAY: + break; + case IS_OBJECT: + break; + case IS_METHOD: + + break; + } + } +} + + +void php_register_COM_class() +{ + zend_class_entry class_entry, *registered_class; + + class_entry.name = strdup("COM"); + class_entry.name_length = sizeof("COM")-1; + + class_entry.handle_property_get = php_COM_get_property_handler; + class_entry.handle_property_set = php_COM_set_property_handler; + class_entry.handle_function_call = php_COM_call_function_handler; + registered_class = register_internal_class(&class_entry); +} + + +static int php_COM_load_typelib(char *typelib_name, int mode) +{ + ITypeLib *TypeLib; + ITypeComp *TypeComp; + OLECHAR *p; + int i; + int interfaces; + ELS_FETCH(); + + p = php_char_to_OLECHAR(typelib_name, strlen(typelib_name)); + + if (FAILED(LoadTypeLib(p, &TypeLib))) { + efree(p); + return FAILURE; + } + + interfaces = TypeLib->lpVtbl->GetTypeInfoCount(TypeLib); + + TypeLib->lpVtbl->GetTypeComp(TypeLib, &TypeComp); + for (i=0; i<interfaces; i++) { + TYPEKIND pTKind; + + TypeLib->lpVtbl->GetTypeInfoType(TypeLib, i, &pTKind); + if (pTKind==TKIND_ENUM) { + ITypeInfo *TypeInfo; + VARDESC *pVarDesc; + UINT NameCount; + int j; +#if 0 + BSTR bstr_EnumId; + char *EnumId; + + TypeLib->lpVtbl->GetDocumentation(TypeLib, i, &bstr_EnumId, NULL, NULL, NULL); + EnumId = php_OLECHAR_to_char(bstr_EnumId, NULL, 0); + printf("Enumeration %d - %s:\n", i, EnumId); + efree(EnumId); +#endif + + TypeLib->lpVtbl->GetTypeInfo(TypeLib, i, &TypeInfo); + + j=0; + while (TypeInfo->lpVtbl->GetVarDesc(TypeInfo, j, &pVarDesc)==S_OK) { + BSTR bstr_ids; + char *ids; + zend_constant c; + + TypeInfo->lpVtbl->GetNames(TypeInfo, pVarDesc->memid, &bstr_ids, 1, &NameCount); + if (NameCount!=1) { + j++; + continue; + } + LocalFree(bstr_ids); + ids = php_OLECHAR_to_char(bstr_ids, NULL, 1); + c.name_len = strlen(ids)+1; + c.name = ids; + php_variant_to_pval(pVarDesc->lpvarValue, &c.value, 1); + c.flags = mode; + + zend_register_constant(&c ELS_CC); + //printf("%s -> %ld\n", ids, pVarDesc->lpvarValue->lVal); + j++; + } + TypeInfo->lpVtbl->Release(TypeInfo); + } + } + + + TypeLib->lpVtbl->Release(TypeLib); + efree(p); + return SUCCESS; +} + +#endif diff --git a/ext/rpc/com/php3_COM.h b/ext/rpc/com/php3_COM.h new file mode 100644 index 0000000000..ed9cc4f526 --- /dev/null +++ b/ext/rpc/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 */ |