emile           Sat Feb 17 15:21:54 2001 EDT

  Modified files:              
    /php4/ext/midgard   .cvsignore ChangeLog INSTALL Makefile.in 
                        article.c attachment.c calendar.c config.m4 
                        element.c event.c eventmember.c file.c group.c 
                        host.c image.c mail.c member.c mgd_access.h 
                        mgd_article.h mgd_attachment.h mgd_calendar.h 
                        mgd_element.h mgd_errno.pl mgd_event.h 
                        mgd_eventmember.h mgd_file.h mgd_group.h 
                        mgd_host.h mgd_image.h mgd_internal.h mgd_mail.h 
                        mgd_member.h mgd_midgard.h mgd_oop.h mgd_page.h 
                        mgd_pageelement.h mgd_pagelink.h mgd_person.h 
                        mgd_preferences.h mgd_preparser.h mgd_sitegroup.h 
                        mgd_snippet.h mgd_snippetdir.h mgd_style.h 
                        mgd_topic.h midgard.c mkall oop.c page.c 
                        pageelement.c pagelink.c parameter.c person.c 
                        php_midgard.h preferences.c preparser-parser.y 
                        preparser-scanner.l preparser.c sitegroup.c 
                        snippet.c snippetdir.c style.c topic.c 
  Log:
  Remove/Add appearantly doesn't cancel the remove... add separately.
  
  
Index: php4/ext/midgard/.cvsignore
diff -u /dev/null php4/ext/midgard/.cvsignore:1.3
--- /dev/null   Sat Feb 17 15:21:51 2001
+++ php4/ext/midgard/.cvsignore Sat Feb 17 15:21:49 2001
@@ -0,0 +1,122 @@
+.deps
+.libs
+CVS
+Makefile
+access.lo
+access.o
+access.slo
+acinclude.m4
+aclocal.m4
+article.lo
+article.o
+article.slo
+attachment.lo
+attachment.o
+attachment.slo
+build
+calendar.lo
+calendar.o
+calendar.slo
+config.cache
+config.guess
+config.log
+config.status
+config.sub
+config_vars.mk
+configure
+configure.in
+dynlib.m4
+element.lo
+element.o
+element.slo
+event.lo
+event.o
+event.slo
+eventmember.lo
+eventmember.o
+eventmember.slo
+file.lo
+file.o
+file.slo
+group.lo
+group.o
+group.slo
+host.lo
+host.o
+host.slo
+image.lo
+image.o
+image.slo
+install-sh
+libs.mk
+libtool
+ltconfig
+ltmain.sh
+mail.lo
+mail.o
+mail.slo
+member.lo
+member.o
+member.slo
+mgd_errno.c
+mgd_errno.h
+mgd_errno.lo
+mgd_errno.o
+mgd_errno.slo
+midgard.la
+midgard.lo
+midgard.o
+midgard.slo
+missing
+mkinstalldirs
+modules
+oop.lo
+oop.o
+oop.slo
+page.lo
+page.o
+page.slo
+pageelement.lo
+pageelement.o
+pageelement.slo
+pagelink.lo
+pagelink.o
+pagelink.slo
+parameter.lo
+parameter.o
+parameter.slo
+person.lo
+person.o
+person.slo
+php_config.h
+php_config.h.in
+preferences.lo
+preferences.o
+preferences.slo
+preparser-parser.h
+preparser-parser.lo
+preparser-parser.o
+preparser-parser.slo
+preparser-scanner.lo
+preparser-scanner.o
+preparser-scanner.slo
+preparser.c.bk
+preparser.lo
+preparser.o
+preparser.slo
+sitegroup.lo
+sitegroup.o
+sitegroup.slo
+snippet.lo
+snippet.o
+snippet.slo
+snippetdir.lo
+snippetdir.o
+snippetdir.slo
+style.lo
+style.o
+style.slo
+topic.lo
+topic.o
+topic.slo
+y.output
Index: php4/ext/midgard/ChangeLog
diff -u /dev/null php4/ext/midgard/ChangeLog:1.3
--- /dev/null   Sat Feb 17 15:21:51 2001
+++ php4/ext/midgard/ChangeLog  Sat Feb 17 15:21:49 2001
@@ -0,0 +1,175 @@
+2001-01-30 10:07  emile
+
+       * MidgardClassWhatever renamed to MidgardWhatever
+
+2001-01-26 02:09  david
+
+       * httpd.error_log.tgz: this is the httpd error_log associated with
+       the backtrace (see bt.txt).
+
+2001-01-26 02:05  david
+
+       * bt.txt: backtrace of an Asgard request (running out of memory).
+
+2001-01-26 02:04  david
+
+       * preparser-parser.y, preparser-scanner.l, preparser.c: debug
+       version. Lots of log, in httpd error_log and in the browser.
+
+2001-01-25 18:25  david
+
+       * preparser-parser.y, preparser-scanner.l, preparser.c: oops,
+       forgot default rule when in eval'ed quoted strings...
+
+2001-01-25 15:18  david
+
+       * article.c: removed some useless logging in mgd_get_article.
+
+2001-01-25 15:15  david
+
+       * Makefile.in, access.c, article.c, attachment.c, config.m4,
+       element.c, host.c, mgd_access.h, midgard.c, page.c, pageelement.c,
+       pagelink.c, preparser.c, style.c, topic.c: Eliminated the warnings
+       at compile, and cleaned the code.
+
+2001-01-25 04:38  david
+
+       * ab_config.m4, ab_mgd_preparser.h, ab_preparser-parser.y,
+       ab_preparser-scanner.l, ab_preparser.c, config.m4, mgd_preparser.h,
+       mkall, preparser-parser.y, preparser-scanner.l, preparser.c: added
+       Alexander's memory management modifications.  changed the lexer to
+       be more readable (easier to debug).  Status: old admin and VMUC
+       still working, Asgard has the same problem
+
+2001-01-24 21:45  david
+
+       * preparser-parser.y, preparser-scanner.l, preparser.c: Syncing. 
+       Asgard still crashing on form-template snippet but this is not a
+       mgd_include_snippet problem
+
+2001-01-24 20:46  david
+
+       * parameter.c, snippet.c: little bug on parameters oop members.
+
+2001-01-24 20:01  ab
+
+       * ab_mgd_preparser.h: Example site now works with dynamic memory
+       management.  Old Admin site has problems with authentication (?)
+
+2001-01-24 19:22  david
+
+       * test-db.tar.gz: My test DB, Asgard was modified in order to fix
+       some PHP3/PHP4 incompatibilities so everybody can test it.
+
+2001-01-24 19:09  david
+
+       * mgd_preparser.h, midgard.c, preparser-parser.y,
+       preparser-scanner.l, preparser.c: Preparser modifications, Asgard
+       is working almost fine, I'm on the way...
+
+2001-01-24 12:05  david
+
+       * preparser-parser.y, preparser.c: just syncing...  added the call
+       to zend_eval_string that seems to work on the snippets...  need to
+       implement it in variables and template elements.
+
+2001-01-24 02:24  david
+
+       * ab_config.m4, ab_mgd_preparser.h, ab_preparser-parser.y,
+       ab_preparser-scanner.l, ab_preparser.c, php_midgard.h: Alexander's
+       patch to the memory management in the preparser.  Doesn't work yet.
+
+2001-01-23 21:12  david
+
+       * BUGS, mgd_preparser.h, preparser-parser.y, preparser-scanner.l,
+       preparser.c: Fixed the variable handling, the VMUC example site now
+       runs fine.
+
+2001-01-23 18:51  david
+
+       * mgd_oop.h, midgard.c, preparser-parser.y, preparser.c: little fix
+       on snippets, MidgardClassSitegroup fix from marius and misc sync.
+
+2001-01-23 15:47  david
+
+       * host.c, parameter.c, preparser-parser.y, preparser.c,
+       sitegroup.c, snippet.c, snippetdir.c: Several bugs on php3/Zend
+       differences fixed.
+
+2001-01-23 11:34  david
+
+       * preparser-parser.y, preparser-scanner.l, preparser.c:
+       Modification on mgd_include_snippet handling in the preparser.
+
+2001-01-23 10:36  david
+
+       * preparser-scanner.l, preparser.c: Fixed snippet bug, doesn't work
+       with Asgard yet though (something like snippet too big).
+
+2001-01-23 09:48  david
+
+       * BUGS, oop.c: Bug on object instanciating fixed.  Now the old
+       admin work !!!
+
+2001-01-23 09:09  david
+
+       * BUGS: Known bugs updated.
+
+2001-01-23 03:13  david
+
+       * article.c, attachment.c, mgd_oop.h, midgard.c, oop.c,
+       parameter.c, preparser-scanner.l, sitegroup.c, topic.c: some more
+       bug fixing and code cleaning.
+
+2001-01-23 00:39  david
+
+       * mgd_internal.h: fixing differences between different Zend API
+       versions (at least between php-4.0.4-1.src.rpm and the current zend
+       CVS)
+
+2001-01-22 19:55  david
+
+       * mgd_internal.h, preparser.c: fixed a bug with variable as array
+
+2001-01-22 19:11  david
+
+       * BUGS, access.c, article.c, element.c, event.c, group.c, host.c,
+       mgd_internal.h, mgd_preparser.h, oop.c, pagelink.c, person.c,
+       preparser-scanner.l, preparser.c, sitegroup.c, snippetdir.c,
+       topic.c: corrected a lot of (maybe) harmful warnings.  added the
+       file BUGS
+
+2001-01-22 16:15  david
+
+       * Makefile.in, config.m4, mgd_internal.h, preparser-parser.y,
+       preparser.c: one of the reasons it segfaults fixed.  it still
+       segfaults on the old admin...
+
+2001-01-22 02:15  david
+
+       * mgd_internal.h, mgd_preparser.h, preparser-scanner.l,
+       preparser.c: Some work done on memory management in the preparser.
+
+2001-01-21 21:01  david
+
+       * midgard-root.php: midgard-root.php used instead of
+       midgard-root.php3
+
+2001-01-21 20:51  david
+
+       * .cvsignore, Makefile.in, access.c, article.c, attachment.c,
+       calendar.c, config.m4, element.c, event.c, eventmember.c, file.c,
+       fudge, genentry.pl, group.c, host.c, image.c, mail.c, member.c,
+       mgd_access.h, mgd_article.h, mgd_attachment.h, mgd_calendar.h,
+       mgd_element.h, mgd_errno.c, mgd_errno.h, mgd_errno.pl, mgd_event.h,
+       mgd_eventmember.h, mgd_file.h, mgd_group.h, mgd_host.h,
+       mgd_image.h, mgd_internal.h, mgd_mail.h, mgd_member.h,
+       mgd_midgard.h, mgd_oop.h, mgd_page.h, mgd_pageelement.h,
+       mgd_pagelink.h, mgd_person.h, mgd_preferences.h, mgd_preparser.h,
+       mgd_sitegroup.h, mgd_snippet.h, mgd_snippetdir.h, mgd_style.h,
+       mgd_topic.h, midgard.c, mkall, oop.c, page.c, pageelement.c,
+       pagelink.c, parameter.c, person.c, php_midgard.h, preferences.c,
+       preparser-parser.y, preparser-scanner.l, preparser.c, sitegroup.c,
+       snippet.c, snippetdir.c, style.c, topic.c: PHP4+preparser self
+       contained module source.
+
Index: php4/ext/midgard/INSTALL
diff -u /dev/null php4/ext/midgard/INSTALL:1.3
--- /dev/null   Sat Feb 17 15:21:51 2001
+++ php4/ext/midgard/INSTALL    Sat Feb 17 15:21:49 2001
@@ -0,0 +1,27 @@
+1 - To install midgard php4-module, you'll first need to have the version 
+4.0.4 of PHP, as well as the matching php-devel package (or install 
+PHP 4.0.4 from source).
+
+
+2 - Then run:
+
+./mkall
+
+or
+
+./mkall /prefix/directory
+
+where /prefix/directory is the directory you specified when ./configure'ing
+midgard-lib (defaults to /usr/local)
+
+
+3 - Copy the file midgard-root.php at the same location as the 
+midgard-root.php3 file, and edit midgard-data.conf accordingly.
+
+
+4 - Edit your php.ini to add:
+
+extension=midgard.so
+
+
+5 - Stop and start httpd.
Index: php4/ext/midgard/Makefile.in
diff -u /dev/null php4/ext/midgard/Makefile.in:1.3
--- /dev/null   Sat Feb 17 15:21:51 2001
+++ php4/ext/midgard/Makefile.in        Sat Feb 17 15:21:49 2001
@@ -0,0 +1,40 @@
+# $Id: Makefile.in,v 1.3 2001/02/17 23:21:49 emile Exp $
+#
+#   Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+#   Copyright (C) 2000 The Midgard Project ry
+#   Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+#  
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+LTLIBRARY_NAME        = libmidgard.la
+LTLIBRARY_SOURCES     = mgd_errno.c midgard.c article.c \
+                        parameter.c attachment.c oop.c \
+                        topic.c element.c mail.c \
+                        group.c file.c host.c image.c member.c \
+                        calendar.c event.c eventmember.c page.c \
+                        pageelement.c pagelink.c person.c \
+                        preferences.c snippet.c \
+                        snippetdir.c style.c sitegroup.c \
+                        preparser-parser.c preparser-scanner.c \
+                        preparser.c
+LTLIBRARY_SHARED_NAME = midgard.la
+LTLIBRARY_SHARED_LIBADD  = $(MIDGARD_SHARED_LIBADD)
+
+YFLAGS=-d -v -p mgd
+EXTRA_CFLAGS=-ggdb -Wall `$(GLIBCONFIG) --cflags`
+include $(top_srcdir)/build/dynlib.mk
+
+mgd_errno.c mgd_errno.h: mgd_errno.pl
+       perl mgd_errno.pl
Index: php4/ext/midgard/article.c
diff -u /dev/null php4/ext/midgard/article.c:1.3
--- /dev/null   Sat Feb 17 15:21:51 2001
+++ php4/ext/midgard/article.c  Sat Feb 17 15:21:49 2001
@@ -0,0 +1,1035 @@
+/* $Id: article.c,v 1.3 2001/02/17 23:21:49 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+#include "mgd_article.h"
+
+MGD_FUNCTION(is_article_owner)
+{
+       IDINIT;
+       CHECK_MGD;
+       RETVAL_LONG(isarticleowner(id));
+}
+
+MGD_FUNCTION(is_article_in_topic_tree)
+{
+       zval **root, **article;
+       int *ids, id, i;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+       if (ZEND_NUM_ARGS() != 2
+           || zend_get_parameters_ex(2, &root, &article) != SUCCESS)
+               WRONG_PARAM_COUNT;
+       convert_to_long_ex(root);
+       convert_to_long_ex(article);
+
+#if 0
+       if (!isarticlereader((*article)->value.lval))
+               return;
+#endif
+
+       ids = mgd_tree(mgd_handle(), "topic", (*root)->value.lval, 0, NULL);
+       if (ids) {
+               id =
+                  mgd_idfield(mgd_handle(), "topic", "article",
+                              (*article)->value.lval);
+               for (i = 0; ids[i]; i++)
+                       if (ids[i] == id)
+                               RETURN_TRUE;
+       }
+}
+
+const char *article_sort(const char *order)
+{
+       static struct
+       {
+               const char *order, *sort;
+       } sort[] =
+       {
+               {
+               "calendar", "article.calstart"}
+               , {
+               "alpha", "title ASC"}
+               , {
+               "reverse alpha", "title DESC"}
+               , {
+               "name", "name ASC"}
+               , {
+               "reverse name", "name DESC"}
+               , {
+               "score", "article.score ASC,title ASC"}
+               , {
+               "reverse score", "article.score DESC, title ASC"}
+               , {
+               "revised", "article.revised ASC"}
+               , {
+               "reverse revised", "article.revised DESC"}
+               , {
+               "created", "article.created ASC"}
+               , {
+               "reverse created", "article.created DESC"}
+               , {
+               NULL, "article.created DESC"}
+       };
+       int i;
+
+       for (i = 0; sort[i].order; i++)
+               if (strcmp(order, sort[i].order) == 0)
+                       return sort[i].sort;
+
+       return sort[i].sort;
+}
+
+MGD_FUNCTION(list_topic_articles)
+{
+       const char *sortv = NULL;
+       int typev = 0;
+       zval **id, **sortn, **typen, **upn;
+       int up = 0, up_wild = 0;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+       switch (ZEND_NUM_ARGS()) {
+               case 4:
+                       if (zend_get_parameters_ex(4, &id, &sortn, &typen, &upn)
+                           == SUCCESS) {
+                               convert_to_long_ex(id);
+                               convert_to_string_ex(sortn);
+                               convert_to_long_ex(typen);
+                               convert_to_long_ex(upn);
+                               sortv = article_sort((*sortn)->value.str.val);
+                               typev = (*typen)->value.lval;
+                               up = (*upn)->value.lval;
+                               up_wild = (up == 0 ? 1 : 0);
+                               break;
+                       }
+               case 3:
+                       if (zend_get_parameters_ex(3, &id, &sortn, &typen) ==
+                           SUCCESS) {
+                               convert_to_long_ex(id);
+                               convert_to_string_ex(sortn);
+                               convert_to_long_ex(typen);
+                               sortv = article_sort((*sortn)->value.str.val);
+                               typev = (*typen)->value.lval;
+                               up = 0;
+                               up_wild = 0;
+                               break;
+                       }
+               case 2:
+                       if (zend_get_parameters_ex(2, &id, &sortn) == SUCCESS) {
+                               convert_to_long_ex(id);
+                               convert_to_string_ex(sortn);
+                               sortv = article_sort((*sortn)->value.str.val);
+                               typev = -1;
+                               up = 0;
+                               up_wild = 0;
+                               break;
+                       }
+               case 1:
+                       if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                               convert_to_long_ex(id);
+                               sortv = "article.created DESC";
+                               typev = -1;
+                               up = 0;
+                               up_wild = 0;
+                               break;
+                       }
+               default:
+                       wrong_param_count();
+       }
+
+       if (typev == -1)
+               php_midgard_select(&MidgardArticle, return_value,
+               ARTICLE_SELECT, ARTICLE_FROM,
+                                  "article.topic=$d AND author=person.id"
+                                  " AND (article.up=$d OR 1=$d)",
+                                  sortv, (*id)->value.lval, up, up_wild);
+       else
+               php_midgard_select(&MidgardArticle, return_value,
+               ARTICLE_SELECT, ARTICLE_FROM,
+                                  "article.type=$d AND article.topic=$d"
+                                  " AND (article.up=$d OR 1=$d)"
+                                  " AND author=person.id",
+                                  sortv, typev, (*id)->value.lval, up,
+                                  up_wild);
+}
+
+MGD_FUNCTION(list_reply_articles)
+{
+       IDINIT;
+       CHECK_MGD;
+       php_midgard_select(&MidgardArticle, return_value,
+            ARTICLE_SELECT, ARTICLE_FROM,
+                          "article.up=$d AND author=person.id",
+                          "article.created DESC", id);
+}
+
+MGD_FUNCTION(list_topic_articles_all)
+{
+       int *topics;
+       const char *sortv = NULL;
+       int typev = 0;
+       zval **id, **sortn, **typen, **upn;
+       int up = 0, up_wild = 0;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+       switch (ZEND_NUM_ARGS()) {
+               case 4:
+                       if (zend_get_parameters_ex(4, &id, &sortn, &typen, &upn)
+                           == SUCCESS) {
+                               convert_to_long_ex(id);
+                               convert_to_string_ex(sortn);
+                               convert_to_long_ex(typen);
+                               convert_to_long_ex(upn);
+                               sortv = article_sort((*sortn)->value.str.val);
+                               typev = (*typen)->value.lval;
+                               up = (*upn)->value.lval;
+                               up_wild = (up == 0 ? 1 : 0);
+                               break;
+                       }
+               case 3:
+                       if (zend_get_parameters_ex(3, &id, &sortn, &typen) ==
+                           SUCCESS) {
+                               convert_to_long_ex(id);
+                               convert_to_string_ex(sortn);
+                               convert_to_long_ex(typen);
+                               sortv = article_sort((*sortn)->value.str.val);
+                               typev = (*typen)->value.lval;
+                               up = 0;
+                               up_wild = 0;
+                               break;
+                       }
+               case 2:
+                       if (zend_get_parameters_ex(2, &id, &sortn) == SUCCESS) {
+                               convert_to_long_ex(id);
+                               convert_to_string_ex(sortn);
+                               sortv = article_sort((*sortn)->value.str.val);
+                               typev = -1;
+                               up = 0;
+                               up_wild = 0;
+                               break;
+                       }
+               case 1:
+                       if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                               convert_to_long_ex(id);
+                               sortv = "article.created DESC";
+                               typev = -1;
+                               up = 0;
+                               up_wild = 0;
+                               break;
+                       }
+               default:
+                       wrong_param_count();
+       }
+
+       topics = mgd_tree(mgd_handle(), "topic", (*id)->value.lval, 0, NULL);
+
+       if (typev == -1)
+               php_midgard_select(&MidgardArticle, return_value,
+               ARTICLE_SELECT,
+                                  ARTICLE_FROM,
+                                  "article.topic IN $D AND author=person.id"
+                                  " AND (article.up=$d OR 1=$d)",
+                                  sortv, topics, up, up_wild);
+       else
+               php_midgard_select(&MidgardArticle, return_value,
+               ARTICLE_SELECT,
+                                  ARTICLE_FROM,
+                                  "article.type=$d AND article.topic IN $D"
+                                  " AND (article.up=$d OR 1=$d)"
+                                  " AND author=person.id",
+                                  sortv, typev, topics, up, up_wild);
+}
+
+MGD_FUNCTION(list_topic_articles_all_fast)
+{
+       int *topics;
+       const char *sortv = NULL;
+       int typev = 0;
+       zval **id, **sortn, **typen, **upn;
+       int up = 0, up_wild = 0;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+       switch (ZEND_NUM_ARGS()) {
+               case 4:
+                       if (zend_get_parameters_ex(4, &id, &sortn, &typen, &upn)
+                           == SUCCESS) {
+                               convert_to_long_ex(id);
+                               convert_to_string_ex(sortn);
+                               convert_to_long_ex(typen);
+                               sortv = article_sort((*sortn)->value.str.val);
+                               typev = (*typen)->value.lval;
+                               up = (*upn)->value.lval;
+                               up_wild = (up == 0 ? 1 : 0);
+                               break;
+                       }
+               case 3:
+                       if (zend_get_parameters_ex(3, &id, &sortn, &typen) ==
+                           SUCCESS) {
+                               convert_to_long_ex(id);
+                               convert_to_string_ex(sortn);
+                               convert_to_long_ex(typen);
+                               sortv = article_sort((*sortn)->value.str.val);
+                               typev = (*typen)->value.lval;
+                               up = 0;
+                               up_wild = 0;
+                               break;
+                       }
+               case 2:
+                       if (zend_get_parameters_ex(2, &id, &sortn) == SUCCESS) {
+                               convert_to_long_ex(id);
+                               convert_to_string_ex(sortn);
+                               sortv = article_sort((*sortn)->value.str.val);
+                               typev = -1;
+                               up = 0;
+                               up_wild = 0;
+                               break;
+                       }
+               case 1:
+                       if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                               convert_to_long_ex(id);
+                               sortv = "article.created DESC";
+                               typev = -1;
+                               up = 0;
+                               up_wild = 0;
+                               break;
+                       }
+               default:
+                       wrong_param_count();
+       }
+
+       topics = mgd_tree(mgd_handle(), "topic", (*id)->value.lval, 0, NULL);
+
+       if (typev == -1)
+               php_midgard_select(&MidgardArticle, return_value,
+                                  ARTICLE_SELECT_FAST,
+                                  ARTICLE_FROM_FAST,
+                                  "article.topic IN $D"
+                                  " AND (article.up=$d OR 1=$d)",
+                                  sortv, topics, up, up_wild);
+       else
+               php_midgard_select(&MidgardArticle, return_value,
+                                  ARTICLE_SELECT_FAST,
+                                  ARTICLE_FROM_FAST,
+                                  "article.type=$d AND article.topic IN $D"
+                                  " AND (article.up=$d OR 1=$d)",
+                                  sortv, typev, topics, up, up_wild);
+}
+
+MGD_FUNCTION(list_topic_articles_all_of_person)
+{
+       int *topics;
+       zval **topic, **person;
+       RETVAL_FALSE;
+       CHECK_MGD;
+       if (ZEND_NUM_ARGS() != 2
+           || zend_get_parameters_ex(2, &topic, &person) != SUCCESS)
+               WRONG_PARAM_COUNT;
+       convert_to_long_ex(topic);
+       convert_to_long_ex(person);
+
+       topics =
+          mgd_tree(mgd_handle(), "topic", (*topic)->value.lval, 0, NULL);
+
+       php_midgard_select(&MidgardArticle, return_value,
+            ARTICLE_SELECT, ARTICLE_FROM,
+                          "article.topic IN $D AND author=person.id AND author=$d AND 
+article.up=0",
+                          "article.created DESC", topics,
+                          (*person)->value.lval);
+}
+
+MGD_FUNCTION(get_article)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+               case 0:
+                       php_midgard_bless(return_value, &MidgardArticle);
+                       mgd_object_init(return_value, "up", "topic", "title",
+                                        "abstract", "content", "author",
+                                        "created", "url", "calstart",
+                                        "caldays", "icon", "view", "print",
+                                        "extra1", "extra2", "extra3", "name",
+                                        "creator", "revisor", "revision",
+                                        "approver", "revised", "approved",
+                                        "score", "type", "locked", "locker",
+                                        NULL);
+                       return;
+               case 1:
+                       if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                               convert_to_long_ex(id);
+                               break;
+                       }       /* else fall through */
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+       php_midgard_get(&MidgardArticle, return_value,
+                       "id,up,topic,name,title,abstract,content,author,"
+                       "Date_format(created,'%d.%m.%Y') AS date,"
+                       "Date_format(created,'%D %b. %Y') AS adate,"
+                       "Date_format(created,'%D %M %Y') AS aldate,"
+                       "extra1,extra2,extra3,article.score,type,"
+                       "Unix_Timestamp(created) AS created,creator,"
+                       "Unix_Timestamp(revised) AS revised,revisor,revision,"
+                       "Unix_Timestamp(approved) AS approved,approver,"
+                       "Unix_Timestamp(locked) AS locked,locker,"
+                       "url,icon,view,print,"
+                       CALENDAR_FIELDS, "article", (*id)->value.lval);
+}
+
+MGD_FUNCTION(get_article_by_name)
+{
+       zval **id, **name;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+               case 0:
+                       php_midgard_bless(return_value, &MidgardArticle);
+                       mgd_object_init(return_value, "up", "topic", "title",
+                                        "abstract", "content", "author",
+                                        "created", "url", "calstart",
+                                        "caldays", "icon", "view", "print",
+                                        "extra1", "extra2", "extra3", "name",
+                                        "creator", "revisor", "revision",
+                                        "approver", "revised", "approved",
+                                        "score", "type", "locked", "locker",
+                                        NULL);
+                       return;
+               case 2:
+                       if (zend_get_parameters_ex(2, &id, &name) == SUCCESS) {
+                               convert_to_long_ex(id);
+                               convert_to_string_ex(name);
+                               break;
+                       }       /* else fall through */
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+       php_midgard_get_by_name(&MidgardArticle, return_value,
+                               "id,up,topic,name,title,abstract,content,author,"
+                               "Date_format(created,'%d.%m.%Y') AS date,"
+                               "Date_format(created,'%D %b. %Y') AS adate,"
+                               "Date_format(created,'%D %M %Y') AS aldate,"
+                               "extra1,extra2,extra3,article.score,type,"
+                               "Unix_Timestamp(created) AS created,creator,"
+                               "Unix_Timestamp(revised) AS revised,revisor,"
+                               "revision,"
+                               "Unix_Timestamp(approved) AS approved,approver,"
+                               "Unix_Timestamp(locked) AS locked,locker,"
+                               "url,icon,view,print,"
+                               CALENDAR_FIELDS, "article", "topic",
+                               (*id)->value.lval, (*name)->value.str.val);
+}
+
+MGD_FUNCTION(get_reply_by_name)
+{
+       zval **id, **name;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+               case 2:
+                       if (zend_get_parameters_ex(2, &id, &name) == SUCCESS) {
+                               convert_to_long_ex(id);
+                               convert_to_string_ex(name);
+                               break;
+                       }       /* else fall through */
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+       php_midgard_get_by_name(&MidgardArticle, return_value,
+                               "id,up,topic,name,title,abstract,content,author,"
+                               "Date_format(created,'%d.%m.%Y') AS date,"
+                               "Date_format(created,'%D %b. %Y') AS adate,"
+                               "Date_format(created,'%D %M %Y') AS aldate,"
+                               "extra1,extra2,extra3,article.score,type,"
+                               "Unix_Timestamp(created) AS created,creator,"
+                               "Unix_Timestamp(revised) AS revised,revisor,"
+                               "revision,"
+                               "Unix_Timestamp(approved) AS approved,approver,"
+                               "Unix_Timestamp(locked) AS locked,locker,"
+                               "url,icon,view,print,"
+                               CALENDAR_FIELDS, "article", "up",
+                               (*id)->value.lval, (*name)->value.str.val);
+}
+
+MGD_FUNCTION(create_article)
+{
+       zval **up, **topic, **name, **title, **abstract, **content, **author;
+       zval **url, **calstart, **caldays, **icon, **view, **print;
+       zval **extra1, **extra2, **extra3, **type;
+       zval *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (!MGD_PROPFIND(self, "up", up)
+                   || !MGD_PROPFIND(self, "topic", topic)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "title", title)
+                   || !MGD_PROPFIND(self, "abstract", abstract)
+                   || !MGD_PROPFIND(self, "content", content)
+                   || !MGD_PROPFIND(self, "author", author)
+                   || !MGD_PROPFIND(self, "url", url)
+                   || !MGD_PROPFIND(self, "calstart", calstart)
+                   || !MGD_PROPFIND(self, "caldays", caldays)
+                   || !MGD_PROPFIND(self, "icon", icon)
+                   || !MGD_PROPFIND(self, "view", view)
+                   || !MGD_PROPFIND(self, "print", print)
+                   || !MGD_PROPFIND(self, "extra1", extra1)
+                   || !MGD_PROPFIND(self, "extra2", extra2)
+                   || !MGD_PROPFIND(self, "extra3", extra3)
+                   || !MGD_PROPFIND(self, "type", type)) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 17
+                   || zend_get_parameters_ex(17, &up, &topic, &name, &title,
+                                             &abstract, &content, &author,
+                                             &url, &calstart, &caldays, &icon,
+                                             &view, &print, &extra1, &extra2,
+                                             &extra3, &type) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(up);
+       convert_to_long_ex(topic);
+       convert_to_string_ex(name);
+       convert_to_string_ex(title);
+       convert_to_string_ex(abstract);
+       convert_to_string_ex(content);
+       convert_to_long_ex(author);
+       convert_to_string_ex(url);
+       convert_to_string_ex(calstart);
+       convert_to_long_ex(caldays);
+       convert_to_long_ex(icon);
+       convert_to_long_ex(view);
+       convert_to_long_ex(print);
+       convert_to_string_ex(extra1);
+       convert_to_string_ex(extra2);
+       convert_to_string_ex(extra3);
+       convert_to_long_ex(type);
+
+       if (!istopicowner((*topic)->value.lval)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+   }
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* up must be in same SG or be 0 */
+       if ((*up)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "article",
+                                                 "id=$d AND sitegroup IN (0,$d)",
+                                                 (*up)->value.lval,
+                                                 mgd_sitegroup(mgd_handle()))) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+   }
+
+       /* topic must be in same SG or be 0 */
+       if ((*topic)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "topic",
+                                                    "id=$d AND sitegroup IN (0,$d)",
+                                                    (*topic)->value.lval,
+                                                    mgd_sitegroup(mgd_handle
+                                                                  ()))) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+   }
+       /* author must be in same SG or be 0 */
+       if ((*author)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "person",
+                                                     "id=$d AND sitegroup IN (0,$d)",
+                                                     (*author)->value.lval,
+                                                     mgd_sitegroup(mgd_handle
+                                                                   ()))) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+   }
+#endif
+
+       php_midgard_create(return_value, "article",
+                          "up,topic,name,title,abstract,content,author,"
+                          "url,calstart,caldays,icon,view,print,"
+                          "extra1,extra2,extra3,score,type,"
+                          "created,creator,revised,revisor,"
+                          "revision,approved,approver",
+                          "$d,$d,$q,$q,$q,$q,$d,$q,$t,$d,$d,$d,$d,$q,$q,$q,0,$d,"
+                          "Now(),$d,Now(),$d,1,0,0",
+                          (*up)->value.lval, (*topic)->value.lval,
+                          (*name)->value.str.val, (*title)->value.str.val,
+                          (*abstract)->value.str.val,
+                          (*content)->value.str.val, (*author)->value.lval,
+                          (*url)->value.str.val, (*calstart)->value.str.val,
+                          (*caldays)->value.lval, (*icon)->value.lval,
+                          (*view)->value.lval, (*print)->value.lval,
+                          (*extra1)->value.str.val, (*extra2)->value.str.val,
+                          (*extra3)->value.str.val, (*type)->value.lval,
+                          mgd_user(mgd_handle()), mgd_user(mgd_handle()));
+       PHP_CREATE_REPLIGARD("article", return_value->value.lval);
+}
+
+MGD_FUNCTION(update_article_score)
+{
+       zval **id, **score, *self;
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1,
+                                                                  &score) !=
+                   SUCCESS) {
+                       WRONG_PARAM_COUNT;
+               }
+               if (!MGD_PROPFIND(self, "id", id)) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 2
+                   || zend_get_parameters_ex(2, &id, &score) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(id);
+       convert_to_long_ex(score);
+
+       if (!isarticleowner((*id)->value.lval)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       }
+
+       php_midgard_update(return_value, "article", "score=$d",
+                          (*id)->value.lval, (*score)->value.lval);
+       PHP_UPDATE_REPLIGARD("article", (*id)->value.lval);
+}
+
+MGD_FUNCTION(update_article_created)
+{
+       zval **id, **timestamp;
+       RETVAL_FALSE;
+       CHECK_MGD;
+       if (ZEND_NUM_ARGS() != 2
+           || zend_get_parameters_ex(2, &id, &timestamp) != SUCCESS)
+               WRONG_PARAM_COUNT;
+       convert_to_long_ex(id);
+       convert_to_long_ex(timestamp);
+
+       if (!isarticleowner((*id)->value.lval)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+   }
+
+       php_midgard_update(return_value, "article", "created=from_unixtime($d)",
+                          (*id)->value.lval, (*timestamp)->value.lval);
+       PHP_UPDATE_REPLIGARD("article", (*id)->value.lval);
+}
+
+MGD_FUNCTION(update_article_replyto)
+{
+       zval **id, **up;
+#if HAVE_MIDGARD_SITEGROUPS
+       int parent_topic;
+#endif
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if (ZEND_NUM_ARGS() != 2
+           || zend_get_parameters_ex(2, &id,
+                                     &up) != SUCCESS) WRONG_PARAM_COUNT;
+
+       convert_to_long_ex(id);
+       convert_to_long_ex(up);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       parent_topic =
+          mgd_idfield(mgd_handle(), "topic", "article", (*up)->value.lval);
+       /* up must be in same SG or be 0 */
+       if ((*up)->value.lval != 0
+           && !mgd_exists_bool(mgd_handle(), "article src, article tgt",
+                          "src.id=$d AND tgt.id=$d"
+                          " AND (src.sitegroup=tgt.sitegroup"
+                          " OR src.sitegroup=0" " OR tgt.sitegroup=0)",
+                          (*id)->value.lval, (*up)->value.lval)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+   }
+#endif
+
+       if (!isarticleowner((*id)->value.lval)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+   }
+
+       php_midgard_update(return_value, "article", "up=$d"
+#if HAVE_MIDGARD_SITEGROUPS
+                          ",topic=$d"
+#endif
+                          , (*id)->value.lval, (*up)->value.lval
+#if HAVE_MIDGARD_SITEGROUPS
+                          , parent_topic
+#endif
+          );
+       PHP_UPDATE_REPLIGARD("article", (*id)->value.lval);
+}
+
+MGD_FUNCTION(update_article_type)
+{
+       zval **id, **type, *self;
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1,
+                                                                  &type) !=
+                   SUCCESS) WRONG_PARAM_COUNT;
+               if (!MGD_PROPFIND(self, "id", id)) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+      }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 2
+                   || zend_get_parameters_ex(2, &id, &type) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(id);
+       convert_to_long_ex(type);
+
+       if (!isarticleowner((*id)->value.lval)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+   }
+
+       php_midgard_update(return_value, "article", "type=$d",
+                          (*id)->value.lval, (*type)->value.lval);
+       PHP_UPDATE_REPLIGARD("article", (*id)->value.lval);
+}
+
+MGD_FUNCTION(toggle_article_lock)
+{
+       zval **id;
+       RETVAL_FALSE;
+       CHECK_MGD;
+       if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &id) != SUCCESS)
+               WRONG_PARAM_COUNT;
+       convert_to_long_ex(id);
+
+       if (!isarticleowner((*id)->value.lval)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+   }
+
+       php_midgard_update(return_value, "article",
+                          "locked=Now(),locker=If(locker,0,$d)",
+                          (*id)->value.lval, mgd_user(mgd_handle()));
+       PHP_UPDATE_REPLIGARD("article", (*id)->value.lval);
+}
+
+MGD_FUNCTION(approve_article)
+{
+       zval **id;
+       zval **approve;
+       int flag;
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+               case 1:
+                       if (zend_get_parameters_ex(1, &id) != SUCCESS)
+                               WRONG_PARAM_COUNT;
+                       convert_to_long_ex(id);
+                       flag = 1;
+                       break;
+
+               case 2:
+                       if (zend_get_parameters_ex(2, &id, &approve) != SUCCESS)
+                               WRONG_PARAM_COUNT;
+                       convert_to_long_ex(id);
+                       convert_to_boolean_ex(approve);
+                       flag = (*approve)->value.lval;
+                       break;
+
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+       if (!isarticleowner((*id)->value.lval)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+   }
+
+       if (flag)
+               php_midgard_update(return_value, "article",
+                                  "approved=Now(),approver=$d",
+                                  (*id)->value.lval, mgd_user(mgd_handle()));
+       else
+               php_midgard_update(return_value, "article",
+                                  "approved='0000-00-00 00:00:00',approver=0",
+                                  (*id)->value.lval);
+       PHP_UPDATE_REPLIGARD("article", (*id)->value.lval);
+}
+
+MGD_FUNCTION(update_article)
+{
+       zval **id, **topic, **name, **title, **abstract, **content, **author;
+       zval **url, **calstart, **caldays, **icon, **view, **print;
+       zval **extra1, **extra2, **extra3;
+       zval **type, **score, **up, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (!MGD_PROPFIND(self, "id", id)
+                   || !MGD_PROPFIND(self, "topic", topic)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "title", title)
+                   || !MGD_PROPFIND(self, "abstract", abstract)
+                   || !MGD_PROPFIND(self, "content", content)
+                   || !MGD_PROPFIND(self, "author", author)
+                   || !MGD_PROPFIND(self, "url", url)
+                   || !MGD_PROPFIND(self, "calstart", calstart)
+                   || !MGD_PROPFIND(self, "caldays", caldays)
+                   || !MGD_PROPFIND(self, "icon", icon)
+                   || !MGD_PROPFIND(self, "view", view)
+                   || !MGD_PROPFIND(self, "print", print)
+                   || !MGD_PROPFIND(self, "extra1", extra1)
+                   || !MGD_PROPFIND(self, "extra2", extra2)
+                   || !MGD_PROPFIND(self, "extra3", extra3)
+                   || !MGD_PROPFIND(self, "type", type)
+                   || !MGD_PROPFIND(self, "up", up)
+                   || !MGD_PROPFIND(self, "score", score)) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               score = type = up = NULL;
+               if (ZEND_NUM_ARGS() != 16
+                   || zend_get_parameters_ex(16, &id, &topic, &name, &title,
+                                             &abstract, &content, &author,
+                                             &url, &calstart, &caldays, &icon,
+                                             &view, &print, &extra1, &extra2,
+                                             &extra3) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+       }
+       convert_to_long_ex(id);
+       convert_to_long_ex(topic);
+       convert_to_string_ex(name);
+       convert_to_string_ex(title);
+       convert_to_string_ex(abstract);
+       convert_to_string_ex(content);
+       convert_to_long_ex(author);
+       convert_to_string_ex(url);
+       convert_to_string_ex(calstart);
+       convert_to_long_ex(caldays);
+       convert_to_long_ex(icon);
+       convert_to_long_ex(view);
+       convert_to_long_ex(print);
+       convert_to_string_ex(extra1);
+       convert_to_string_ex(extra2);
+       convert_to_string_ex(extra3);
+
+       /* EEH: conversion to string is intentional, see update code */
+       if (type)
+               convert_to_string_ex(type);
+       if (score)
+               convert_to_string_ex(score);
+       if (up)
+               convert_to_string_ex(up);
+
+       if (!isarticleowner((*id)->value.lval)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+   }
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* TODO: If we change topic here we should clear 'up' */
+
+       /* topic must be in same SG or be 0 */
+       if ((*topic)->value.lval != 0
+           && !mgd_exists_bool(mgd_handle(), "article,topic",
+                          "article.id=$d AND topic.id=$d"
+                          " AND (article.sitegroup=topic.sitegroup"
+                          " OR article.sitegroup=0" " OR topic.sitegroup=0)",
+                          (*id)->value.lval, (*topic)->value.lval)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+   }
+
+       /* author must be in same SG or be 0 */
+       if ((*author)->value.lval != 0
+           && !mgd_exists_bool(mgd_handle(), "article,person",
+                          "article.id=$d AND person.id=$d"
+                          " AND (article.sitegroup=person.sitegroup"
+                          " OR article.sitegroup=0" " OR person.sitegroup=0)",
+                          (*id)->value.lval, (*author)->value.lval)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+   }
+#endif
+
+       php_midgard_update(return_value, "article",
+                          "name=$q,title=$q,abstract=$q,content=$q,"
+                          "author=$d,url=$q,calstart=$t,caldays=$d,icon=$d,"
+                          "view=$d,print=$d,extra1=$q,extra2=$q,extra3=$q,"
+                          "revised=Now(),revisor=$d,revision=revision+1,"
+                          "type=$s,score=$s,up=$s",
+                          (*id)->value.lval, (*name)->value.str.val,
+                          (*title)->value.str.val, (*abstract)->value.str.val,
+                          (*content)->value.str.val, (*author)->value.lval,
+                          (*url)->value.str.val, (*calstart)->value.str.val,
+                          (*caldays)->value.lval, (*icon)->value.lval,
+                          (*view)->value.lval, (*print)->value.lval,
+                          (*extra1)->value.str.val, (*extra2)->value.str.val,
+                          (*extra3)->value.str.val, mgd_user(mgd_handle()),
+                          type ? (*type)->value.str.val : "type",
+                          score ? (*score)->value.str.val : "score",
+                          up ? (*up)->value.str.val : "up" );
+
+       PHP_UPDATE_REPLIGARD("article", (*id)->value.lval);
+}
+
+MGD_FUNCTION(delete_article)
+{
+       IDINIT;
+       CHECK_MGD;
+
+       if (mgd_has_dependants(mgd_handle(), id, "article")) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+   }
+
+       if (mgd_exists_id(mgd_handle(), "article", "up=$d", id)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+   }
+
+       if (!isarticleowner(id)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+   }
+
+       php_midgard_delete(return_value, "article", id);
+       PHP_DELETE_REPLIGARD("article", id);
+}
+
+MGD_FUNCTION(copy_article)
+{
+       zval **id, **newtopic;
+       RETVAL_FALSE;
+       CHECK_MGD;
+       switch (ZEND_NUM_ARGS()) {
+               case 2:
+                       if (zend_get_parameters_ex(2, &id, &newtopic) !=
+                           SUCCESS) WRONG_PARAM_COUNT;
+                       break;
+               case 1:
+                       if (zend_get_parameters_ex(1, &id) != SUCCESS)
+                               WRONG_PARAM_COUNT;
+                       newtopic = NULL;
+                       break;
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(id);
+       if (newtopic)
+               convert_to_long_ex(newtopic);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* newtopic must be in same SG or be 0 */
+       if (newtopic && !mgd_exists_bool(mgd_handle(), "topic,article",
+                                   "topic.id=$d AND article.id=$d"
+                                   " AND (topic.sitegroup=article.sitegroup"
+                                   " OR topic.sitegroup=0"
+                                   " OR article.sitegroup=0)",
+                                   (*newtopic)->value.lval, (*id)->value.lval)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+   }
+#endif
+
+       RETVAL_LONG(mgd_copy_article(mgd_handle(), (*id)->value.lval,
+                                    newtopic ? (*newtopic)->value.lval : 0));
+}
+
+MGD_FUNCTION(delete_article_tree)
+{
+       IDINIT;
+       CHECK_MGD;
+
+       if (!isarticleowner(id)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+   }
+
+       if (mgd_delete_article(mgd_handle(), id)) {
+               RETURN_TRUE;
+   }
+
+   RETURN_FALSE;
+}
+
+MGD_MOVE_FUNCTION(article, topic, article, topic)
+MGD_MOVE_FUNCTION(article, article, reply, up)
+
+MidgardProperty MidgardArticleProperties [] = {
+       { IS_LONG,              "up"            },
+       { IS_LONG,              "topic"         },
+       { IS_STRING,    "name"          },
+       { IS_STRING,    "title"         },
+       { IS_STRING,    "abstract"      },
+       { IS_STRING,    "content"       },
+       { IS_LONG,              "author"        },
+       { IS_STRING,    "url"           },
+       { IS_LONG,              "calstart"      },
+       { IS_LONG,              "caldays"       },
+       { IS_LONG,              "icon"          },
+       { IS_LONG,              "view"          },
+       { IS_LONG,              "print"         },
+       { IS_STRING,    "extra1"        },
+       { IS_STRING,    "extra2"        },
+       { IS_STRING,    "extra3"        },
+       { IS_LONG,              "creator"       },
+       { IS_LONG,              "created"       },
+       { IS_LONG,              "revisor"       },
+       { IS_LONG,              "revision"      },
+       { IS_LONG,              "revised"       },
+       { IS_LONG,              "locker"        },
+       { IS_LONG,              "locked"        },
+       { IS_LONG,              "approver"      },
+       { IS_LONG,              "approved"      },
+       { IS_LONG,              "score"         },
+       { IS_LONG,              "type"          },
+       { 0,                    NULL            }
+};
+
+MIDGARD_HANDLERS_DECL(article)
+static zend_function_entry MidgardArticleMethods[] = {
+   PHP_FALIAS(midgardarticle,   mgd_ctor_article,        NULL)
+   PHP_FALIAS(create,   mgd_create_article,        NULL)
+   PHP_FALIAS(update,   mgd_update_article,        NULL)
+   PHP_FALIAS(delete,   mgd_delete_article,        NULL)
+   PHP_FALIAS(settype,  mgd_update_article_type,   NULL)
+   PHP_FALIAS(setscore, mgd_update_article_score,  NULL)
+   PHP_FALIAS(fetch,    mgd_oop_list_fetch,        NULL)
+   MIDGARD_OOP_PARAMETER_METHODS
+   MIDGARD_OOP_ATTACHMENT_METHODS
+   MIDGARD_OOP_SITEGROUP_METHODS
+   {  NULL,             NULL,                      NULL}
+};
+MidgardClass MidgardArticle = {
+   "MidgardArticle",
+   "article",
+   MidgardArticleMethods,
+   {},
+   mgd_article_call_function_handler,
+   mgd_article_get_property_handler,
+   mgd_article_set_property_handler,
+   MidgardArticleProperties,
+   NULL
+};
+MIDGARD_HANDLERS(MidgardArticle, article)
Index: php4/ext/midgard/attachment.c
diff -u /dev/null php4/ext/midgard/attachment.c:1.3
--- /dev/null   Sat Feb 17 15:21:51 2001
+++ php4/ext/midgard/attachment.c       Sat Feb 17 15:21:49 2001
@@ -0,0 +1,771 @@
+/* $Id: attachment.c,v 1.3 2001/02/17 23:21:49 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "php.h"
+#include "php_ini.h"
+#include "php_globals.h"
+#include "ext/standard/file.h"
+#include "php_midgard.h"
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+#include "mgd_errno.h"
+#include "mgd_access.h"
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+enum { MGD_BLOB_CALL_FUNC, MGD_BLOB_CALL_SELF, MGD_BLOB_CALL_OTHER };
+
+static long mgd_get_blob_id(zval *self, zval **name, int *calltype)
+{
+zval **table, **id;
+
+   if (self == NULL) {
+      if (calltype) *calltype = MGD_BLOB_CALL_FUNC;
+      if (name == NULL) return MGD_ERR_INVALID_NAME;
+      convert_to_long_ex(name);
+      return (*name)->value.lval;
+   }
+
+   if (!MGD_PROPFIND(self, "__table__", table)) {
+      return MGD_ERR_NOT_OBJECT;
+   }
+   if (!MGD_PROPFIND(self, "id", id)) {
+      return MGD_ERR_NOT_OBJECT;
+   }
+
+   if ((*table)->type != IS_STRING) {
+      return MGD_ERR_NOT_OBJECT;
+   }
+
+   if (strcmp((*table)->value.str.val, "blobs") == 0) {
+      if (calltype) *calltype = MGD_BLOB_CALL_SELF;
+      convert_to_long_ex(id);
+      return (*id)->value.lval;
+   }
+
+   if (calltype) *calltype = MGD_BLOB_CALL_OTHER;
+   if (name == NULL) return MGD_ERR_INVALID_NAME;
+   convert_to_string_ex(name);
+   return mgd_exists_id(mgd_handle(), "blobs",
+            "ptable=$q AND pid=$d AND name=$q",
+            (*table)->value.str.val, (*id)->value.lval,
+            (*name)->value.str.val);
+}
+
+MGD_FUNCTION(oop_attachment_create)
+{
+       zval *self;
+       zval **zv_table, **zv_id;
+       zval **zv_name, **zv_title, **zv_mimetype, **zv_score;
+       int id;
+       int table;
+       int score;
+       char location[MIDGARD_REPLIGARD_TAG_LENGTH + 5];
+       static char dir[16] = "0123456789ABCDEF";
+       char *path;
+       struct stat statbuf;
+       midgard_pool *pool;
+       FILE *fp;
+       const char *blobdir;
+
+       CHECK_MGD;
+
+       blobdir = mgd_get_blobdir(mgd_handle());
+       if (!blobdir || (*blobdir != '/')
+           || (stat(blobdir, &statbuf) != 0)
+           || !S_ISDIR(statbuf.st_mode)) {
+         php_log_err("Midgard: Invalid blobdir or blobdir not set");
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       }
+
+       if ((self = getThis()) == NULL) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+       }
+
+       if (!MGD_PROPFIND(self, "__table__", zv_table)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+       if (!MGD_PROPFIND(self, "id", zv_id)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+
+       convert_to_string_ex(zv_table);
+       convert_to_long_ex(zv_id);
+
+       switch (ZEND_NUM_ARGS()) {
+               case 3:
+                       if (zend_get_parameters_ex
+                           (3, &zv_name, &zv_title, &zv_mimetype) != SUCCESS) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       score = 0;
+                       break;
+               case 4:
+                       if (zend_get_parameters_ex
+                           (4, &zv_name, &zv_title, &zv_mimetype, &zv_score)
+                           != SUCCESS) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       convert_to_long_ex(zv_score);
+                       score = (*zv_score)->value.lval;
+                       break;
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_string_ex(zv_name);
+       convert_to_string_ex(zv_title);
+       convert_to_string_ex(zv_mimetype);
+
+       if (mgd_exists_id
+           (mgd_handle(), "blobs", "ptable=$q AND pid=$d AND name=$q",
+            (*zv_table)->value.str.val, (*zv_id)->value.lval,
+            (*zv_name)->value.str.
+            val)) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_DUPLICATE);
+   }
+
+       id = (*zv_id)->value.lval;
+       table = mgd_lookup_table_id((*zv_table)->value.str.val);
+
+       if (!isglobalowner(table, id)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+   }
+
+       do {
+               strcpy(location + 4,
+                      mgd_create_guid(mgd_handle(),
+                                      (*zv_table)->value.str.val, id));
+       } while (strstr(location + 4, ".."));
+
+       /* some basic hashing to aid in dirsize balancing. This probably
+          needs refinement since the rc5 checksum we use to generate the names
+          returns all readable chars which don't distribute well with the
+          simple method below
+        */
+       location[1] = location[3] = '/';
+       location[0] = dir[((unsigned char) location[4]) / 16];
+       location[2] = dir[((unsigned char) location[4]) % 16];
+
+       if (!(pool = mgd_alloc_pool())) {
+               php_log_err("Midgard: out of memory");
+               RETURN_FALSE_BECAUSE(MGD_ERR_INTERNAL);
+       }
+
+       path = mgd_format(mgd_handle(), pool, "$s/$s", blobdir, location);
+
+       if ((fp = fopen(path, "w")) == NULL) {
+               php_log_err("Midgard: Can't create blob");
+               RETVAL_FALSE_BECAUSE(MGD_ERR_INTERNAL);
+       }
+       else {
+               fclose(fp);
+               php_midgard_create(return_value, "blobs",
+                                  
+"ptable,pid,name,title,location,mimetype,author,created,score",
+                                  "$q,$d,$q,$q,$q,$q,$d,Now(),$d",
+                                  (*zv_table)->value.str.val, id,
+                                  (*zv_name)->value.str.val,
+                                  (*zv_title)->value.str.val, location,
+                                  (*zv_mimetype)->value.str.val,
+                                  mgd_user(mgd_handle()), score);
+               PHP_CREATE_REPLIGARD("blobs", return_value->value.lval);
+       }
+
+       mgd_free_pool(pool);
+}
+
+MGD_FUNCTION(oop_attachment_list)
+{
+       zval *self, **zv_table, **zv_id, **zv_order;
+       char *order = NULL;
+
+       CHECK_MGD;
+
+       if ((self = getThis()) == NULL) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+       }
+
+       if (!MGD_PROPFIND(self, "__table__", zv_table)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+       if (!MGD_PROPFIND(self, "id", zv_id)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+
+       convert_to_string_ex(zv_table);
+       convert_to_long_ex(zv_id);
+
+       if (ZEND_NUM_ARGS() == 1) {
+               if (zend_get_parameters_ex(1, &zv_order) == FAILURE) {
+                       WRONG_PARAM_COUNT;
+               }
+               else {
+                       convert_to_string_ex(zv_order);
+                       order = (*zv_order)->value.str.val;
+               }
+       }
+
+       php_midgard_select(&MidgardAttachment, return_value,
+                          "id,name,title,mimetype,score,author,created",
+                          "blobs", "ptable=$q AND pid=$d", order,
+                          (*zv_table)->value.str.val, (*zv_id)->value.lval);
+}
+
+MGD_FUNCTION(open_attachment)
+{
+       int pid;
+       int ptable;
+       FILE *fp;
+       const char *location;
+       char *path;
+       midgard_pool *pool;
+       midgard_res *res;
+       const char *blobdir;
+       zval **zv_id, **zv_mode;
+   zval *self;
+   long aid;
+
+       CHECK_MGD;
+       RETVAL_FALSE;
+
+       blobdir = mgd_get_blobdir(mgd_handle());
+       if (!blobdir || *blobdir != '/') {
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+   }
+
+       switch (ZEND_NUM_ARGS()) {
+      case 0:
+         zv_id = NULL;
+                       zv_mode = NULL;
+         break;
+               case 1:
+                       if (zend_get_parameters_ex(1, &zv_id) != SUCCESS) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       zv_mode = NULL;
+                       break;
+               case 2:
+                       if (zend_get_parameters_ex(1, &zv_id, &zv_mode) !=
+                           SUCCESS) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       break;
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+   aid = mgd_get_blob_id((self = getThis()), zv_id, NULL);
+   if (aid == 0) { RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS); }
+   else if (aid == MGD_ERR_INVALID_NAME) { WRONG_PARAM_COUNT; }
+   else if (aid < 0) { RETURN_FALSE_BECAUSE(aid); }
+
+       if (zv_mode)
+               convert_to_string_ex(zv_mode);
+
+       res = mgd_sitegroup_record(mgd_handle(), "ptable,pid,location",
+                                  "blobs", aid);
+
+       if (!res || !mgd_fetch(res)) {
+               if (res) {
+                       mgd_release(res);
+      }
+
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+       }
+
+       ptable = mgd_lookup_table_id(mgd_colvalue(res, 0));
+       pid = mgd_sql2id(res, 1);
+       location = mgd_colvalue(res, 2);
+
+       if (strstr(location, "..") || !isglobalowner(ptable, pid)) {
+               mgd_release(res);
+               php_log_err("Midgard: blobdir location relative or not owner");
+
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       }
+
+       pool = mgd_alloc_pool();
+       path = mgd_format(mgd_handle(), pool, "$s/$s", blobdir, location);
+       fp = fopen(path, zv_mode ? (*zv_mode)->value.str.val : "w");
+
+       if (!fp) {
+               RETVAL_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       }
+       else {
+               if (mgd_update
+                   (mgd_handle(), "blobs", aid,
+                    "author=$d,created=Now()", mgd_user(mgd_handle()))) {
+         ZEND_REGISTER_RESOURCE(return_value, fp, php_file_le_fopen());
+               }
+               else {
+                       fclose(fp);
+                       fp = NULL;
+               }
+       }
+
+       if (!fp) {
+               RETVAL_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+               php_log_err("Midgard: failed to open blob");
+       }
+
+       mgd_free_pool(pool);
+       mgd_release(res);
+}
+
+MGD_FUNCTION(get_attachment)
+{
+       zval **id;
+   zval *self;
+   long aid;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+      /* EEH/TODO: Why this?
+               case 0:
+                       php_midgard_bless(return_value, &MidgardAttachment);
+                       return;
+      */
+               case 1:
+                       if (zend_get_parameters_ex(1, &id) != SUCCESS) 
+WRONG_PARAM_COUNT;
+         break;
+
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+   aid = mgd_get_blob_id((self = getThis()), id, NULL);
+   if (aid == 0) { RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS); }
+   else if (aid == MGD_ERR_INVALID_NAME) { WRONG_PARAM_COUNT; }
+   else if (aid < 0) { RETURN_FALSE_BECAUSE(aid); }
+
+       php_midgard_get(&MidgardAttachment, return_value,
+                       "id,name,title,mimetype,score,author,created,ptable,pid",
+                       "blobs", aid);
+}
+
+MGD_FUNCTION(serve_attachment)
+{
+       midgard_res *res;
+       const char *location, *mimetype;
+       midgard_pool *pool;
+       char *path;
+       FILE *fp;
+       int b;
+       char buf[1024];
+       const char *blobdir;
+   int id;
+   zval *self, **zv_id;
+   char *content_type;
+
+       CHECK_MGD;
+       RETVAL_FALSE;
+
+       switch (ZEND_NUM_ARGS()) {
+               case 0:
+         zv_id = NULL;
+         break;
+
+               case 1:
+                       if (zend_get_parameters_ex(1, &zv_id) != SUCCESS) 
+WRONG_PARAM_COUNT;
+         break;
+
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+   id = mgd_get_blob_id((self = getThis()), zv_id, NULL);
+   if (id == 0) { RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS); }
+   else if (id == MGD_ERR_INVALID_NAME) { WRONG_PARAM_COUNT; }
+   else if (id < 0) { RETURN_FALSE_BECAUSE(id); }
+
+       blobdir = mgd_get_blobdir(mgd_handle());
+       if (!blobdir || *blobdir != '/') {
+               RETURN_FALSE_BECAUSE(MGD_ERR_INTERNAL);
+   }
+
+       res =
+          mgd_sitegroup_record(mgd_handle(), "location,mimetype", "blobs",
+                               id);
+
+       if (!res || !mgd_fetch(res)) {
+               if (res) { mgd_release(res); }
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+       }
+
+       location = mgd_colvalue(res, 0);
+       mimetype = mgd_colvalue(res, 1);
+       if (!mimetype || !*mimetype) {
+               mimetype = "application/binary";
+       }
+
+       if (!location || !*location || strstr(location, "..")) {
+               mgd_release(res);
+
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+       }
+
+       pool = mgd_alloc_pool();
+       path = mgd_format(mgd_handle(), pool, "$s/$s", blobdir, location);
+
+       if (!(fp = fopen(path, "r"))) {
+               mgd_free_pool(pool);
+               mgd_release(res);
+
+               RETURN_FALSE_BECAUSE(MGD_ERR_INTERNAL);
+       }
+
+   content_type
+      = mgd_format (mgd_handle(), pool, "Content-type: $s", mimetype);
+   sapi_add_header(content_type, strlen(content_type), 1);
+
+       if (sapi_send_headers() != SUCCESS) {
+               mgd_free_pool(pool);
+               mgd_release(res);
+
+               RETURN_FALSE_BECAUSE(MGD_ERR_INTERNAL);
+       }
+
+       while ((b = fread(buf, 1, sizeof(buf), fp)) > 0) {
+               PHPWRITE(buf, b);
+       }
+
+       mgd_free_pool(pool);
+       mgd_release(res);
+       RETVAL_TRUE;
+}
+
+MGD_FUNCTION(stat_attachment)
+{
+       midgard_res *res;
+       const char *location;
+       midgard_pool *pool;
+       char *path;
+       struct stat blobstat;
+   long id;
+   zval **zv_id, *self;
+
+       CHECK_MGD;
+       RETVAL_FALSE;
+
+       switch (ZEND_NUM_ARGS()) {
+               case 0:
+         zv_id = NULL;
+         break;
+
+               case 1:
+                       if (zend_get_parameters_ex(1, &zv_id) != SUCCESS) 
+WRONG_PARAM_COUNT;
+         break;
+
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+   id = mgd_get_blob_id((self = getThis()), zv_id, NULL);
+   if (id == 0) { RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS); }
+   else if (id == MGD_ERR_INVALID_NAME) { WRONG_PARAM_COUNT; }
+   else if (id < 0) { RETURN_FALSE_BECAUSE(id); }
+
+       if (!mgd_dcfg() || !mgd_dcfg()->blobdir
+           || *(mgd_dcfg()->blobdir) != '/') {
+               RETURN_FALSE_BECAUSE(MGD_ERR_INTERNAL);
+   }
+
+       res = mgd_sitegroup_record(mgd_handle(), "location", "blobs", id);
+
+       if (!res || !mgd_fetch(res)) {
+               if (res) { mgd_release(res); }
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+       }
+
+       location = mgd_colvalue(res, 0);
+
+       if (!location || !*location || strstr(location, "..")) {
+               mgd_release(res);
+
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+       }
+
+       pool = mgd_alloc_pool();
+       path =
+          mgd_format(mgd_handle(), pool, "$s/$s", mgd_dcfg()->blobdir,
+                     location);
+       stat(path, &blobstat);
+
+       if (array_init(return_value) == FAILURE) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_INTERNAL);
+       }
+       add_next_index_long(return_value, blobstat.st_dev);
+       add_next_index_long(return_value, blobstat.st_ino);
+       add_next_index_long(return_value, blobstat.st_mode);
+       add_next_index_long(return_value, blobstat.st_nlink);
+       add_next_index_long(return_value, blobstat.st_uid);
+       add_next_index_long(return_value, blobstat.st_gid);
+#ifdef HAVE_ST_BLKSIZE
+       add_next_index_long(return_value, blobstat.st_rdev);
+#else
+       add_next_index_long(return_value, -1);
+#endif
+       add_next_index_long(return_value, blobstat.st_size);
+       add_next_index_long(return_value, blobstat.st_atime);
+       add_next_index_long(return_value, blobstat.st_mtime);
+       add_next_index_long(return_value, blobstat.st_ctime);
+#ifdef HAVE_ST_BLKSIZE
+       add_next_index_long(return_value, blobstat.st_blksize);
+#else
+       add_next_index_long(return_value, -1);
+#endif
+#ifdef HAVE_ST_BLOCKS
+       add_next_index_long(return_value, blobstat.st_blocks);
+#else
+       add_next_index_long(return_value, -1);
+#endif
+}
+
+MGD_FUNCTION(delete_attachment)
+{
+       int pid;
+       int ptable;
+       const char *location;
+       char *path;
+       midgard_pool *pool;
+       midgard_res *res;
+       const char *blobdir;
+   long id;
+   zval *self, **zv_id;
+
+       CHECK_MGD;
+       RETVAL_FALSE;
+
+       switch (ZEND_NUM_ARGS()) {
+               case 0:
+         zv_id = NULL;
+         break;
+
+               case 1:
+                       if (zend_get_parameters_ex(1, &zv_id) != SUCCESS) 
+WRONG_PARAM_COUNT;
+         break;
+
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+   id = mgd_get_blob_id((self = getThis()), zv_id, NULL);
+   if (id == 0) { RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS); }
+   else if (id == MGD_ERR_INVALID_NAME) { WRONG_PARAM_COUNT; }
+   else if (id < 0) { RETURN_FALSE_BECAUSE(id); }
+
+       if (mgd_has_dependants(mgd_handle(), id, "blobs")) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+   }
+
+       blobdir = mgd_get_blobdir(mgd_handle());
+       if (!blobdir || *blobdir != '/') {
+               RETURN_FALSE_BECAUSE(MGD_ERR_INTERNAL);
+   }
+
+       res =
+          mgd_sitegroup_record(mgd_handle(), "ptable,pid,location", "blobs",
+                               id);
+
+       if (!res || !mgd_fetch(res)) {
+               if (res) { mgd_release(res); }
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+       }
+
+       ptable = mgd_lookup_table_id(mgd_colvalue(res, 0));
+       pid = mgd_sql2id(res, 1);
+       location = mgd_colvalue(res, 2);
+
+       if (strstr(location, "..") || !isglobalowner(ptable, pid)) {
+               mgd_release(res);
+
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       }
+
+       pool = mgd_alloc_pool();
+       path = mgd_format(mgd_handle(), pool, "$s/$s", blobdir, location);
+
+       if (unlink(path) == 0 || errno == ENOENT) {
+               php_midgard_delete(return_value, "blobs", id);
+               PHP_DELETE_REPLIGARD("blobs", id);
+       }
+
+       mgd_free_pool(pool);
+       mgd_release(res);
+}
+
+MGD_FUNCTION(update_attachment)
+{
+       zval **id, **name, **title, **mimetype, **score, **author, *self;
+       int ptable, pid;
+       midgard_res *res = NULL;
+       const char *location;
+       int sc, auth, calltype;
+   long aid;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+               case 6:
+                       if (zend_get_parameters_ex
+                           (6, &id, &name, &title, &mimetype, &score,
+                            &author) != SUCCESS) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       break;
+
+               case 5:
+                       if (zend_get_parameters_ex
+                           (5, &id, &name, &title, &mimetype,
+                            &score) != SUCCESS) {WRONG_PARAM_COUNT;
+                       }
+                       author = NULL;
+                       break;
+
+               case 4:
+                       if (zend_get_parameters_ex
+                           (4, &id, &name, &title, &mimetype) != SUCCESS) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       author = NULL;
+                       score = NULL;
+                       break;
+
+      case 0:
+         id = NULL;
+         break;
+
+               default:
+                       WRONG_PARAM_COUNT;
+                       break;
+       }
+
+   aid = mgd_get_blob_id((self = getThis()), id, &calltype);
+   if (aid == 0) { RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS); }
+   else if (aid == MGD_ERR_INVALID_NAME) { WRONG_PARAM_COUNT; }
+   else if (aid < 0) { RETURN_FALSE_BECAUSE(aid); }
+
+   if (calltype == MGD_BLOB_CALL_SELF) {
+      if (!MGD_PROPFIND(self, "name", name)
+            || !MGD_PROPFIND(self, "title", title)
+            || !MGD_PROPFIND(self, "mimetype", mimetype)) {
+         RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+      }
+
+      if (!MGD_PROPFIND(self, "author", author)) { author = NULL; }
+      if (!MGD_PROPFIND(self, "score", score)) { score = NULL; }
+   }
+
+       convert_to_string_ex(name);
+       convert_to_string_ex(title);
+       convert_to_string_ex(mimetype);
+
+       if (mgd_exists_bool(mgd_handle(), "blobs me, blobs other",
+                      "me.id=$d AND me.id<>other.id"
+                      " AND me.ptable=other.ptable AND me.pid=other.pid"
+                      " AND other.name=$q",
+                      aid, (*name)->value.str.val)) {
+      mgd_release(res);
+      RETURN_FALSE_BECAUSE(MGD_ERR_DUPLICATE);
+       }
+
+       res =
+          mgd_sitegroup_record(mgd_handle(), "ptable,pid,location", "blobs",
+                               aid);
+
+       if (!res || !mgd_fetch(res)) {
+               if (res) { mgd_release(res); }
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+       }
+
+       ptable = mgd_lookup_table_id(mgd_colvalue(res, 0));
+       pid = mgd_sql2id(res, 1);
+       location = mgd_colvalue(res, 2);
+
+       if (!isglobalowner(ptable, pid)) {
+               mgd_release(res);
+
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       }
+
+       if (score) {
+               convert_to_long_ex(score);
+               sc = (*score)->value.lval;
+       }
+       else
+               sc = 0;
+       if (author) {
+               convert_to_long_ex(author);
+               auth = (*author)->value.lval;
+       }
+       else
+               auth = 0;
+
+       php_midgard_update(return_value, "blobs",
+                          (author ?
+                           "name=$q,title=$q,mimetype=$q,score=$d,author=$d"
+                           : (score ? "name=$q,title=$q,mimetype=$q,score=$d" :
+                              "name=$q,title=$q,mimetype=$q")),
+                          aid, (*name)->value.str.val,
+                          (*title)->value.str.val, (*mimetype)->value.str.val,
+                          sc, auth);
+       PHP_UPDATE_REPLIGARD("blobs", aid);
+       mgd_release(res);
+}
+
+MidgardProperty MidgardAttachmentProperties [] = {
+       { IS_STRING,    "name"          },
+       { IS_STRING,    "title"         },
+       { IS_STRING,    "mimetype"      },
+       { IS_LONG,              "score"         },
+       { IS_STRING,    "ptable"        },
+       { IS_LONG,              "pid"           },
+       { IS_LONG,              "author"        },
+       { IS_LONG,              "created"       },
+       { 0,                    NULL            }
+};
+
+MIDGARD_HANDLERS_DECL(attachment)
+static zend_function_entry MidgardAttachmentMethods[] =
+   {
+//      MidgardAttachment class constructor
+//      PHP_FALIAS(midgardattachment,   mgd_ctor_attachment,  NULL)
+      PHP_FALIAS(update,   mgd_update_attachment,  NULL)
+      PHP_FALIAS(delete,   mgd_delete_attachment,  NULL)
+      PHP_FALIAS(stat,     mgd_stat_attachment,    NULL)
+      PHP_FALIAS(fetch,    mgd_oop_list_fetch,     NULL)
+      MIDGARD_OOP_PARAMETER_METHODS
+      MIDGARD_OOP_SITEGROUP_METHODS
+      { NULL, NULL, NULL }
+   };
+MidgardClass MidgardAttachment = {
+   "MidgardAttachment",
+   "blobs",
+   MidgardAttachmentMethods,
+   {},
+   mgd_attachment_call_function_handler,
+   mgd_attachment_get_property_handler,
+   mgd_attachment_set_property_handler,
+   MidgardAttachmentProperties,
+   NULL
+};
+MIDGARD_HANDLERS(MidgardAttachment, attachment)
Index: php4/ext/midgard/calendar.c
diff -u /dev/null php4/ext/midgard/calendar.c:1.3
--- /dev/null   Sat Feb 17 15:21:51 2001
+++ php4/ext/midgard/calendar.c Sat Feb 17 15:21:49 2001
@@ -0,0 +1,205 @@
+/* $Id: calendar.c,v 1.3 2001/02/17 23:21:49 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#define DATE_MAX 0x7FFFFFFF
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(list_topic_calendar_all)
+{
+    int *topics;
+    int typev = 0, startv = 0, stopv = 0;
+    const char *sortv = NULL;
+    zval **id, **startn, **stopn, **sortn, **typen;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    switch (ZEND_NUM_ARGS()) {
+       case 5:
+               if (zend_get_parameters_ex(5,
+                                                 &id, &startn, &stopn, &sortn, 
+&typen) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       convert_to_long_ex(startn);
+                       convert_to_long_ex(stopn);
+                       convert_to_string_ex(sortn);
+                       convert_to_long_ex(typen);
+                       typev = (*typen)->value.lval;
+                       sortv = article_sort((*sortn)->value.str.val);
+                       startv = (*startn)->value.lval;
+                       stopv = ((*stopn)->value.lval > 0) ? (*stopn)->value.lval : 
+DATE_MAX;
+                       break;
+               }
+       case 4:
+               if (zend_get_parameters_ex(4, &id, &startn, &stopn, &sortn) == 
+SUCCESS) {
+                       convert_to_long_ex(id);
+                       convert_to_long_ex(startn);
+                       convert_to_long_ex(stopn);
+                       convert_to_string_ex(sortn);
+                       typev = -1;
+                       sortv = article_sort((*sortn)->value.str.val);
+                       startv = (*startn)->value.lval;
+                       stopv = ((*stopn)->value.lval > 0) ? (*stopn)->value.lval : 
+DATE_MAX;
+                       break;
+               }
+       case 3:
+               if (zend_get_parameters_ex(3, &id, &startn, &stopn) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       convert_to_long_ex(startn);
+                       convert_to_long_ex(stopn);
+                       typev = -1;
+                       sortv = "article.calstart";
+                       startv = (*startn)->value.lval;
+                       stopv = ((*stopn)->value.lval > 0) ? (*stopn)->value.lval : 
+DATE_MAX;
+                       break;
+               }
+    case 2:
+               if (zend_get_parameters_ex(2, &id, &typen) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       convert_to_long_ex(typen);
+                       typev = (*typen)->value.lval;
+                       sortv = "article.calstart";
+                       startv = time(NULL);
+                       stopv = DATE_MAX;
+                       break;
+               }
+    case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       typev = -1;
+                       sortv = "article.calstart";
+                       startv = time(NULL);
+                       stopv = DATE_MAX;
+                       break;
+               }
+    default:
+               wrong_param_count();
+    }
+       
+    topics = mgd_tree(mgd_handle(), "topic", (*id)->value.lval, 0, NULL);
+       
+    if (typev == -1)
+           php_midgard_select(&MidgardArticle, return_value,
+                                          ARTICLE_SELECT "," ARTICLE_CALENDAR, 
+ARTICLE_FROM,
+                                          "article.topic IN $D AND author=person.id"
+                                          " AND article.up=0 AND 
+Unix_Timestamp(calstart)<$d"
+                                          " AND 24*60*60-1+Unix_timestamp("
+                                          "       Date_Add(calstart, INTERVAL caldays 
+DAY))>$d",
+                                          sortv, topics, stopv, startv);
+    else
+           php_midgard_select(&MidgardArticle, return_value,
+                                          ARTICLE_SELECT "," ARTICLE_CALENDAR, 
+ARTICLE_FROM,
+                                          "article.type=$d AND article.topic IN $D"
+                                          " AND author=person.id"
+                                          " AND article.up=0 AND 
+Unix_Timestamp(calstart)<$d"
+                                          " AND 24*60*60-1+Unix_timestamp("
+                                          "       Date_Add(calstart, INTERVAL caldays 
+DAY))>$d",
+                                          sortv, typev, topics, stopv, startv);
+}
+
+MGD_FUNCTION(list_topic_calendar_all_fast)
+{
+    int *topics;
+    int typev = 0, startv = 0, stopv = 0;
+    const char *sortv = NULL;
+    zval **id, **startn, **stopn, **sortn, **typen;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    switch (ZEND_NUM_ARGS()) {
+       case 5:
+               if (zend_get_parameters_ex(5,
+                                                 &id, &startn, &stopn, &sortn, 
+&typen) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       convert_to_long_ex(startn);
+                       convert_to_long_ex(stopn);
+                       convert_to_string_ex(sortn);
+                       convert_to_long_ex(typen);
+                       typev = (*typen)->value.lval;
+                       sortv = article_sort((*sortn)->value.str.val);
+                       startv = (*startn)->value.lval;
+                       stopv = ((*stopn)->value.lval > 0) ? (*stopn)->value.lval : 
+DATE_MAX;
+                       break;
+               }
+       case 4:
+               if (zend_get_parameters_ex(4, &id, &startn, &stopn, &sortn) == 
+SUCCESS) {
+                       convert_to_long_ex(id);
+                       convert_to_long_ex(startn);
+                       convert_to_long_ex(stopn);
+                       convert_to_string_ex(sortn);
+                       typev = -1;
+                       sortv = article_sort((*sortn)->value.str.val);
+                       startv = (*startn)->value.lval;
+                       stopv = ((*stopn)->value.lval > 0) ? (*stopn)->value.lval : 
+DATE_MAX;
+                       break;
+               }
+       case 3:
+               if (zend_get_parameters_ex(3, &id, &startn, &stopn) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       convert_to_long_ex(startn);
+                       convert_to_long_ex(stopn);
+                       typev = -1;
+                       sortv = "article.calstart";
+                       startv = (*startn)->value.lval;
+                       stopv = ((*stopn)->value.lval > 0) ? (*stopn)->value.lval : 
+DATE_MAX;
+                       break;
+               }
+    case 2:
+               if (zend_get_parameters_ex(2, &id, &typen) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       convert_to_long_ex(typen);
+                       typev = (*typen)->value.lval;
+                       sortv = "article.calstart";
+                       startv = time(NULL);
+                       stopv = DATE_MAX;
+                       break;
+               }
+    case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       typev = -1;
+                       sortv = "article.calstart";
+                       startv = time(NULL);
+                       stopv = DATE_MAX;
+                       break;
+               }
+    default:
+               wrong_param_count();
+    }
+       
+    topics = mgd_tree(mgd_handle(), "topic", (*id)->value.lval, 0, NULL);
+       
+    if (typev == -1)
+           php_midgard_select(&MidgardArticle, return_value, ARTICLE_SELECT_FAST "," 
+ARTICLE_CALENDAR,
+                                          ARTICLE_FROM_FAST,
+                                          "article.topic IN $D"
+                                          " AND article.up=0 AND 
+Unix_Timestamp(calstart)<$d"
+                                          " AND 24*60*60-1+Unix_timestamp("
+                                          "       Date_Add(calstart, INTERVAL caldays 
+DAY))>$d",
+                                          sortv, topics, stopv, startv);
+    else
+           php_midgard_select(&MidgardArticle, return_value, ARTICLE_SELECT_FAST "," 
+ARTICLE_CALENDAR,
+                                          ARTICLE_FROM_FAST,
+                                          "article.type=$d AND article.topic IN $D"
+                                          " AND article.up=0 AND 
+Unix_Timestamp(calstart)<$d"
+                                          " AND 24*60*60-1+Unix_timestamp("
+                                          "       Date_Add(calstart, INTERVAL caldays 
+DAY))>$d",
+                                          sortv, typev, topics, stopv, startv);
+}
Index: php4/ext/midgard/config.m4
diff -u /dev/null php4/ext/midgard/config.m4:1.5
--- /dev/null   Sat Feb 17 15:21:51 2001
+++ php4/ext/midgard/config.m4  Sat Feb 17 15:21:49 2001
@@ -0,0 +1,59 @@
+dnl $Id: config.m4,v 1.5 2001/02/17 23:21:49 emile Exp $
+
+dnl  Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+dnl  Copyright (C) 2000 The Midgard Project ry
+dnl  Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+dnl 
+dnl  This program is free software; you can redistribute it and/or modify it
+dnl  under the terms of the GNU Lesser General Public License as published
+dnl  by the Free Software Foundation; either version 2 of the License, or
+dnl  (at your option) any later version.
+dnl 
+dnl  This program is distributed in the hope that it will be useful,
+dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+dnl  GNU General Public License for more details.
+dnl 
+dnl  You should have received a copy of the GNU General Public License
+dnl  along with this program; if not, write to the Free Software
+dnl  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+AC_PROG_YACC
+AC_DECL_YYTEXT
+AC_PROG_LEX
+
+PHP_ARG_WITH(midgard, for midgard support,
+[  --with-midgard          Include midgard 1.4 support])
+
+if test "$PHP_MIDGARD" != "no"; then
+  if test "$PHP_MIDGARD" != "yes"; then
+    AC_ADD_LIBRARY_WITH_PATH(midgard, "$PHP_MIDGARD/lib", MIDGARD_SHARED_LIBADD)
+    AC_ADD_INCLUDE("$PHP_MIDGARD/include")
+  else
+    AC_ADD_LIBRARY(midgard)
+  fi
+  AC_DEFINE(HAVE_MIDGARD, 1, [ ])
+  PHP_EXTENSION(midgard, $ext_shared)
+
+dnl EEH/TODO: Add checks for apache-static compilation
+  AC_PATH_PROG(APXS, apxs)
+  if test -z $APXS; then
+    AC_MSG_ERROR(apxs not found.)
+  fi
+  APACHE_INCLUDES=`$APXS -q INCLUDEDIR`
+  AC_ADD_INCLUDE($APACHE_INCLUDES)
+  
+  AC_PATH_PROG(GLIBCONFIG, glib-config)
+  dnl Ackackack... why do people do this?
+  if test -z $GLIBCONFIG; then
+    AC_PATH_PROG(GLIBCONFIG, glib12-config)
+  fi
+  if test -z $GLIBCONFIG; then
+    AC_MSG_ERROR(glib-config not found. Did you install glib?)
+  fi
+  CFLAGS="$CFLAGS "`$GLIBCONFIG --cflags`
+  LIBS="$LIBS "`$GLIBCONFIG --libs`
+  LFLAGS="$LFLAGS -Pmgd -olex.yy.c"
+  
+  PHP_SUBST(GLIBCONFIG)
+fi
Index: php4/ext/midgard/element.c
diff -u /dev/null php4/ext/midgard/element.c:1.3
--- /dev/null   Sat Feb 17 15:21:51 2001
+++ php4/ext/midgard/element.c  Sat Feb 17 15:21:49 2001
@@ -0,0 +1,231 @@
+/* $Id: element.c,v 1.3 2001/02/17 23:21:49 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_access.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(list_elements)
+{
+       IDINIT;
+       CHECK_MGD;
+       php_midgard_select(&MidgardElement, return_value,
+                          "id,name", "element", "style=$d", "name", id);
+}
+
+MGD_FUNCTION(get_element)
+{
+       zval **id;
+       zval **style, **name;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+               case 0:
+                       php_midgard_bless(return_value, &MidgardElement);
+                       mgd_object_init(return_value, "id", "style", "name",
+                                        "value", NULL);
+                       return;
+               case 1:
+                       if (zend_get_parameters_ex(1, &id) != SUCCESS) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       convert_to_long_ex(id);
+
+                       php_midgard_get(&MidgardElement,
+                                       return_value,
+                                       "id,style,name,value",
+                                       "element", (*id)->value.lval);
+                       break;
+               case 2:
+                       if (zend_get_parameters_ex(2, &style, &name) != SUCCESS) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       convert_to_long_ex(style);
+                       convert_to_string_ex(name);
+                       php_midgard_get_by_name(&MidgardElement,
+                                               return_value,
+                                               "id,style,name,value",
+                                               "element", "style",
+                                               (*style)->value.lval,
+                                               (*name)->value.str.val);
+                       break;
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+}
+
+MGD_FUNCTION(get_element_by_name)
+{
+       /* EEH: just an alias for get_element */
+       php_if_mgd_get_element(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+MGD_FUNCTION(create_element)
+{
+       zval **style, **name, **value, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (!MGD_PROPFIND(self, "style", style)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "value", value)) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 3
+                   || zend_get_parameters_ex(3, &style, &name,
+                                             &value) == FAILURE) {
+                       WRONG_PARAM_COUNT;
+               }
+       }
+
+       convert_to_long_ex(style);
+       convert_to_string_ex(name);
+       convert_to_string_ex(value);
+
+       if (!(*style)->value.lval
+           || !mgd_exists_id(mgd_handle(), "style", "id=$d",
+                          (*style)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+
+       if (!isstyleowner((*style)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       if (mgd_exists_id(mgd_handle(), "element", "style=$d AND name=$q",
+                      (*style)->value.lval, (*name)->value.str.val))
+               RETURN_FALSE_BECAUSE(MGD_ERR_DUPLICATE);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* style must be in same SG or be 0 */
+       if ((*style)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "style",
+                                                    "id=$d AND sitegroup IN (0,$d)",
+                                                    (*style)->value.lval,
+                                                    mgd_sitegroup(mgd_handle
+                                                                  
+())))RETURN_FALSE_BECAUSE
+                  (MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+       php_midgard_create(return_value,
+                          "element", "style,name,value",
+                          "$d,$q,$q", (*style)->value.lval,
+                          (*name)->value.str.val, (*value)->value.str.val);
+       PHP_CREATE_REPLIGARD("element", return_value->value.lval);
+}
+
+MGD_FUNCTION(update_element)
+{
+       zval **id, **name, **value, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (!MGD_PROPFIND(self, "id", id)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "value", value)) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 3
+                   || zend_get_parameters_ex(3, &id, &name, &value) == FAILURE) {
+                       WRONG_PARAM_COUNT;
+               }
+       }
+       convert_to_long_ex(id);
+       convert_to_string_ex(name);
+       convert_to_string_ex(value);
+
+       if (!isstyleowner(mgd_idfield(mgd_handle(), "style", "element",
+                                     (*id)->value.lval)))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       php_midgard_update(return_value, "element", "name=$q,value=$q",
+                          (*id)->value.lval,
+                          (*name)->value.str.val, (*value)->value.str.val);
+       PHP_UPDATE_REPLIGARD("element", (*id)->value.lval);
+}
+
+MGD_FUNCTION(delete_element)
+{
+       IDINIT;
+       CHECK_MGD;
+       if (mgd_has_dependants(mgd_handle(), id, "element"))
+               RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+       if (!isstyleowner(mgd_idfield(mgd_handle(), "style", "element", id)))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       php_midgard_delete(return_value, "element", id);
+       PHP_DELETE_REPLIGARD("element", id);
+}
+
+MGD_FUNCTION(copy_element)
+{
+       zval **id, **newstyle;
+       RETVAL_FALSE;
+       CHECK_MGD;
+       switch (ZEND_NUM_ARGS()) {
+               case 2:
+                       if (zend_get_parameters_ex(2, &id, &newstyle) !=
+                           SUCCESS) WRONG_PARAM_COUNT;
+                       break;
+               case 1:
+                       if (zend_get_parameters_ex(1, &id) != SUCCESS)
+                               WRONG_PARAM_COUNT;
+                       newstyle = NULL;
+                       break;
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(id);
+       if (newstyle)
+               convert_to_long_ex(newstyle);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* newstyle must be in same SG or be 0 */
+       if (newstyle && !mgd_exists_bool(mgd_handle(), "style,element",
+                                   "style.id=$d AND element.id=$d"
+                                   " AND (style.sitegroup=element.sitegroup"
+                                   " OR style.sitegroup=0"
+                                   " OR element.sitegroup=0)",
+                                   (*newstyle)->value.lval, (*id)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+       RETVAL_LONG(mgd_copy_element(mgd_handle(), (*id)->value.lval,
+                                    newstyle ? (*newstyle)->value.lval : 0));
+
+}
+
+MGD_MOVE_FUNCTION(element, style, element, style)
+
+MidgardProperty MidgardElementProperties [] = {
+       { IS_LONG,              "style"         },
+       { IS_STRING,    "name"          },
+       { IS_STRING,    "value"         },
+       { 0,                    NULL            }
+};
+MIDGARD_CLASS(MidgardElement, element)
+
Index: php4/ext/midgard/event.c
diff -u /dev/null php4/ext/midgard/event.c:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/event.c    Sat Feb 17 15:21:49 2001
@@ -0,0 +1,865 @@
+/* $Id: event.c,v 1.3 2001/02/17 23:21:49 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+/* begin calendar functions */
+
+MGD_FUNCTION(is_event_owner)
+{
+    IDINIT;
+    CHECK_MGD;
+    RETVAL_LONG(iseventowner(id));
+}
+
+MGD_FUNCTION(create_event)
+{
+       zval **up, **start, **end, **title, **description;
+       zval **type, **extra, **owner, **busy, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "up", up)
+                   || !MGD_PROPFIND(self, "start", start)
+                   || !MGD_PROPFIND(self, "end", end)
+                   || !MGD_PROPFIND(self, "title", title)
+                   || !MGD_PROPFIND(self, "description", description)
+                   || !MGD_PROPFIND(self, "type", type)
+                   || !MGD_PROPFIND(self, "extra", extra)
+                   || !MGD_PROPFIND(self, "owner", owner)
+                   || !MGD_PROPFIND(self, "busy", busy)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 9
+                   || zend_get_parameters_ex(9, &up, &start, &end, &title,
+                                    &description, &type, &extra, &owner,
+                                    &busy) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(up);
+       convert_to_long_ex(start);
+       convert_to_long_ex(end);
+       convert_to_string_ex(title);
+       convert_to_string_ex(description);
+       convert_to_long_ex(type);
+       convert_to_string_ex(extra);
+       convert_to_long_ex(owner);
+       convert_to_boolean_ex(busy);
+
+       if ((*start)->value.lval > (*end)->value.lval)
+               RETURN_FALSE_BECAUSE(MGD_ERR_RANGE);
+
+       if ((*up)->value.lval && !iseventowner((*up)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* up must be in same SG or be 0 */
+       if ((*up)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "event",
+                                                 "id=$d AND sitegroup IN (0,$d)",
+                                                 (*up)->value.lval,
+                                                 mgd_sitegroup(mgd_handle())))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+       /* owner must be in same SG or be 0 */
+       /* TODO: should we in fact allow owner == 0 for non-root? */
+       if ((*owner)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "grp",
+                                                    "id=$d AND sitegroup IN (0,$d)",
+                                                    (*owner)->value.lval,
+                                                    mgd_sitegroup(mgd_handle())))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#else
+       if ((*up)->value.lval != 0
+           && !mgd_exists_id(mgd_handle(), "event", "id=$d",
+                             (*up)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+#endif
+
+       php_midgard_create(return_value, "event", "up,start,end,title,"
+                          
+"description,type,extra,owner,creator,created,revisor,revised,revision,busy",
+                          "$d,$d,$d,$q,$q,$d,$q,$d,$d,Now(),$d,Now(),0,$d",
+                          (*up)->value.lval, (*start)->value.lval, (*end)->value.lval,
+                          (*title)->value.str.val, (*description)->value.str.val,
+                          (*type)->value.lval, (*extra)->value.str.val,
+                          (*owner)->value.lval, mgd_user(mgd_handle()),
+                          mgd_user(mgd_handle()), (*busy)->value.lval);
+
+       PHP_CREATE_REPLIGARD("event", return_value->value.lval);
+}
+
+MGD_FUNCTION(update_event)
+{
+       zval **id, **start, **end, **title, **description;
+       zval **type, **extra, **owner, **busy, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "id", id)
+                   || !MGD_PROPFIND(self, "start", start)
+                   || !MGD_PROPFIND(self, "end", end)
+                   || !MGD_PROPFIND(self, "title", title)
+                   || !MGD_PROPFIND(self, "description", description)
+                   || !MGD_PROPFIND(self, "type", type)
+                   || !MGD_PROPFIND(self, "extra", extra)
+                   || !MGD_PROPFIND(self, "owner", owner)
+                   || !MGD_PROPFIND(self, "busy", busy)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 9
+                   || zend_get_parameters_ex(9, &id, &start, &end,
+                                    &title, &description, &type, &extra,
+                                    &owner, &busy) == FAILURE)
+
+                       WRONG_PARAM_COUNT;
+       }
+       convert_to_long_ex(id);
+       convert_to_long_ex(start);
+       convert_to_long_ex(end);
+       convert_to_string_ex(title);
+       convert_to_string_ex(description);
+       convert_to_long_ex(type);
+       convert_to_string_ex(extra);
+       convert_to_long_ex(owner);
+       convert_to_boolean_ex(busy);
+
+       if ((*start)->value.lval > (*end)->value.lval)
+               RETURN_FALSE_BECAUSE(MGD_ERR_RANGE);
+
+       if (!(*id)->value.lval || !iseventowner((*id)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* owner must be in same SG or be 0 */
+       /* should we in fact allow owner == 0 for non-root? */
+       if ((*owner)->value.lval != 0
+           && !mgd_exists_bool(mgd_handle(), "event,grp",
+                               "event.id=$d AND grp.id=$d"
+                               " AND (event.sitegroup=grp.sitegroup"
+                               " OR event.sitegroup=0"
+                               " OR grp.sitegroup=0)",
+                               (*id)->value.lval,
+                               (*owner)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+       php_midgard_update(return_value, "event",
+                          "start=$d,end=$d,title=$q,"
+                          
+"description=$q,type=$d,extra=$q,owner=$d,revisor=$d,revised=Now(),revision=revision+1,busy=$d",
+                          (*id)->value.lval,
+                          (*start)->value.lval, (*end)->value.lval,
+                          (*title)->value.str.val, (*description)->value.lval,
+                          (*type)->value.lval, (*extra)->value.str.val,
+                          (*owner)->value.lval, mgd_user(mgd_handle()),
+                          (*busy)->value.lval);
+       PHP_UPDATE_REPLIGARD("event", (*id)->value.lval);
+}
+
+MGD_FUNCTION(delete_event)
+{
+    IDINIT;
+       CHECK_MGD;
+    if(mgd_has_dependants(mgd_handle(),id,"event"))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+    if (mgd_exists_id(mgd_handle(), "event", "up=$d", id)
+        || mgd_exists_id(mgd_handle(), "eventmember", "eid=$d", id))
+               RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+       if (!id || !iseventowner(id))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       
+    php_midgard_delete(return_value, "event", id);
+    PHP_DELETE_REPLIGARD("event", id);
+}
+
+MGD_FUNCTION(delete_event_tree)
+{
+    IDINIT;
+    CHECK_MGD;
+    if (!iseventowner(mgd_idfield(mgd_handle(), "up", "event", id))) 
+RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+    if(mgd_delete_event(mgd_handle(),  id)) { RETURN_TRUE; }
+    RETURN_FALSE;
+}
+
+MGD_FUNCTION(get_event)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+               php_midgard_bless(return_value, &MidgardEvent);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+
+    php_midgard_get(&MidgardEvent, return_value, "id,up,start,end,title,description,"
+                       
+"type,extra,owner,creator,created,revisor,revised,revision,busy", 
+                                       "event", (*id)->value.lval);
+}
+
+static const char *event_sort(const char *order)
+{
+    static struct { const char *order, *sort; } sort[] = {
+               { "start", "event.start ASC" },
+               { "reverse start", "event.start DESC" },
+               { "alpha", "event.title ASC" },
+               { "reverse alpha", "event.title DESC" },
+               { "end", "event.end ASC" },
+               { "reverse end", "event.end DESC" },
+               { "up", "event.up ASC,event.id ASC" },
+               { "reverse up", "event.up DESC,event.id DESC" },
+               { "created", "event.created ASC" },
+               { NULL, "event.created DESC" }
+    };
+    int i;
+
+    for (i = 0; sort[i].order; i++)
+       if (strcmp(order, sort[i].order) == 0)
+           return sort[i].sort;
+
+    return sort[i].sort;
+}
+
+MGD_FUNCTION(list_events)
+{
+    const char *sortv;
+    int typev;
+    zval **id, **sortn, **typen;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    switch (ZEND_NUM_ARGS()) {
+    case 3:
+       if (zend_get_parameters_ex(3, &id, &sortn, &typen) == SUCCESS) {
+           convert_to_long_ex(id);
+           convert_to_string_ex(sortn);
+           convert_to_long_ex(typen);
+           sortv = event_sort((*sortn)->value.str.val);
+           typev = (*typen)->value.lval;
+           break;
+       }
+    case 2:
+       if (zend_get_parameters_ex(2, &id, &sortn) == SUCCESS) {
+           convert_to_long_ex(id);
+           convert_to_string_ex(sortn);
+           sortv = event_sort((*sortn)->value.str.val);
+           typev = -1;
+           break;
+       }
+    case 1:
+       if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+           convert_to_long_ex(id);
+           sortv = "event.id DESC";
+           typev = -1;
+           break;
+       }
+    default:
+       WRONG_PARAM_COUNT;
+    }
+
+    if (typev == -1)
+           php_midgard_select(&MidgardEvent, return_value, "id,up,start,end,title,"
+                                  "description,type,extra,owner,busy",
+                                                  "event", "event.up=$d",
+                                      sortv, (*id)->value.lval);
+    else
+           php_midgard_select(&MidgardEvent, return_value, "id,up,start,end,title,"
+                                  "description,type,extra,owner,busy",
+                                                  "event",
+                                      "event.type=$d AND event.up=$d",
+                                      sortv, typev, (*id)->value.lval);
+}
+
+MGD_FUNCTION(list_events_between)
+{
+    const char *sortv;
+    int typev;
+    zval **id, **sortn, **typen;
+    zval **start, **end;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    switch (ZEND_NUM_ARGS()) {
+    case 5:
+       if (zend_get_parameters_ex(5, &id, &start, &end, &sortn, &typen) == SUCCESS) {
+           convert_to_long_ex(id);
+           convert_to_long_ex(start);
+           convert_to_long_ex(end);
+           convert_to_string_ex(sortn);
+           convert_to_long_ex(typen);
+           sortv = event_sort((*sortn)->value.str.val);
+           typev = (*typen)->value.lval;
+           break;
+       }
+    case 4:
+       if (zend_get_parameters_ex(4, &id, &start, &end, &sortn) == SUCCESS) {
+           convert_to_long_ex(id);
+           convert_to_long_ex(start);
+           convert_to_long_ex(end);
+           convert_to_string_ex(sortn);
+           sortv = event_sort((*sortn)->value.str.val);
+           typev = -1;
+           break;
+       }
+    case 3:
+       if (zend_get_parameters_ex(3, &id, &start, &end) == SUCCESS) {
+           convert_to_long_ex(id);
+           convert_to_long_ex(start);
+           convert_to_long_ex(end);
+           sortv = "event.id DESC";
+           typev = -1;
+           break;
+       }
+    default:
+       WRONG_PARAM_COUNT;
+    }
+
+    if (typev == -1)
+           php_midgard_select(&MidgardEvent, return_value, "id,up,start,end,title,"
+                                  "description,type,extra,owner,busy",
+                                                  "event", "event.up=$d AND "
+                                                  "((event.start>=$d AND 
+event.start<=$d) OR "
+                                                  "(event.start<=$d AND 
+event.end>=$d) OR "
+                                                  "(event.end>=$d AND 
+event.end<=$d))",
+                                      sortv, (*id)->value.lval,
+                                                  
+(*start)->value.lval,(*end)->value.lval,
+                                                  
+(*start)->value.lval,(*end)->value.lval,
+                                                  
+(*start)->value.lval,(*end)->value.lval);
+    else
+           php_midgard_select(&MidgardEvent, return_value, "id,up,start,end,title,"
+                                  "description,type,extra,owner,busy",
+                                                  "event",
+                                      "event.type=$d AND event.up=$d AND "
+                                                  "((event.start>=$d AND 
+event.start<=$d) OR "
+                                                  "(event.start<=$d AND 
+event.end>=$d) OR "
+                                                  "(event.end>=$d AND 
+event.end<=$d))",
+                                      sortv, typev, (*id)->value.lval,
+                                                  
+(*start)->value.lval,(*end)->value.lval,
+                                                  
+(*start)->value.lval,(*end)->value.lval,
+                                                  
+(*start)->value.lval,(*end)->value.lval);
+}
+
+MGD_FUNCTION(list_events_all)
+{
+    int *events;
+    const char *sortv;
+    int typev;
+    zval **id, **sortn, **typen;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    switch (ZEND_NUM_ARGS()) {
+    case 3:
+       if (zend_get_parameters_ex(3, &id, &sortn, &typen) == SUCCESS) {
+           convert_to_long_ex(id);
+           convert_to_string_ex(sortn);
+           convert_to_long_ex(typen);
+           sortv = event_sort((*sortn)->value.str.val);
+           typev = (*typen)->value.lval;
+           break;
+       }
+    case 2:
+       if (zend_get_parameters_ex(2, &id, &sortn) == SUCCESS) {
+           convert_to_long_ex(id);
+           convert_to_string_ex(sortn);
+           sortv = event_sort((*sortn)->value.str.val);
+           typev = -1;
+           break;
+       }
+    case 1:
+       if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+           convert_to_long_ex(id);
+           sortv = "event.id DESC";
+           typev = -1;
+           break;
+       }
+    default:
+       WRONG_PARAM_COUNT;
+    }
+
+       if((*id)->value.lval) {
+               if(!(events = mgd_tree(mgd_handle(), "event", (*id)->value.lval, 0, 
+NULL)))
+                       RETURN_FALSE_BECAUSE(MGD_ERR_ERROR);
+       if (typev == -1)
+               php_midgard_select(&MidgardEvent, return_value, 
+"id,up,start,end,title,"
+                                          "description,type,extra,owner,busy",
+                                                          "event", "event.id IN $D",
+                                              sortv, events);
+       else
+               php_midgard_select(&MidgardEvent, return_value, 
+"id,up,start,end,title,"
+                                          "description,type,extra,owner,busy",
+                                                          "event",
+                                              "event.type=$d AND event.id IN $D",
+                                              sortv, typev, events);
+
+               free(events);
+       }
+       else {
+       if (typev == -1)
+               php_midgard_select(&MidgardEvent, return_value, 
+"id,up,start,end,title,"
+                                          "description,type,extra,owner,busy",
+                                                          "event", NULL, sortv);
+       else
+               php_midgard_select(&MidgardEvent, return_value, 
+"id,up,start,end,title,"
+                                          "description,type,extra,owner,busy",
+                                                          "event", "event.type=$d",
+                                              sortv, typev);
+       }
+}
+
+MGD_FUNCTION(list_events_all_between)
+{
+    int *events;
+    const char *sortv;
+    int typev;
+    zval **id, **sortn, **typen;
+    zval **start, **end;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    switch (ZEND_NUM_ARGS()) {
+    case 5:
+       if (zend_get_parameters_ex(5, &id, &start, &end, &sortn, &typen) == SUCCESS) {
+           convert_to_long_ex(id);
+           convert_to_long_ex(start);
+           convert_to_long_ex(end);
+           convert_to_string_ex(sortn);
+           convert_to_long_ex(typen);
+           sortv = event_sort((*sortn)->value.str.val);
+           typev = (*typen)->value.lval;
+           break;
+       }
+    case 4:
+       if (zend_get_parameters_ex(4, &id, &start, &end, &sortn) == SUCCESS) {
+           convert_to_long_ex(id);
+           convert_to_long_ex(start);
+           convert_to_long_ex(end);
+           convert_to_string_ex(sortn);
+           sortv = event_sort((*sortn)->value.str.val);
+           typev = -1;
+           break;
+       }
+    case 3:
+       if (zend_get_parameters_ex(3, &id, &start, &end) == SUCCESS) {
+           convert_to_long_ex(id);
+           convert_to_long_ex(start);
+           convert_to_long_ex(end);
+           sortv = "event.id DESC";
+           typev = -1;
+           break;
+       }
+    default:
+       WRONG_PARAM_COUNT;
+    }
+
+       if((*id)->value.lval) {
+               if(!(events = mgd_tree(mgd_handle(), "event", (*id)->value.lval, 0, 
+NULL)))
+                       RETURN_FALSE_BECAUSE(MGD_ERR_ERROR);
+           if (typev == -1)
+                   php_midgard_select(&MidgardEvent, return_value, 
+"id,up,start,end,title,"
+                                          "description,type,extra,owner,busy",
+                                                          "event", "event.id in $D 
+AND "
+                                                          "((event.start>=$d AND 
+event.start<=$d) OR "
+                                                          "(event.start<=$d AND 
+event.end>=$d) OR "
+                                                          "(event.end>=$d AND 
+event.end<=$d))",
+                                              sortv, events,
+                                                          
+(*start)->value.lval,(*end)->value.lval,
+                                                          
+(*start)->value.lval,(*end)->value.lval,
+                                                          
+(*start)->value.lval,(*end)->value.lval);
+           else
+                   php_midgard_select(&MidgardEvent, return_value, 
+"id,up,start,end,title,"
+                                          "description,type,extra,owner,busy",
+                                                          "event",
+                                              "event.type=$d AND event.id IN $D AND "
+                                                          "((event.start>=$d AND 
+event.start<=$d) OR "
+                                                          "(event.start<=$d AND 
+event.end>=$d) OR "
+                                                          "(event.end>=$d AND 
+event.end<=$d))",
+                                              sortv, typev, events,
+                                                          
+(*start)->value.lval,(*end)->value.lval,
+                                                          
+(*start)->value.lval,(*end)->value.lval,
+                                                          
+(*start)->value.lval,(*end)->value.lval);
+       } else {
+           if (typev == -1)
+                   php_midgard_select(&MidgardEvent, return_value, 
+"id,up,start,end,title,"
+                                          "description,type,extra,owner,busy",
+                                                          "event",
+                                                          "((event.start>=$d AND 
+event.start<=$d) OR "
+                                                          "(event.start<=$d AND 
+event.end>=$d) OR "
+                                                          "(event.end>=$d AND 
+event.end<=$d))",
+                                              sortv,
+                                                          
+(*start)->value.lval,(*end)->value.lval,
+                                                          
+(*start)->value.lval,(*end)->value.lval,
+                                                          
+(*start)->value.lval,(*end)->value.lval);
+               else
+                   php_midgard_select(&MidgardEvent, return_value, 
+"id,up,start,end,title,"
+                                          "description,type,extra,owner,busy",
+                                                          "event",
+                                              "event.type=$d AND "
+                                                          "((event.start>=$d AND 
+event.start<=$d) OR "
+                                                          "(event.start<=$d AND 
+event.end>=$d) OR "
+                                                          "(event.end>=$d AND 
+event.end<=$d))",
+                                              sortv, typev,
+                                                          
+(*start)->value.lval,(*end)->value.lval,
+                                                          
+(*start)->value.lval,(*end)->value.lval,
+                                                          
+(*start)->value.lval,(*end)->value.lval);
+       }
+}
+
+void php_midgard_select_count_event_in_month(zval *return_value,
+   const char *tables, const char *where,
+   struct tm *start, struct tm *end)
+{
+   midgard_res *res=NULL;
+       zval day;
+       struct { int total; int both; int start; int end; int none; } days[31];
+       struct tm s,e;
+       time_t tss,tse,tsstart,tsend;
+       int i;
+
+    RETVAL_FALSE;
+
+       res = mgd_query(mgd_handle(),"SELECT start, end FROM $s WHERE $s",
+                                tables, where);
+       if(res) {
+               array_init(return_value);
+               add_assoc_long(return_value,"total",mgd_rows(res));
+               for(i=0;i<31;i++)
+               {
+                       days[i].total=0;
+                       days[i].both=0;
+                       days[i].start=0;
+                       days[i].end=0;
+                       days[i].none=0;
+               }
+               while(mgd_fetch(res))
+               {
+                       tss=mgd_sql2int(res,EVENT_START);
+                       tse=mgd_sql2int(res,EVENT_END);
+                       tsstart=mktime(start);
+                       tsend=mktime(end);
+                       memcpy((void *)&s,(void *)localtime(&tss),sizeof(s));
+                       memcpy((void *)&e,(void *)localtime(&tse),sizeof(e));
+                       if(tss<tsstart && tse>tsend)
+                       {
+                               for(i=start->tm_mday;i<=end->tm_mday;i++)
+                               {
+                                       days[i].none++;
+                                       days[i].total++;
+                               }
+                               continue;
+                       }
+                       if(tss<tsend && tse>tsend)
+                       {
+                               days[s.tm_mday].start++;
+                               days[s.tm_mday].total++;
+                               for(i=s.tm_mday+1;i<=end->tm_mday;i++)
+                               {
+                                       days[i].none++;
+                                       days[i].total++;
+                               }
+                               continue;
+                       }
+                       if(tss<tsstart && tse>tsstart)
+                       {
+                               days[e.tm_mday].end++;
+                               days[e.tm_mday].total++;
+                               for(i=start->tm_mday;i<e.tm_mday;i++)
+                               {
+                                       days[i].none++;
+                                       days[i].total++;
+                               }
+                               continue;
+                       }
+                       if(tss>=tsstart && tss<=tsend && tse<=tsend)
+                       {
+                               if ( s.tm_mday == e.tm_mday 
+                                 && s.tm_mon  == e.tm_mon 
+                                 && s.tm_year == e.tm_year)
+                               {
+                                       days[s.tm_mday].both++;
+                                       days[s.tm_mday].start++;
+                                       days[e.tm_mday].end++;
+                                       days[e.tm_mday].total++;
+                               }
+                               else
+                               {
+                                       days[s.tm_mday].start++;
+                                       days[s.tm_mday].total++;
+                                       days[e.tm_mday].end++;
+                                       days[e.tm_mday].total++;
+                                       for(i=s.tm_mday+1;i<e.tm_mday;i++)
+                                       {
+                                               days[i].none++;
+                                               days[i].total++;
+                                       }
+                               }
+                       }
+               }
+               for(i=1;i<=end->tm_mday;i++)
+               {
+                       array_init(&day);
+                       add_assoc_long(&day,"total",days[i].total);
+                       add_assoc_long(&day,"both",days[i].both);
+                       add_assoc_long(&day,"start",days[i].start);
+                       add_assoc_long(&day,"end",days[i].end);
+                       add_assoc_long(&day,"none",days[i].none);
+                       zend_hash_index_update(return_value->value.ht,i,
+                                                        &day,sizeof(pval),NULL);
+               }
+               mgd_release(res);
+    }
+       else {
+               array_init(return_value);
+               add_assoc_long(return_value,"total",0);
+       }
+}
+
+MGD_FUNCTION(count_events_in_period)
+{
+    midgard_res *res;
+    zval **startn, **endn, **uidn, **typen;
+    const char *table=EVENT_COUNT_TABLE;
+    char *where;
+    midgard_pool *pool=NULL;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    switch (ZEND_NUM_ARGS()) {
+    case 4:
+       if (zend_get_parameters_ex(4, &startn, &endn, &uidn, &typen) == SUCCESS) {
+               convert_to_long_ex(startn);
+               convert_to_long_ex(endn);
+           convert_to_long_ex(uidn);
+           convert_to_long_ex(typen);
+               pool=mgd_alloc_pool();
+               if((*uidn)->value.lval<=0)
+                       where=mgd_format(mgd_handle(),pool,EVENT_COUNT_WHERE_43,
+                                        (*startn)->value.lval,(*endn)->value.lval,
+                                                        (*typen)->value.lval
+#if HAVE_MIDGARD_SITEGROUPS
+                                                        ,mgd_sitegroup(mgd_handle())
+#endif                                                  
+                                                        );
+               else {
+                       table=EVENT_COUNT_TABLE_2;
+                       where=mgd_format(mgd_handle(),pool,EVENT_COUNT_WHERE_4,
+                                        (*startn)->value.lval,(*endn)->value.lval,
+                                                        
+(*uidn)->value.lval,(*typen)->value.lval
+#if HAVE_MIDGARD_SITEGROUPS
+                                                        
+,mgd_sitegroup(mgd_handle()),mgd_sitegroup(mgd_handle())
+#endif                                                  
+                                                        );
+               }
+           break;
+       }
+    case 3:
+       if (zend_get_parameters_ex(3, &startn, &endn, &uidn) == SUCCESS) {
+               convert_to_long_ex(startn);
+               convert_to_long_ex(endn);
+           convert_to_long_ex(uidn);
+               pool=mgd_alloc_pool();
+               where=mgd_format(mgd_handle(),pool,EVENT_COUNT_WHERE_3,
+                                (*startn)->value.lval,(*endn)->value.lval,
+                                                (*uidn)->value.lval
+#if HAVE_MIDGARD_SITEGROUPS
+                                                ,mgd_sitegroup(mgd_handle())
+#endif                                          
+                                                );
+           break;
+       }
+    case 2:
+       if (zend_get_parameters_ex(2, &startn, &endn) == SUCCESS) {
+               convert_to_long_ex(startn);
+               convert_to_long_ex(endn);
+               pool=mgd_alloc_pool();
+               where=mgd_format(mgd_handle(),pool,EVENT_COUNT_WHERE_2,
+                                (*startn)->value.lval,(*endn)->value.lval
+#if HAVE_MIDGARD_SITEGROUPS
+                                                ,mgd_sitegroup(mgd_handle())
+#endif                                          
+                                                );
+           break;
+       }
+    case 1:
+       if (zend_get_parameters_ex(1, &endn) == SUCCESS) {
+               convert_to_long_ex(endn);
+               pool=mgd_alloc_pool();
+               where=mgd_format(mgd_handle(),pool,EVENT_COUNT_WHERE_1,
+                                (*endn)->value.lval
+#if HAVE_MIDGARD_SITEGROUPS
+                                                ,mgd_sitegroup(mgd_handle())
+#endif                                          
+                                                );
+           break;
+       }
+    case 0:
+               pool=mgd_alloc_pool();
+#if HAVE_MIDGARD_SITEGROUPS
+               where=mgd_format(mgd_handle(),pool,EVENT_COUNT_WHERE_0,
+                                mgd_sitegroup(mgd_handle()));
+#else                                           
+               where=EVENT_COUNT_WHERE_0;
+#endif                                          
+           break;
+    default:
+               WRONG_PARAM_COUNT;
+    }
+       res = mgd_query(mgd_handle(),"SELECT count(*) FROM $s WHERE $s",
+                                table, where);
+       if(res && mgd_fetch(res)) {
+               RETVAL_LONG(mgd_sql2int(res,0));
+               mgd_release(res);
+       }
+       if(pool!=NULL)
+               mgd_free_pool(pool);
+}
+
+MGD_FUNCTION(count_events_in_month)
+{
+    zval **monthn, **yearn, **typen;
+    char *where;
+    midgard_pool *pool=NULL;
+    struct tm start,end;
+    time_t tsstart,tsend;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    switch (ZEND_NUM_ARGS()) {
+    case 3:
+       if (zend_get_parameters_ex(3, &monthn, &yearn, &typen) == SUCCESS) {
+               convert_to_long_ex(monthn);
+               convert_to_long_ex(yearn);
+           convert_to_long_ex(typen);
+           break;
+       }
+    case 2:
+       if (zend_get_parameters_ex(2, &monthn, &yearn) == SUCCESS) {
+               convert_to_long_ex(monthn);
+               convert_to_long_ex(yearn);
+           break;
+       }
+    default:
+               WRONG_PARAM_COUNT;
+    }
+       start.tm_year=end.tm_year=(*yearn)->value.lval-1900;
+       start.tm_mon=(*monthn)->value.lval-1; end.tm_mon=(*monthn)->value.lval;
+       start.tm_mday=end.tm_mday=1;
+       start.tm_hour=end.tm_hour=0;
+       start.tm_min=end.tm_min=0;
+       start.tm_sec=0; end.tm_sec=-1;
+       tsstart=mktime(&start);
+       tsend=mktime(&end);
+       memcpy((void *)&end,(void *)localtime(&tsend),sizeof(end));
+    pool=mgd_alloc_pool();
+       if(ZEND_NUM_ARGS()==3) {
+               where=mgd_format(mgd_handle(),pool,EVENT_MONTH_WHERE_TYPE,
+                                                tsstart,tsend,
+                                                tsstart,tsend,
+                                                tsstart,tsend,
+                                                (*typen)->value.lval
+#if HAVE_MIDGARD_SITEGROUPS
+                                                ,mgd_sitegroup(mgd_handle())
+#endif
+                                                );
+       } else {
+               where=mgd_format(mgd_handle(),pool,EVENT_MONTH_WHERE,
+                                                tsstart,tsend,
+                                                tsstart,tsend,
+                                                tsstart,tsend
+#if HAVE_MIDGARD_SITEGROUPS
+                                                ,mgd_sitegroup(mgd_handle())
+#endif
+                                                );
+       }
+       php_midgard_select_count_event_in_month(return_value,
+      "event", where, &start, &end);
+       if(pool!=NULL)
+               mgd_free_pool(pool);
+}
+
+MGD_FUNCTION(copy_event)
+{
+    zval **id, **root; int id_r;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    if (ZEND_NUM_ARGS() != 2
+       || zend_get_parameters_ex(2, &id, &root) != SUCCESS)
+       WRONG_PARAM_COUNT;
+    convert_to_long_ex(id);
+    convert_to_long_ex(root);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* root must be in same SG or be 0 */
+       if ((*root)->value.lval != 0 && !mgd_exists_bool(mgd_handle(), "event src, 
+event tgt",
+                                                                               
+"src.id=$d AND tgt.id=$d"
+                                                                               " AND 
+(src.sitegroup=tgt.sitegroup"
+                                                                                      
+ " OR src.sitegroup=0"
+                                                                                      
+ " OR tgt.sitegroup=0)",
+                                                                               
+(*id)->value.lval,(*root)->value.lval)) 
+RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+    id_r = mgd_copy_event(mgd_handle(),  (*id)->value.lval);
+    if(id_r) {
+      php_midgard_update(return_value, "event", "up=$i", id_r, (*root)->value.lval);
+      PHP_UPDATE_REPLIGARD("event",id_r);
+    }
+}
+
+MGD_MOVE_FUNCTION(event,event,event,up);
+
+MidgardProperty MidgardEventProperties [] = {
+       { IS_LONG,              "up"                    },
+       { IS_LONG,              "start"                 },
+       { IS_LONG,              "end"                   },
+       { IS_STRING,    "title"                 },
+       { IS_STRING,    "description"   },
+       { IS_LONG,              "type"                  },
+       { IS_STRING,    "extra"                 },
+       { IS_LONG,              "owner"                 },
+       { IS_LONG,              "busy"                  },
+       { 0,                    NULL                    }
+};
+MIDGARD_CLASS(MidgardEvent, event)
Index: php4/ext/midgard/eventmember.c
diff -u /dev/null php4/ext/midgard/eventmember.c:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/eventmember.c      Sat Feb 17 15:21:50 2001
@@ -0,0 +1,293 @@
+/* $Id: eventmember.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+int event_collides(int first, int second)
+{
+    midgard_res *res;
+    int s1,s2,e1,e2;
+    const char query[]="SELECT start,end FROM event WHERE id=$d AND busy=1";
+
+    if((res = mgd_query(mgd_handle(),query,first)) && mgd_fetch(res))
+       {
+        s1=mgd_sql2int(res, 0);
+        e1=mgd_sql2int(res, 1);
+       }
+       else
+               return 0;
+    mgd_release(res);
+
+    if((res = mgd_query(mgd_handle(),query,second)) && mgd_fetch(res))
+       {
+        s2=mgd_sql2int(res, 0);
+        e2=mgd_sql2int(res, 1);
+       }
+       else
+               return 0;
+    mgd_release(res);
+
+       if(s1>=e2 || e1<=s2)
+           return 0;
+       else
+               return 1;
+}
+
+MGD_FUNCTION(create_event_member)
+{
+       midgard_res *res;
+       const char query[] = "SELECT eid FROM eventmember WHERE uid=$d";
+       zval **eid, **uid, **extra, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "eid", eid)
+                   || !MGD_PROPFIND(self, "uid", uid)
+                   || !MGD_PROPFIND(self, "extra", extra)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 3
+                   || zend_get_parameters_ex(3, &eid, &uid, &extra) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(eid);
+       convert_to_long_ex(uid);
+       convert_to_string_ex(extra);
+
+       /* event must exist and be in the same sitegroup as the current sitegroup
+        */
+       if (!mgd_exists_id(mgd_handle(), "event", "id=$d", (*eid)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+
+       /* person must exist and be in the same sitegroup as the current sitegroup
+        */
+       if (!mgd_exists_id(mgd_handle(), "person", "id=$d", (*uid)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+
+       if (!iseventowner((*eid)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       /* check collision if event is marked as busy */
+       if (mgd_exists_id
+           (mgd_handle(), "event", "id=$d AND busy=1", (*eid)->value.lval)) {
+               if ((res = mgd_query(mgd_handle(), query, (*uid)->value.lval))) {
+                       while (mgd_fetch(res)) {
+                               if (event_collides
+                                   ((*eid)->value.lval, mgd_sql2int(res, 0))) {
+                                       mgd_release(res);
+                                       RETURN_FALSE_BECAUSE(MGD_ERR_ERROR);
+                               }
+                       }
+                       mgd_release(res);
+               }
+       }
+       php_midgard_create(return_value, "eventmember", "eid,uid,extra",
+                          "$d,$d,$q", (*eid)->value.lval,
+                          (*uid)->value.lval, (*extra)->value.str.val);
+
+       PHP_CREATE_REPLIGARD("eventmember", return_value->value.lval);
+}
+
+MGD_FUNCTION(update_event_member)
+{
+       zval **id, **extra, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "id", id)
+                   || !MGD_PROPFIND(self, "extra", extra)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 2
+                   || zend_get_parameters_ex(2, &id, &extra) == FAILURE)
+                          WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(id);
+       convert_to_string_ex(extra);
+
+       /* event member must exist and be in the same sitegroup as the current 
+sitegroup
+        */
+       if (!mgd_exists_id(mgd_handle(), "eventmember", "id=$d", (*id)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+
+       if (!iseventowner
+           (mgd_idfield(mgd_handle(), "eid", "eventmember", (*id)->value.lval)))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       php_midgard_update(return_value, "eventmember",
+                          "extra=$q", (*id)->value.lval, (*extra)->value.str.val);
+       PHP_UPDATE_REPLIGARD("eventmember", (*id)->value.lval);
+}
+
+MGD_FUNCTION(delete_event_member)
+{
+    IDINIT;
+       CHECK_MGD;
+    if(mgd_has_dependants(mgd_handle(),id,"eventmember"))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+       if(!iseventowner(mgd_idfield(mgd_handle(), "eid", "eventmember", id)) && 
+mgd_user(mgd_handle())!=mgd_idfield(mgd_handle(), "uid", "eventmember", id)) 
+RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+    php_midgard_delete(return_value, "eventmember", id);
+    PHP_DELETE_REPLIGARD("eventmember", id);
+}
+
+MGD_FUNCTION(get_event_member)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+               php_midgard_bless(return_value, &MidgardEventMember);
+               mgd_object_init(return_value, "eid", "uid", "extra", NULL);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+
+    php_midgard_get(&MidgardEventMember, return_value, "id,eid,uid,extra",
+                                       "eventmember", (*id)->value.lval);
+}
+
+static const char *eventmember_sort(const char *order)
+{
+    static struct { const char *order, *sort; } sort[] = {
+               { "username", "username ASC" },
+               { "reverse username", "username DESC" },
+               { "reverse rname", "rname DESC" },
+               { "name", "name ASC" },
+               { "reverse name", "name DESC" },
+               { NULL, "rname ASC" }
+    };
+    int i;
+
+    for (i = 0; sort[i].order; i++)
+       if (strcmp(order, sort[i].order) == 0)
+           return sort[i].sort;
+
+    return sort[i].sort;
+}
+
+
+MGD_FUNCTION(list_event_members)
+{
+    const char *sortv;
+    zval **id, **sortn;
+    char *query;
+       midgard_pool *pool;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    switch (ZEND_NUM_ARGS()) {
+    case 2:
+       if (zend_get_parameters_ex(2, &id, &sortn) == SUCCESS) {
+           convert_to_long_ex(id);
+           convert_to_string_ex(sortn);
+           sortv = eventmember_sort((*sortn)->value.str.val);
+           break;
+       }
+    case 1:
+       if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+           convert_to_long_ex(id);
+           sortv = "rname";
+           break;
+       }
+    default:
+       WRONG_PARAM_COUNT;
+    }
+
+    if (mgd_isadmin(mgd_handle())) {
+       php_midgard_select(&MidgardEventMember, return_value, 
+                                                  "eventmember.id AS 
+id,eid,uid,eventmember.extra"
+                                      ", " EMAIL_FIELDS ", " NAME_FIELDS
+                                  , "eventmember,person",
+                                  "eid=$d AND person.id=eventmember.uid", 
+                                                  sortv, (*id)->value.lval);
+       }
+       else {
+               pool=mgd_alloc_pool();
+               query=mgd_format(mgd_handle(),pool, 
+                                "eventmember.id AS id,eid,uid,eventmember.extra"
+                                ", " NAME_FIELDS ", " EVENT_PUBLIC_FIELD(16,email)
+                                    ", " EVENT_EMAIL_FIELD
+                         ,mgd_user(mgd_handle()), mgd_user(mgd_handle()));
+       php_midgard_select(&MidgardEventMember, return_value, query, 
+"eventmember,person",
+                                  "eid=$d AND person.id=eventmember.uid", 
+                                                  sortv, (*id)->value.lval);
+               
+       }
+}
+
+MGD_FUNCTION(count_event_members)
+{
+    midgard_res *res;
+
+    IDINIT;
+       CHECK_MGD;
+
+   RETVAL_FALSE;
+
+       res = mgd_query(mgd_handle(),"SELECT count(*) FROM $s WHERE eid=$d"
+                              EVENT_SITEGROUP, "eventmember" , id
+#if HAVE_MIDGARD_SITEGROUPS
+                                                ,mgd_sitegroup(mgd_handle())
+#endif                                          
+                                                );
+       if(res && mgd_fetch(res)) {
+               RETVAL_LONG(mgd_sql2int(res,0));
+               mgd_release(res);
+       }
+}
+
+/* end calendar functions */
+
+MidgardProperty MidgardEventMemberProperties [] = {
+       { IS_LONG,              "eid"           },
+       { IS_LONG,              "uid"           },
+       { IS_STRING,    "extra"         },
+       { 0,                    NULL            }
+};
+MIDGARD_CLASS(MidgardEventMember, event_member)
Index: php4/ext/midgard/file.c
diff -u /dev/null php4/ext/midgard/file.c:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/file.c     Sat Feb 17 15:21:50 2001
@@ -0,0 +1,165 @@
+/* $Id: file.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(list_files)
+{
+       IDINIT;
+       CHECK_MGD;
+       php_midgard_select(&MidgardFile, return_value, 
+"id,article,type,name,content,size,md5", "file", "article=$d", "name", id);
+}
+
+MGD_FUNCTION(get_file)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+       php_midgard_bless(return_value, &MidgardFile);
+       mgd_object_init(return_value, "article", "type", "name", "content", "size", 
+"md5", NULL);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+       php_midgard_get(&MidgardFile, return_value, 
+"id,article,type,name,content,size,md5", "file", (*id)->value.lval);
+}
+
+MGD_FUNCTION(create_file)
+{
+       zval **article, **type, **name, **content, **size, **md5, *self;
+       
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+   if ((self = getThis()) != NULL) {
+      if (ZEND_NUM_ARGS() != 0) { WRONG_PARAM_COUNT; }
+
+      if (!MGD_PROPFIND(self, "article", article)
+            || !MGD_PROPFIND(self, "type", type)
+            || !MGD_PROPFIND(self, "name", name)
+            || !MGD_PROPFIND(self, "content", content)
+            || !MGD_PROPFIND(self, "size", size)
+            || !MGD_PROPFIND(self, "md5", md5)
+            ) {
+         RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+      }
+   } else {
+          if (ZEND_NUM_ARGS() != 6
+           || zend_get_parameters_ex(6, &article, &type, &name,
+                            &content, &size, &md5) != SUCCESS)
+               WRONG_PARAM_COUNT;
+   }
+
+       convert_to_long_ex(article);
+       convert_to_string_ex(type);
+       convert_to_string_ex(name);
+       convert_to_string_ex(content);
+       convert_to_long_ex(size);
+       convert_to_string_ex(md5);
+       
+       if (!isarticleowner((*article)->value.lval)) 
+RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       
+#if HAVE_MIDGARD_SITEGROUPS
+       /* article must be in same SG */
+       if (!mgd_exists_id(mgd_handle(), "article", "id=$d",
+                                                                               
+(*article)->value.lval)) RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+       php_midgard_create(return_value, "file",
+                      "article,type,name,content,size,md5",
+                      "$d,$q,$q,$q,$d,$q", (*article)->value.lval,
+                      (*type)->value.str.val, (*name)->value.str.val,
+                      (*content)->value.str.val, (*size)->value.lval,
+                      (*md5)->value.str.val);
+
+       PHP_CREATE_REPLIGARD("file", return_value->value.lval);
+}
+
+MGD_FUNCTION(update_file)
+{
+       zval **id, **type, **name, **content, *self;
+       
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+   if ((self = getThis()) != NULL) {
+      if (ZEND_NUM_ARGS() != 0) { WRONG_PARAM_COUNT; }
+
+      if (!MGD_PROPFIND(self, "id", id)
+            || !MGD_PROPFIND(self, "type", type)
+            || !MGD_PROPFIND(self, "name", name)
+            || !MGD_PROPFIND(self, "content", content)
+            ) {
+         RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+      }
+   } else {
+          if (ZEND_NUM_ARGS() != 4
+           || zend_get_parameters_ex(4,
+                                                &id, &type, &name, &content) != 
+SUCCESS)
+               WRONG_PARAM_COUNT;
+   }
+
+       convert_to_long_ex(id);
+       convert_to_string_ex(type);
+       convert_to_string_ex(name);
+       convert_to_string_ex(content);
+       
+       if (!isarticleowner(mgd_idfield(mgd_handle(), "article", "file",
+                                                                       
+(*id)->value.lval)))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       
+       php_midgard_update(return_value, "file", "type=$q,name=$q,content=$q",
+                      (*id)->value.lval, (*type)->value.str.val,
+                      (*name)->value.str.val, (*content)->value.str.val);
+       PHP_UPDATE_REPLIGARD("file",(*id)->value.lval);
+}
+
+MGD_FUNCTION(delete_file)
+{
+       IDINIT;
+       CHECK_MGD;
+    if(mgd_has_dependants(mgd_handle(),id,"file"))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+       if (!isarticleowner(mgd_idfield(mgd_handle(), "article", "file", id)))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       php_midgard_delete(return_value, "file", id);
+       PHP_DELETE_REPLIGARD("file", id);
+}
+
+MidgardProperty MidgardFileProperties [] = {
+       { IS_LONG,              "article"       },
+       { IS_STRING,    "name"          },
+       { IS_STRING,    "type"          },
+       { IS_STRING,    "content"       },
+       { IS_STRING,    "md5"           },
+       { IS_LONG,              "size"          },
+       { 0,                    NULL            }
+};
+
+MIDGARD_CLASS(MidgardFile, file)
Index: php4/ext/midgard/group.c
diff -u /dev/null php4/ext/midgard/group.c:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/group.c    Sat Feb 17 15:21:50 2001
@@ -0,0 +1,306 @@
+/* $Id: group.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(is_group_owner)
+{
+    IDINIT;
+       CHECK_MGD;
+    RETVAL_LONG(isgroupowner(id));
+}
+
+MGD_FUNCTION(list_groups)
+{
+       zval **id;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+               php_midgard_select(&MidgardGroup, return_value,
+         "id,name,official", "grp", NULL, "name"); 
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+       if((*id)->value.lval && !mgd_exists_id(mgd_handle(), "grp", "id=$d", 
+(*id)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+       php_midgard_select(&MidgardGroup, return_value, "id,name,official", "grp", 
+"owner=$d", "name",(*id)->value.lval); 
+}
+
+MGD_FUNCTION(get_group)
+{
+       zval **id;
+       CHECK_MGD;
+
+       RETVAL_FALSE;
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+      php_midgard_bless(return_value, &MidgardGroup);
+      mgd_object_init(return_value, "name", "official", "street", "postcode", "city", 
+"homepage", "email", "extra", "owner", NULL);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+
+    php_midgard_get(&MidgardGroup, return_value, "id,name,official," ADDRESS_FIELDS 
+","
+                                       GROUP_HOMEPAGE_FIELDS "," GROUP_EMAIL_FIELDS 
+","
+                                       "extra,owner", "grp", (*id)->value.lval);
+}
+
+MGD_FUNCTION(get_group_by_name)
+{
+       zval **id, **name;
+       int gid=0;
+       CHECK_MGD;
+
+       RETVAL_FALSE;
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+               php_midgard_bless(return_value, &MidgardGroup);
+               mgd_object_init(return_value, "name", "official", "street",
+                   "postcode", "city", "homepage", "email",
+                   "extra", "owner", NULL);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &name) == SUCCESS) {
+                       convert_to_string_ex(name);
+                       
+if(!(gid=mgd_exists_id(mgd_handle(),"grp","name=$q",(*name)->value.str.val)))
+                           RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+            php_midgard_get(&MidgardGroup, return_value, "id,name,official," 
+ADDRESS_FIELDS ","
+                                       GROUP_HOMEPAGE_FIELDS "," GROUP_EMAIL_FIELDS 
+","
+                                       "extra,owner", "grp", gid);
+                       break;
+               } 
+       case 2:
+               if (zend_get_parameters_ex(2, &id, &name) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       gid=(*id)->value.lval;
+                       convert_to_string_ex(name);
+            php_midgard_get_by_name(&MidgardGroup, return_value, "id,name,official,"
+                                       ADDRESS_FIELDS ","
+                                       GROUP_HOMEPAGE_FIELDS "," GROUP_EMAIL_FIELDS 
+","
+                                       "extra,owner", "grp", "owner", gid, 
+(*name)->value.str.val);
+                       
+gid=mgd_exists_id(mgd_handle(),"grp","name=$q",(*name)->value.str.val);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+}
+
+MGD_FUNCTION(create_group)
+{
+       zval **name, **official, **street, **postcode, **city;
+       zval **homepage, **email, **extra, **owner;
+       zval *self = NULL;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "official", official)
+                   || !MGD_PROPFIND(self, "street", street)
+                   || !MGD_PROPFIND(self, "postcode", postcode)
+                   || !MGD_PROPFIND(self, "city", city)
+                   || !MGD_PROPFIND(self, "homepage", homepage)
+                   || !MGD_PROPFIND(self, "email", email)
+                   || !MGD_PROPFIND(self, "extra", extra)
+                   || !MGD_PROPFIND(self, "owner", owner)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 9
+                   || zend_get_parameters_ex(9, &name, &official, &street,
+                                    &postcode, &city, &homepage, &email,
+                                    &extra, &owner) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_string_ex(name);
+       convert_to_string_ex(official);
+       convert_to_string_ex(street);
+       convert_to_string_ex(postcode);
+       convert_to_string_ex(city);
+       convert_to_string_ex(homepage);
+       convert_to_string_ex(email);
+       convert_to_string_ex(extra);
+       convert_to_long_ex(owner);
+
+#if HAVE_MIDGARD_SITEGROUPS
+//   Creating a group in SG0 is needed in Asgard to avoid reloging twice
+//   Note: creating a group in SG0  is absolutely useless outside of Asgard.
+//   if (mgd_sitegroup(mgd_handle()) == 0)
+//      RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+       if (!isgroupowner((*owner)->value.lval)
+           || mgd_exists_id(mgd_handle(), "grp", "name=$q",
+                            (*name)->value.str.
+                            val)) RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       php_midgard_create(return_value, "grp",
+                          "name,official,street,postcode,city,"
+                          "homepage,email,extra,owner",
+                          "$q,$q,$q,$q,$q,$q,$q,$q,$d", (*name)->value.str.val,
+                          (*official)->value.str.val, (*street)->value.str.val,
+                          (*postcode)->value.str.val, (*city)->value.str.val,
+                          (*homepage)->value.str.val, (*email)->value.str.val,
+                          (*extra)->value.str.val, (*owner)->value.lval);
+
+       PHP_CREATE_REPLIGARD("grp", return_value->value.lval);
+}
+
+MGD_FUNCTION(update_group)
+{
+       zval **gid, **name, **official, **street, **postcode, **city;
+       zval **homepage, **email, **extra, **owner;
+       zval *self = NULL;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "id", gid)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "official", official)
+                   || !MGD_PROPFIND(self, "street", street)
+                   || !MGD_PROPFIND(self, "postcode", postcode)
+                   || !MGD_PROPFIND(self, "city", city)
+                   || !MGD_PROPFIND(self, "homepage", homepage)
+                   || !MGD_PROPFIND(self, "email", email)
+                   || !MGD_PROPFIND(self, "extra", extra)
+                   || !MGD_PROPFIND(self, "owner", owner)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 10
+                   || zend_get_parameters_ex(10, &gid, &name, &official, &street,
+                                    &postcode, &city, &homepage, &email,
+                                    &extra, &owner) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(gid);
+       convert_to_string_ex(name);
+       convert_to_string_ex(official);
+       convert_to_string_ex(street);
+       convert_to_string_ex(postcode);
+       convert_to_string_ex(city);
+       convert_to_string_ex(homepage);
+       convert_to_string_ex(email);
+       convert_to_string_ex(extra);
+       convert_to_long_ex(owner);
+
+       if (!isgroupowner((*gid)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       php_midgard_update(return_value, "grp",
+                          "name=$q,official=$q,street=$q,postcode=$q,city=$q,"
+                          "homepage=$q,email=$q,extra=$q,owner=$d",
+                          (*gid)->value.lval,
+                          (*name)->value.str.val, (*official)->value.str.val,
+                          (*street)->value.str.val, (*postcode)->value.str.val,
+                          (*city)->value.str.val, (*homepage)->value.str.val,
+                          (*email)->value.str.val, (*extra)->value.str.val,
+                          (*owner)->value.lval);
+       PHP_UPDATE_REPLIGARD("grp", (*gid)->value.lval);
+}
+
+MGD_FUNCTION(delete_group)
+{
+    IDINIT;
+       CHECK_MGD;
+    if(mgd_has_dependants(mgd_handle(),id,"group"))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+    if(mgd_global_exists(mgd_handle(), "owner=$d", id)
+           || mgd_exists_id(mgd_handle(), "member", "gid=$d", id))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+    if (!isgroupowner(id))
+        RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+    php_midgard_delete(return_value, "grp", id);
+    PHP_DELETE_REPLIGARD("grp", id);
+}
+
+MidgardProperty MidgardGroupProperties [] = {
+       { IS_LONG,              "owner"         },
+       { IS_STRING,    "name"          },
+       { IS_STRING,    "official"      },
+       { IS_STRING,    "street"        },
+       { IS_STRING,    "postcode"      },
+       { IS_STRING,    "city"          },
+       { IS_STRING,    "email"         },
+       { IS_STRING,    "homepage"      },
+       { IS_STRING,    "extra"         },
+       { 0,                    NULL            }
+};
+
+MIDGARD_HANDLERS_DECL(group)
+static zend_function_entry MidgardGroupMethods[] =
+   {
+      PHP_FALIAS(midgardgroup,   mgd_ctor_group,   NULL)
+      PHP_FALIAS(create,   mgd_create_group,   NULL)
+      PHP_FALIAS(update,   mgd_update_group,   NULL)
+      PHP_FALIAS(delete,   mgd_delete_group,   NULL)
+      PHP_FALIAS(fetch,    mgd_oop_list_fetch,     NULL)
+      MIDGARD_OOP_ATTACHMENT_METHODS
+      MIDGARD_OOP_SITEGROUP_METHODS
+      MIDGARD_OOP_PARAMETER_METHODS
+      {NULL, NULL, NULL}
+   };
+MidgardClass MidgardGroup = {
+   "MidgardGroup",
+   "grp",
+   MidgardGroupMethods,
+   {},
+   mgd_group_call_function_handler,
+   mgd_group_get_property_handler,
+   mgd_group_set_property_handler,
+   MidgardGroupProperties,
+   NULL
+};
+MIDGARD_HANDLERS(MidgardGroup, group)
Index: php4/ext/midgard/host.c
diff -u /dev/null php4/ext/midgard/host.c:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/host.c     Sat Feb 17 15:21:50 2001
@@ -0,0 +1,366 @@
+/* $Id: host.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(is_host_owner)
+{
+    IDINIT;
+    CHECK_MGD;
+    RETVAL_LONG(ishostowner(id));
+}
+
+MGD_FUNCTION(list_hosts)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+       php_midgard_select(&MidgardHost, return_value,
+                  "id,name,port,online,root,style,owner,info&1 AS auth,prefix," 
+HOSTNAME_FIELD,
+                  "host", NULL, "hostname, online DESC");
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+               php_midgard_select(&MidgardHost, return_value,
+                          "id,name,port,online,root,style,owner,info&1 AS 
+auth,prefix," HOSTNAME_FIELD ,
+                          "host", "root=$d", "hostname, online DESC", 
+(*id)->value.lval);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+}
+
+MGD_FUNCTION(get_host)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+       php_midgard_bless(return_value, &MidgardHost);
+       mgd_object_init(return_value, "name", "port", "online", "root", "style", 
+"auth", "owner", NULL);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+       php_midgard_get(&MidgardHost, return_value,
+                               "id,name,port,online,root,style,info&1 AS 
+auth,owner,prefix," HOSTNAME_FIELD,
+                               "host", (*id)->value.lval);
+}
+
+MGD_FUNCTION(get_host_by_name)
+{
+    zval **name, **prefix;
+       CHECK_MGD;
+    if (ZEND_NUM_ARGS() != 2
+       || zend_get_parameters_ex(2, &name, &prefix) != SUCCESS) {
+          WRONG_PARAM_COUNT;
+   }
+
+    convert_to_string_ex(name);
+    convert_to_string_ex(prefix);
+
+    php_midgard_get_by_name2(&MidgardHost, return_value,
+                       "id,name,port,online,root,style,info&1 AS auth,owner,prefix," 
+HOSTNAME_FIELD,
+                       "host", "name", (*name)->value.str.val,
+                       "prefix", (*prefix)->value.str.val);
+}
+
+MGD_FUNCTION(create_host)
+{
+       zval **name, **port, **online, **root, **style, **auth, **owner, **prefix, 
+*self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "port", port)
+                   || !MGD_PROPFIND(self, "online", online)
+                   || !MGD_PROPFIND(self, "root", root)
+                   || !MGD_PROPFIND(self, "style", style)
+                   || !MGD_PROPFIND(self, "auth", auth)
+                   || !MGD_PROPFIND(self, "owner", owner)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+               if (!MGD_PROPFIND(self, "prefix", prefix))
+                       prefix = NULL;
+       }
+       else {
+               switch (ZEND_NUM_ARGS()) {
+                       case 7:
+                               if (zend_get_parameters_ex
+                                   (7, &name, &port, &online, &root,
+                                    &style, &auth, &owner) != SUCCESS) {
+                                       WRONG_PARAM_COUNT;
+            }
+
+                               prefix = NULL;
+                               break;
+                       case 8:
+                               if (zend_get_parameters_ex
+                                   (8, &name, &port, &online, &root,
+                                    &style, &auth, &owner, &prefix) != SUCCESS) {
+                                       WRONG_PARAM_COUNT;
+            }
+
+                               break;
+                       default:
+                               WRONG_PARAM_COUNT;
+               }
+       }
+       if (prefix)
+       convert_to_string_ex(prefix);
+       convert_to_string_ex(name);
+       convert_to_long_ex(port);
+       convert_to_long_ex(online);
+       convert_to_long_ex(root);
+       convert_to_long_ex(style);
+       convert_to_long_ex(auth);
+       convert_to_long_ex(owner);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       if (!mgd_isroot(mgd_handle()))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+#else
+       if (!mgd_isadmin(mgd_handle()))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+#endif
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* root must be in same SG or be 0 */
+       if ((*root)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "page",
+                                                   "id=$d",
+                                                   (*root)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+       /* style must be in same SG or be 0 */
+       if ((*style)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "style",
+                                                    "id=$d",
+                                                    (*style)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+       /* style must be in same SG or be 0 */
+       if ((*owner)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "grp",
+                                                    "id=$d",
+                                                    (*owner)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+       php_midgard_create(return_value, "host",
+                          "name,port,online,root,style,info,owner,prefix",
+                          "$q,$d,$d,$d,$d,$d,$d,$q", (*name)->value.str.val,
+                          (*port)->value.lval, (*online)->value.lval == 1,
+                          (*root)->value.lval, (*style)->value.lval,
+                          (*auth)->value.lval == 1, (*owner)->value.lval,
+                          prefix ? (*prefix)->value.str.val : "");
+
+       PHP_CREATE_REPLIGARD("host", return_value->value.lval);
+}
+
+MGD_FUNCTION(update_host)
+{
+       zval **id, **name, **port, **online, **root, **style, **auth, **owner, 
+**prefix, *self;
+
+       midgard_pool *pool = NULL;
+       char *prefix_sql = "";
+       char *name_port_sql = "";
+
+#if HAVE_MIDGARD_SITEGROUPS
+       int xref_ok = 1;
+#endif
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if (!(pool = mgd_alloc_pool()))
+               RETURN_FALSE_BECAUSE(MGD_ERR_NO_MEM);
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "id", id)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "port", port)
+                   || !MGD_PROPFIND(self, "online", online)
+                   || !MGD_PROPFIND(self, "root", root)
+                   || !MGD_PROPFIND(self, "style", style)
+                   || !MGD_PROPFIND(self, "auth", auth)
+                   || !MGD_PROPFIND(self, "owner", owner)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+
+               if (
+#if HAVE_MIDGARD_SITEGROUPS
+                          !mgd_isroot(mgd_handle()) ||
+#endif
+                          !MGD_PROPFIND(self, "prefix", prefix))
+                       prefix = NULL;
+       }
+       else {
+               switch (ZEND_NUM_ARGS()) {
+                       case 8:
+                               if (zend_get_parameters_ex
+                                   (8, &id, &name, &port, &online, &root,
+                                    &style, &auth, &owner) != SUCCESS) {
+                                       WRONG_PARAM_COUNT;
+            }
+
+                               prefix = NULL;
+                               break;
+                       case 9:
+                               if (zend_get_parameters_ex
+                                   (9, &id, &name, &port, &online, &root,
+                                    &style, &auth, &owner, &prefix) != SUCCESS) {
+                                       WRONG_PARAM_COUNT;
+            }
+
+#if HAVE_MIDGARD_SITEGROUPS
+                               if (mgd_isroot(mgd_handle())) {
+                                       convert_to_string_ex(prefix);
+                               } else
+                                       prefix = NULL;
+#endif
+                               break;
+                       default:
+                               WRONG_PARAM_COUNT;
+               }
+       }
+
+       if (prefix) convert_to_string_ex(prefix);
+       convert_to_long_ex(id);
+       convert_to_string_ex(name);
+       convert_to_long_ex(port);
+       convert_to_long_ex(online);
+       convert_to_long_ex(root);
+       convert_to_long_ex(style);
+       convert_to_long_ex(auth);
+       convert_to_long_ex(owner);
+
+       if (!ishostowner((*id)->value.lval)) {
+               mgd_free_pool(pool);
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       }
+
+       if (prefix != NULL)
+               prefix_sql =
+                  mgd_format(mgd_handle(), pool, ",prefix=$q",
+                             (*prefix)->value.str.val);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       if (mgd_isroot(mgd_handle()))
+               name_port_sql =
+                  mgd_format(mgd_handle(), pool, ",name=$q,port=$d",
+                             (*name)->value.str.val, (*port)->value.lval);
+#else
+       name_port_sql =
+          mgd_format(mgd_handle(), pool, ",name=$q,port=$d",
+                     (*name)->value.str.val, (*port)->value.lval);
+#endif
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* root must be in same SG or be 0 */
+       if ((*root)->value.lval != 0 && !mgd_exists_bool(mgd_handle(), "host,page",
+                                                     "host.id=$d AND page.id=$d"
+                                                     " AND 
+(host.sitegroup=page.sitegroup"
+                                                     " OR host.sitegroup=0"
+                                                     " OR page.sitegroup=0)",
+                                                     (*id)->value.lval,
+                                                     (*root)->value.lval)) xref_ok = 
+0;
+       /* style must be in same SG or be 0 */
+       if ((*style)->value.lval != 0
+           && !mgd_exists_bool(mgd_handle(), "host,style",
+                               "host.id=$d AND style.id=$d"
+                               " AND (host.sitegroup=style.sitegroup"
+                               " OR host.sitegroup=0" " OR style.sitegroup=0)",
+                               (*id)->value.lval, (*style)->value.lval))
+               xref_ok = 0;
+       /* owner must be in same SG or be 0 */
+       if ((*owner)->value.lval != 0 && !mgd_exists_bool(mgd_handle(), "host,grp",
+                                                      "host.id=$d AND grp.id=$d"
+                                                      " AND 
+(host.sitegroup=grp.sitegroup"
+                                                      " OR host.sitegroup=0"
+                                                      " OR grp.sitegroup=0)",
+                                                      (*id)->value.lval,
+                                                      (*owner)->value.lval)) xref_ok 
+= 0;
+
+       if (!xref_ok) {
+               mgd_free_pool(pool);
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+       }
+#endif
+
+       php_midgard_update(return_value, "host",
+                          "online=$d,root=$d,"
+                          "style=$d,info=$d,owner=$d $s $s",
+                          (*id)->value.lval,
+                          (*online)->value.lval == 1,
+                          (*root)->value.lval, (*style)->value.lval,
+                          (*auth)->value.lval == 1, (*owner)->value.lval,
+                          prefix_sql, name_port_sql);
+       PHP_UPDATE_REPLIGARD("host", (*id)->value.lval);
+       mgd_free_pool(pool);
+}
+
+MGD_FUNCTION(delete_host)
+{
+    IDINIT;
+       CHECK_MGD;
+    if(mgd_has_dependants(mgd_handle(),id,"host"))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       if (!mgd_isroot(mgd_handle())) RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+#else
+    if (!ishostowner(id)) RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+#endif
+    php_midgard_delete(return_value, "host", id);
+    PHP_DELETE_REPLIGARD("host", id);
+}
+
+MidgardProperty MidgardHostProperties [] = {
+       { IS_STRING,    "name"          },
+       { IS_LONG,              "port"          },
+       { IS_STRING,    "prefix"        },
+       { IS_LONG,              "online"        },
+       { IS_LONG,              "root"          },
+       { IS_LONG,              "style"         },
+       { IS_LONG,              "owner"         },
+       { IS_LONG,              "auth"          },
+       { 0,                    NULL            }
+};
+
+MIDGARD_CLASS(MidgardHost, host)
Index: php4/ext/midgard/image.c
diff -u /dev/null php4/ext/midgard/image.c:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/image.c    Sat Feb 17 15:21:50 2001
@@ -0,0 +1,202 @@
+/* $Id: image.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(list_images)
+{
+    RETVAL_FALSE;
+       CHECK_MGD;
+    if (ZEND_NUM_ARGS() != 0)
+        WRONG_PARAM_COUNT;
+    php_midgard_select(&MidgardImage, return_value, "id,src,x,y,info&1 AS online",
+                    "image", NULL, NULL);
+}
+
+#if 0
+MGD_FUNCTION(html_image)
+{
+    php_midgard_res *res;
+    zval **id, **extra, eextra;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    switch (ZEND_NUM_ARGS()) {
+    case 2:
+        if (zend_get_parameters_ex(2, &id, &extra) != SUCCESS)
+            WRONG_PARAM_COUNT;
+        convert_to_string_ex(extra);
+        break;
+    case 1:
+        if (zend_get_parameters_ex(1, &id) != SUCCESS)
+            WRONG_PARAM_COUNT;
+        extra = &eextra;
+        (*extra)->value.str.val = "";
+        break;
+    default:
+        WRONG_PARAM_COUNT;
+    }
+    convert_to_long_ex(id);
+
+    res = mgd_query(midgard.mgd,
+                    "SELECT src,x,y,info&1 FROM image WHERE id=$d",
+                    (*id)->value.lval);
+    if (res) {
+        if (mgd_fetch(res) && mgd_sql2int(res, 3) == 0) {
+          PUTS("<img src=\"/img/");
+          PUTS(mgd_sql2str(res, 0));
+          PUTS("\" ");
+          PUTS((*extra)->value.str.val);
+          PUTS(" width=\"");
+          PUTS(mgd_sql2str(res, 1));
+          PUTS("\" height=\"");
+          PUTS(mgd_sql2str(res, 2));
+          PUTS("\">");
+          PUTS("\" height=\"");
+          RETVAL_TRUE;
+        }
+        mgd_release(res);
+    }
+}
+#endif
+
+MGD_FUNCTION(get_image)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+       php_midgard_bless(return_value, &MidgardImage);
+       mgd_object_init(return_value, "src", "x", "y", "offline", NULL);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+    php_midgard_get(&MidgardImage, return_value,
+                "id,src,x,y,info&1=1 AS offline,"
+                "If(info&1,Concat('<img src=\"/img/',src,"
+                "'\" width=\"',x,'\" height=\"',y,'\">'),'') AS img",
+                "image", (*id)->value.lval);
+}
+
+
+MGD_FUNCTION(create_image)
+{
+       zval **src, **x, **y, **offline, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "src", src)
+                   || !MGD_PROPFIND(self, "x", x)
+                   || !MGD_PROPFIND(self, "y", y)
+                   || !MGD_PROPFIND(self, "offline", offline)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 4
+                   || zend_get_parameters_ex(4, &src, &x, &y, &offline) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_string_ex(src);
+       convert_to_long_ex(x);
+       convert_to_long_ex(y);
+       convert_to_long_ex(offline);
+
+       php_midgard_create(return_value, "image", "src,x,y,info", "$q,$d,$d,$d",
+                          (*src)->value.str.val, (*x)->value.lval, (*y)->value.lval,
+                          (*offline)->value.lval == 1);
+
+       PHP_CREATE_REPLIGARD("image", return_value->value.lval);
+}
+
+MGD_FUNCTION(update_image)
+{
+       zval **id, **src, **x, **y, **offline, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "id", id)
+                   || !MGD_PROPFIND(self, "src", src)
+                   || !MGD_PROPFIND(self, "x", x)
+                   || !MGD_PROPFIND(self, "y", y)
+                   || !MGD_PROPFIND(self, "offline", offline)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 5
+                   || zend_get_parameters_ex(5, &id, &src, &x, &y,
+                                    &offline) != SUCCESS) WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(id);
+       convert_to_string_ex(src);
+       convert_to_long_ex(x);
+       convert_to_long_ex(y);
+       convert_to_long_ex(offline);
+
+       php_midgard_update(return_value, "image", "src=$q,x=$d,y=$d,info=$d",
+                          (*id)->value.lval,
+                          (*src)->value.str.val, (*x)->value.lval, (*y)->value.lval,
+                          (*offline)->value.lval == 1);
+       PHP_UPDATE_REPLIGARD("image", (*id)->value.lval);
+}
+
+MGD_FUNCTION(delete_image)
+{
+    IDINIT;
+       CHECK_MGD;
+    if(mgd_has_dependants(mgd_handle(),id,"image"))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+    php_midgard_delete(return_value, "image", id);
+    PHP_DELETE_REPLIGARD("image", id);
+}
+
+MidgardProperty MidgardImageProperties [] = {
+       { IS_STRING,    "src"           },
+       { IS_LONG,              "x"                     },
+       { IS_LONG,              "y"                     },
+       { IS_LONG,              "online"        },
+       { 0,                    NULL            }
+};
+MIDGARD_CLASS(MidgardImage, image)
Index: php4/ext/midgard/mail.c
diff -u /dev/null php4/ext/midgard/mail.c:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/mail.c     Sat Feb 17 15:21:50 2001
@@ -0,0 +1,177 @@
+/* $Id: mail.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <stdio.h>
+#include <Zend/zend_API.h>
+#include <midgard.h>
+#include <mgd_internal.h>
+#include <php_ini.h>
+
+static void q_encode(FILE * out, const char *in, const char *encoding)
+{
+       unsigned char ch;
+       int i, n = 0, encode = 0;
+
+       for (i = 0; (ch=in[i]); i++) 
+               if (ch > 127 || ch < 32)
+                       encode = 1;
+       if (!encode) {
+               fprintf(out, "%s", in);
+               return;
+       }
+
+       fprintf(out, "=?%s?Q?", encoding);
+       for (; (ch = *in); in++) {
+               switch (ch) {
+                       case ' ':
+                               putc('_', out);
+                               n += 1;
+                               break;
+                       case '=':
+                       case '?':
+                       case '_':
+                               fprintf(out, "=%.2X", ch);
+                               n += 3;
+                               break;
+                       default:
+                               if (ch > 127 || ch < 32) {
+                                       fprintf(out, "=%2X", ch);
+                                       n += 3;
+                               }
+                               else {
+                                       putc(ch, out);
+                                       n += 1;
+                               }
+                               break;
+               }
+       }
+       fprintf(out, "?=");
+}
+
+static void qp_encode(FILE * out, const char *in)
+{
+       unsigned char ch, ws = '\0';
+       int n = 0;
+
+       for (; (ch = *in); in++) {
+               switch (ch) {
+                       case ' ':
+                       case '\t':
+                               if (ws) {
+                                       putc(ws, out);
+                                       n += 1;
+                               }
+                               ws = ch;
+                               break;
+                       case '\r':
+                       case '\n':
+                               if (ws) {
+                                       fprintf(out, "=%.2X", ws);
+                                       ws = '\0';
+                               }
+                               putc(ch, out);
+                               n = 0;
+                               break;
+                       default:
+                               if (ws) {
+                                       putc(ws, out);
+                                       n += 1;
+                                       ws = '\0';
+                               }
+                               if (ch > 127 || ch < 32 || ch == '=') {
+                                       fprintf(out, "=%2X", ch);
+                                       n += 3;
+                               }
+                               else {
+                                       putc(ch, out);
+                                       n += 1;
+                               }
+                               break;
+               }
+               if (n > 71) {
+                       if (ws) {
+                               putc(ws, out);
+                               ws = '\0';
+                       }
+                       fprintf(out, "=\n");
+                       n = 0;
+               }
+       }
+}
+
+MGD_FUNCTION(create_mail)
+{
+       zval **from, **to, **subject, **message;
+       FILE *sendmail;
+       midgard_pool *pool;
+       char *header;
+   char *sendmail_path = INI_STR("sendmail_path");
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if (ZEND_NUM_ARGS() != 4
+           || zend_get_parameters_ex(4, &from, &to, &subject, &message) != SUCCESS)
+       {
+               WRONG_PARAM_COUNT;
+      }
+       convert_to_string_ex(from);
+       convert_to_string_ex(to);
+       convert_to_string_ex(subject);
+       convert_to_string_ex(message);
+
+       if (!sendmail_path)
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       sendmail = popen(sendmail_path, "w");
+       if (sendmail) {
+               pool = mgd_alloc_pool();
+               header = mgd_format(mgd_handle(), pool,
+                                   "From: $s\nTo: $s\n", (*from)->value.str.val,
+                                   (*to)->value.str.val);
+               fprintf(sendmail, header);
+               fprintf(sendmail, "Subject: ");
+               q_encode(sendmail, (*subject)->value.str.val,
+                        mgd_get_encoding(mgd_handle()));
+               header =
+                  mgd_format(mgd_handle(), pool,
+                             "\nX-Mailer: Midgard $s\nMIME-Version: 1.0\n"
+                             "Content-Type: text/plain; charset=$s\n",
+                             mgd_version(mgd_handle()),
+                             mgd_get_encoding(mgd_handle()));
+               fprintf(sendmail, header);
+               mgd_free_pool(pool);
+               if (mgd_mail_need_qp(mgd_handle())) {
+                       fprintf(sendmail,
+                               "Content-Transfer-Encoding: quoted-printable\n\n");
+                       qp_encode(sendmail, (*message)->value.str.val);
+               }
+               else {
+                       fprintf(sendmail, "\n%s", (*message)->value.str.val);
+               }
+               putc('\n', sendmail);
+               if (pclose(sendmail) != -1)
+                       RETVAL_TRUE;
+       }
+       else
+               zend_error(E_WARNING,
+                          "Could not execute mail delivery program");
+}
+
Index: php4/ext/midgard/member.c
diff -u /dev/null php4/ext/midgard/member.c:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/member.c   Sat Feb 17 15:21:50 2001
@@ -0,0 +1,202 @@
+/* $Id: member.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(list_members)
+{
+    IDINIT;
+       CHECK_MGD;
+    php_midgard_select(&MidgardMember, return_value, "member.id AS id, person.id AS 
+uid,"
+                  NAME_FIELD " AS name," RNAME_FIELD " AS rname,department,"
+                  "member.extra as extra",
+                  "person,member", "member.gid=$d AND member.uid=person.id",
+                  "lastname,firstname", id);
+}
+
+MGD_FUNCTION(list_memberships)
+{
+    IDINIT;
+       CHECK_MGD;
+    if (!isuserowner(id)) RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+    php_midgard_select(&MidgardMember, return_value,
+                                       "distinct member.id AS id, gid, "
+                                       "IF(gid!=0,name,'Midgard Administrators') AS 
+name",
+                  "grp,member", "member.uid=$d AND member.gid IN (0,grp.id)",
+                  "name", id);
+}
+
+MGD_FUNCTION(get_member)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+       php_midgard_bless(return_value, &MidgardMember);
+       mgd_object_init(return_value, "uid", "gid", "extra", NULL);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+
+    if (!isgroupowner(mgd_idfield(mgd_handle(), "gid", "member", (*id)->value.lval)))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+    php_midgard_get(&MidgardMember, return_value,
+                                       "id,gid,uid,extra", "member", 
+(*id)->value.lval);
+}
+
+MGD_FUNCTION(create_member)
+{
+       zval **uid, **gid, **extra, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "uid", uid)
+                   || !MGD_PROPFIND(self, "gid", gid)
+                   || !MGD_PROPFIND(self, "extra", extra)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 3
+                   || zend_get_parameters_ex(3, &uid, &gid, &extra) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(uid);
+       convert_to_long_ex(gid);
+       convert_to_string_ex(extra);
+
+       if (!isgroupowner((*gid)->value.lval)
+           || mgd_exists_id(mgd_handle(), "member", "uid=$d AND gid=$d",
+                            (*uid)->value.lval, (*gid)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       if ((*gid)->value.lval == 0) {
+               /* only root can put users in root group */
+               if (!mgd_isroot(mgd_handle()))
+                       RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+               if (mgd_sitegroup(mgd_handle()) != 0)
+                       RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+
+               /* person must exist and be in SG0 */
+               if (!mgd_exists_bool(mgd_handle(),
+                                    "person",
+                                    "id=$d AND sitegroup=0",
+                                    (*uid)->value.lval))
+                          RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+       }
+       else {
+               /* only root users in SG0 please */
+               if (mgd_sitegroup(mgd_handle()) == 0)
+                       RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+               /* group must exist and be in the same sitegroup as the person and
+                  the current sitegroup
+                */
+               if (!mgd_exists_bool(mgd_handle(),
+                                    "person,grp",
+                                    "person.id=$d AND person.sitegroup=$d"
+                                    " AND grp.id=$d AND grp.sitegroup=$d",
+                                    (*uid)->value.lval,
+                                    mgd_sitegroup(mgd_handle()),
+                                    (*gid)->value.lval,
+                                    mgd_sitegroup(mgd_handle())))
+                          RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+       }
+#endif
+
+       php_midgard_create(return_value, "member", "uid,gid,extra", "$d,$d,$q",
+                          (*uid)->value.lval, (*gid)->value.lval,
+                          (*extra)->value.str.val);
+
+       PHP_CREATE_REPLIGARD("member", return_value->value.lval);
+}
+
+MGD_FUNCTION(update_member)
+{
+       zval **id, **extra, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "id", id)
+                   || !MGD_PROPFIND(self, "extra", extra)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 2
+                   || zend_get_parameters_ex(2, &id,
+                                    &extra) != SUCCESS) WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(id);
+       convert_to_string_ex(extra);
+
+       if (!isgroupowner
+           (mgd_idfield(mgd_handle(), "gid", "member", (*id)->value.lval)))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       php_midgard_update(return_value, "member", "extra=$q", (*id)->value.lval,
+                          (*extra)->value.str.val);
+       PHP_UPDATE_REPLIGARD("member", (*id)->value.lval);
+}
+
+MGD_FUNCTION(delete_member)
+{
+    IDINIT;
+       CHECK_MGD;
+    if(mgd_has_dependants(mgd_handle(),id,"member"))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+    if (!isgroupowner(mgd_idfield(mgd_handle(), "gid", "member", id))) 
+RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+    php_midgard_delete(return_value, "member", id);
+    PHP_DELETE_REPLIGARD("member", id);
+}
+
+MidgardProperty MidgardMemberProperties [] = {
+       { IS_LONG,              "uid"           },
+       { IS_LONG,              "gid"           },
+       { IS_STRING,    "extra"         },
+       { 0,                    NULL            }
+};
+
+MIDGARD_CLASS(MidgardMember, member)
Index: php4/ext/midgard/mgd_access.h
diff -u /dev/null php4/ext/midgard/mgd_access.h:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/mgd_access.h       Sat Feb 17 15:21:50 2001
@@ -0,0 +1,43 @@
+/* $Id: mgd_access.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_ACCESS_H
+#define MGD_ACCESS_H
+
+#include <midgard.h>
+
+#define istopicreader(topic) mgd_istopicreader(mgd_handle(), (topic))
+#define istopicowner(topic) mgd_istopicowner(mgd_handle(),(topic))
+#define issnippetdirowner(snippetdir) mgd_issnippetdirowner(mgd_handle(),(snippetdir))
+#define isgroupowner(group) mgd_isgroupowner(mgd_handle(),(group))
+#define isuserowner(user) mgd_isuserowner(mgd_handle(),(user))
+#define ispageelementowner(pageelement) 
+mgd_ispageelementowner(mgd_handle(),(pageelement))
+#define isarticlereader(article) mgd_isarticlereader(mgd_handle(),(article))
+#define isarticleowner(article) mgd_isarticleowner(mgd_handle(),(article))
+#define iseventowner(event) mgd_iseventowner(mgd_handle(),(event))
+#define ishostowner(host) mgd_ishostowner(mgd_handle(),(host))
+#define ispageowner(page) mgd_ispageowner(mgd_handle(),(page))
+#define isstyleowner(style) mgd_isstyleowner(mgd_handle(),(style))
+#define isglobalowner(table,id) mgd_global_is_owner(mgd_handle(),(table),(id))
+#if HAVE_MIDGARD_PAGELINKS
+#define ispagelinkowner(pagelink) mgd_ispagelinkowner(mgd_handle(),(pagelink))
+#endif
+
+#endif
Index: php4/ext/midgard/mgd_article.h
diff -u /dev/null php4/ext/midgard/mgd_article.h:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/mgd_article.h      Sat Feb 17 15:21:50 2001
@@ -0,0 +1,49 @@
+/* $Id: mgd_article.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_ARTICLE_H
+#define MGD_ARTICLE_H
+
+extern MGD_FUNCTION(is_article_owner);
+extern MGD_FUNCTION(is_article_in_topic_tree);
+extern MGD_FUNCTION(list_topic_articles);
+extern MGD_FUNCTION(list_reply_articles);
+extern MGD_FUNCTION(list_topic_articles_all);
+extern MGD_FUNCTION(list_topic_articles_all_fast);
+extern MGD_FUNCTION(list_topic_articles_all_of_person);
+extern MGD_FUNCTION(get_article);
+extern MGD_FUNCTION(get_article_by_name);
+extern MGD_FUNCTION(get_reply_by_name);
+extern MGD_FUNCTION(create_article);
+extern MGD_FUNCTION(update_article_score);
+extern MGD_FUNCTION(update_article_created);
+extern MGD_FUNCTION(update_article_replyto);
+extern MGD_FUNCTION(update_article_type);
+extern MGD_FUNCTION(toggle_article_lock);
+extern MGD_FUNCTION(approve_article);
+extern MGD_FUNCTION(update_article);
+extern MGD_FUNCTION(delete_article);
+extern MGD_FUNCTION(copy_article);
+extern MGD_FUNCTION(move_article);
+extern MGD_FUNCTION(copy_reply);
+extern MGD_FUNCTION(move_reply);
+extern MGD_FUNCTION(delete_article_tree);
+
+#endif
Index: php4/ext/midgard/mgd_attachment.h
diff -u /dev/null php4/ext/midgard/mgd_attachment.h:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/mgd_attachment.h   Sat Feb 17 15:21:50 2001
@@ -0,0 +1,33 @@
+/* $Id: mgd_attachment.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_ATTACHMENT_H
+#define MGD_ATTACHMENT_H
+
+extern MGD_FUNCTION(oop_attachment_create);
+extern MGD_FUNCTION(oop_attachment_list);
+extern MGD_FUNCTION(open_attachment);
+extern MGD_FUNCTION(get_attachment);
+extern MGD_FUNCTION(serve_attachment);
+extern MGD_FUNCTION(stat_attachment);
+extern MGD_FUNCTION(delete_attachment);
+extern MGD_FUNCTION(update_attachment);
+
+#endif
Index: php4/ext/midgard/mgd_calendar.h
diff -u /dev/null php4/ext/midgard/mgd_calendar.h:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/mgd_calendar.h     Sat Feb 17 15:21:50 2001
@@ -0,0 +1,27 @@
+/* $Id: mgd_calendar.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_CALENDAR_H
+#define MGD_CALENDAR_H
+
+extern MGD_FUNCTION(list_topic_calendar_all);
+extern MGD_FUNCTION(list_topic_calendar_all_fast);
+
+#endif
Index: php4/ext/midgard/mgd_element.h
diff -u /dev/null php4/ext/midgard/mgd_element.h:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/mgd_element.h      Sat Feb 17 15:21:50 2001
@@ -0,0 +1,33 @@
+/* $Id: mgd_element.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_ELEMENT_H
+#define MGD_ELEMENT_H
+
+extern MGD_FUNCTION(list_elements);
+extern MGD_FUNCTION(get_element);
+extern MGD_FUNCTION(get_element_by_name);
+extern MGD_FUNCTION(create_element);
+extern MGD_FUNCTION(update_element);
+extern MGD_FUNCTION(delete_element);
+extern MGD_FUNCTION(copy_element);
+extern MGD_FUNCTION(move_element);
+
+#endif
Index: php4/ext/midgard/mgd_errno.pl
diff -u /dev/null php4/ext/midgard/mgd_errno.pl:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/mgd_errno.pl       Sat Feb 17 15:21:50 2001
@@ -0,0 +1,96 @@
+#!/usr/bin/perl
+#Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+#Copyright (C) 2000 The Midgard Project ry
+#Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+#
+#This program is free software; you can redistribute it and/or modify it
+#under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+$commonprefix = "MGD_ERR_";
+
+$errcodes=<<EOERRS;
+
+OK
+ERROR                                          Error
+ACCESS_DENIED                  Access denied
+SITEGROUP_VIOLATION    Resource link crosses sitegroup borders
+NOT_OBJECT                             Object has no ID
+NOT_EXISTS                             Object does not exist
+NO_MEM                                 Can't allocate memory
+INVALID_NAME                   Username has invalid characters
+DUPLICATE                              Name exists
+HAS_DEPENDANTS                 Resource has dependants
+RANGE                                          Date range error
+NOT_CONNECTED        Not connected to the Midgard database
+SG_NOTFOUND          Sitegroup not found
+INVALID_OBJECT       Object doesn't have the expected set of properties
+
+INTERNAL                                       Internal error
+
+EOERRS
+
+###################################################################
+
+($basename) = ($0 =~ /(.*)\.pl/);
+
+$basename || die "$0 must end in .pl\n";
+
+open H, ">$basename.h";
+open C, ">$basename.c";
+
+print H "#ifndef MGD_ERRNO_H\n#define MGD_ERRNO_H\n\n";
+print C "#include \"mgd_errno.h\"\n";
+
+foreach (split(/\n/, $errcodes)) {
+       ($name, $comment) = /([A-Z][_A-Z0-9]*)\t+(.*)/;
+       if (!$name) {
+               ($name, $value) = /([A-Z][_A-Z0-9]*)/;
+       }
+       $name || next;
+
+       $comment =~ s/"/\\"/;
+
+       $name = "$commonprefix$name";
+
+       if (! $comment ) { $comment = $name; }
+
+       push @names, $name;
+       $defines{$name} = -$#names;
+       $comments{$name} = $comment;
+}
+
+foreach (@names) {
+       print H "#define $_ $defines{$_}\n";
+}
+print H "\n";
+
+print H "typedef struct { char *name; int value; } mgd_errno_codename_def;\n";
+print H "extern mgd_errno_codename_def mgd_errno_codename[];\n";
+
+print C "mgd_errno_codename_def mgd_errno_codename[]= {\n";
+foreach (@names) {
+       print C "\t{\t\"$_\",\t$_\t},\n";
+}
+print C "\t{\t(void*)0,\t0\t}\n};\n\n";
+
+print H "char* mgd_errstr(int errcode);\n";
+print C "char* mgd_errstr(int errcode)\n{\n";
+print C "\tswitch (errcode) {\n";
+foreach (@names) {
+       print C "\t\tcase $_: return \"$comments{$_}\";\n";
+}
+print C "\t}\n\n";
+print C "\treturn \"Unknow error code\";\n}\n";
+
+print H "\n#endif\n";
Index: php4/ext/midgard/mgd_event.h
diff -u /dev/null php4/ext/midgard/mgd_event.h:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/mgd_event.h        Sat Feb 17 15:21:50 2001
@@ -0,0 +1,39 @@
+/* $Id: mgd_event.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_EVENT_H
+#define MGD_EVENT_H
+
+extern MGD_FUNCTION(is_event_owner);
+extern MGD_FUNCTION(create_event);
+extern MGD_FUNCTION(update_event);
+extern MGD_FUNCTION(delete_event);
+extern MGD_FUNCTION(delete_event_tree);
+extern MGD_FUNCTION(get_event);
+extern MGD_FUNCTION(list_events);
+extern MGD_FUNCTION(list_events_between);
+extern MGD_FUNCTION(list_events_all);
+extern MGD_FUNCTION(list_events_all_between);
+extern MGD_FUNCTION(count_events_in_period);
+extern MGD_FUNCTION(count_events_in_month);
+extern MGD_FUNCTION(copy_event);
+extern MGD_FUNCTION(move_event);
+
+#endif
Index: php4/ext/midgard/mgd_eventmember.h
diff -u /dev/null php4/ext/midgard/mgd_eventmember.h:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/mgd_eventmember.h  Sat Feb 17 15:21:50 2001
@@ -0,0 +1,31 @@
+/* $Id: mgd_eventmember.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_EVENTMEMBER_H
+#define MGD_EVENTMEMBER_H
+
+extern MGD_FUNCTION(create_event_member);
+extern MGD_FUNCTION(update_event_member);
+extern MGD_FUNCTION(delete_event_member);
+extern MGD_FUNCTION(get_event_member);
+extern MGD_FUNCTION(list_event_members);
+extern MGD_FUNCTION(count_event_members);
+
+#endif
Index: php4/ext/midgard/mgd_file.h
diff -u /dev/null php4/ext/midgard/mgd_file.h:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/mgd_file.h Sat Feb 17 15:21:50 2001
@@ -0,0 +1,30 @@
+/* $Id: mgd_file.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_FILE_H
+#define MGD_FILE_H
+
+extern MGD_FUNCTION(list_files);
+extern MGD_FUNCTION(get_file);
+extern MGD_FUNCTION(create_file);
+extern MGD_FUNCTION(update_file);
+extern MGD_FUNCTION(delete_file);
+
+#endif
Index: php4/ext/midgard/mgd_group.h
diff -u /dev/null php4/ext/midgard/mgd_group.h:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/mgd_group.h        Sat Feb 17 15:21:50 2001
@@ -0,0 +1,32 @@
+/* $Id: mgd_group.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_GROUP_H
+#define MGD_GROUP_H
+
+extern MGD_FUNCTION(is_group_owner);
+extern MGD_FUNCTION(list_groups);
+extern MGD_FUNCTION(get_group);
+extern MGD_FUNCTION(get_group_by_name);
+extern MGD_FUNCTION(create_group);
+extern MGD_FUNCTION(update_group);
+extern MGD_FUNCTION(delete_group);
+
+#endif
Index: php4/ext/midgard/mgd_host.h
diff -u /dev/null php4/ext/midgard/mgd_host.h:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/mgd_host.h Sat Feb 17 15:21:50 2001
@@ -0,0 +1,32 @@
+/* $Id: mgd_host.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_HOST_H
+#define MGD_HOST_H
+
+extern MGD_FUNCTION(is_host_owner);
+extern MGD_FUNCTION(list_hosts);
+extern MGD_FUNCTION(get_host);
+extern MGD_FUNCTION(get_host_by_name);
+extern MGD_FUNCTION(create_host);
+extern MGD_FUNCTION(update_host);
+extern MGD_FUNCTION(delete_host);
+
+#endif
Index: php4/ext/midgard/mgd_image.h
diff -u /dev/null php4/ext/midgard/mgd_image.h:1.3
--- /dev/null   Sat Feb 17 15:21:52 2001
+++ php4/ext/midgard/mgd_image.h        Sat Feb 17 15:21:50 2001
@@ -0,0 +1,31 @@
+/* $Id: mgd_image.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_IMAGE_H
+#define MGD_IMAGE_H
+
+extern MGD_FUNCTION(list_images);
+extern MGD_FUNCTION(html_image);
+extern MGD_FUNCTION(get_image);
+extern MGD_FUNCTION(create_image);
+extern MGD_FUNCTION(update_image);
+extern MGD_FUNCTION(delete_image);
+
+#endif
Index: php4/ext/midgard/mgd_internal.h
diff -u /dev/null php4/ext/midgard/mgd_internal.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_internal.h     Sat Feb 17 15:21:50 2001
@@ -0,0 +1,361 @@
+/* $Id: mgd_internal.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "php.h"
+#include "php_ini.h"
+#include "SAPI.h"
+#include "php_midgard.h"
+#include "Zend/zend.h"
+#include "Zend/zend_API.h"
+#include "mgd_errno.h"
+#include "mgd_access.h"
+
+const char *article_sort(const char *order);
+
+#define php_rqst    ((request_rec *) SG(server_context))
+#define MGD_LOG_START(fmt)     ap_log_rerror(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 
+php_rqst, (fmt)
+#define MGD_LOG_ARG(arg)       , (arg)
+#define MGD_LOG_END()          );
+
+#define RETURN_FALSE_BECAUSE(reason) { mgd_set_errno(reason); RETURN_FALSE; }
+#define RETVAL_FALSE_BECAUSE(reason) { mgd_set_errno(reason); RETVAL_FALSE; }
+
+#define CHECK_MGD \
+   do { \
+      if (!mgd_rcfg()) { \
+         RETURN_FALSE_BECAUSE(MGD_ERR_NOT_CONNECTED); \
+      } \
+      mgd_set_errno(MGD_ERR_OK); \
+   } while (0);
+
+#define MGD_FUNCTION(name) \
+   PHP_FUNCTION(mgd_##name)
+
+#define MGD_FE(name, arg_types) \
+   PHP_FE(mgd_##name, arg_types)
+
+#define MGD_PROPFIND(object, prop, retval) \
+   (zend_hash_find((object)->value.obj.properties, (prop), strlen(prop)+1, \
+      (void**)&(retval)) == SUCCESS)
+       
+#define MGD_PROPFIND_CONST(object, prop, retval) \
+   (zend_hash_find((object)->value.obj.properties, (prop), sizeof(prop), \
+      (void**)&(retval)) == SUCCESS)
+
+#define IDINIT \
+   int id; zval *self, **id_zval; \
+   if (!mgd_rcfg()) \
+      RETURN_FALSE_BECAUSE(MGD_ERR_NOT_CONNECTED); \
+   if ((self = getThis()) != NULL) { \
+      if (! MGD_PROPFIND(self, "id", id_zval)) { \
+         RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT); \
+      } \
+   } else { \
+      if (ZEND_NUM_ARGS() != 1 \
+            || zend_get_parameters_ex(1, &id_zval) != SUCCESS) \
+      WRONG_PARAM_COUNT; \
+   } \
+   convert_to_long_ex(id_zval); \
+   id = (*id_zval)->value.lval;
+
+#define PHP_CREATE_REPLIGARD(table,id)\
+   { \
+      if(id != 0) CREATE_REPLIGARD(mgd_handle(), table, id) \
+      else RETURN_FALSE_BECAUSE(MGD_ERR_ERROR); \
+   }
+
+#define PHP_DELETE_REPLIGARD(table,id) \
+   { \
+      if(id != 0) DELETE_REPLIGARD(mgd_handle(), table, id) \
+      else RETURN_FALSE_BECAUSE(MGD_ERR_ERROR); \
+   }
+
+#define PHP_CREATE_REPLIGARD_VOID(table,id) \
+   { \
+      if(id != 0) CREATE_REPLIGARD(mgd_handle(), table, id)\
+   }
+
+#define PHP_UPDATE_REPLIGARD(table,id) \
+   UPDATE_REPLIGARD(mgd_handle(), table, id)
+
+#define MGD_MOVE_FUNCTION(table,roottable,name,rootname) \
+MGD_FUNCTION(move_##name) \
+{ \
+   zval **id, **root; \
+   RETVAL_FALSE; \
+   CHECK_MGD; \
+   if (ZEND_NUM_ARGS() != 2 \
+         || zend_get_parameters_ex(2, &id, &root) != SUCCESS) \
+      WRONG_PARAM_COUNT; \
+   convert_to_long_ex(id); \
+   convert_to_long_ex(root); \
+   if(mgd_move_object(mgd_handle(), #table, #rootname, \
+      (*id)->value.lval, (*root)->value.lval)) RETVAL_TRUE; \
+   PHP_UPDATE_REPLIGARD(#table, (*id)->value.lval); \
+   PHP_UPDATE_REPLIGARD(#roottable, (*root)->value.lval); \
+}
+
+#define MGD_WALK_FUNCTION(table) \
+/* {{{ proto void walk_ ## table ## _tree(string func, id, level, xparam[, order]) \
+*/ \
+MGD_FUNCTION(walk_ ## table ## _tree) \
+{ \
+   zval **id, **level, **xparam, **order; \
+       zval **old_user_func; \
+       midgard_tree *tree; int mlevel, i; \
+       TLS_VARS; \
+\
+       old_user_func = midgard_user_call_func_name; \
+       switch (ZEND_NUM_ARGS()) { \
+       case 5: \
+      if (zend_get_parameters_ex(5, &midgard_user_call_func_name, &id, \
+            &level, &xparam, &order) == FAILURE) { \
+         midgard_user_call_func_name = old_user_func; \
+         WRONG_PARAM_COUNT; \
+      } \
+      break; \
+   case 4: \
+      if (zend_get_parameters_ex(4, &midgard_user_call_func_name, &id, \
+            &level, &xparam) == FAILURE) { \
+         midgard_user_call_func_name = old_user_func; \
+         WRONG_PARAM_COUNT; \
+      } else { \
+         order = NULL; \
+      } \
+      break; \
+   default: \
+      midgard_user_call_func_name = old_user_func; \
+      WRONG_PARAM_COUNT; \
+      break; \
+   }\
+\
+   convert_to_string_ex(midgard_user_call_func_name); \
+       convert_to_long_ex(level); \
+       if (order) convert_to_long_ex(order); \
+       convert_to_long_ex(id); \
+\
+       tree = mgd_tree_build(mgd_handle(), #table, &mlevel, NULL); \
+\
+       if (!tree) { \
+      RETURN_FALSE_BECAUSE(MGD_ERR_ERROR); \
+   } \
+       /* Be aware of top level trees */ \
+       if ((*id)->value.lval == 0) { \
+      i = 0; \
+      while (tree[i].id) { \
+         walktree(tree, order ? (*order)->value.lval : 1, i, 0, \
+            (*level)->value.lval ? (*level)->value.lval : mlevel, xparam); \
+         i += tree[i].cn; \
+      } \
+   } else { \
+      /* Traverse regular sub tree */ \
+      i = mgd_tree_find(tree, id->value.lval); \
+      if (i != -1) \
+         walktree(tree, order ? (*order)->value.lval : 1, i, tree[i].lv-1, \
+                     (*level)->value.lval ? (*level)->value.lval : mlevel, xparam); \
+       } \
+       free(tree);     \
+       midgard_user_call_func_name = old_user_func; \
+       RETURN_TRUE; \
+} \
+\
+/* }}} */
+
+/* Commonly used macros
+*/
+
+#define HOSTNAME_FIELD \
+  "Concat('http', If(host.port=443, 's',''), '://', host.name, If(host.port=0 || 
+host.port=443, '', Concat(':', host.port)),If(host.prefix='/', '/', 
+Concat(host.prefix, '/'))) AS hostname"
+
+#define PUBLIC_FIELD(n,name) "If(info&" #n "," #name ",'') AS " #name
+#define PUBLIC_FIELDS \
+  "info&2=2 AS addressp,info&4=4 as phonep,info&8=8 AS homepagep," \
+  "info&16=16 AS emailp,info&32=32 AS extrap"
+
+#define NAME_FIELD \
+  "Concat(firstname,If(firstname=''||lastname='','',' '),lastname)"
+#define RNAME_FIELD \
+  "Concat(lastname,If(firstname=''||lastname='','',', '),firstname)"
+#define NAME_FIELDS "firstname,lastname,username," \
+  NAME_FIELD " AS name," RNAME_FIELD " AS rname"
+
+#define ADDRESS_FIELD "Concat(street," \
+  "If(street!=''&&(postcode!=''||city!=''),', ','')," \
+  "postcode,If(postcode!=''&&city!='',' ',''),city)"
+#define ADDRESS_FIELDS "street,postcode,city," ADDRESS_FIELD " AS address"
+
+#define PHONE_FIELD "Concat(" \
+  "handphone,If(handphone=''||(homephone=''&&workphone=''),'',', ')," \
+  "homephone,If(homephone=''||workphone='','',', ')," \
+  "workphone,If(workphone='','',' (työ)'))"
+#define PHONE_FIELDS "handphone,homephone,workphone," PHONE_FIELD " AS phone"
+
+#define HOMEPAGE_FIELD "If(homepage='',''," \
+  "Concat('<a href=\\\"',homepage,'\\\" title=\\\"',firstname,' ',lastname," \
+  "'\\\">',homepage,'</a>'))"
+#define HOMEPAGE_FIELDS "homepage," HOMEPAGE_FIELD " AS homepagelink"
+
+#define EMAIL_FIELD "If(email='',''," \
+  "Concat('<a href=\\\"mailto:',email,'\\\" title=\\\"',firstname,' '," \
+  "lastname,'\\\">',email,'</a>'))"
+#define EMAIL_FIELDS  "email," EMAIL_FIELD " AS emaillink"
+
+#define GROUP_HOMEPAGE_FIELD "If(homepage='',''," \
+  "Concat('<a href=\\\"',homepage,'\\\" title=\\\"',name," \
+  "'\\\">',homepage,'</a>'))"
+#define GROUP_HOMEPAGE_FIELDS "homepage," \
+  GROUP_HOMEPAGE_FIELD " AS homepagelink"
+
+#define GROUP_EMAIL_FIELD "If(email='',''," \
+  "Concat('<a href=\\\"mailto:',email,'\\\" title=\\\"',name," \
+  "'\\\">',email,'</a>'))"
+#define GROUP_EMAIL_FIELDS  "email," GROUP_EMAIL_FIELD " AS emaillink"
+
+/* Person macroses */
+#define PERSON_SELECT \
+  "id,username," NAME_FIELD " AS name," RNAME_FIELD " AS rname,extra," \
+  "topic,department,office,info&1 AS admin,info>1 AS public"
+
+/* Article macroses */
+#define CALENDAR_FIELD \
+  "If(IsNull(calstart),'',If(caldays=0,Date_Format(calstart,'%d.%m.%Y')," \
+  "Concat(Date_Format(calstart," \
+  "If(Year(calstart)!=Year(From_Days(To_Days(calstart)+caldays)),'%d.%m.%Y'," \
+  
+"If(Month(calstart)!=Month(From_Days(To_Days(calstart)+caldays)),'%d.%m.','%d.')))," \
+  "Date_Format(From_Days(To_Days(calstart)+caldays),'-%d.%m.%Y'))))"
+#define ACALENDAR_FIELD \
+  "If(IsNull(calstart),'',If(caldays=0,Date_Format(calstart,'%D %b. %Y')," \
+  "Concat(Date_Format(calstart," \
+  "If(Year(calstart)!=Year(From_Days(To_Days(calstart)+caldays)),'%D %b. %Y'," \
+  "If(Month(calstart)!=Month(From_Days(To_Days(calstart)+caldays)),'%D %b.','%D')))," 
+\
+  "Date_Format(From_Days(To_Days(calstart)+caldays),'-%D %b. %Y'))))"
+#define ALCALENDAR_FIELD \
+  "If(IsNull(calstart),'',If(caldays=0,Date_Format(calstart,'%D %M %Y')," \
+  "Concat(Date_Format(calstart," \
+  "If(Year(calstart)!=Year(From_Days(To_Days(calstart)+caldays)),'%D %M %Y'," \
+  "If(Month(calstart)!=Month(From_Days(To_Days(calstart)+caldays)),'%D %M','%D')))," \
+  "Date_Format(From_Days(To_Days(calstart)+caldays),'-%D %M %Y'))))"
+#define CALENDAR_FIELDS \
+  CALENDAR_FIELD " AS calendar," \
+  ACALENDAR_FIELD " AS acalendar," \
+  ALCALENDAR_FIELD " AS alcalendar," \
+  "Unix_Timestamp(calstart) AS startdate," \
+  "Unix_Timestamp(Date_Add(calstart, INTERVAL caldays DAY)) AS enddate," \
+  "caldays,Date_Format(calstart,'%d.%m.%Y') AS calstart," \
+  "Date_Format(From_Days(To_Days(calstart)+caldays),'%d.%m.%Y') As calstop"
+
+#define ARTICLE_CALENDAR CALENDAR_FIELDS
+#define ARTICLE_SELECT \
+  "article.id AS id,article.name AS name,title,abstract,content,author," \
+  NAME_FIELD " AS authorname,article.topic AS topic," \
+  "Date_format(article.created,'%d.%m.%Y') AS date," \
+  "Date_format(article.created,'%D %b. %Y') AS adate," \
+  "Date_format(article.created,'%D %M %Y') AS aldate," \
+  "url,icon,extra1,extra2,extra3,article.score AS score,type," \
+  "Unix_Timestamp(article.created) AS created,article.creator AS creator," \
+  "Unix_Timestamp(revised) AS revised,revisor,revision," \
+  "Unix_Timestamp(locked) AS locked,locker," \
+  "Unix_Timestamp(approved) AS approved,approver"
+#define ARTICLE_SELECT_FAST \
+  "id,name,title,abstract,content,author,topic," \
+  "Date_format(article.created,'%d.%m.%Y') AS date," \
+  "Date_format(article.created,'%D %b. %Y') AS adate," \
+  "Date_format(article.created,'%D %M %Y') AS aldate," \
+  "url,icon,extra1,extra2,extra3,article.score AS score,type," \
+  "Unix_Timestamp(article.created) AS created,article.creator AS creator," \
+  "Unix_Timestamp(revised) AS revised,revisor,revision," \
+  "Unix_Timestamp(locked) AS locked,locker," \
+  "Unix_Timestamp(approved) AS approved,approver"
+#define ARTICLE_FROM "article,person"
+#define ARTICLE_FROM_FAST "article"
+
+/* Macroses for Events */
+#if HAVE_MIDGARD_SITEGROUPS
+#define EVENT_SITEGROUP     " AND sitegroup in (0,$d)"
+#define EVENT_SITEGROUP2    " AND event.sitegroup in (0,$d)"\
+                                                       " AND eventmember.sitegroup in 
+(0,$d)"
+#else
+#define EVENT_SITEGROUP     ""
+#define EVENT_SITEGROUP2    ""
+#endif
+#define EVENT_COUNT_WHERE_0 "start>=Unix_Timestamp(Now())" EVENT_SITEGROUP
+#define EVENT_COUNT_WHERE_1 "start>=Unix_Timestamp(Now())"\
+                                                       " AND end<=$d" EVENT_SITEGROUP
+#define EVENT_COUNT_WHERE_2 "start>=$d AND end<=$d" EVENT_SITEGROUP
+#define EVENT_COUNT_WHERE_3 "start>=$d AND end<=$d"\
+                                                       " AND 
+event.id=eventmember.eid"\
+                                                       " AND eventmember.uid=$d" 
+EVENT_SITEGROUP
+#define EVENT_COUNT_WHERE_4 "start>=$d AND end<=$d"\
+                                                       " AND 
+event.id=eventmember.eid"\
+                                                       " AND eventmember.uid=$d"\
+                                                       " AND event.type=$d" 
+EVENT_SITEGROUP2
+#define EVENT_COUNT_WHERE_43 "start>=$d AND end<=$d"\
+                                                       " AND event.type=$d" 
+EVENT_SITEGROUP
+#define EVENT_COUNT_TABLE      "event"
+#define EVENT_COUNT_TABLE_2 "event,eventmember"
+
+#define EVENT_START 0
+#define EVENT_END   1
+
+#define EVENT_MONTH_WHERE         "((start<$d AND end>$d)"\
+                                                          " OR (start>$d AND 
+start<$d)"\
+                                                          " OR (end>$d AND end<$d))" 
+EVENT_SITEGROUP
+#define EVENT_MONTH_WHERE_TYPE "((start<$d AND end>$d)"\
+                                                      " OR (start>$d AND start<$d)"\
+                                                          " OR (end>$d AND end<$d))"\
+                                                          " AND type=$d" 
+EVENT_SITEGROUP
+/* Macroses for Event Members */
+#define EVENT_PUBLIC_FIELD(n,name) \
+               "If(person.id<>$d,If(info&" #n "," #name ",'')," #name ") AS " #name
+
+#define EVENT_EMAIL_FIELD \
+               "If(person.id<>$d,If(Info&16,If(email='',''," \
+  "Concat('<a href=\\\"mailto:',email,'\\\" title=\\\"',firstname,' '," \
+  "lastname,'\\\">',email,'</a>')),'')," \
+  "Concat('<a href=\\\"mailto:',email,'\\\" title=\\\"',firstname,' '," \
+  "lastname,'\\\">',email,'</a>')) AS emaillink"
+
+/* DG: fixing an incompatibility with a certain state of PHP's CVS...
+ * not needed anymore, but who knows...
+#ifdef add_property_unset
+#undef add_property_unset
+#define add_property_unset(__arg, __key) add_property_unset_ex(__arg, __key, 
+strlen(__key) + 1)
+#endif
+*/
+
+#define MGD_INIT_CLASS_ENTRY(class_container, class_name, functions) \
+       { \
+               class_container.name = strdup(class_name); \
+               class_container.name_length = strlen(class_name); \
+               class_container.builtin_functions = functions; \
+               class_container.handle_function_call = NULL; \
+               class_container.handle_property_get = NULL; \
+               class_container.handle_property_set = NULL; \
+       }
+
+#define MGD_INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, 
+handle_fcall, handle_propget, handle_propset) \
+       {                                                                              
+                                         \
+               class_container.name = strdup(class_name);                             
+ \
+               class_container.name_length = strlen(class_name);               \
+               class_container.builtin_functions = functions;                  \
+               class_container.handle_function_call = handle_fcall;    \
+               class_container.handle_property_get = handle_propget;   \
+               class_container.handle_property_set = handle_propset;   \
+       }
Index: php4/ext/midgard/mgd_mail.h
diff -u /dev/null php4/ext/midgard/mgd_mail.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_mail.h Sat Feb 17 15:21:50 2001
@@ -0,0 +1,26 @@
+/* $Id: mgd_mail.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_MAIL_H
+#define MGD_MAIL_H
+
+extern MGD_FUNCTION(create_mail);
+
+#endif
Index: php4/ext/midgard/mgd_member.h
diff -u /dev/null php4/ext/midgard/mgd_member.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_member.h       Sat Feb 17 15:21:50 2001
@@ -0,0 +1,31 @@
+/* $Id: mgd_member.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_MEMBER_H
+#define MGD_MEMBER_H
+
+extern MGD_FUNCTION(list_members);
+extern MGD_FUNCTION(list_memberships);
+extern MGD_FUNCTION(get_member);
+extern MGD_FUNCTION(create_member);
+extern MGD_FUNCTION(update_member);
+extern MGD_FUNCTION(delete_member);
+
+#endif
Index: php4/ext/midgard/mgd_midgard.h
diff -u /dev/null php4/ext/midgard/mgd_midgard.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_midgard.h      Sat Feb 17 15:21:50 2001
@@ -0,0 +1,36 @@
+/* $Id: mgd_midgard.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_MIDGARD_H
+#define MGD_MIDGARD_H
+
+void php_midgard_select(zval * return_value,
+                       const char *fields, const char *tables,
+                       const char *where, const char *order, ...);
+
+void php_midgard_update(zval * return_value, const
+                       char *table, const char *fields, int id, ...);
+
+void php_midgard_create(zval * return_value, const char *table,
+                       const char *fields, const char *values, ...);
+
+void php_midgard_delete(zval * return_value, const char *table, int id);
+
+#endif
Index: php4/ext/midgard/mgd_oop.h
diff -u /dev/null php4/ext/midgard/mgd_oop.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_oop.h  Sat Feb 17 15:21:50 2001
@@ -0,0 +1,348 @@
+/* $Id: mgd_oop.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_OOP_H
+#define MGD_OOP_H
+
+#include <zend.h>
+
+MGD_FUNCTION(oop_parameter);
+MGD_FUNCTION(oop_parameter_list);
+MGD_FUNCTION(oop_parameter_search);
+
+MGD_FUNCTION(get_attachment);
+MGD_FUNCTION(oop_attachment_create);
+MGD_FUNCTION(oop_attachment_list);
+MGD_FUNCTION(open_attachment);
+MGD_FUNCTION(serve_attachment);
+MGD_FUNCTION(delete_attachment);
+MGD_FUNCTION(update_attachment);
+
+MGD_FUNCTION(oop_guid_get);
+
+MGD_FUNCTION(oop_list_fetch);
+
+// DG: are all these oop_xxxx_create functions actually exist ?
+MGD_FUNCTION(oop_element_create);
+MGD_FUNCTION(delete_element);
+MGD_FUNCTION(update_element);
+
+MGD_FUNCTION(oop_group_create);
+MGD_FUNCTION(delete_group);
+MGD_FUNCTION(update_group);
+
+MGD_FUNCTION(oop_article_create);
+MGD_FUNCTION(oop_article_score);
+MGD_FUNCTION(delete_article);
+MGD_FUNCTION(update_article);
+
+MGD_FUNCTION(oop_topic_create);
+MGD_FUNCTION(oop_topic_score);
+MGD_FUNCTION(delete_topic);
+MGD_FUNCTION(update_topic);
+
+MGD_FUNCTION(oop_file_create);
+MGD_FUNCTION(delete_file);
+MGD_FUNCTION(update_file);
+
+MGD_FUNCTION(oop_host_create);
+MGD_FUNCTION(delete_host);
+MGD_FUNCTION(update_host);
+
+MGD_FUNCTION(oop_image_create);
+MGD_FUNCTION(delete_image);
+MGD_FUNCTION(update_image);
+
+MGD_FUNCTION(oop_member_create);
+MGD_FUNCTION(delete_member);
+MGD_FUNCTION(update_member);
+
+MGD_FUNCTION(oop_person_create);
+MGD_FUNCTION(delete_person);
+MGD_FUNCTION(update_person);
+
+MGD_FUNCTION(oop_preference_create);
+MGD_FUNCTION(delete_preference);
+MGD_FUNCTION(update_preference);
+
+MGD_FUNCTION(oop_page_create);
+MGD_FUNCTION(delete_page);
+MGD_FUNCTION(update_page);
+
+#if HAVE_MIDGARD_PAGELINKS
+MGD_FUNCTION(oop_pagelink_create);
+MGD_FUNCTION(delete_pagelink);
+MGD_FUNCTION(update_pagelink);
+#endif
+
+MGD_FUNCTION(oop_event_create);
+MGD_FUNCTION(delete_event);
+MGD_FUNCTION(update_event);
+MGD_FUNCTION(oop_event_member_create);
+MGD_FUNCTION(delete_event_member);
+MGD_FUNCTION(update_event_member);
+
+#if HAVE_MIDGARD_SITEGROUPS
+MGD_FUNCTION(oop_sitegroup_set);
+MGD_FUNCTION(oop_sitegroup_get);
+
+MGD_FUNCTION(create_sitegroup);
+MGD_FUNCTION(delete_sitegroup);
+MGD_FUNCTION(update_sitegroup);
+#endif
+
+MGD_FUNCTION(oop_style_create);
+MGD_FUNCTION(delete_style);
+MGD_FUNCTION(update_style);
+
+MGD_FUNCTION(oop_pageelement_create);
+MGD_FUNCTION(delete_pageelement);
+MGD_FUNCTION(update_pageelement);
+
+MGD_FUNCTION(oop_snippetdir_create);
+MGD_FUNCTION(delete_snippetdir);
+MGD_FUNCTION(update_snippetdir);
+
+MGD_FUNCTION(oop_snippet_create);
+MGD_FUNCTION(delete_snippet);
+MGD_FUNCTION(update_snippet);
+
+typedef struct {
+       int type;
+       char * name;
+/* default value ? */
+} MidgardProperty;
+
+typedef MidgardProperty* MidgardPropertyPtr;
+
+typedef struct {
+   const char *name;
+   const char *table;
+   zend_function_entry *methods;
+   zend_class_entry class_entry;
+   void (*function_call)(INTERNAL_FUNCTION_PARAMETERS,
+                                       zend_property_reference *property_reference);
+   zval (*get_property)(zend_property_reference *property_reference);
+   int (*set_property)(zend_property_reference *property_reference,
+                                               zval *value);
+   MidgardProperty *properties;
+   zend_class_entry *entry_ptr;
+} MidgardClass;
+
+typedef MidgardClass* MidgardClassPtr;
+extern MidgardClassPtr MidgardClasses[];
+
+void mgd_object_init(zval *obj, ...);
+void php_midgard_bless(zval *object, MidgardClass *species);
+void php_midgard_ctor(zval *object, MidgardClass *species);
+void php_midgard_delete(zval * return_value, const char *table, int id);
+void php_midgard_delete_repligard(const char *table, int id);
+void php_midgard_update(zval * return_value, const char *table,
+   const char *fields, int id, ...);
+void php_midgard_create(zval * return_value, const char *table,
+   const char *fields, const char *values, ...);
+void php_midgard_select(MidgardClass *species, zval * return_value,
+   const char *fields, const char *tables,
+   const char *where, const char *order, ...);
+#if HAVE_MIDGARD_SITEGROUPS
+void php_midgard_sitegroup_get(MidgardClass *species,
+               zval * return_value, int grouped,
+               const char *fields, const char *table, int id);
+#endif
+void php_midgard_get(MidgardClass *species, zval * return_value,
+   const char *fields, const char *table, int id);
+void php_midgard_get_by_name(MidgardClass *species, zval * return_value,
+   const char *fields, const char *table,
+   const char *idfield, int parent_id, const char *name);
+void php_midgard_get_by_name2(MidgardClass *species, zval * return_value,
+   const char *fields, const char *table,
+   const char *firstfield, const char *first,
+   const char *secondfield, const char *second);
+void php_midgard_get_by_name_only(MidgardClass *species, zval * return_value,
+   const char *fields, const char *table, const char *name);
+zval _midgard_getset_property(MidgardClass *Class,
+               zend_property_reference *property_reference,
+                                               zval *value);
+
+extern MidgardClass MidgardArticle;
+extern MidgardClass MidgardAttachment;
+extern MidgardClass MidgardElement;
+extern MidgardClass MidgardEvent;
+extern MidgardClass MidgardEventMember;
+extern MidgardClass MidgardFile;
+extern MidgardClass MidgardGroup;
+extern MidgardClass MidgardHost;
+extern MidgardClass MidgardImage;
+extern MidgardClass MidgardMember;
+extern MidgardClass MidgardPage;
+extern MidgardClass MidgardPageElement;
+extern MidgardClass MidgardParameter;
+extern MidgardClass MidgardPerson;
+extern MidgardClass MidgardPreferences;
+extern MidgardClass MidgardSnippet;
+extern MidgardClass MidgardSnippetdir;
+extern MidgardClass MidgardStyle;
+extern MidgardClass MidgardTopic;
+#if HAVE_MIDGARD_SITEGROUPS
+extern MidgardClass MidgardSitegroup;
+#endif
+#if HAVE_MIDGARD_PAGELINKS
+extern MidgardClass MidgardPagelink;
+#endif
+
+/* OOP_SITEGROUP_METHODS include also method for
+   gathering GUID for given object
+*/
+#if HAVE_MIDGARD_SITEGROUPS
+#define MIDGARD_OOP_SITEGROUP_METHODS \
+       PHP_FALIAS(setsitegroup,      mgd_oop_sitegroup_set, NULL) \
+       PHP_FALIAS(getsitegroup,      mgd_oop_sitegroup_get, NULL) \
+       PHP_FALIAS(guid,              mgd_oop_guid_get,          NULL)
+#else
+#define MIDGARD_OOP_SITEGROUP_METHODS \
+       PHP_FALIAS(guid,              mgd_oop_guid_get,          NULL)
+#endif
+
+#define MIDGARD_OOP_ATTACHMENT_METHODS \
+   PHP_FALIAS(getattachment,     mgd_get_attachment,        NULL) \
+   PHP_FALIAS(createattachment,  mgd_oop_attachment_create, NULL) \
+   PHP_FALIAS(listattachments,   mgd_oop_attachment_list,   NULL) \
+   PHP_FALIAS(openattachment,    mgd_open_attachment,       NULL) \
+   PHP_FALIAS(serveattachment,   mgd_serve_attachment,      NULL) \
+   PHP_FALIAS(deleteattachment,  mgd_delete_attachment,     NULL) \
+   PHP_FALIAS(updateattachment,  mgd_update_attachment,     NULL)
+
+#define MIDGARD_OOP_PARAMETER_METHODS \
+       PHP_FALIAS(parameter,         mgd_oop_parameter,         NULL) \
+       PHP_FALIAS(searchparameters,  mgd_oop_parameter_search,  NULL) \
+       PHP_FALIAS(listparameters,    mgd_oop_parameter_list,    NULL)
+
+#define MIDGARD_CLASS(name,type) \
+MIDGARD_HANDLERS_DECL(type) \
+static zend_function_entry name ## Methods[] = \
+   { \
+      PHP_FALIAS(midgard # type,   mgd_ctor_ ## type ,   NULL) \
+      PHP_FALIAS(create,   mgd_create_ ## type ,   NULL) \
+      PHP_FALIAS(update,   mgd_update_ ## type ,   NULL) \
+      PHP_FALIAS(delete,   mgd_delete_ ## type ,   NULL) \
+      PHP_FALIAS(fetch,    mgd_oop_list_fetch,     NULL) \
+      MIDGARD_OOP_ATTACHMENT_METHODS \
+      MIDGARD_OOP_SITEGROUP_METHODS \
+      MIDGARD_OOP_PARAMETER_METHODS \
+      {NULL, NULL, NULL} \
+   }; \
+MidgardClass name = { \
+   #name, \
+   #type, \
+   name ## Methods, \
+   {}, \
+   mgd_ ## type ## _call_function_handler, \
+   mgd_ ## type ## _get_property_handler, \
+   mgd_ ## type ## _set_property_handler, \
+   name ## Properties, \
+   NULL \
+}; \
+MIDGARD_HANDLERS(name, type)
+
+#define MIDGARD_HANDLERS_DECL(type) \
+void mgd_ ## type ## _call_function_handler(INTERNAL_FUNCTION_PARAMETERS, \
+                                       zend_property_reference *property_reference); \
+zval mgd_ ## type ## _get_property_handler(zend_property_reference 
+*property_reference); \
+int mgd_ ## type ## _set_property_handler(zend_property_reference 
+*property_reference, \
+                                               zval *value); \
+MGD_FUNCTION(ctor_ ## type);
+
+#define MIDGARD_HANDLERS(name, type) \
+void mgd_ ## type ## _call_function_handler(INTERNAL_FUNCTION_PARAMETERS, \
+                                       zend_property_reference *property_reference) \
+{ \
+       zval *object = property_reference->object; \
+       zend_overloaded_element *function_name = (zend_overloaded_element *) \
+                                               
+property_reference->elements_list->tail->data; \
+ \
+/*     int arg_count = 0; \
+       zval **arguments = NULL; \
+        \
+       if((arg_count = ZEND_NUM_ARGS()) > 0) { \
+               arguments = (pval **) emalloc(sizeof(pval *)*arg_count); \
+       } */ \
+       RETVAL_TRUE; \
+ \
+       CHECK_MGD; \
+ \
+/*     getParametersArray(ht, arg_count, arguments); */ \
+       /* if the constructor is called */ \
+       if (!strcasecmp( #name ,function_name->element.value.str.val)) { \
+       /* construct a Midgard object */ \
+               pval *object_handle; \
+               php_midgard_bless(object, &name); \
+               ALLOC_ZVAL(object_handle); \
+               *object_handle = *return_value; \
+               pval_copy_constructor(object_handle); \
+               INIT_PZVAL(object_handle); \
+/*             zend_hash_index_update(object->value.obj.properties, 0, 
+&object_handle, sizeof(pval *), NULL); */ \
+ \
+       } else { \
+               zend_function_entry * methods = name ## Methods; \
+               int ok = 0; \
+               while(methods && methods->fname) { \
+                       if(!strcmp(function_name->element.value.str.val, 
+methods->fname)) { \
+                               methods->handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); \
+                               ok = 1; \
+                               break; \
+                       } \
+                       methods++; \
+               } \
+               if(!ok) { \
+                       /* pval_destructor(&function_name->element); */ \
+                       php_error(E_ERROR, \
+                                               "Midgard: Method '%s' is not a member 
+of " #name, \
+                                               function_name->element.value.str.val); 
+\
+               } \
+/*             PHP_FN(manage function aliases 
+here)(INTERNAL_FUNCTION_PARAM_PASSTHRU); */ \
+       } \
+/*     efree(arguments); */ \
+       pval_destructor(&function_name->element); \
+} \
+ \
+zval mgd_ ## type ## _get_property_handler(zend_property_reference 
+*property_reference) \
+{ \
+       zval result; \
+       result = _midgard_getset_property(&name, property_reference, NULL); \
+       return result; \
+} \
+ \
+int mgd_ ## type ## _set_property_handler(zend_property_reference 
+*property_reference, \
+                                               zval *value) \
+{ \
+       zval result; \
+       result = _midgard_getset_property(&name, property_reference, value); \
+       /* TODO: test result to know if we return SUCCESS or FAILURE */ \
+       return SUCCESS; \
+} \
+MGD_FUNCTION(ctor_ ## type) \
+{ \
+       if ((return_value = getThis()) == NULL) { \
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT); \
+       } \
+       php_midgard_ctor(return_value, &name); \
+}
+
+#endif
Index: php4/ext/midgard/mgd_page.h
diff -u /dev/null php4/ext/midgard/mgd_page.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_page.h Sat Feb 17 15:21:50 2001
@@ -0,0 +1,37 @@
+/* $Id: mgd_page.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_PAGE_H
+#define MGD_PAGE_H
+
+extern MGD_FUNCTION(is_page_owner);
+extern MGD_FUNCTION(copy_page);
+extern MGD_FUNCTION(move_page);
+extern MGD_FUNCTION(list_pages);
+extern MGD_FUNCTION(is_in_page_tree);
+extern MGD_FUNCTION(get_page);
+extern MGD_FUNCTION(get_page_by_name);
+extern MGD_FUNCTION(create_page);
+extern MGD_FUNCTION(update_page);
+extern MGD_FUNCTION(delete_page);
+extern MGD_FUNCTION(page_has_children);
+extern MGD_FUNCTION(delete_page_tree);
+
+#endif
Index: php4/ext/midgard/mgd_pageelement.h
diff -u /dev/null php4/ext/midgard/mgd_pageelement.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_pageelement.h  Sat Feb 17 15:21:50 2001
@@ -0,0 +1,33 @@
+/* $Id: mgd_pageelement.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_PAGEELEMENT_H
+#define MGD_PAGEELEMENT_H
+
+extern MGD_FUNCTION(list_page_elements);
+extern MGD_FUNCTION(get_page_element);
+extern MGD_FUNCTION(get_page_element_by_name);
+extern MGD_FUNCTION(create_page_element);
+extern MGD_FUNCTION(update_page_element);
+extern MGD_FUNCTION(delete_page_element);
+extern MGD_FUNCTION(copy_page_element);
+extern MGD_FUNCTION(move_page_element);
+
+#endif
Index: php4/ext/midgard/mgd_pagelink.h
diff -u /dev/null php4/ext/midgard/mgd_pagelink.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_pagelink.h     Sat Feb 17 15:21:50 2001
@@ -0,0 +1,34 @@
+/* $Id: mgd_pagelink.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_PAGELINK_H
+#define MGD_PAGELINK_H
+
+extern MGD_FUNCTION(has_pagelinks);
+extern MGD_FUNCTION(is_pagelink_owner);
+extern MGD_FUNCTION(list_pagelinks);
+extern MGD_FUNCTION(list_pagelinks_targeted_at);
+extern MGD_FUNCTION(get_pagelink);
+extern MGD_FUNCTION(get_pagelink_by_name);
+extern MGD_FUNCTION(create_pagelink);
+extern MGD_FUNCTION(update_pagelink);
+extern MGD_FUNCTION(delete_pagelink);
+
+#endif
Index: php4/ext/midgard/mgd_person.h
diff -u /dev/null php4/ext/midgard/mgd_person.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_person.h       Sat Feb 17 15:21:50 2001
@@ -0,0 +1,40 @@
+/* $Id: mgd_person.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_PERSON_H
+#define MGD_PERSON_H
+
+extern MGD_FUNCTION(is_person_owner);
+extern MGD_FUNCTION(is_member);
+extern MGD_FUNCTION(list_persons);
+extern MGD_FUNCTION(list_persons_in_department);
+extern MGD_FUNCTION(list_topic_persons);
+extern MGD_FUNCTION(list_persons_in_department_all);
+extern MGD_FUNCTION(list_topic_persons_all);
+extern MGD_FUNCTION(list_persons_in_office);
+extern MGD_FUNCTION(get_person);
+extern MGD_FUNCTION(create_person);
+extern MGD_FUNCTION(update_person);
+extern MGD_FUNCTION(update_password);
+extern MGD_FUNCTION(update_password_plain);
+extern MGD_FUNCTION(update_public);
+extern MGD_FUNCTION(delete_person);
+
+#endif
Index: php4/ext/midgard/mgd_preferences.h
diff -u /dev/null php4/ext/midgard/mgd_preferences.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_preferences.h  Sat Feb 17 15:21:50 2001
@@ -0,0 +1,30 @@
+/* $Id: mgd_preferences.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_PREFERENCES_H
+#define MGD_PREFERENCES_H
+
+extern MGD_FUNCTION(list_preferences);
+extern MGD_FUNCTION(get_preference);
+extern MGD_FUNCTION(create_preference);
+extern MGD_FUNCTION(update_preference);
+extern MGD_FUNCTION(delete_preference);
+
+#endif
Index: php4/ext/midgard/mgd_preparser.h
diff -u /dev/null php4/ext/midgard/mgd_preparser.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_preparser.h    Sat Feb 17 15:21:50 2001
@@ -0,0 +1,58 @@
+/* $Id: mgd_preparser.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_PREPARSER_H
+#define MGD_PREPARSER_H
+#include "mgd_internal.h"
+#include "midgard.h"
+#include <glib.h>
+
+extern MGD_FUNCTION(template);
+extern MGD_FUNCTION(variable);
+extern MGD_FUNCTION(snippet);
+extern MGD_FUNCTION(eval);
+extern MGD_FUNCTION(register_filter);
+char * php_midgard_variable(midgard_pool * pool, char * name, char * member, char * 
+type);
+char * php_eval_midgard(midgard_pool * pool, const char *name, char *value, int 
+exit_php);
+int mgdparse(void);
+
+extern GByteArray *mgd_output_buffer;
+#define mgd_append_byte(buffer, str) if((*str) != '\0' )\
+           g_byte_array_append((buffer), (str), 1);
+#define mgd_set_buffer(buffer, str) { \
+       (buffer) = g_byte_array_new(); \
+       if(strlen(str) > 0 ) { \
+               g_byte_array_append((buffer), (str), strlen(str)); \
+       } \
+}
+
+#define mgd_free_buffer(buffer) g_byte_array_free((buffer), TRUE)
+#define mgd_append_buffer(buffer, str) if(strlen(str) > 0 )\
+           g_byte_array_append((buffer), (str), strlen(str));
+#define mgd_append_output_buffer_const(str) if(sizeof(str) > 0 )\
+           g_byte_array_append(mgd_output_buffer, (str), (sizeof(str) == 1) ? 1 : 
+sizeof(str)-1 );
+#define mgd_append_output_buffer(str) if(strlen(str) > 0 )\
+           g_byte_array_append(mgd_output_buffer, (str), strlen(str));
+#define mgd_append_output_buffer_data(gstr) if((gstr)->len > 0 )\
+           g_byte_array_append(mgd_output_buffer, (gstr)->data, (gstr)->len);
+
+//#define MGD_PREPARSER_LOG
+
+#endif
Index: php4/ext/midgard/mgd_sitegroup.h
diff -u /dev/null php4/ext/midgard/mgd_sitegroup.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_sitegroup.h    Sat Feb 17 15:21:50 2001
@@ -0,0 +1,31 @@
+/* $Id: mgd_sitegroup.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_SITEGROUP_H
+#define MGD_SITEGROUP_H
+
+extern MGD_FUNCTION(has_sitegroups);
+extern MGD_FUNCTION(list_sitegroups);
+extern MGD_FUNCTION(create_sitegroup);
+extern MGD_FUNCTION(get_sitegroup);
+extern MGD_FUNCTION(update_sitegroup);
+extern MGD_FUNCTION(delete_sitegroup);
+
+#endif
Index: php4/ext/midgard/mgd_snippet.h
diff -u /dev/null php4/ext/midgard/mgd_snippet.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_snippet.h      Sat Feb 17 15:21:50 2001
@@ -0,0 +1,34 @@
+/* $Id: mgd_snippet.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_SNIPPET_H
+#define MGD_SNIPPET_H
+
+extern MGD_FUNCTION(snippet_exists);
+extern MGD_FUNCTION(list_snippets);
+extern MGD_FUNCTION(get_snippet);
+extern MGD_FUNCTION(get_snippet_by_name);
+extern MGD_FUNCTION(create_snippet);
+extern MGD_FUNCTION(update_snippet);
+extern MGD_FUNCTION(delete_snippet);
+extern MGD_FUNCTION(copy_snippet);
+extern MGD_FUNCTION(move_snippet);
+
+#endif
Index: php4/ext/midgard/mgd_snippetdir.h
diff -u /dev/null php4/ext/midgard/mgd_snippetdir.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_snippetdir.h   Sat Feb 17 15:21:50 2001
@@ -0,0 +1,35 @@
+/* $Id: mgd_snippetdir.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_SNIPPETDIR_H
+#define MGD_SNIPPETDIR_H
+
+extern MGD_FUNCTION(is_snippetdir_owner);
+extern MGD_FUNCTION(list_snippetdirs);
+extern MGD_FUNCTION(get_snippetdir);
+extern MGD_FUNCTION(get_snippetdir_by_path);
+extern MGD_FUNCTION(create_snippetdir);
+extern MGD_FUNCTION(update_snippetdir);
+extern MGD_FUNCTION(delete_snippetdir);
+extern MGD_FUNCTION(delete_snippetdir_tree);
+extern MGD_FUNCTION(copy_snippetdir);
+extern MGD_FUNCTION(move_snippetdir);
+
+#endif
Index: php4/ext/midgard/mgd_style.h
diff -u /dev/null php4/ext/midgard/mgd_style.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_style.h        Sat Feb 17 15:21:50 2001
@@ -0,0 +1,35 @@
+/* $Id: mgd_style.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_STYLE_H
+#define MGD_STYLE_H
+
+extern MGD_FUNCTION(is_style_owner);
+extern MGD_FUNCTION(list_styles);
+extern MGD_FUNCTION(get_style);
+extern MGD_FUNCTION(get_style_by_name);
+extern MGD_FUNCTION(create_style);
+extern MGD_FUNCTION(update_style);
+extern MGD_FUNCTION(delete_style);
+extern MGD_FUNCTION(copy_style);
+extern MGD_FUNCTION(move_style);
+extern MGD_FUNCTION(delete_style_tree);
+
+#endif
Index: php4/ext/midgard/mgd_topic.h
diff -u /dev/null php4/ext/midgard/mgd_topic.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mgd_topic.h        Sat Feb 17 15:21:50 2001
@@ -0,0 +1,37 @@
+/* $Id: mgd_topic.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef MGD_TOPCC_H
+#define MGD_TOPIC_H
+
+extern MGD_FUNCTION(is_topic_owner);
+extern MGD_FUNCTION(list_topics);
+extern MGD_FUNCTION(is_in_topic_tree);
+extern MGD_FUNCTION(get_topic);
+extern MGD_FUNCTION(get_topic_by_name);
+extern MGD_FUNCTION(create_topic);
+extern MGD_FUNCTION(update_topic);
+extern MGD_FUNCTION(update_topic_score);
+extern MGD_FUNCTION(delete_topic);
+extern MGD_FUNCTION(copy_topic);
+extern MGD_FUNCTION(move_topic);
+extern MGD_FUNCTION(delete_topic_tree);
+
+#endif
Index: php4/ext/midgard/midgard.c
diff -u /dev/null php4/ext/midgard/midgard.c:1.4
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/midgard.c  Sat Feb 17 15:21:50 2001
@@ -0,0 +1,700 @@
+/* $Id: midgard.c,v 1.4 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "php.h"
+#include "php_ini.h"
+#include "php_logos.h"
+#include "php_main.h"
+#include "SAPI.h"
+#include "ext/standard/info.h"
+#include "php_midgard.h"
+
+/* You should tweak config.m4 so this symbol (or some else suitable)
+   gets defined.
+*/
+#if HAVE_MIDGARD
+
+#include <http_config.h>
+#include "mgd_errno.h"
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+#include "mgd_mail.h"
+#include "mgd_article.h"
+#include "mgd_topic.h"
+#include "mgd_attachment.h"
+#include "mgd_element.h"
+#include "mgd_group.h"
+#include "mgd_file.h"
+#include "mgd_member.h"
+#include "mgd_host.h"
+#include "mgd_image.h"
+#include "mgd_calendar.h"
+#include "mgd_event.h"
+#include "mgd_eventmember.h"
+#include "mgd_page.h"
+#include "mgd_pageelement.h"
+#include "mgd_pagelink.h"
+#include "mgd_person.h"
+#include "mgd_preferences.h"
+#include "mgd_sitegroup.h"
+#include "mgd_snippet.h"
+#include "mgd_snippetdir.h"
+#include "mgd_style.h"
+#include "mgd_preparser.h"
+
+
+ZEND_DECLARE_MODULE_GLOBALS(midgard)
+
+/* True global resources - no need for thread safety here */
+/* DG: supress warning
+static int le_midgard;
+*/
+
+MGD_FUNCTION(errno);
+MGD_FUNCTION(errstr);
+MGD_FUNCTION(version);
+MGD_FUNCTION(get_midgard);
+MGD_FUNCTION(auth_midgard);
+
+/* Every user visible function must have an entry in midgard_functions[].
+*/
+function_entry midgard_functions[] = {
+PHP_FE(confirm_midgard_compiled,       NULL)           /* For testing, remove later. 
+*/
+MGD_FE(is_article_owner, NULL)
+MGD_FE(is_article_in_topic_tree, NULL)
+MGD_FE(list_topic_articles, NULL)
+MGD_FE(list_reply_articles, NULL)
+MGD_FE(list_topic_articles_all, NULL)
+MGD_FE(list_topic_articles_all_fast, NULL)
+MGD_FE(list_topic_articles_all_of_person, NULL)
+MGD_FE(get_article, NULL)
+MGD_FE(get_article_by_name, NULL)
+MGD_FE(get_reply_by_name, NULL)
+MGD_FE(create_article, NULL)
+MGD_FE(update_article_score, NULL)
+MGD_FE(update_article_created, NULL)
+MGD_FE(update_article_replyto, NULL)
+MGD_FE(update_article_type, NULL)
+MGD_FE(toggle_article_lock, NULL)
+MGD_FE(approve_article, NULL)
+MGD_FE(update_article, NULL)
+MGD_FE(delete_article, NULL)
+MGD_FE(copy_article, NULL)
+MGD_FE(move_article, NULL)
+MGD_FE(move_reply, NULL)
+MGD_FE(delete_article_tree, NULL)
+MGD_FE(open_attachment, NULL)
+MGD_FE(get_attachment, NULL)
+MGD_FE(serve_attachment, NULL)
+MGD_FE(stat_attachment, NULL)
+MGD_FE(delete_attachment, NULL)
+MGD_FE(update_attachment, NULL)
+//MGD_FE(errno, NULL)
+//MGD_FE(errstr, NULL)
+//MGD_FE(version, NULL)
+MGD_FE(is_topic_owner, NULL)
+MGD_FE(list_topics, NULL)
+MGD_FE(is_in_topic_tree, NULL)
+MGD_FE(get_topic, NULL)
+MGD_FE(get_topic_by_name, NULL)
+MGD_FE(create_topic, NULL)
+MGD_FE(update_topic, NULL)
+MGD_FE(update_topic_score, NULL)
+MGD_FE(delete_topic, NULL)
+MGD_FE(copy_topic, NULL)
+MGD_FE(move_topic, NULL)
+MGD_FE(delete_topic_tree, NULL)
+MGD_FE(list_elements, NULL)
+MGD_FE(get_element, NULL)
+MGD_FE(get_element_by_name, NULL)
+MGD_FE(create_element, NULL)
+MGD_FE(update_element, NULL)
+MGD_FE(delete_element, NULL)
+MGD_FE(copy_element, NULL)
+MGD_FE(move_element, NULL)
+MGD_FE(errno, NULL)
+MGD_FE(errstr, NULL)
+MGD_FE(version, NULL)
+MGD_FE(get_midgard, NULL)
+MGD_FE(auth_midgard, NULL)
+MGD_FE(create_mail, NULL)
+MGD_FE(is_group_owner, NULL)
+MGD_FE(list_groups, NULL)
+MGD_FE(get_group, NULL)
+MGD_FE(get_group_by_name, NULL)
+MGD_FE(create_group, NULL)
+MGD_FE(update_group, NULL)
+MGD_FE(delete_group, NULL)
+MGD_FE(list_files, NULL)
+MGD_FE(get_file, NULL)
+MGD_FE(create_file, NULL)
+MGD_FE(update_file, NULL)
+MGD_FE(delete_file, NULL)
+MGD_FE(list_members, NULL)
+MGD_FE(list_memberships, NULL)
+MGD_FE(get_member, NULL)
+MGD_FE(create_member, NULL)
+MGD_FE(update_member, NULL)
+MGD_FE(delete_member, NULL)
+MGD_FE(is_host_owner, NULL)
+MGD_FE(list_hosts, NULL)
+MGD_FE(get_host, NULL)
+MGD_FE(get_host_by_name, NULL)
+MGD_FE(create_host, NULL)
+MGD_FE(update_host, NULL)
+MGD_FE(delete_host, NULL)
+MGD_FE(list_images, NULL)
+#if 0
+MGD_FE(html_image, NULL)
+#endif
+MGD_FE(get_image, NULL)
+MGD_FE(create_image, NULL)
+MGD_FE(update_image, NULL)
+MGD_FE(delete_image, NULL)
+MGD_FE(list_topic_calendar_all, NULL)
+MGD_FE(list_topic_calendar_all_fast, NULL)
+MGD_FE(is_event_owner, NULL)
+MGD_FE(create_event, NULL)
+MGD_FE(update_event, NULL)
+MGD_FE(delete_event, NULL)
+MGD_FE(delete_event_tree, NULL)
+MGD_FE(get_event, NULL)
+MGD_FE(list_events, NULL)
+MGD_FE(list_events_between, NULL)
+MGD_FE(list_events_all, NULL)
+MGD_FE(list_events_all_between, NULL)
+MGD_FE(count_events_in_period, NULL)
+MGD_FE(count_events_in_month, NULL)
+MGD_FE(copy_event, NULL)
+MGD_FE(move_event, NULL)
+MGD_FE(create_event_member, NULL)
+MGD_FE(update_event_member, NULL)
+MGD_FE(delete_event_member, NULL)
+MGD_FE(get_event_member, NULL)
+MGD_FE(list_event_members, NULL)
+MGD_FE(count_event_members, NULL)
+MGD_FE(is_page_owner, NULL)
+MGD_FE(copy_page, NULL)
+MGD_FE(move_page, NULL)
+MGD_FE(list_pages, NULL)
+MGD_FE(is_in_page_tree, NULL)
+MGD_FE(get_page, NULL)
+MGD_FE(get_page_by_name, NULL)
+MGD_FE(create_page, NULL)
+MGD_FE(update_page, NULL)
+MGD_FE(delete_page, NULL)
+MGD_FE(page_has_children, NULL)
+MGD_FE(delete_page_tree, NULL)
+MGD_FE(list_page_elements, NULL)
+MGD_FE(get_page_element, NULL)
+MGD_FE(get_page_element_by_name, NULL)
+MGD_FE(create_page_element, NULL)
+MGD_FE(update_page_element, NULL)
+MGD_FE(delete_page_element, NULL)
+MGD_FE(copy_page_element, NULL)
+MGD_FE(move_page_element, NULL)
+MGD_FE(has_pagelinks, NULL)
+#if HAVE_MIDGARD_PAGELINKS
+MGD_FE(is_pagelink_owner, NULL)
+MGD_FE(list_pagelinks, NULL)
+MGD_FE(list_pagelinks_targeted_at, NULL)
+MGD_FE(get_pagelink, NULL)
+MGD_FE(get_pagelink_by_name, NULL)
+MGD_FE(create_pagelink, NULL)
+MGD_FE(update_pagelink, NULL)
+MGD_FE(delete_pagelink, NULL)
+#endif
+MGD_FE(is_person_owner, NULL)
+MGD_FE(is_member, NULL)
+MGD_FE(list_persons, NULL)
+MGD_FE(list_persons_in_department, NULL)
+MGD_FE(list_topic_persons, NULL)
+MGD_FE(list_persons_in_department_all, NULL)
+MGD_FE(list_topic_persons_all, NULL)
+MGD_FE(list_persons_in_office, NULL)
+MGD_FE(get_person, NULL)
+MGD_FE(create_person, NULL)
+MGD_FE(update_person, NULL)
+MGD_FE(update_password, NULL)
+MGD_FE(update_password_plain, NULL)
+MGD_FE(update_public, NULL)
+MGD_FE(delete_person, NULL)
+MGD_FE(list_preferences, NULL)
+MGD_FE(get_preference, NULL)
+MGD_FE(create_preference, NULL)
+MGD_FE(update_preference, NULL)
+MGD_FE(delete_preference, NULL)
+MGD_FE(has_sitegroups, NULL)
+#if HAVE_MIDGARD_SITEGROUPS
+MGD_FE(list_sitegroups, NULL)
+MGD_FE(create_sitegroup, NULL)
+MGD_FE(get_sitegroup, NULL)
+MGD_FE(update_sitegroup, NULL)
+MGD_FE(delete_sitegroup, NULL)
+#endif
+MGD_FE(snippet_exists, NULL)
+MGD_FE(list_snippets, NULL)
+MGD_FE(get_snippet, NULL)
+MGD_FE(get_snippet_by_name, NULL)
+MGD_FE(create_snippet, NULL)
+MGD_FE(update_snippet, NULL)
+MGD_FE(delete_snippet, NULL)
+MGD_FE(copy_snippet, NULL)
+MGD_FE(move_snippet, NULL)
+MGD_FE(is_snippetdir_owner, NULL)
+MGD_FE(list_snippetdirs, NULL)
+MGD_FE(get_snippetdir, NULL)
+MGD_FE(get_snippetdir_by_path, NULL)
+MGD_FE(create_snippetdir, NULL)
+MGD_FE(update_snippetdir, NULL)
+MGD_FE(delete_snippetdir, NULL)
+MGD_FE(delete_snippetdir_tree, NULL)
+MGD_FE(copy_snippetdir, NULL)
+MGD_FE(move_snippetdir, NULL)
+MGD_FE(is_style_owner, NULL)
+MGD_FE(list_styles, NULL)
+MGD_FE(get_style, NULL)
+MGD_FE(get_style_by_name, NULL)
+MGD_FE(create_style, NULL)
+MGD_FE(update_style, NULL)
+MGD_FE(delete_style, NULL)
+MGD_FE(copy_style, NULL)
+MGD_FE(move_style, NULL)
+MGD_FE(delete_style_tree, NULL)
+/* preparser functions */
+MGD_FE(template, NULL)
+MGD_FE(variable, NULL)
+MGD_FE(snippet, NULL)
+MGD_FE(eval, NULL)
+MGD_FE(register_filter, NULL)
+       {NULL, NULL, NULL}      /* Must be the last line in midgard_functions[] */
+};
+
+zend_module_entry midgard_module_entry = {
+       "midgard",
+       midgard_functions,
+       PHP_MINIT(midgard),
+       PHP_MSHUTDOWN(midgard),
+       PHP_RINIT(midgard),             /* Replace with NULL if there's nothing to do 
+at request start */
+       PHP_RSHUTDOWN(midgard), /* Replace with NULL if there's nothing to do at 
+request end */
+       PHP_MINFO(midgard),
+       STANDARD_MODULE_PROPERTIES
+};
+
+#ifdef COMPILE_DL_MIDGARD
+ZEND_GET_MODULE(midgard)
+#endif
+
+/* Remove comments and fill if you need to have entries in php.ini
+PHP_INI_BEGIN()
+PHP_INI_END()
+*/
+
+static void php_midgard_init_globals(zend_midgard_globals *midgard_globals)
+{
+       midgard_globals->rcfg = NULL;
+       midgard_globals->dcfg = NULL;
+       midgard_globals->mgd = NULL;
+       midgard_globals->mgd_errno = MGD_ERR_OK;
+       midgard_globals->udf = NULL;
+}
+
+PHP_MINIT_FUNCTION(midgard)
+{
+       MidgardClassPtr *midgard_class;
+
+       ZEND_INIT_MODULE_GLOBALS(midgard, php_midgard_init_globals, NULL);
+/* Remove comments if you have entries in php.ini
+       REGISTER_INI_ENTRIES();
+*/
+
+       for (midgard_class = MidgardClasses; midgard_class &&
+                                                       *midgard_class; 
+midgard_class++) {
+               if(*midgard_class && (*midgard_class)->name) {
+                       MGD_INIT_OVERLOADED_CLASS_ENTRY(
+                               (*midgard_class)->class_entry,
+                               (*midgard_class)->name,
+                               (*midgard_class)->methods,
+                               NULL,
+                               //(*midgard_class)->function_call,
+                               NULL,
+                               //(*midgard_class)->get_property,
+                               (*midgard_class)->set_property
+                       );
+               }
+      (*midgard_class)->entry_ptr =
+         zend_register_internal_class(&((*midgard_class)->class_entry));
+      assert((*midgard_class)->entry_ptr);
+   }
+       return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(midgard)
+{
+/* Remove comments if you have entries in php.ini
+       UNREGISTER_INI_ENTRIES();
+*/
+       return SUCCESS;
+}
+
+/* Remove if there's nothing to do at request start */
+PHP_RINIT_FUNCTION(midgard)
+{
+request_rec *r;
+module *midgard_module;
+
+   SLS_FETCH();
+   MGDLS_FETCH();
+
+       midgard_module = ap_find_linked_module("mod_midgard.c");
+       if (!midgard_module) {
+          MGDG(rcfg) = NULL;
+          MGDG(dcfg) = NULL;
+          return FAILURE;
+       }
+
+       /* Failure on Apache 1.3.18-dev (Marius) ??? */
+       r = ((request_rec *) SG(server_context));
+
+       MGDG(rcfg) = (midgard_request_config *)
+          ap_get_module_config(r->request_config, midgard_module);
+       if(MGDG(rcfg) == NULL) {
+               php_error(E_ERROR, "Cannot get midgard module config");
+               return FAILURE;
+       }
+       MGDG(dcfg) = (midgard_directory_config *)
+          ap_get_module_config(r->per_dir_config, midgard_module);
+       if(MGDG(rcfg) == NULL) {
+               php_error(E_ERROR, "Cannot get midgard module directory config");
+               return FAILURE;
+       }
+
+       MGDG(mgd) = MGDG(rcfg)->mgd;
+       ALLOC_INIT_ZVAL(MGDG(udf));
+       if(MGDG(udf)) array_init(MGDG(udf));
+       return SUCCESS;
+}
+
+/* Remove if there's nothing to do at request end */
+PHP_RSHUTDOWN_FUNCTION(midgard)
+{
+       zval *udf = mgd_getudf();
+       if(udf) zval_dtor(udf);
+
+       if (mgd_rcfg() == NULL && mgd_handle() != NULL) {
+               mgd_close(mgd_handle());
+               /* EEH: not safe! mgd_done(); */
+       }
+
+       return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(midgard)
+{
+       int i;
+       php_info_print_table_start();
+       php_info_print_table_header(2, "Midgard Support", "enabled");
+       php_info_print_table_row(2, "Midgard version", mgd_version());
+       i = 0;
+       /* TODO: pretify output by arranging functions according object classes */
+       while (midgard_module_entry.functions[i].fname) {
+               php_info_print_table_row(2, "", 
+midgard_module_entry.functions[i].fname);
+               i++;
+       }
+       php_info_print_table_end();
+       php_info_print_box_start(0);
+       PUTS("<H3><a href=\"http://www.midgard-project.org/\">");
+       PUTS("The Midgard Project Home Page</a></H3>\n");
+
+       php_printf("This program makes use of the Midgard Content Management 
+engine:<BR>");
+       php_printf("&copy; 1998-2001 The Midgard Project Ry - 2000-2001 Aurora 
+Linux</BR>\n");
+       php_info_print_box_end();
+
+       /* Remove comments if you have entries in php.ini
+       DISPLAY_INI_ENTRIES();
+       */
+}
+
+/* Remove the following function when you have succesfully modified config.m4
+   so that your module can be compiled into PHP, it exists only for testing
+   purposes. */
+
+/* Every user-visible function in PHP should document itself in the source */
+/* {{{ proto string confirm_midgard_compiled(string arg)
+   Return a string to confirm that the module is compiled in */
+PHP_FUNCTION(confirm_midgard_compiled)
+{
+       zval **arg;
+       int len;
+       char string[256];
+
+       if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+
+       convert_to_string_ex(arg);
+
+       len = sprintf(string, "Congratulations, you have successfully modified 
+ext/midgard/config.m4, module %s is compiled into PHP", Z_STRVAL_PP(arg));
+       RETURN_STRINGL(string, len, 1);
+}
+/* }}} */
+/* The previous line is meant for emacs, so it can correctly fold and unfold
+   functions in source code. See the corresponding marks just before function
+   definition, where the functions purpose is also documented. Please follow
+   this convention for the convenience of others editing your code.
+*/
+
+MGD_FUNCTION(errno)
+{
+   if (ZEND_NUM_ARGS() != 0) WRONG_PARAM_COUNT;
+
+    RETURN_LONG(mgd_get_errno());
+}
+
+MGD_FUNCTION(errstr)
+{
+   zval **errcode;
+   char *err;
+
+   switch(ZEND_NUM_ARGS()) {
+      case 0:
+         errcode = NULL;
+         break;
+      case 1:
+         if (zend_get_parameters_ex(1, &errcode)==FAILURE)
+            WRONG_PARAM_COUNT;
+         break;
+      default:
+         WRONG_PARAM_COUNT;
+   }
+
+   if (errcode) convert_to_long_ex(errcode);
+
+   err = mgd_errstr(errcode ? (*errcode)->value.lval : mgd_get_errno());
+
+   RETURN_STRING(err, 1);
+}
+
+MGD_FUNCTION(version)
+{
+   RETURN_STRING((char*)mgd_version(), 1);
+}
+
+/* Fetch static globals. Unfortunately these need to be here since the
+   module globals are declared static by the Zend macros
+*/
+midgard_request_config *mgd_rcfg()
+{
+   MGDLS_FETCH();
+   return MGDG(rcfg);
+}
+
+midgard_directory_config *mgd_dcfg()
+{
+   MGDLS_FETCH();
+   return MGDG(dcfg);
+}
+
+midgard *mgd_handle()
+{
+   MGDLS_FETCH();
+   return MGDG(mgd);
+}
+
+zval *mgd_getudf()
+{
+   MGDLS_FETCH();
+   return MGDG(udf);
+}
+
+void mgd_set_errno(int mgd_errno)
+{
+   MGDLS_FETCH();
+   if (MGDG(mgd_errno) == MGD_ERR_OK)
+      MGDG(mgd_errno) = mgd_errno;
+}
+
+int mgd_get_errno()
+{
+   MGDLS_FETCH();
+   return MGDG(mgd_errno);
+}
+
+MGD_FUNCTION(get_midgard)
+{
+       int i;
+       zval *argv;
+       char **mm_argv;
+   long mm_argc;
+       midgard *mgd = mgd_handle();
+       midgard_request_config *rcfg = mgd_rcfg();
+
+       if (rcfg == NULL) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_CONNECTED);
+       }
+
+       object_init(return_value);
+
+       add_property_long(return_value, "host", rcfg->host);
+       add_property_long(return_value, "style", rcfg->style);
+       add_property_long(return_value, "page", rcfg->resource.id);
+       add_property_long(return_value, "cookieauth", rcfg->auth.cookie);
+       add_property_long(return_value, "auth", rcfg->auth.required);
+       add_property_long(return_value, "author", rcfg->author);
+
+       add_property_long(return_value, "user", mgd_user(mgd));
+       add_property_long(return_value, "admin", mgd_isadmin(mgd));
+
+#if HAVE_MIDGARD_SITEGROUPS
+       add_property_long(return_value, "root", mgd_isroot(mgd));
+       add_property_long(return_value, "sitegroup", mgd_sitegroup(mgd));
+#endif
+
+       mm_argv = (char**)rcfg->argv->elts;
+       mm_argc = rcfg->argv->nelts;
+       add_property_long(return_value, "argc", mm_argc);
+
+       MAKE_STD_ZVAL(argv);
+       array_init(argv);
+       for (i = 0; i < mm_argc; i++) {
+               add_index_string(argv, i, mm_argv[i], 1);
+       }
+
+       /* EEH {HACK ALERT}: We add this property with hash_update
+          manually since Zend doesn't offer a add_property_array.
+        */
+       zend_hash_update(return_value->value.obj.properties, "argv", 5,
+                        &argv, sizeof(argv), NULL);
+
+       add_property_string(return_value, "uri", rcfg->req->uri, 1);
+
+       add_property_stringl(return_value, "self",
+                            rcfg->req->uri, rcfg->self_len, 1);
+}
+
+MGD_FUNCTION(auth_midgard)
+{
+       zval **username, **password, **send_cookie;
+       char *cookie1;
+       static const char *cookie2;
+       char cookie3[256];
+       static const char *u, *p;
+       int rv;
+       int sc;
+
+   request_rec *r;
+
+   SLS_FETCH();
+
+   r = ((request_rec *) SG(server_context));
+
+       CHECK_MGD;
+
+       RETVAL_FALSE;
+
+       switch (ZEND_NUM_ARGS()) {
+               case 2:
+                       if (zend_get_parameters_ex(2, &username, &password) !=
+                           SUCCESS) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       sc = 1;
+                       break;
+
+               case 3:
+                       if (zend_get_parameters_ex
+                           (3, &username, &password,
+                            &send_cookie) != SUCCESS) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       convert_to_boolean_ex(send_cookie);
+                       sc = (*send_cookie)->value.lval;
+                       break;
+
+               default:
+                       WRONG_PARAM_COUNT;
+                       break;
+       }
+
+       convert_to_string_ex(username);
+       convert_to_string_ex(password);
+
+       if ((*username)->value.str.len)
+               u = ap_pstrdup(mgd_rcfg()->pool, (*username)->value.str.val);
+       else
+               u = "";
+       if ((*password)->value.str.len)
+               p = ap_pstrdup(mgd_rcfg()->pool, (*password)->value.str.val);
+       else
+               p = "";
+
+       rv = mgd_auth(mgd_handle(), u, p);
+       if (rv >= 0 && sc) {
+               cookie1 = ap_psprintf(r->pool, "%s:%s",
+                                     (*username)->value.str.val,
+                                     (*password)->value.str.val);
+               cookie2 = ap_uuencode(r->pool, cookie1);
+               sprintf(cookie3,
+                       "MidgardLogin=%s;"
+                       " Expires=Friday, 1-Jan-%d10 12:00:00 GMT;"
+                       " Path=/", cookie2, mgd_user(mgd_handle())? 20 : 10);
+               ap_table_set(r->headers_out, "Set-Cookie",
+                            cookie3);
+       }
+
+       switch (rv) {
+               case MGD_AUTH_NOT_CONNECTED:
+                       RETURN_FALSE_BECAUSE(MGD_ERR_NOT_CONNECTED);
+
+               case MGD_AUTH_INVALID_NAME:
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_NAME);
+
+               case MGD_AUTH_SG_NOTFOUND:
+                       RETURN_FALSE_BECAUSE(MGD_ERR_SG_NOTFOUND);
+
+               case MGD_AUTH_DUPLICATE:
+                       RETURN_FALSE_BECAUSE(MGD_ERR_DUPLICATE);
+
+               case MGD_AUTH_NOTFOUND:
+                       RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+
+               case MGD_AUTH_REAUTH:
+               case MGD_AUTH_INVALID_PWD:
+                       RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+               default:
+                       if (rv >= 0) {
+                               RETVAL_TRUE;
+                       }
+                       else {
+                               RETURN_FALSE_BECAUSE(MGD_ERR_INTERNAL);
+                       }
+       }
+}
+
+#endif /* HAVE_MIDGARD */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
Index: php4/ext/midgard/mkall
diff -u /dev/null php4/ext/midgard/mkall:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/mkall      Sat Feb 17 15:21:50 2001
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+[ "x$1" != "x" ] && MIDGARD_PATH="=$1"
+
+[ -f Makefile ] && make distclean
+rm -f preparser-scanner.c preparser-parser.c preparser-parser.h
+phpize && ./configure --with-midgard$MIDGARD_PATH && make install
Index: php4/ext/midgard/oop.c
diff -u /dev/null php4/ext/midgard/oop.c:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/oop.c      Sat Feb 17 15:21:50 2001
@@ -0,0 +1,498 @@
+/* $Id: oop.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+typedef char *charp;
+void mgd_object_init(zval *obj, ...)
+{
+/* TODO: DG: not needed anymore cause php_midgard_bless initializes the object
+ * with all the properties (didn't check everywhere yet though)
+
+va_list args;
+char *propname;
+
+   va_start(args, obj);
+   while ((propname = va_arg(args, charp)) != NULL) {
+      add_property_unset(obj, propname);
+   }
+   va_end(args);
+*/
+}
+
+void php_midgard_bless(zval *object, MidgardClass *species)
+{
+       object_init_ex(object, species->entry_ptr);
+       php_midgard_ctor(object, species);
+}
+
+void php_midgard_ctor(zval *object, MidgardClass *species)
+{
+       MidgardProperty *midgard_props;
+
+       /* add default properties */
+       add_property_string(object, "__table__", (char*)species->table, 1);
+       add_property_long(object, "id", 0);
+       add_property_long(object, "sitegroup", 0);
+
+       /* add other properties */
+       for (midgard_props = species->properties; midgard_props && 
+                                                       midgard_props->name; 
+midgard_props++) {
+               switch(midgard_props->type) {
+                       case IS_LONG:
+                               add_property_long(object, midgard_props->name, 0);
+                               break;
+                       case IS_STRING:
+                               add_property_string(object, midgard_props->name, "", 
+1);
+                               break;
+                       default: /* should not happen, but just in case */
+                               add_property_unset(object, midgard_props->name);
+                               break;
+               }
+       }
+}
+
+void php_midgard_bless_oop(zval *object, MidgardClass *species)
+{
+   object_init_ex(object, species->entry_ptr);
+
+       add_property_string(object, "__table__", (char*)species->table, 1);
+       add_property_long(object, "id", 0);
+       add_property_long(object, "sitegroup", 0);
+}
+
+zval _midgard_getset_property(MidgardClass *species, 
+                                                         zend_property_reference 
+*property_reference,
+                                                         zval *value)
+{
+       zval result, **ppresult;
+       zval *object = property_reference->object;
+       
+       /* get the property name */
+       zend_llist_element *element = property_reference->elements_list->head;
+       zend_overloaded_element *property=(zend_overloaded_element *)element->data;
+       char * propname = property->element.value.str.val;
+       int proplen = property->element.value.str.len;
+
+       INIT_ZVAL(result);
+
+       if(value == NULL) {                                                     /* get 
+property */
+/* DG: this should never happen now (check midgard.c MINIT function,
+ * the get_property is set to NULL) */
+               if(zend_hash_find(object->value.obj.properties, propname, proplen+1,
+                                               (void **)&ppresult) == FAILURE) {
+                       php_error(E_WARNING,
+                                               "Midgard: Property '%s' is not a 
+member of %s",
+                                               propname, species->name);
+               } else {
+                       result = **ppresult;
+                       zval_copy_ctor(&result);
+                       return result;
+               }
+
+       } else if(strcasecmp("__table__", propname)) {  /* set r/w property */
+               zend_hash_update(object->value.obj.properties, propname, proplen+1,
+                                               &value, sizeof(zval *), NULL);
+       } else {                                                                       
+ /* cannot set ro property */
+               php_error(E_WARNING,
+                                               "Midgard: Write access to property 
+'%s' forbidden",
+                                               propname);
+       }
+       return result;
+}
+
+void php_midgard_delete(zval * return_value, const char *table, int id)
+{
+       if (!mgd_rcfg()) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_CONNECTED);
+   }
+
+       RETVAL_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+
+       if (mgd_delete(mgd_handle(), table, id)) {
+      RETURN_TRUE;
+   }
+
+   RETVAL_FALSE_BECAUSE(MGD_ERR_INTERNAL);
+
+   /* EEH: TODO: log_error(
+      "Midgard: delete of %s %d failed",
+         table ? table : "<null class>", id);
+   */
+}
+
+void php_midgard_delete_repligard(const char *table, int id)
+{
+       if (!mgd_rcfg())
+               return;
+
+       (void) mgd_delete_repligard(mgd_handle(), table, id);
+}
+
+void php_midgard_update(zval * return_value, const char *table,
+                       const char *fields, int id, ...)
+{
+   va_list args;
+   RETVAL_FALSE_BECAUSE(MGD_ERR_INTERNAL);
+
+       if (!mgd_rcfg()) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_CONNECTED);
+   }
+
+   va_start(args, id);
+       if (mgd_vupdate(mgd_handle(), table, id, fields, args)) {
+      RETVAL_TRUE;
+   }
+   else {
+      /* EEH: TODO: log_error(
+         "Midgard: update of %s %d failed",
+            table ? table : "<null class>", id);
+      */
+   }
+
+   va_end(args);
+}
+
+void php_midgard_create(zval * return_value, const char *table,
+                       const char *fields, const char *values, ...)
+{
+       va_list args;
+       int id;
+       CHECK_MGD;
+
+       RETVAL_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+
+       va_start(args, values);
+       id = mgd_vcreate(mgd_handle(), table, fields, values, args);
+       va_end(args);
+
+   if (!id) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_INTERNAL);
+
+      /* EEH: TODO: log_error(
+         "Midgard: create of %s failed",
+            table ? table : "<null class>"); */
+   }
+
+       RETVAL_LONG(id);
+}
+
+void php_midgard_select(MidgardClass *species, zval * return_value,
+                       const char *fields, const char *tables,
+                       const char *where, const char *order, ...)
+{
+       va_list args;
+       midgard_res *res;
+
+       if (!mgd_rcfg()) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_CONNECTED);
+   }
+
+       RETVAL_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+
+       va_start(args, order);
+       res =
+          mgd_sitegroup_vselect(mgd_handle(), fields, tables, where, order,
+                                args);
+       va_end(args);
+       if (res) {
+               php_midgard_bless_oop(return_value, species);
+               add_property_long(return_value, "N", mgd_rows(res));
+               add_property_long(return_value, "__res__", (long) res);
+       }
+}
+
+#if HAVE_MIDGARD_SITEGROUPS
+void php_midgard_sitegroup_get(MidgardClass *species, zval * return_value,
+               int grouped, const char *fields, const char *table, int id);
+void php_midgard_get(MidgardClass *species, zval * return_value,
+                    const char *fields, const char *table, int id)
+{
+       php_midgard_sitegroup_get(species, return_value, 1, fields, table, id);
+}
+
+void php_midgard_sitegroup_get(MidgardClass *species, zval * return_value,
+               int grouped, const char *fields, const char *table, int id)
+#else
+void php_midgard_get(MidgardClass *species, zval * return_value,
+                    const char *fields, const char *table, int id)
+#endif
+{
+       midgard_res *res;
+       int i;
+       midgard_res *params = NULL;
+       midgard_pool *pool = NULL;
+       char *propname, *value=NULL;
+
+       if (!mgd_rcfg()) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_CONNECTED);
+   }
+
+       RETVAL_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       if (grouped)
+               res = mgd_sitegroup_record(mgd_handle(), fields, table, id);
+       else
+               res = mgd_ungrouped_record(mgd_handle(), fields, table, id);
+#else
+       res = mgd_ungrouped_record(mgd_handle(), fields, table, id);
+#endif
+       if (res && mgd_fetch(res)) {
+               php_midgard_bless_oop(return_value, species);
+
+               params =
+                  mgd_ungrouped_select(mgd_handle(), "domain,name,value",
+                                       "record_extension",
+                                       "tablename=$q AND oid=$d", NULL, table,
+                                       id);
+               if (params) {
+                       pool = mgd_alloc_pool();
+                       while (mgd_fetch(params)) {
+                               propname =
+                                  mgd_format(mgd_handle(), pool, "$s_$s",
+                                             mgd_colvalue(params, 0),
+                                             mgd_colvalue(params, 1));
+                               add_property_string(return_value, propname,
+                                                   (char*)mgd_colvalue (params, 2), 
+1);
+                       }
+               }
+
+               for (i = 0; i < mgd_cols(res); i++) {
+                       if((value = (char *)mgd_colvalue(res, i)) == NULL ) {
+                               value = "";
+                       }
+                       add_property_string(return_value,
+                                           (char*)mgd_colname(res, i),
+                                           value, 1);
+               }
+       }
+
+       if (res)
+               mgd_release(res);
+       if (params)
+               mgd_release(params);
+       if (pool)
+               mgd_free_pool(pool);
+}
+
+/*
+  midgard_get_by_name is responsible for returning topics and articles using
+  their names instead ids. In other aspects it is equal to midgard_get.
+  Additional parameters are:
+  idfield - name of field used for id compare (should be 'topic' for article
+            and 'up' for topic)
+  parent_id      - id of idfield of seeking record (father's id for topic & article)
+  name    - name of topic or article
+  It allows to use equal names of articles and subtopics under different topics
+*/
+
+void php_midgard_get_by_name(MidgardClass *species, zval * return_value,
+                            const char *fields, const char *table,
+                            const char *idfield, int parent_id, const char *name)
+{
+       midgard_res *res;
+       char * value=NULL;
+       int i;
+       CHECK_MGD;
+
+       RETVAL_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+
+       res =
+          mgd_record_by_name(mgd_handle(), fields, table, idfield,
+         parent_id, name);
+       if (res && mgd_fetch(res)) {
+               php_midgard_bless_oop(return_value, species);
+               for (i = 0; i < mgd_cols(res); i++) {
+                       if((value = (char *)mgd_colvalue(res, i)) == NULL ) {
+                               value = "";
+                       }
+                       add_property_string(return_value,
+                                           (char*)mgd_colname(res, i),
+                                           value, 1);
+               }
+       }
+       if (res)
+               mgd_release(res);
+}
+
+void php_midgard_get_by_name2(MidgardClass *species, zval * return_value,
+                             const char *fields, const char *table,
+                             const char *firstfield, const char *first,
+                             const char *secondfield, const char *second)
+{
+       midgard_res *res;
+       char *value=NULL;
+       int i;
+
+       CHECK_MGD;
+
+       RETVAL_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+
+       res = mgd_record_by_name2(mgd_handle(), fields, table,
+                                 firstfield, first, secondfield, second);
+       if (res && mgd_fetch(res)) {
+               php_midgard_bless_oop(return_value, species);
+               for (i = 0; i < mgd_cols(res); i++) {
+                       if((value = (char *)mgd_colvalue(res, i)) == NULL ) {
+                               value = "";
+                       }
+                       add_property_string(return_value,
+                                           (char*)mgd_colname(res, i),
+                                           value, 1);
+               }
+       }
+       if (res)
+               mgd_release(res);
+}
+
+void php_midgard_get_by_name_only(MidgardClass *species, zval * return_value,
+                                 const char *fields, const char *table,
+                                 const char *name)
+{
+       midgard_res *res;
+       int i;
+       char *value=NULL;
+       CHECK_MGD;
+
+       RETVAL_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+
+       res = mgd_record_by_name_only(mgd_handle(), fields, table, name);
+       if (res && mgd_fetch(res)) {
+               php_midgard_bless_oop(return_value, species);
+               for (i = 0; i < mgd_cols(res); i++) {
+                       if((value = (char *)mgd_colvalue(res, i)) == NULL ) {
+                               value = "";
+                       }
+                       add_property_string(return_value,
+                                           (char*)mgd_colname(res, i),
+                                           value, 1);
+               }
+       }
+       if (res)
+               mgd_release(res);
+}
+
+MGD_FUNCTION(oop_guid_get)
+{
+       zval *self;
+       zval **zv_table, **zv_id;
+       midgard_pool *pool;
+       char *guid;
+
+       CHECK_MGD;
+
+       if ((self = getThis()) == NULL) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+       }
+
+       if (zend_hash_find
+           (self->value.obj.properties, "__table__", 10,
+            (void **) &zv_table) != SUCCESS) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+
+       if (zend_hash_find
+           (self->value.obj.properties, "id", 3,
+            (void **) &zv_id) !=
+           SUCCESS) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+
+       if (ZEND_NUM_ARGS() != 0) {
+               WRONG_PARAM_COUNT;
+       }
+
+       pool = mgd_pool(mgd_handle());
+       guid =
+          mgd_repligard_guid(mgd_handle(), pool, (*zv_table)->value.str.val,
+                             (*zv_id)->value.lval);
+       if (guid) {
+               RETVAL_STRING(guid, 1);
+               mgd_free_from_pool(pool, guid);
+       }
+       else {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+       }
+}
+
+MGD_FUNCTION(oop_list_fetch)
+{
+       zval *self;
+       zval **key;
+       midgard_res *res;
+   int i;
+
+       CHECK_MGD;
+       RETVAL_FALSE;
+
+       if ((self = getThis()) == NULL) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+
+       if (zend_hash_find(self->value.obj.properties, "__res__", 8, (void
+                                                                     **) &key)
+           != SUCCESS) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+   }
+
+   if ((res = (midgard_res *) (*key)->value.lval) == NULL) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+   }
+
+   if (mgd_fetch(res)) {
+      for (i = 0; i < mgd_cols(res); i++)
+         add_property_string(self, (char*)mgd_colname(res, i),
+            (char*)mgd_colvalue(res, i), 1);
+      RETVAL_TRUE;
+   } else {
+      mgd_release(res);
+      zend_hash_del(self->value.obj.properties, "__res__", 8);
+
+      RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+   }
+}
+
+MidgardClassPtr MidgardClasses [] = {
+   &MidgardArticle,
+   &MidgardAttachment,
+   &MidgardElement,
+   &MidgardEvent,
+   &MidgardEventMember,
+   &MidgardFile,
+   &MidgardGroup,
+   &MidgardHost,
+   &MidgardImage,
+   &MidgardMember,
+   &MidgardPage,
+   &MidgardPageElement,
+   &MidgardParameter,
+   &MidgardPerson,
+   &MidgardPreferences,
+#if HAVE_MIDGARD_SITEGROUPS
+   &MidgardSitegroup,
+#endif
+   &MidgardSnippet,
+   &MidgardSnippetdir,
+   &MidgardStyle,
+   &MidgardTopic,
+   NULL
+};
Index: php4/ext/midgard/page.c
diff -u /dev/null php4/ext/midgard/page.c:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/page.c     Sat Feb 17 15:21:50 2001
@@ -0,0 +1,334 @@
+/* $Id: page.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(is_page_owner)
+{
+    IDINIT;
+    CHECK_MGD;
+    RETVAL_LONG(ispageowner(id));
+}
+
+MGD_FUNCTION(copy_page)
+{
+    zval **id, **root; int id_r;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    if (ZEND_NUM_ARGS() != 2
+       || zend_get_parameters_ex(2, &id, &root) != SUCCESS)
+       WRONG_PARAM_COUNT;
+    convert_to_long_ex(id);
+    convert_to_long_ex(root);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* root must be in same SG or be 0 */
+       if ((*root)->value.lval != 0 && !mgd_exists_bool(mgd_handle(), "page src, page 
+tgt",
+                                                                               
+"src.id=$d AND tgt.id=$d"
+                                                                               " AND 
+(src.sitegroup=tgt.sitegroup"
+                                                                                      
+ " OR src.sitegroup=0"
+                                                                                      
+ " OR tgt.sitegroup=0)",
+                                                                               
+(*id)->value.lval,(*root)->value.lval)) 
+RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+    id_r = mgd_copy_page(mgd_handle(),  (*id)->value.lval);
+    if(id_r) {
+      php_midgard_update(return_value, "page", "up=$i", id_r, (*root)->value.lval);
+      PHP_UPDATE_REPLIGARD("page",id_r);
+    }
+       RETVAL_LONG(id_r);
+}
+
+MGD_FUNCTION(list_pages)
+{
+    IDINIT;
+       CHECK_MGD;
+    php_midgard_select(&MidgardPage, return_value, "page.id AS 
+id,name,style,title,changed,author,"
+              NAME_FIELD " AS authorname", "page,person",
+              "up=$d AND person.id=page.author", "name", id);
+}
+
+MGD_FUNCTION(is_in_page_tree)
+{
+    zval **root, **page;
+    int *ids, i;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    if (ZEND_NUM_ARGS() != 2
+       || zend_get_parameters_ex(2, &root, &page) != SUCCESS)
+       WRONG_PARAM_COUNT;
+    convert_to_long_ex(root);
+    convert_to_long_ex(page);
+
+    ids = mgd_tree(mgd_handle(), "page", (*root)->value.lval, 0, NULL);
+       if (ids)
+               for (i = 0; ids[i]; i++)
+                       if (ids[i] == (*page)->value.lval) RETURN_TRUE;
+}
+
+MGD_FUNCTION(get_page)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+               case 0:
+               php_midgard_bless(return_value, &MidgardPage);
+               mgd_object_init(return_value, "up", "name", "style", "title", 
+"content", "author", "auth", "active", NULL);
+                       return;
+               case 1:
+                       if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                               convert_to_long_ex(id);
+                               break;
+                       } /* else fall through */
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+    php_midgard_get(&MidgardPage, return_value, 
+"id,up,name,style,title,changed,content,author,"
+           "info&1=1 AS auth,info&2=2 AS active",
+           "page", (*id)->value.lval);
+}
+
+MGD_FUNCTION(get_page_by_name)
+{
+    zval **root, **page;
+       CHECK_MGD;
+    if (ZEND_NUM_ARGS() != 2
+       || zend_get_parameters_ex(2, &root, &page) != SUCCESS)
+       WRONG_PARAM_COUNT;
+    convert_to_long_ex(root);
+    convert_to_string_ex(page);
+
+    php_midgard_get_by_name(&MidgardPage, return_value, 
+"id,up,name,style,title,changed,content,author,"
+           "info&1=1 AS auth,info&2=2 AS active",
+           "page", "up", (*root)->value.lval, (*page)->value.str.val);
+}
+
+MGD_FUNCTION(create_page)
+{
+       zval **up, **name, **style, **title, **content, **author, **auth, **active, 
+*self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "up", up)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "style", style)
+                   || !MGD_PROPFIND(self, "title", title)
+                   || !MGD_PROPFIND(self, "content", content)
+                   || !MGD_PROPFIND(self, "author", author)
+                   || !MGD_PROPFIND(self, "auth", auth)
+                   || !MGD_PROPFIND(self, "active", active)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 8
+                   || zend_get_parameters_ex(8, &up, &name, &style, &title,
+                                    &content, &author, &auth,
+                                    &active) == FAILURE) WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(up);
+       convert_to_string_ex(name);
+       convert_to_long_ex(style);
+       convert_to_string_ex(title);
+       convert_to_string_ex(content);
+       convert_to_long_ex(author);
+       convert_to_long_ex(auth);
+       convert_to_long_ex(active);
+
+       if (!ispageowner((*up)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       if ((*up)->value.lval != 0
+           && mgd_exists_id(mgd_handle(), "page", "up=$d AND name=$q",
+                            (*up)->value.lval, (*name)->value.str.val))
+               RETURN_FALSE_BECAUSE(MGD_ERR_DUPLICATE);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* up must be in same SG or be 0 */
+       if ((*up)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "page",
+                                                 "id=$d",
+                                                 (*up)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+       /* style must be in same SG or be 0 */
+       if ((*style)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "style",
+                                                    "id=$d",
+                                                    (*style)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+       /* author must be in same SG or be 0 */
+       if ((*author)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "person",
+                                                     "id=$d",
+                                                     (*author)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+       php_midgard_create(return_value, "page",
+                          "up,name,style,title,changed,content,author,info",
+                          "$d,$q,$d,$q,Curdate(),$q,$d,$d",
+                          (*up)->value.lval, (*name)->value.str.val,
+                          (*style)->value.lval, (*title)->value.str.val,
+                          (*content)->value.str.val, (*author)->value.lval,
+                          ((*auth)->value.lval == 1) | ((*active)->value.lval ==
+                                                     1) << 1);
+
+       PHP_CREATE_REPLIGARD("page", return_value->value.lval);
+}
+
+MGD_FUNCTION(update_page)
+{
+       zval **id, **name, **style, **title, **content, **author, **auth, **active, 
+*self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "id", id)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "style", style)
+                   || !MGD_PROPFIND(self, "title", title)
+                   || !MGD_PROPFIND(self, "content", content)
+                   || !MGD_PROPFIND(self, "author", author)
+                   || !MGD_PROPFIND(self, "auth", auth)
+                   || !MGD_PROPFIND(self, "active", active)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 8
+                   || zend_get_parameters_ex(8, &id, &name, &style, &title,
+                                    &content, &author, &auth,
+                                    &active) == FAILURE) WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(id);
+       convert_to_string_ex(name);
+       convert_to_long_ex(style);
+       convert_to_string_ex(title);
+       convert_to_string_ex(content);
+       convert_to_long_ex(author);
+       convert_to_long_ex(auth);
+       convert_to_long_ex(active);
+
+       if (!ispageowner((*id)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* style must be in same SG or be 0 */
+       if ((*style)->value.lval != 0
+           && !mgd_exists_bool(mgd_handle(), "page,style",
+                               "page.id=$d AND style.id=$d"
+                               " AND (page.sitegroup=style.sitegroup"
+                               " OR page.sitegroup=0" " OR style.sitegroup=0)",
+                               (*id)->value.lval, (*style)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+       /* author must be in same SG or be 0 */
+       if ((*author)->value.lval != 0
+           && !mgd_exists_bool(mgd_handle(), "page,person",
+                               "page.id=$d AND person.id=$d"
+                               " AND (page.sitegroup=person.sitegroup"
+                               " OR page.sitegroup=0"
+                               " OR person.sitegroup=0)", (*id)->value.lval,
+                               (*author)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+       php_midgard_update(return_value, "page",
+                          "name=$q,style=$d,title=$q,changed=Curdate(),"
+                          "content=$q,author=$d,info=$d", (*id)->value.lval,
+                          (*name)->value.str.val, (*style)->value.lval,
+                          (*title)->value.str.val, (*content)->value.str.val,
+                          (*author)->value.lval,
+                          ((*auth)->value.lval == 1) | ((*active)->value.lval == 1) 
+<< 1);
+       PHP_UPDATE_REPLIGARD("page", (*id)->value.lval);
+}
+
+MGD_FUNCTION(delete_page)
+{
+    IDINIT;
+       CHECK_MGD;
+    if(mgd_has_dependants(mgd_handle(),id,"page")
+           || mgd_exists_id(mgd_handle(), "page", "up=$d", id)
+           || mgd_exists_id(mgd_handle(), "host", "root=$d", id)) 
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+    if (!ispageowner(id))
+       RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       /* check for page elements */
+    if (mgd_exists_id(mgd_handle(), "pageelement", "page=$d", id)) 
+RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+#if HAVE_MIDGARD_PAGELINKS
+       /* check for page links */
+    if (mgd_exists_id(mgd_handle(), "pagelink", "$d IN (up,target)", id))
+    RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+#endif
+
+    php_midgard_delete(return_value, "page", id);
+    PHP_DELETE_REPLIGARD("page", id);
+}
+
+MGD_FUNCTION(page_has_children)
+{
+    IDINIT;
+       CHECK_MGD;
+   RETVAL_FALSE;
+    if (mgd_exists_id(mgd_handle(), "page", "up=$d", id)) { RETVAL_TRUE; }
+}
+MGD_FUNCTION(delete_page_tree)
+{
+    IDINIT;
+       CHECK_MGD;
+   RETVAL_FALSE;
+    if (!ispageowner(mgd_idfield(mgd_handle(), "up", "page", id)))
+       RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+    if(mgd_exists_id(mgd_handle(), "host", "root=$d", id)) 
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+    if(mgd_delete_page(mgd_handle(),  id))
+      RETVAL_TRUE;
+}
+
+MGD_MOVE_FUNCTION(page,page,page,up)
+
+MidgardProperty MidgardPageProperties [] = {
+       { IS_LONG,              "up"            },
+       { IS_STRING,    "name"          },
+       { IS_STRING,    "title"         },
+       { IS_STRING,    "content"       },
+       { IS_LONG,              "style"         },
+       { IS_LONG,              "author"        },
+       { IS_LONG,              "auth"          },
+       { IS_LONG,              "active"        },
+       { 0,                    NULL            }
+};
+MIDGARD_CLASS(MidgardPage, page)
Index: php4/ext/midgard/pageelement.c
diff -u /dev/null php4/ext/midgard/pageelement.c:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/pageelement.c      Sat Feb 17 15:21:50 2001
@@ -0,0 +1,225 @@
+/* $Id: pageelement.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(list_page_elements)
+{
+    IDINIT;
+       CHECK_MGD;
+    php_midgard_select(&MidgardPageElement, return_value, "id,name", "pageelement", 
+"page=$d", "name", id);
+}
+
+MGD_FUNCTION(get_page_element)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+               php_midgard_bless(return_value, &MidgardPageElement);
+               mgd_object_init(return_value, "page", "name", "value", "inherit", 
+NULL);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+    php_midgard_get(&MidgardPageElement, return_value, "id,page,name,value,info&1 AS 
+inherit",
+           "pageelement", (*id)->value.lval);
+}
+
+MGD_FUNCTION(get_page_element_by_name)
+{
+    zval **page, **name;
+       CHECK_MGD;
+    if (ZEND_NUM_ARGS() != 2
+       || zend_get_parameters_ex(2, &page, &name) != SUCCESS)
+       WRONG_PARAM_COUNT;
+    convert_to_long_ex(page);
+    convert_to_string_ex(name);
+    php_midgard_get_by_name(&MidgardPageElement, return_value, 
+"id,page,name,value,info&1 AS inherit",
+           "pageelement", "page", (*page)->value.lval, (*name)->value.str.val);
+}
+
+MGD_FUNCTION(create_page_element)
+{
+   zval **page, **name, **value, **inherit, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "page", page)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "value", value)
+                   || !MGD_PROPFIND(self, "inherit", inherit)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 4
+                   || zend_get_parameters_ex(4, &page, &name, &value,
+                                    &inherit) != SUCCESS) WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(page);
+       convert_to_string_ex(name);
+       convert_to_string_ex(value);
+       convert_to_long_ex(inherit);
+
+       if (!(*page)->value.lval || !mgd_exists_id(mgd_handle(), "page", "id=$d",
+                                               (*page)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+
+       if (!ispageowner((*page)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       if (mgd_exists_id(mgd_handle(), "pageelement", "page=$d AND name=$q",
+                         (*page)->value.lval, (*name)->value.str.val))
+               RETURN_FALSE_BECAUSE(MGD_ERR_DUPLICATE);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* page must be in same SG or be 0 */
+       if ((*page)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "page",
+                                                   "id=$d",
+                                                   (*page)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+       php_midgard_create(return_value, "pageelement", "page,name,value,info",
+                          "$d,$q,$q,$d", (*page)->value.lval, (*name)->value.str.val,
+                          (*value)->value.str.val, ((*inherit)->value.lval != 0));
+
+       PHP_CREATE_REPLIGARD("pageelement", return_value->value.lval);
+}
+
+MGD_FUNCTION(update_page_element)
+{
+       zval **id, **name, **value, **inherit, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "id", id)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "value", value)
+                   || !MGD_PROPFIND(self, "inherit", inherit)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 4
+                   || zend_get_parameters_ex(4, &id, &name, &value,
+                                    &inherit) != SUCCESS) WRONG_PARAM_COUNT;
+       }
+       convert_to_long_ex(id);
+       convert_to_string_ex(name);
+       convert_to_string_ex(value);
+       convert_to_long_ex(inherit);
+
+       if (!ispageowner(mgd_idfield(mgd_handle(), "page", "pageelement",
+                                    (*id)->value.lval)))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       php_midgard_update(return_value, "pageelement",
+                          "name=$q,value=$q,info=$d", (*id)->value.lval,
+                          (*name)->value.str.val, (*value)->value.str.val,
+                          ((*inherit)->value.lval != 0));
+       PHP_UPDATE_REPLIGARD("pageelement", (*id)->value.lval);
+}
+
+MGD_FUNCTION(delete_page_element)
+{
+    IDINIT;
+       CHECK_MGD;
+    if(mgd_has_dependants(mgd_handle(),id,"pageelement"))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+    if (!ispageowner(mgd_idfield(mgd_handle(), "page", "pageelement", id)))
+      RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+    php_midgard_delete(return_value, "pageelement", id);
+    PHP_DELETE_REPLIGARD("pageelement", id);
+}
+
+MGD_FUNCTION(copy_page_element)
+{
+    zval **id, **newpage;
+       RETVAL_FALSE;
+       CHECK_MGD;
+    switch (ZEND_NUM_ARGS()) {
+       case 2:
+           if (zend_get_parameters_ex(2, &id, &newpage) != SUCCESS)
+               WRONG_PARAM_COUNT;
+       break;
+       case 1:
+           if (zend_get_parameters_ex(1, &id) != SUCCESS)
+               WRONG_PARAM_COUNT;
+           newpage = NULL;
+       break;
+       default:
+               WRONG_PARAM_COUNT;
+    }
+    
+    convert_to_long_ex(id);
+    if(newpage) convert_to_long_ex(newpage);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* newpage must be in same SG or be 0 */
+       if (newpage && (*newpage)->value.lval != 0
+               && !mgd_exists_bool(mgd_handle(), "page src,page tgt",
+                                                                               
+"src.id=$d AND tgt.id=$d"
+                                                                               " AND 
+(src.sitegroup=tgt.sitegroup"
+                                                                                      
+ " OR src.sitegroup=0"
+                                                                                      
+ " OR tgt.sitegroup=0)",
+                                                                               
+(*id)->value.lval, (*newpage)->value.lval)) 
+RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+    RETVAL_LONG(mgd_copy_page_element(mgd_handle(), (*id)->value.lval, 
+       newpage ? (*newpage)->value.lval : 0));
+
+}
+
+
+MGD_MOVE_FUNCTION(pageelement,page,page_element,page)
+
+MidgardProperty MidgardPageElementProperties [] = {
+       { IS_LONG,              "page"          },
+       { IS_STRING,    "name"          },
+       { IS_STRING,    "value"         },
+       { IS_LONG,              "inherit"       },
+       { 0,                    NULL            }
+};
+MIDGARD_CLASS(MidgardPageElement, page_element)
Index: php4/ext/midgard/pagelink.c
diff -u /dev/null php4/ext/midgard/pagelink.c:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/pagelink.c Sat Feb 17 15:21:50 2001
@@ -0,0 +1,284 @@
+/* $Id: pagelink.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(has_pagelinks)
+{
+#if HAVE_MIDGARD_PAGELINKS
+       RETURN_TRUE;
+#else
+       RETURN_FALSE;
+#endif
+}
+
+#if HAVE_MIDGARD_PAGELINKS
+/* pagelink */
+
+MGD_FUNCTION(is_pagelink_owner)
+{
+    IDINIT;
+    CHECK_MGD;
+    RETVAL_LONG(ispagelinkowner(id));
+}
+
+
+MGD_FUNCTION(list_pagelinks)
+{
+    IDINIT;
+       CHECK_MGD;
+    php_midgard_select(&MidgardPagelink, return_value,
+               "pagelink.id AS id,"
+               "pagelink.name AS name,"
+               "pagelink.grp,"
+               "pagelink.up,"
+               "pagelink.target,"
+               "page.name AS pname,"
+               "page.style,"
+               "page.title,"
+               "page.changed,"
+               "page.author,"
+           NAME_FIELD " AS authorname",
+               "pagelink,page,person",
+           "pagelink.up=$d AND pagelink.target=page.id AND person.id=page.author",
+               "pagelink.name", id);
+}
+
+MGD_FUNCTION(list_pagelinks_targeted_at)
+{
+    IDINIT;
+       CHECK_MGD;
+    php_midgard_select(&MidgardPagelink, return_value,
+               "pagelink.id AS id,"
+               "pagelink.name AS name,"
+               "pagelink.grp,"
+               "pagelink.up,"
+               "pagelink.target,"
+               "page.name AS pname,"
+               "page.style,"
+               "page.title,"
+               "page.changed,"
+               "page.author,"
+           NAME_FIELD " AS authorname",
+               "pagelink,page,person",
+           "pagelink.target=$d AND pagelink.up=page.id AND person.id=page.author",
+               "pagelink.name", id);
+}
+
+MGD_FUNCTION(get_pagelink)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+               php_midgard_bless(return_value, &MidgardPagelink);
+               mgd_object_init(return_value, "up", "name", "target", "grp", "owner", 
+NULL);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+    php_midgard_get(&MidgardPagelink, return_value, "id,up,name,target,grp,owner",
+           "pagelink", (*id)->value.lval);
+}
+
+MGD_FUNCTION(get_pagelink_by_name)
+{
+    zval **root, **pagelink;
+       CHECK_MGD;
+    if (ZEND_NUM_ARGS() != 2
+       || zend_get_parameters_ex(2, &root, &pagelink) != SUCCESS)
+       WRONG_PARAM_COUNT;
+    convert_to_long_ex(root);
+    convert_to_string_ex(pagelink);
+
+    php_midgard_get_by_name(&MidgardPagelink, return_value, 
+"id,up,name,target,grp,owner",
+           "pagelink", "up", (*root)->value.lval, (*pagelink)->value.str.val);
+}
+
+MGD_FUNCTION(create_pagelink)
+{
+    zval **up, **name, **target, **grp, **owner, *self;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+
+   if ((self = getThis()) != NULL) {
+      if (ZEND_NUM_ARGS() != 0) { WRONG_PARAM_COUNT; }
+
+      if (!MGD_PROPFIND(self, "up", up)
+            || !MGD_PROPFIND(self, "name", name)
+            || !MGD_PROPFIND(self, "target", target)
+            || !MGD_PROPFIND(self, "grp", grp)
+            || !MGD_PROPFIND(self, "owner", owner)
+            ) {
+         RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+      }
+   } else {
+    if (ZEND_NUM_ARGS() != 5
+               || zend_get_parameters_ex(5, &up, &name, &target, &grp, &owner) == 
+FAILURE)
+       WRONG_PARAM_COUNT;
+   }
+
+    convert_to_long_ex(up);
+    convert_to_string_ex(name);
+    convert_to_long_ex(target);
+    convert_to_long_ex(grp);
+    convert_to_long_ex(owner);
+
+    if (!(*up)->value.lval || !ispageowner((*up)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+    if (!(*target)->value.lval || !ispageowner((*target)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       if (mgd_exists_id(mgd_handle(), "pagelink", "up=$d AND name=$q and grp=$d",
+                                 (*up)->value.lval, (*name)->value.str.val, 
+(*grp)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_DUPLICATE);
+       
+#if HAVE_MIDGARD_SITEGROUPS
+       /* up must be in same SG or be 0 */
+       if ((*up)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "page",
+                       "id=$d AND sitegroup IN (0,$d)",
+       (*up)->value.lval, mgd_sitegroup(mgd_handle())))
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+       /* target must be in same SG or be 0 */
+       if ((*target)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "page",
+                       "id=$d AND sitegroup IN (0,$d)",
+       (*target)->value.lval, mgd_sitegroup(mgd_handle())))
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+       /* grp must be in same SG or be 0 */
+       if ((*grp)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "grp",
+                       "id=$d AND sitegroup IN (0,$d)",
+                       (*grp)->value.lval, mgd_sitegroup(mgd_handle())))
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+       /* owner must be in same SG or be 0 */
+       if ((*owner)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "grp",
+                       "id=$d AND sitegroup IN (0,$d)",
+                       (*owner)->value.lval, mgd_sitegroup(mgd_handle())))
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+    php_midgard_create(return_value, "pagelink",
+                                  "up,name,target,grp,owner",
+                                  "$d,$q,$d,$d,$d",
+                                  (*up)->value.lval, (*name)->value.str.val,
+                                  (*target)->value.lval,
+                                  (*grp)->value.lval, (*owner)->value.lval);
+    PHP_CREATE_REPLIGARD("pagelink",return_value->value.lval);
+}
+
+MGD_FUNCTION(update_pagelink)
+{
+    zval **id, **name, **target, **grp, **owner, *self;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+   if ((self = getThis()) != NULL) {
+      if (ZEND_NUM_ARGS() != 0) { WRONG_PARAM_COUNT; }
+
+      if (!MGD_PROPFIND(self, "id", id)
+            || !MGD_PROPFIND(self, "name", name)
+            || !MGD_PROPFIND(self, "target", target)
+            || !MGD_PROPFIND(self, "grp", grp)
+            || !MGD_PROPFIND(self, "owner", owner)
+            ) {
+         RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+      }
+   } else {
+    if (ZEND_NUM_ARGS() != 5
+       || zend_get_parameters_ex(5, &id, &name, &target, &grp, &owner) == FAILURE)
+       WRONG_PARAM_COUNT;
+   }
+
+    convert_to_long_ex(id);
+    convert_to_string_ex(name);
+    convert_to_long_ex(target);
+    convert_to_long_ex(grp);
+    convert_to_long_ex(owner);
+
+    if (!ispagelinkowner((*id)->value.lval)
+                       || !ispageowner((*target)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* target must be in same SG or be 0 */
+       if ((*target)->value.lval == 0 || !mgd_exists_bool(mgd_handle(), 
+"page,pagelink",
+                                                                       
+"pagelink.id=$d AND page.id=$d"
+                                                                       " AND 
+(pagelink.sitegroup=page.sitegroup"
+                                                                                      
+ " OR pagelink.sitegroup=0"
+                                                                                      
+ " OR page.sitegroup=0)",
+                                                                               
+(*id)->value.lval, (*target)->value.lval)) 
+RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+       /* grp must be in same SG or be 0 */
+       if ((*grp)->value.lval != 0 && !mgd_exists_bool(mgd_handle(), "pagelink,grp",
+                                                                               
+"pagelink.id=$d AND grp.id=$d"
+                                                                               " AND 
+(pagelink.sitegroup=grp.sitegroup"
+                                                                                      
+ " OR pagelink.sitegroup=0"
+                                                                                      
+ " OR grp.sitegroup=0)",
+                                                                               
+(*id)->value.lval, (*grp)->value.lval)) 
+RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+       /* owner must be in same SG or be 0 */
+       if ((*owner)->value.lval != 0 && !mgd_exists_bool(mgd_handle(), "pagelink,grp",
+                                                                               
+"pagelink.id=$d AND grp.id=$d"
+                                                                               " AND 
+(pagelink.sitegroup=grp.sitegroup"
+                                                                                      
+ " OR pagelink.sitegroup=0"
+                                                                                      
+ " OR grp.sitegroup=0)",
+                                                                               
+(*id)->value.lval, (*owner)->value.lval)) 
+RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+    php_midgard_update(return_value, "pagelink",
+              "name=$q,target=$d,grp=$d,owner=$d",
+              (*id)->value.lval,
+              (*name)->value.str.val, (*target)->value.lval, (*grp)->value.lval,
+              (*owner)->value.lval);
+    PHP_UPDATE_REPLIGARD("pagelink",(*id)->value.lval);
+}
+
+MGD_FUNCTION(delete_pagelink)
+{
+    IDINIT;
+       CHECK_MGD;
+    if(mgd_has_dependants(mgd_handle(),id,"pagelink"))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+    if (!ispagelinkowner(id))
+        RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+    php_midgard_delete(return_value, "pagelink", id);
+    PHP_DELETE_REPLIGARD("pagelink", id);
+}
+/* /pagelink */
+
+MidgardProperty MidgardPagelinkProperties [] = {
+       { IS_LONG,              "up"            },
+       { IS_STRING,    "name"          },
+       { IS_LONG,              "target"        },
+       { IS_LONG,              "grp"           },
+       { IS_LONG,              "owner"         },
+       { 0,                    NULL            }
+};
+MIDGARD_CLASS(MidgardPagelink, pagelink)
+
+#endif
+
+
Index: php4/ext/midgard/parameter.c
diff -u /dev/null php4/ext/midgard/parameter.c:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/parameter.c        Sat Feb 17 15:21:50 2001
@@ -0,0 +1,323 @@
+/* $Id: parameter.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "php.h"
+#include "php_ini.h"
+#include "php_midgard.h"
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION (oop_parameter)
+{
+       zval *self;
+       zval **zv_domain, **zv_name, **zv_value;
+       zval **zv_table, **zv_id;
+       int id = 0;
+       midgard_res *res;
+       int exists;
+
+       CHECK_MGD;
+
+       if ((self = getThis()) == NULL) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+       }
+
+   if (zend_hash_find(self->value.obj.properties, "__table__", 10,
+            (void **) &zv_table) != SUCCESS) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+
+   if (zend_hash_find(self->value.obj.properties, "id", 3,
+            (void **) &zv_id) !=
+           SUCCESS) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+
+       convert_to_string_ex(zv_table);
+       convert_to_long_ex(zv_id);
+
+       switch (ZEND_NUM_ARGS()) {
+               case 2:
+                       if (zend_get_parameters_ex(2, &zv_domain, &zv_name) ==
+                           FAILURE) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       convert_to_string_ex(zv_domain);
+                       convert_to_string_ex(zv_name);
+                       zv_value = NULL;
+                       break;
+
+               case 3:
+                       if (zend_get_parameters_ex
+                           (3, &zv_domain, &zv_name, &zv_value) == FAILURE) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       convert_to_string_ex(zv_domain);
+                       convert_to_string_ex(zv_name);
+                       convert_to_string_ex(zv_value);
+                       break;
+
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+       res = mgd_ungrouped_select(mgd_handle(), "id,value,sitegroup",
+                                  "record_extension",
+                                  "tablename=$q AND oid=$d AND domain=$q AND name=$q",
+                                  NULL,
+                                  (*zv_table)->value.str.val,
+                                  (*zv_id)->value.lval,
+                                  (*zv_domain)->value.str.val,
+                                  (*zv_name)->value.str.val);
+
+       exists = res ? mgd_fetch(res) : 0;
+       if (exists)
+               id = atoi(mgd_colvalue(res, 0));
+
+       /* delete parameter */
+       if (zv_value && (*zv_value)->value.str.len == 0) {
+
+               if (res) { mgd_release(res); }
+
+               if (!isglobalowner(
+                               mgd_lookup_table_id((*zv_table)->value.str.val),
+                               (*zv_id)->value.lval)) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+               }
+
+               if (!exists) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+               }
+
+               if (mgd_delete(mgd_handle(), "record_extension", id)) {
+                       PHP_DELETE_REPLIGARD("record_extension", id);
+                       RETURN_TRUE;
+               }
+               else {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INTERNAL);
+               }
+       }
+
+       /* return parameter */
+       if (!zv_value) {
+
+               if (!res) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+               }
+               if (!exists) {
+                       mgd_release(res);
+                       RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+               }
+
+               RETVAL_STRING((char *) mgd_colvalue(res, 1), 1);
+       }
+       else {
+               /* update parameter */
+
+               if (exists) {
+                       if (!isglobalowner(
+                                       
+mgd_lookup_table_id((*zv_table)->value.str.val),
+                                       (*zv_id)->value.lval)) {
+                               if (res) mgd_release(res);
+                               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+                       }
+
+                       php_midgard_update(return_value, "record_extension",
+                                          "value=$q", id,
+                                          (*zv_value)->value.str.val);
+                       PHP_UPDATE_REPLIGARD("record_extension", id);
+               }
+               else {
+                       php_midgard_create(return_value, "record_extension",
+                                          "tablename,oid,domain,name,value",
+                                          "$q,$d,$q,$q,$q",
+                                          (*zv_table)->value.str.val,
+                                          (*zv_id)->value.lval,
+                                          (*zv_domain)->value.str.val,
+                                          (*zv_name)->value.str.val,
+                                          (*zv_value)->value.str.val);
+                       PHP_CREATE_REPLIGARD("record_extension",
+                                            return_value->value.lval);
+               }
+       }
+
+       if (res)
+               mgd_release(res);
+}
+
+MGD_FUNCTION(oop_parameter_list)
+{
+       zval *self;
+       zval **zv_domain;
+       zval **zv_table, **zv_id;
+
+       CHECK_MGD;
+
+       if ((self = getThis()) == NULL) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+       }
+
+   if (zend_hash_find(self->value.obj.properties, "id", 3,
+            (void **) &zv_id) !=
+           SUCCESS) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+
+   if (zend_hash_find(self->value.obj.properties, "__table__", 10,
+            (void **) &zv_table) != SUCCESS) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+
+       convert_to_string_ex(zv_table);
+       convert_to_long_ex(zv_id);
+
+       switch (ZEND_NUM_ARGS()) {
+               case 1:
+                       if (zend_get_parameters_ex(1, &zv_domain) == FAILURE) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       convert_to_string_ex(zv_domain);
+                       break;
+
+               case 0:
+                       zv_domain = NULL;
+                       break;
+
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+       if (zv_domain)
+               php_midgard_select(&MidgardParameter, return_value,
+               "domain,name,value",
+                                  "record_extension",
+                                  "tablename=$q AND oid=$d AND domain=$q",
+                                  "name",
+                                  (*zv_table)->value.str.val,
+                                  (*zv_id)->value.lval,
+                                  (*zv_domain)->value.str.val);
+       else
+               php_midgard_select(&MidgardParameter, return_value,
+               "DISTINCT domain",
+                                  "record_extension",
+                                  "tablename=$q AND oid=$d", "domain",
+                                  (*zv_table)->value.str.val,
+                                  (*zv_id)->value.lval);
+}
+
+MGD_FUNCTION(oop_parameter_search)
+{
+       zval *self, **table;
+       zval **where, **all;
+       char *cond = NULL;
+       midgard_pool *pool;
+
+       RETVAL_FALSE;
+
+       CHECK_MGD;
+
+       if ((self = getThis()) == NULL) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+
+   if (zend_hash_find(self->value.obj.properties, "__table__", 10,
+      (void **) &table)
+           != SUCCESS) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+
+       convert_to_string_ex(table);
+
+       switch (ZEND_NUM_ARGS()) {
+               case 1:
+                       if (zend_get_parameters_ex(1, &where) != SUCCESS) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       convert_to_string_ex(where);
+                       all = NULL;
+                       break;
+               case 2:
+                       if (zend_get_parameters_ex(2, &where, &all) != SUCCESS) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       convert_to_string_ex(where);
+                       convert_to_boolean_ex(all);
+                       break;
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+       if (*((*table)->value.str.val) == '\0') {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+       }
+
+       if (!(pool = mgd_alloc_pool())) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_NO_MEM);
+       }
+
+       cond = mgd_format(mgd_handle(), pool, "tablename = $q AND ($s)",
+                         (*table)->value.str.val,
+                         ((*((*where)->value.str.val) == '\0') ? (*where)->
+                          value.str.val : "1=1")
+          );
+
+       if (all != NULL && (*all)->value.lval) {
+               php_midgard_select(&MidgardParameter, return_value,
+                                  "oid AS id,id AS pid,domain,name,value",
+                                  "record_extension", cond, NULL);
+       }
+       else {
+               php_midgard_select(&MidgardParameter, return_value,
+                                  "DISTINCT oid AS id",
+                                  "record_extension", cond, NULL);
+       }
+
+       mgd_free_pool(pool);
+}
+
+MidgardProperty MidgardParameterProperties [] = {
+       { IS_LONG,              "oid"           },
+       { IS_STRING,    "tablename"     },
+       { IS_STRING,    "domain"        },
+       { IS_STRING,    "name"          },
+       { IS_STRING,    "value"         },
+       { 0,                    NULL            }
+};
+
+MIDGARD_HANDLERS_DECL(parameter)
+static zend_function_entry MidgardParameterMethods[] = {
+//      MidgardParameter class constructor
+//      PHP_FALIAS(midgardparameter,   mgd_ctor_parameter,  NULL)
+   PHP_FALIAS(fetch,    mgd_oop_list_fetch,        NULL)
+   {  NULL,             NULL,                      NULL}
+};
+MidgardClass MidgardParameter = {
+   "MidgardParameter",
+   "record_extension",
+   MidgardParameterMethods,
+   {},
+   mgd_parameter_call_function_handler,
+   mgd_parameter_get_property_handler,
+   mgd_parameter_set_property_handler,
+   MidgardParameterProperties,
+   NULL
+};
+MIDGARD_HANDLERS(MidgardParameter, parameter)
+
Index: php4/ext/midgard/person.c
diff -u /dev/null php4/ext/midgard/person.c:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/person.c   Sat Feb 17 15:21:50 2001
@@ -0,0 +1,522 @@
+/* $Id: person.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+int isowner()
+{
+       return mgd_isadmin(mgd_handle()) || mgd_exists_id(mgd_handle(), "grp",
+   "owner IN $D", mgd_groups(mgd_handle()));
+}
+
+MGD_FUNCTION(is_person_owner)
+{
+    IDINIT;
+
+    CHECK_MGD;
+    RETVAL_LONG(isuserowner(id));
+}
+
+MGD_FUNCTION(is_member)
+{
+zval **zv_gid, **zv_uid;;
+
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+               case 1:
+                       if (zend_get_parameters_ex(1, &zv_gid)==FAILURE) { 
+WRONG_PARAM_COUNT; }
+                       convert_to_long_ex(zv_gid);
+                       RETVAL_LONG(mgd_ismember(mgd_handle(), (*zv_gid)->value.lval));
+                       break;
+
+               case 2:
+                       if (zend_get_parameters_ex(2, &zv_gid, &zv_uid)==FAILURE) {
+                               WRONG_PARAM_COUNT;
+                       }
+                       RETVAL_LONG(mgd_exists_id(mgd_handle(), "member",
+                                                                                      
+                                 "uid=$d AND gid=$d",
+                                                                                      
+                                 (*zv_uid)->value.lval,
+                                                                                      
+                                 (*zv_gid)->value.lval))
+                       break;
+
+               default:
+                       WRONG_PARAM_COUNT;
+                       break;
+  }
+}
+
+MGD_FUNCTION(list_persons)
+{
+    php_midgard_select(&MidgardPerson, return_value, PERSON_SELECT,
+                  "person", NULL, "lastname,firstname");
+}
+
+static const char *person_sort(const char *order)
+{
+    static struct { const char *order, *sort; } sort[] = {
+       { "alpha", "lastname,firstname" },
+       { "created", "created ASC" },
+       { NULL, "created DESC" }
+    };
+    int i;
+
+    for (i = 0; sort[i].order; i++) 
+       if (strcmp(order, sort[i].order) == 0)
+           return sort[i].sort;
+
+    return sort[i].sort;
+}
+
+MGD_FUNCTION(list_persons_in_department)
+{
+    const char *sortv = NULL;
+    zval **id, **sortn;
+
+       CHECK_MGD;
+
+    switch (ZEND_NUM_ARGS()) {
+    case 2:
+       if (zend_get_parameters_ex(2, &id, &sortn) == SUCCESS) {
+           convert_to_long_ex(id);
+           convert_to_string_ex(sortn);
+           sortv = person_sort((*sortn)->value.str.val);
+           break;
+       }
+    case 1:
+       if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+           convert_to_long_ex(id);
+           sortv = person_sort("");
+           break;
+       }
+    default:
+       wrong_param_count();
+    }
+
+    php_midgard_select(&MidgardPerson, return_value, PERSON_SELECT,
+                  "person", "department=$d", sortv, (*id)->value.lval);
+}
+
+MGD_FUNCTION(list_topic_persons)
+{
+   php_if_mgd_list_persons_in_department(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+
+MGD_FUNCTION(list_persons_in_department_all)
+{
+    int *deps;
+    const char *sortv = NULL;
+    zval **id, **sortn;
+
+       CHECK_MGD;
+    switch (ZEND_NUM_ARGS()) {
+    case 2:
+       if (zend_get_parameters_ex(2, &id, &sortn) == SUCCESS) {
+           convert_to_long_ex(id);
+           convert_to_string_ex(sortn);
+           sortv = person_sort((*sortn)->value.str.val);
+           break;
+       }
+    case 1:
+       if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+           convert_to_long_ex(id);
+           sortv = person_sort("");
+           break;
+       }
+    default:
+       wrong_param_count();
+    }
+
+    deps = mgd_tree(mgd_handle(), "topic", (*id)->value.lval, 0, NULL);
+
+    php_midgard_select(&MidgardPerson, return_value, PERSON_SELECT,
+                  "person", "department IN $D", sortv, deps);
+}
+
+MGD_FUNCTION(list_topic_persons_all)
+{
+   php_if_mgd_list_persons_in_department_all(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+MGD_FUNCTION(list_persons_in_office)
+{
+    const char *sortv = NULL;
+    zval **id, **sortn;
+
+       CHECK_MGD;
+    switch (ZEND_NUM_ARGS()) {
+    case 2:
+       if (zend_get_parameters_ex(2, &id, &sortn) == SUCCESS) {
+           convert_to_long_ex(id);
+           convert_to_string_ex(sortn);
+           sortv = person_sort((*sortn)->value.str.val);
+           break;
+       }
+    case 1:
+       if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+           convert_to_long_ex(id);
+           sortv = person_sort("");
+           break;
+       }
+    default:
+       wrong_param_count();
+    }
+
+    php_midgard_select(&MidgardPerson, return_value, PERSON_SELECT,
+                  "person", "office=$d", sortv, (*id)->value.lval);
+}
+
+MGD_FUNCTION(get_person)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+               php_midgard_bless(return_value, &MidgardPerson);
+               mgd_object_init(return_value, "firstname", "lastname", "birthdate", 
+"street", "postcode", "city", "handphone", "homephone", "workphone", "homepage", 
+"email", "topic", "department", "office", "extra", NULL);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+
+       if (isuserowner((*id)->value.lval))
+               php_midgard_get(&MidgardPerson, return_value, "id," NAME_FIELDS ","
+                                               
+"If(Left(password,2)='**',Substring(password,3),'')"
+                                               " AS password,"
+                                               ADDRESS_FIELDS "," PHONE_FIELDS ","
+                                               HOMEPAGE_FIELDS "," EMAIL_FIELDS ","
+                                               "Date_format(birthdate,'%d.%m.%Y') AS 
+birthdate,extra,"
+                                               "img,topic,department,office,pgpkey," 
+PUBLIC_FIELDS,
+                                               "person", (*id)->value.lval);
+       else
+               php_midgard_get(&MidgardPerson, return_value, "id," NAME_FIELDS ",'' 
+AS password,"
+                                               "If(info&2," ADDRESS_FIELD ",'') AS 
+address,"
+                                               PUBLIC_FIELD(2,street) ","
+                                               PUBLIC_FIELD(2,postcode) ","
+                                               PUBLIC_FIELD(2,city) ","
+                                               "If(info&4," PHONE_FIELD ",'') AS 
+phone,"
+                                               PUBLIC_FIELD(4,handphone) ","
+                                               PUBLIC_FIELD(4,homephone) ","
+                                               PUBLIC_FIELD(4,workphone) ","
+                                               "If(info&8," HOMEPAGE_FIELD ",'') AS 
+homepagelink,"
+                                               PUBLIC_FIELD(8,homepage) ","
+                                               "If(info&16," EMAIL_FIELD ",'') AS 
+emaillink,"
+                                               PUBLIC_FIELD(16,email) ","
+                                               "'' AS birthdate," 
+PUBLIC_FIELD(32,extra) ","
+                                               PUBLIC_FIELD(32,img) 
+",topic,department,office,pgpkey,"
+                                               PUBLIC_FIELDS, "person", 
+(*id)->value.lval);
+}
+
+MGD_FUNCTION(create_person)
+{
+    zval **firstname, **lastname, **birthdate;
+    zval **street, **postcode, **city, **handphone, **homephone, **workphone;
+    zval **homepage, **email, **topic, **department, **office, **extra, *self;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+
+   if ((self = getThis()) != NULL) {
+      if (ZEND_NUM_ARGS() != 0) { WRONG_PARAM_COUNT; }
+
+      if (!MGD_PROPFIND(self, "firstname", firstname)
+            || !MGD_PROPFIND(self, "lastname", lastname)
+            || !MGD_PROPFIND(self, "birthdate", birthdate)
+            || !MGD_PROPFIND(self, "street", street)
+            || !MGD_PROPFIND(self, "postcode", postcode)
+            || !MGD_PROPFIND(self, "city", city)
+            || !MGD_PROPFIND(self, "handphone", handphone)
+            || !MGD_PROPFIND(self, "homephone", homephone)
+            || !MGD_PROPFIND(self, "workphone", workphone)
+            || !MGD_PROPFIND(self, "homepage", homepage)
+            || !MGD_PROPFIND(self, "email", email)
+            || !MGD_PROPFIND(self, "topic", topic)
+            || !MGD_PROPFIND(self, "department", department)
+            || !MGD_PROPFIND(self, "office", office)
+            || !MGD_PROPFIND(self, "extra", extra)
+            ) {
+         RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+      }
+   } else {
+    if (ZEND_NUM_ARGS() != 15
+               || zend_get_parameters_ex(15, &firstname, &lastname, &birthdate, 
+&street,
+                                                &postcode, &city, &handphone, 
+&homephone, &workphone,
+                                                &homepage, &email, &topic, 
+&department, &office,
+                                                &extra) != SUCCESS)
+               WRONG_PARAM_COUNT;
+   }
+
+    convert_to_string_ex(firstname);
+    convert_to_string_ex(lastname);
+    convert_to_string_ex(birthdate);
+    convert_to_string_ex(street);
+    convert_to_string_ex(postcode);
+    convert_to_string_ex(city);
+    convert_to_string_ex(handphone);
+    convert_to_string_ex(homephone);
+    convert_to_string_ex(workphone);
+    convert_to_string_ex(homepage);
+    convert_to_string_ex(email);
+    convert_to_long_ex(topic);
+    convert_to_long_ex(department);
+    convert_to_long_ex(office);
+    convert_to_string_ex(extra);
+
+       if (!isowner()) RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+    php_midgard_create(return_value, "person", "firstname,lastname,"
+                                  "birthdate,street,postcode,city,handphone,"
+                                  "homephone,workphone,homepage,email,"
+                                  "topic,department,office,extra,created,creator",
+                                  
+"$q,$q,$t,$q,$q,$q,$q,$q,$q,$q,$q,$d,$d,$d,$q,Now(),$d",
+                                  (*firstname)->value.str.val, 
+(*lastname)->value.str.val,
+                                  (*birthdate)->value.str.val,
+                                  (*street)->value.str.val,    
+(*postcode)->value.str.val,
+                                  (*city)->value.str.val,      
+(*handphone)->value.str.val,
+                                  (*homephone)->value.str.val, 
+(*workphone)->value.str.val,
+                                  (*homepage)->value.str.val,  
+(*email)->value.str.val,
+                                  (*topic)->value.lval,        
+(*department)->value.lval,
+                                  (*office)->value.lval,       
+(*extra)->value.str.val,
+                                  mgd_user(mgd_handle()));
+
+    PHP_CREATE_REPLIGARD("person",return_value->value.lval);
+}
+
+MGD_FUNCTION(update_person)
+{
+    zval **id, **firstname, **lastname, **birthdate, **street, **postcode, **city;
+    zval **handphone, **homephone, **workphone, **homepage, **email;
+    zval **topic, **department, **office, **extra, *self;
+
+       CHECK_MGD;
+   if ((self = getThis()) != NULL) {
+      if (ZEND_NUM_ARGS() != 0) { WRONG_PARAM_COUNT; }
+
+      if (!MGD_PROPFIND(self, "id", id)
+            || !MGD_PROPFIND(self, "firstname", firstname)
+            || !MGD_PROPFIND(self, "lastname", lastname)
+            || !MGD_PROPFIND(self, "birthdate", birthdate)
+            || !MGD_PROPFIND(self, "street", street)
+            || !MGD_PROPFIND(self, "postcode", postcode)
+            || !MGD_PROPFIND(self, "city", city)
+            || !MGD_PROPFIND(self, "handphone", handphone)
+            || !MGD_PROPFIND(self, "homephone", homephone)
+            || !MGD_PROPFIND(self, "workphone", workphone)
+            || !MGD_PROPFIND(self, "homepage", homepage)
+            || !MGD_PROPFIND(self, "email", email)
+            || !MGD_PROPFIND(self, "topic", topic)
+            || !MGD_PROPFIND(self, "department", department)
+            || !MGD_PROPFIND(self, "office", office)
+            || !MGD_PROPFIND(self, "extra", extra)
+            ) {
+         RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+      }
+   } else {
+    if (ZEND_NUM_ARGS() != 16
+       || zend_get_parameters_ex(16, &id, &firstname, &lastname, &birthdate,
+                         &street, &postcode, &city,
+                        &handphone, &homephone, &workphone, &homepage, &email,
+                        &topic, &department, &office, &extra) != SUCCESS)
+       WRONG_PARAM_COUNT;
+   }
+
+    convert_to_long_ex(id);
+    convert_to_string_ex(firstname);
+    convert_to_string_ex(lastname);
+    convert_to_string_ex(birthdate);
+    convert_to_string_ex(street);
+    convert_to_string_ex(postcode);
+    convert_to_string_ex(city);
+    convert_to_string_ex(handphone);
+    convert_to_string_ex(homephone);
+    convert_to_string_ex(workphone);
+    convert_to_string_ex(homepage);
+    convert_to_string_ex(email);
+    convert_to_long_ex(topic);
+    convert_to_long_ex(department);
+    convert_to_long_ex(office);
+    convert_to_string_ex(extra);
+
+    if (!isuserowner((*id)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+    php_midgard_update(return_value, "person", "firstname=$q,lastname=$q,"
+                                  "birthdate=$t,street=$q,postcode=$q,city=$q,"
+                                  
+"handphone=$q,homephone=$q,workphone=$q,homepage=$q,"
+                                  
+"email=$q,topic=$d,department=$d,office=$d,extra=$q",
+                                  (*id)->value.lval,
+                                  (*firstname)->value.str.val, 
+(*lastname)->value.str.val,
+                                  (*birthdate)->value.str.val, 
+(*street)->value.str.val,
+                                  (*postcode)->value.str.val,  (*city)->value.str.val,
+                                  (*handphone)->value.str.val, 
+(*homephone)->value.str.val,
+                                  (*workphone)->value.str.val, 
+(*homepage)->value.str.val,
+                                  (*email)->value.str.val,     (*topic)->value.lval,
+                                  (*department)->value.lval,   (*office)->value.lval,
+                                  (*extra)->value.str.val);
+    PHP_UPDATE_REPLIGARD("person",(*id)->value.lval);
+}
+
+MGD_FUNCTION(update_password)
+{
+    zval **uid, **username, **password;
+
+       CHECK_MGD;
+    if (ZEND_NUM_ARGS() != 3
+               || zend_get_parameters_ex(3, &uid, &username, &password) != SUCCESS)
+               WRONG_PARAM_COUNT;
+    convert_to_long_ex(uid);
+    convert_to_string_ex(username);
+    convert_to_string_ex(password);
+       
+    if (!mgd_isadmin(mgd_handle()) && !mgd_isuser(mgd_handle(), (*uid)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       
+    /* no 'magic' chars in username */
+    if (strpbrk((*username)->value.str.val, MIDGARD_LOGIN_RESERVED_CHARS))
+               RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_NAME);
+
+    if ((*username)->value.str.len != 0
+                       && mgd_exists_bool(mgd_handle(), "person this, person other",
+                                                                               
+"this.id=$d"
+                                                                               " AND 
+other.id<>$d AND other.username=$q"
+#if HAVE_MIDGARD_SITEGROUPS
+                                                                               " AND 
+this.sitegroup=other.sitegroup"
+#endif
+                                                                               ,
+                                                                               
+(*uid)->value.lval, (*uid)->value.lval,
+                                                                               
+(*username)->value.str.val)) RETURN_FALSE_BECAUSE(MGD_ERR_DUPLICATE);
+
+    php_midgard_update(return_value, "person", "username=$q,password=Encrypt($q)",
+                                  (*uid)->value.lval, (*username)->value.str.val,
+                                  (*password)->value.str.val);
+    PHP_UPDATE_REPLIGARD("person",(*uid)->value.lval);
+}
+
+MGD_FUNCTION(update_password_plain)
+{
+    zval **uid, **username, **password;
+
+       CHECK_MGD;
+    if (ZEND_NUM_ARGS() != 3
+               || zend_get_parameters_ex(3, &uid, &username, &password) != SUCCESS)
+               WRONG_PARAM_COUNT;
+    convert_to_long_ex(uid);
+    convert_to_string_ex(username);
+    convert_to_string_ex(password);
+       
+    if (!mgd_isadmin(mgd_handle()) && !mgd_isuser(mgd_handle(), (*uid)->value.lval)
+               && !(isuserowner((*uid)->value.lval)
+                        && mgd_exists_id(mgd_handle(), "person",
+                                                  "id=$d AND (password='' OR 
+Left(password,2)='**')",
+                                                  (*uid)->value.lval)))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       
+    /* no 'magic' chars in username */
+    if (strpbrk((*username)->value.str.val, MIDGARD_LOGIN_RESERVED_CHARS)) 
+RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_NAME);
+
+    if ((*username)->value.str.len != 0
+                       && mgd_exists_bool(mgd_handle(), "person this, person other",
+                                                                               
+"this.id=$d"
+                                                                               " AND 
+other.id<>$d AND other.username=$q"
+                                                                               " AND 
+this.sitegroup=other.sitegroup",
+                                                                               
+(*uid)->value.lval, (*uid)->value.lval,
+                                                                               
+(*username)->value.str.val)) RETURN_FALSE_BECAUSE(MGD_ERR_DUPLICATE);
+
+    php_midgard_update(return_value, "person",
+                                  "username=$q,password=Concat('**',$q)",
+                                  (*uid)->value.lval, (*username)->value.str.val,
+                                  (*password)->value.str.val);
+    PHP_UPDATE_REPLIGARD("person",(*uid)->value.lval);
+}
+
+MGD_FUNCTION(update_public)
+{
+    zval **uid, **addressp, **phonep, **homepagep, **emailp, **extrap;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    if (ZEND_NUM_ARGS() != 6
+               || zend_get_parameters_ex(6, &uid, &addressp, &phonep,
+                                                &homepagep, &emailp, &extrap) != 
+SUCCESS)
+       WRONG_PARAM_COUNT;
+    convert_to_long_ex(uid);
+    convert_to_long_ex(addressp);
+    convert_to_long_ex(phonep);
+    convert_to_long_ex(homepagep);
+    convert_to_long_ex(emailp);
+    convert_to_long_ex(extrap);
+
+    if (!isuserowner((*uid)->value.lval)) RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+    php_midgard_update(return_value, "person", "info=(info&1)|$d",
+                                  (*uid)->value.lval, 
+                                  ((*addressp)->value.lval != 0) << 1
+                                  | ((*phonep)->value.lval != 0) << 2
+                                  | ((*homepagep)->value.lval != 0) << 3
+                                  | ((*emailp)->value.lval != 0) << 4
+                                  | ((*extrap)->value.lval != 0) << 5);
+    PHP_UPDATE_REPLIGARD("person",(*uid)->value.lval);
+}
+
+MGD_FUNCTION(delete_person)
+{
+    IDINIT;
+       CHECK_MGD;
+    if(mgd_has_dependants(mgd_handle(),id,"person"))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+       if(mgd_exists_id(mgd_handle(), "article", "author=$d", id)
+               || mgd_exists_id(mgd_handle(), "member", "uid=$d", id)
+               || mgd_exists_id(mgd_handle(), "eventmember", "uid=$d", id)
+               || mgd_exists_id(mgd_handle(), "page", "author=$d", id))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+    if (!isuserowner(id)) RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+    php_midgard_delete(return_value, "person", id);
+    PHP_DELETE_REPLIGARD("person", id);
+}
+
+MidgardProperty MidgardPersonProperties [] = {
+       { IS_STRING,    "firstname"             },
+       { IS_STRING,    "lastname"              },
+       { IS_STRING,    "birthdate"             },
+       { IS_STRING,    "street"                },
+       { IS_STRING,    "postcode"              },
+       { IS_STRING,    "city"                  },
+       { IS_STRING,    "handphone"             },
+       { IS_STRING,    "homephone"             },
+       { IS_STRING,    "workphone"             },
+       { IS_STRING,    "homepage"              },
+       { IS_STRING,    "email"                 },
+       { IS_LONG,              "topic"                 },
+       { IS_LONG,              "department"    },
+       { IS_LONG,              "office"                },
+       { IS_STRING,    "extra"                 },
+       { 0,                    NULL                    }
+};
+
+MIDGARD_CLASS(MidgardPerson, person)
Index: php4/ext/midgard/php_midgard.h
diff -u /dev/null php4/ext/midgard/php_midgard.h:1.3
--- /dev/null   Sat Feb 17 15:21:53 2001
+++ php4/ext/midgard/php_midgard.h      Sat Feb 17 15:21:50 2001
@@ -0,0 +1,97 @@
+/* $Id: php_midgard.h,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef PHP_MIDGARD_H
+#define PHP_MIDGARD_H
+
+/* You should tweak config.m4 so this symbol (or some else suitable)
+   gets defined.
+*/
+#include <php_config.h>
+
+#if HAVE_MIDGARD
+
+#include <php.h>
+#include <midgard.h>
+#include <mgd_apache.h>
+#include <Zend/modules.h>
+
+midgard_request_config *mgd_rcfg();
+midgard_directory_config *mgd_dcfg();
+midgard *mgd_handle();
+zval *mgd_getudf();
+int mgd_get_errno();
+void mgd_set_errno(int mgd_errno);
+
+extern zend_module_entry midgard_module_entry;
+#define phpext_midgard_ptr &midgard_module_entry
+
+#ifdef PHP_WIN32
+#define PHP_MIDGARD_API __declspec(dllexport)
+#else
+#define PHP_MIDGARD_API
+#endif
+
+PHP_MINIT_FUNCTION(midgard);
+PHP_MSHUTDOWN_FUNCTION(midgard);
+PHP_RINIT_FUNCTION(midgard);
+PHP_RSHUTDOWN_FUNCTION(midgard);
+PHP_MINFO_FUNCTION(midgard);
+
+PHP_FUNCTION(confirm_midgard_compiled);        /* For testing, remove later. */
+
+ZEND_BEGIN_MODULE_GLOBALS(midgard)
+       midgard_request_config *rcfg;
+       midgard_directory_config *dcfg;
+   midgard *mgd;
+   int mgd_errno;
+   zval *udf;
+ZEND_END_MODULE_GLOBALS(midgard)
+
+/* In every function that needs to use variables in php_midgard_globals,
+   do call MGDLS_FETCH(); after declaring other variables used by
+   that function, and always refer to them as MGDG(variable).
+   You are encouraged to rename these macros something shorter, see
+   examples in any other php module directory.
+*/
+
+#ifdef ZTS
+#define MGDG(v) (midgard_globals->v)
+#define MGDLS_FETCH() php_midgard_globals *midgard_globals = 
+ts_resource(midgard_globals_id)
+#else
+#define MGDG(v) (midgard_globals.v)
+#define MGDLS_FETCH()
+#endif
+
+#else
+
+#define phpext_midgard_ptr NULL
+
+#endif
+
+#endif /* PHP_MIDGARD_H */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
Index: php4/ext/midgard/preferences.c
diff -u /dev/null php4/ext/midgard/preferences.c:1.3
--- /dev/null   Sat Feb 17 15:21:54 2001
+++ php4/ext/midgard/preferences.c      Sat Feb 17 15:21:50 2001
@@ -0,0 +1,219 @@
+/* $Id: preferences.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(list_preferences)
+{
+       zval **uid, **dom;
+       int user;
+       char *domain;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+    switch (ZEND_NUM_ARGS()) {
+       case 0:
+               user = mgd_user(mgd_handle());
+               domain = NULL;
+               break;
+       case 1:
+               if (zend_get_parameters_ex(1, &uid) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+               convert_to_long_ex(uid);
+               user = (*uid)->value.lval;
+               domain = NULL;
+               break;
+       case 2:
+               if (zend_get_parameters_ex(2, &uid, &dom) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+               convert_to_long_ex(uid);
+               convert_to_string_ex(dom);
+               user = (*uid)->value.lval;
+               domain = (*dom)->value.str.val;
+               break;
+       default:
+               WRONG_PARAM_COUNT;
+       }
+
+       if (user != mgd_user(mgd_handle()) && !mgd_isadmin(mgd_handle()))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       
+       if (domain)
+               php_midgard_select(&MidgardPreferences, return_value, 
+"id,uid,domain,name,value",
+                                                  "preference", "uid=$d AND 
+domain=$q", "name",
+                                                  user, domain);
+       else
+               php_midgard_select(&MidgardPreferences, return_value, 
+"id,uid,domain,name,value",
+                                                  "preference", "uid=$d", 
+"domain,name", user);
+}
+
+MGD_FUNCTION(get_preference)
+{
+       zval **pid, **dom, **name;
+       int id;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+    switch (ZEND_NUM_ARGS()) {
+       case 0:
+               php_midgard_bless(return_value, &MidgardPreferences);
+               mgd_object_init(return_value, "uid", "domain", "name", "value", NULL);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &pid) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+               convert_to_long_ex(pid);
+               id = (*pid)->value.lval;
+               break;
+       case 2:
+               if (zend_get_parameters_ex(2, &dom, &name) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+               convert_to_string_ex(dom);
+               convert_to_string_ex(name);
+               id = mgd_exists_id(mgd_handle(), "preference",
+                                               "uid=$d AND domain=$q AND name=$q",
+                                               mgd_user(mgd_handle()),
+                                               (*dom)->value.str.val, 
+(*name)->value.str.val);
+               break;
+       case 3:
+               if (zend_get_parameters_ex(3, &pid, &dom, &name) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+               convert_to_long_ex(pid);
+               id = (*pid)->value.lval;
+               convert_to_string_ex(dom);
+               convert_to_string_ex(name);
+               id = mgd_exists_id(mgd_handle(), "preference",
+                                               "uid=$d AND domain=$q AND name=$q",
+                                               id,
+                                               (*dom)->value.str.val, 
+(*name)->value.str.val);
+               break;
+       default:
+               WRONG_PARAM_COUNT;
+       }
+
+       if (!id) RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+       if (!mgd_isadmin(mgd_handle()) &&
+               mgd_user(mgd_handle()) != mgd_idfield(mgd_handle(), "uid", 
+"preference", id))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       php_midgard_get(&MidgardPreferences, return_value,
+                                       "id,uid,domain,name,value", "preference", id);
+}
+
+MGD_FUNCTION(create_preference)
+{
+       zval **uid, **domain, **name, **value, *self;
+       
+       RETVAL_FALSE;
+       CHECK_MGD;
+   if ((self = getThis()) != NULL) {
+      if (ZEND_NUM_ARGS() != 0) { WRONG_PARAM_COUNT; }
+
+      if (!MGD_PROPFIND(self, "uid", uid)
+            || !MGD_PROPFIND(self, "domain", domain)
+            || !MGD_PROPFIND(self, "name", name)
+            || !MGD_PROPFIND(self, "value", value)
+            ) {
+         RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+      }
+   } else {
+       if (ZEND_NUM_ARGS() != 4
+           || zend_get_parameters_ex(4, &uid, &domain, &name, &value) != SUCCESS)
+               WRONG_PARAM_COUNT;
+   }
+       convert_to_long_ex(uid);
+       convert_to_string_ex(domain);
+       convert_to_string_ex(name);
+       convert_to_string_ex(value);
+       
+       if (mgd_user(mgd_handle()) != (*uid)->value.lval &&
+   !mgd_isadmin(mgd_handle()))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       if (!mgd_exists_id(mgd_handle(), "person",
+                                                                               
+"id=$d",
+                                                                               
+(*uid)->value.lval)) RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+#endif
+
+       php_midgard_create(return_value, "preference", "uid,domain,name,value",
+                                          "$d,$q,$q,$q", (*uid)->value.lval, 
+(*domain)->value.str.val,
+                                          (*name)->value.str.val, 
+(*value)->value.str.val);
+
+       PHP_CREATE_REPLIGARD("preference",return_value->value.lval);
+}
+
+MGD_FUNCTION(update_preference)
+{
+       zval **id, **value, *self;
+       
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+   if ((self = getThis()) != NULL) {
+      if (ZEND_NUM_ARGS() != 0) { WRONG_PARAM_COUNT; }
+
+      if (!MGD_PROPFIND(self, "id", id)
+            || !MGD_PROPFIND(self, "value", value)
+            ) {
+         RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+      }
+   } else {
+       if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &id, &value) != SUCCESS)
+               WRONG_PARAM_COUNT;
+   }
+
+       convert_to_long_ex(id);
+       convert_to_string_ex(value);
+       
+       if (!mgd_isadmin(mgd_handle()) && mgd_user(mgd_handle()) !=
+           mgd_idfield(mgd_handle(), "uid", "preference", (*id)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       
+       php_midgard_update(return_value, "preference", "value=$q",
+                                          (*id)->value.lval, (*value)->value.str.val);
+       PHP_UPDATE_REPLIGARD("preference", (*id)->value.lval);
+}
+
+MGD_FUNCTION(delete_preference)
+{
+       IDINIT;
+       RETVAL_FALSE;
+       CHECK_MGD;
+    if(mgd_has_dependants(mgd_handle(),id,"preference"))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+       if (!mgd_isadmin(mgd_handle()) &&
+               mgd_user(mgd_handle()) != mgd_idfield(mgd_handle(), "uid", 
+"preference", id))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       
+       php_midgard_delete(return_value, "preference", id);
+       PHP_DELETE_REPLIGARD("preference", id); 
+}
+
+MidgardProperty MidgardPreferencesProperties [] = {
+       { IS_LONG,              "uid"           },
+       { IS_STRING,    "domain"        },
+       { IS_STRING,    "name"          },
+       { IS_STRING,    "value"         },
+       { 0,                    NULL            }
+};
+
+MIDGARD_CLASS(MidgardPreferences, preference)
Index: php4/ext/midgard/preparser-parser.y
diff -u /dev/null php4/ext/midgard/preparser-parser.y:1.3
--- /dev/null   Sat Feb 17 15:21:54 2001
+++ php4/ext/midgard/preparser-parser.y Sat Feb 17 15:21:50 2001
@@ -0,0 +1,212 @@
+%{
+/* $Id: preparser-parser.y,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+  /*#include "mgd_wild.h"*/
+  /*#define PARSER_DEBUG*/
+  
+  #include <stdio.h>
+  #include <malloc.h>
+  #include <strings.h>
+  #include "php_midgard.h"
+  #include "midgard.h"
+  #include "mgd_preparser.h"
+%}
+
+%union {
+//  char string[256];
+  GByteArray *gstring;
+}
+
+%token <gstring> STRING
+%token MGD_TMPL
+%token MGD_TMPLE
+%token MGD_VAR
+%token MGD_VARE
+%token MGD_SNIP
+%token MGD_SNIPE
+%token MGD_EVAL
+%token MGD_EVALE
+
+%%
+
+input:
+ | input instructions
+;
+
+instructions:
+ | MGD_TMPL STRING MGD_TMPLE {
+#ifdef PARSER_DEBUG
+   mgd_append_output_buffer_const("parsed elem: ");
+   mgd_append_output_buffer_data($2);
+#endif
+   mgd_append_output_buffer_const("<? mgd_eval(\"?>\".mgd_template(\"");
+   mgd_append_output_buffer_data($2);
+   mgd_append_output_buffer_const("\"). \"<?\", \"");
+   mgd_append_output_buffer_data($2);
+   mgd_append_output_buffer_const("\"); ?>");
+   mgd_free_buffer($2);
+ }
+ | MGD_VAR MGD_VARE {
+   yyerror("parse error, missing variable");
+ }
+ | MGD_VAR STRING MGD_VARE {
+#ifdef PARSER_DEBUG
+   mgd_append_output_buffer_const("parsed var 1: ");
+   mgd_append_output_buffer_data($2);
+#endif
+   mgd_append_output_buffer_const("<? echo mgd_variable(\"");
+   mgd_append_output_buffer_data($2);
+   mgd_append_output_buffer_const("\"); ?>");
+   mgd_free_buffer($2);
+ }
+ | MGD_VAR STRING ':' MGD_VARE {
+   yyerror("parse error, missing formatter");
+ }
+ | MGD_VAR STRING ':' STRING MGD_VARE {
+#ifdef PARSER_DEBUG
+   mgd_append_output_buffer_const("parsed var 2: ");
+   mgd_append_output_buffer_data($2);
+   if( (($4)->data[0] == 'h') || (($4)->data[0] == 'H') ||
+       (($4)->data[0] == 'f') || (($4)->data[0] == 'F') ||
+       (($4)->data[0] == 'p') || (($4)->data[0] == 'u') ) {
+#endif
+   if(($4)->data[0] == 'p') {
+     mgd_append_output_buffer_const("<? mgd_eval(\"?>\".$");
+     mgd_append_output_buffer_data($2);
+     mgd_append_output_buffer_const(".\"<?\",\'");
+     mgd_append_output_buffer_data($2);
+     mgd_append_output_buffer_const("\'); ?>");
+   } else if(($4)->data[0] == 'i') {
+     mgd_append_output_buffer_const("<? ");
+     g_byte_array_append(($2), "", 1);
+     mgd_append_output_buffer(php_midgard_variable(NULL, ($2)->data, NULL, "i"));
+     mgd_append_output_buffer_const(" ?>");
+   } else {
+     mgd_append_output_buffer_const("<? echo mgd_variable(\"");
+     mgd_append_output_buffer_data($2);
+     mgd_append_output_buffer_const("\",\"");
+     mgd_append_output_buffer_data($4);
+     mgd_append_output_buffer_const("\"); ?>");
+   }
+#ifdef PARSER_DEBUG
+   } else {
+     yyerror("parse error, wrong formatter");
+   }
+#endif
+   mgd_free_buffer($2);
+   mgd_free_buffer($4);
+ }
+ | MGD_VAR STRING '.' STRING MGD_VARE {
+#ifdef PARSER_DEBUG
+   mgd_append_output_buffer_const("parsed var 3: ");
+   mgd_append_output_buffer_data($2);
+#endif
+   mgd_append_output_buffer_const("<? echo mgd_variable(\"");
+   mgd_append_output_buffer_data($2);
+   mgd_append_output_buffer_const("\",\"");
+   mgd_append_output_buffer_data($4);
+   mgd_append_output_buffer_const("\",\"\"); ?>");
+   mgd_free_buffer($2);
+   mgd_free_buffer($4);
+ }
+ | MGD_VAR STRING '.' STRING ':' STRING MGD_VARE {
+#ifdef PARSER_DEBUG
+   mgd_append_output_buffer_const("parsed var 4: ");
+   mgd_append_output_buffer_data($2);
+#endif
+   if(($6)->data[0] == 'p') {
+     mgd_append_output_buffer_const("<? mgd_eval(\"?>\".$");
+     mgd_append_output_buffer_data($2);
+     mgd_append_output_buffer_const("->");
+     mgd_append_output_buffer_data($4);
+/*
+     mgd_append_output_buffer_const(".\"<?\",'$");
+     mgd_append_output_buffer_data($2);
+     mgd_append_output_buffer_const("->");
+     mgd_append_output_buffer_data($4);
+     mgd_append_output_buffer_const("'); ?>");
+*/
+     mgd_append_output_buffer_const(".\"<?\"); ?>");
+   } else if(($6)->data[0] == 'i') {
+     mgd_append_output_buffer_const("<? ");
+     g_byte_array_append(($2), "", 1);
+     g_byte_array_append(($4), "", 1);
+     mgd_append_output_buffer(php_midgard_variable(NULL, ($2)->data, ($4)->data, 
+"i"));
+     mgd_append_output_buffer_const(" ?>");
+   } else {
+     mgd_append_output_buffer_const("<? echo mgd_variable(\"");
+     mgd_append_output_buffer_data($2);
+     mgd_append_output_buffer_const("\",\"");
+     mgd_append_output_buffer_data($4);
+     mgd_append_output_buffer_const("\",\"");
+     mgd_append_output_buffer_data($6);
+     mgd_append_output_buffer_const("\"); ?>");
+   }
+   mgd_free_buffer($2);
+   mgd_free_buffer($4);
+   mgd_free_buffer($6);
+ }
+ | MGD_SNIP STRING {
+#ifdef PARSER_DEBUG
+   mgd_append_output_buffer_const("parsed snippet: ");
+   mgd_append_output_buffer_data($2);
+#endif
+   mgd_append_output_buffer_const("mgd_eval(\"?>\".mgd_snippet(");
+   mgd_append_output_buffer_data($2);
+   mgd_append_output_buffer_const(").\"<?\",\"snippet://\".");
+   mgd_append_output_buffer_data($2);
+   mgd_append_output_buffer_const(")");
+   mgd_free_buffer($2);
+ }
+ | MGD_EVAL STRING {
+#ifdef PARSER_DEBUG
+   mgd_append_output_buffer_const("parsed eval: ");
+   mgd_append_output_buffer_data($2);
+#endif
+   mgd_append_output_buffer_const("mgd_eval(");
+   mgd_append_output_buffer_data($2);
+   mgd_append_output_buffer_const(")");
+   mgd_free_buffer($2);
+ }
+;
+
+%%
+
+/* TODO: work on the errors */
+
+//extern FILE *mgdin;
+
+/*
+int main(void)
+{
+  do {
+    yyparse();
+  } while (!feof(mgdin));
+
+  return 0;
+}
+*/
+
+void yyerror(char *s)
+{
+    char *temp = g_strdup_printf("ERROR: %s\n", s);
+    mgd_append_output_buffer(temp);
+    g_free(temp);
+}
Index: php4/ext/midgard/preparser-scanner.l
diff -u /dev/null php4/ext/midgard/preparser-scanner.l:1.3
--- /dev/null   Sat Feb 17 15:21:54 2001
+++ php4/ext/midgard/preparser-scanner.l        Sat Feb 17 15:21:50 2001
@@ -0,0 +1,307 @@
+
+%{
+/* $Id: preparser-scanner.l,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_preparser.h"
+#include "preparser-parser.h"
+/*#define SCANNER_DEBUG */
+
+GByteArray *mgd_output_buffer;
+static int par_stack;
+static char in_string=0;
+
+/*
+<IN_PHP>{ANY}|{LCOMMENT} {
+#ifdef SCANNER_DEBUG
+  mgd_append_output_buffer_const(" <6: misc char> ");
+#endif
+  mgd_append_output_buffer(yytext);
+}
+*/
+%}
+
+%x IN_PHP
+%x IN_TEMPLATE
+%x IN_FORMAT
+%x IN_SNIPPET
+%x IN_SNIPPETQ
+%x IN_SNIPPETQQ
+%x IN_EVAL
+%x IN_EVALQ
+%x IN_EVALQQ
+
+%option stack
+%option noyywrap
+%option noyylineno
+
+dqstring   [\"][^\"\n]*[\"]
+qstring    [\'][^\'\n]*[\']
+WHITESPACE [ \n\r\t]
+ANY        .|{WHITESPACE}
+LCOMMENT   "//".*
+quote      [\']
+dquote     [\"]
+MIDGARD_TEMPLATE_NAME [a-zA-Z0-9_ \x7f-\xff-]+
+MIDGARD_VARSPEC 
+{MIDGARD_TEMPLATE_NAME}("."{MIDGARD_TEMPLATE_NAME})?(":"{MIDGARD_TEMPLATE_NAME})?
+
+%%
+
+<INITIAL>{ANY} {
+#ifdef SCANNER_DEBUG
+  mgd_append_output_buffer_const(" <1: Misc char> ");
+#endif
+  mgd_append_output_buffer(yytext);
+}
+
+<INITIAL>"<?php"|"<?"|"<script"{WHITESPACE}+"language"{WHITESPACE}*"="{WHITESPACE}*("php"|"\"php\""|"\'php\'"){WHITESPACE}*">"
+ {
+#ifdef SCANNER_DEBUG
+  mgd_append_output_buffer_const(" <2: Found php entry> ");
+#endif
+  mgd_append_output_buffer(yytext);
+  yy_push_state(IN_PHP);
+}
+
+<IN_PHP>("?>"|"</script"{WHITESPACE}*">") {
+#ifdef SCANNER_DEBUG
+  mgd_append_output_buffer_const(" <4: Found php end> ");
+#endif
+  mgd_append_output_buffer(yytext);
+  yy_pop_state();
+}
+
+<IN_PHP>{ANY}|{LCOMMENT} {
+#ifdef SCANNER_DEBUG
+  mgd_append_output_buffer_const(" <6: misc char> ");
+#endif
+  mgd_append_output_buffer(yytext);
+}
+
+<IN_PHP>{qstring}|{dqstring} {
+#ifdef SCANNER_DEBUG
+  mgd_append_output_buffer_const(" <5: String> ");
+#endif
+  mgd_append_output_buffer(yytext);
+}
+
+<INITIAL>"<"[\[\(]/{MIDGARD_TEMPLATE_NAME}[\]\)]">" {
+#ifdef SCANNER_DEBUG
+  mgd_append_output_buffer_const(" <9: Found start of element> ");
+#endif
+  yy_push_state(IN_TEMPLATE);
+  return MGD_TMPL;
+}
+
+<IN_TEMPLATE>[\]\)]">" {
+#ifdef SCANNER_DEBUG
+  mgd_append_output_buffer_const(" <10: Found end of element> ");
+#endif
+  yy_pop_state();
+  return MGD_TMPLE;
+}
+
+<INITIAL>"&("/{MIDGARD_VARSPEC}");" {
+#ifdef SCANNER_DEBUG
+  mgd_append_output_buffer_const(" <11: Found start of variable> ");
+#endif
+  yy_push_state(IN_FORMAT);
+  return MGD_VAR;
+}
+
+<IN_FORMAT>");" { 
+#ifdef SCANNER_DEBUG
+  mgd_append_output_buffer_const(" <12: Found end of variable> ");
+#endif
+  yy_pop_state();
+  return MGD_VARE;
+}
+
+<IN_FORMAT,IN_TEMPLATE>[a-zA-Z0-9_ -]+ {
+#ifdef SCANNER_DEBUG
+  mgd_append_output_buffer_const(" <13: Found string> ");
+#endif
+  mgd_set_buffer(mgdlval.gstring,mgdtext);
+  return STRING;
+}
+
+<IN_FORMAT,IN_TEMPLATE>{ANY} {
+#ifdef SCANNER_DEBUG
+  mgd_append_output_buffer_const(" <14: Found char> ");
+#endif
+  return yytext[0];
+}
+
+<IN_PHP>"mgd_include_snippet"{WHITESPACE}*"(" {
+  yy_push_state(IN_SNIPPET);
+  par_stack=0;
+  in_string = 0;
+  mgdlval.gstring = g_byte_array_new();
+  return MGD_SNIP;
+}
+
+<IN_SNIPPET>{quote} {
+  yy_push_state(IN_SNIPPETQ);
+  in_string = mgdtext[0];
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+}
+
+<IN_SNIPPET>{dquote} {
+  yy_push_state(IN_SNIPPETQQ);
+  in_string = mgdtext[0];
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+}
+
+<IN_SNIPPETQ>[\\]{quote} {
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+  mgd_append_byte(mgdlval.gstring, mgdtext+1);
+}
+
+<IN_SNIPPETQ>{quote} {
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+  yy_pop_state();
+}
+
+<IN_SNIPPETQ>{ANY} {
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+}
+
+<IN_SNIPPETQQ>[\\]{dquote} {
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+  mgd_append_byte(mgdlval.gstring, mgdtext+1);
+}
+
+<IN_SNIPPETQQ>{dquote} {
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+  yy_pop_state();
+}
+
+<IN_SNIPPETQQ>{ANY} {
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+}
+
+<IN_SNIPPET>{ANY} {
+  if(yytext[0] == '(') par_stack++;
+  if(yytext[0] == ')') par_stack--;
+  if(par_stack < 0) {
+    yy_pop_state();
+    return STRING;
+  }
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+}
+
+<IN_PHP>[^_]"eval"{WHITESPACE}*"(" {
+/* TODO: change the [^_] to make it conditional, so it's not part of the match
+ */
+  mgd_append_byte(mgd_output_buffer, mgdtext);
+  yy_push_state(IN_EVAL);
+  par_stack=0;
+  in_string = 0;
+  mgdlval.gstring = g_byte_array_new();
+  return MGD_EVAL;
+}
+
+<IN_EVAL>{quote} {
+  yy_push_state(IN_EVALQ);
+  in_string = mgdtext[0];
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+}
+
+<IN_EVAL>{dquote} {
+  yy_push_state(IN_EVALQQ);
+  in_string = mgdtext[0];
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+}
+
+<IN_EVALQ>[\\]{quote} {
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+  mgd_append_byte(mgdlval.gstring, mgdtext+1);
+}
+
+<IN_EVALQ>{quote} {
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+  yy_pop_state();
+}
+
+<IN_EVALQ>{ANY} {
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+}
+
+<IN_EVALQQ>[\\]{dquote} {
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+  mgd_append_byte(mgdlval.gstring, mgdtext+1);
+}
+
+<IN_EVALQQ>{dquote} {
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+  yy_pop_state();
+}
+
+<IN_EVALQQ>{ANY} {
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+}
+
+<IN_EVAL>{ANY} {
+  if(yytext[0] == '(') par_stack++;
+  if(yytext[0] == ')') par_stack--;
+  if(par_stack < 0) {
+    yy_pop_state();
+    return STRING;
+  }
+  mgd_append_byte(mgdlval.gstring, mgdtext);
+}
+
+%%
+
+char * php_eval_midgard(midgard_pool * pool, const char *name, char *value, int 
+exit_php)
+{
+  YY_BUFFER_STATE bufferState;
+  int   len = strlen(value);
+  char *tmp;
+
+  if (len == 0)
+    return NULL;
+
+  tmp = (char *) emalloc(len + 2);
+  memcpy(tmp, value, len+1);
+  tmp[len + 1] = 0;
+  value = tmp;
+
+//  mgdin  = NULL;
+
+  /* TODO: dynamic scale this buffer */
+  mgd_output_buffer = g_byte_array_new();
+
+  if(exit_php) mgd_append_output_buffer_const("?>");
+
+  bufferState = yy_scan_buffer(value, len + 2);
+  BEGIN(INITIAL);
+  mgdparse();
+  yy_delete_buffer(bufferState);
+
+  if(exit_php) mgd_append_output_buffer_const("<?\n");
+
+  tmp = estrndup(mgd_output_buffer->data, mgd_output_buffer->len);
+
+  efree(value);
+  g_byte_array_free(mgd_output_buffer, TRUE);
+
+  return tmp;
+}
Index: php4/ext/midgard/preparser.c
diff -u /dev/null php4/ext/midgard/preparser.c:1.3
--- /dev/null   Sat Feb 17 15:21:54 2001
+++ php4/ext/midgard/preparser.c        Sat Feb 17 15:21:50 2001
@@ -0,0 +1,452 @@
+/* $Id: preparser.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "php.h"
+#include "php_ini.h"
+//#include "../../php-4.0.4/Zend/zend_hilight.h"
+#include "zend_highlight.h"
+#include "ext/standard/basic_functions.h"
+#include "php_midgard.h"
+#include "mgd_internal.h"
+#include "mgd_preparser.h"
+//#include "internal_functions.h"
+
+#if HAVE_MIDGARD
+
+#include <mgd_apache.h>
+#include <mgd_select_db.h>
+
+#include "midgard.h"
+
+void php_mgd_call_udf_function(char *type, zval *return_value, zval *arg)
+{
+       zval retval, **function_name;
+       zval *udf = mgd_getudf();
+
+       if(!return_value) {
+               INIT_ZVAL(retval);
+               return_value = &retval;
+       }
+
+       if(zend_hash_find(udf->value.ht, type,
+                                                  strlen(type)+1,
+                                                  (void **)&function_name) != 
+SUCCESS) {
+               php_error(E_WARNING,"Unknown user formatter [x]%s", type);
+               RETURN_FALSE;
+       }       
+//     *return_value = **function_name; zval_copy_ctor(return_value);
+       
+       RETVAL_FALSE;
+       if (call_user_function(CG(function_table), NULL, *function_name,
+                               return_value, 1, &arg) != SUCCESS) {
+               php_error(E_WARNING,"Unable to call %s() - function does not exist",
+                                 (*function_name)->value.str.val);
+               RETURN_FALSE;
+       }
+}
+
+char * php_midgard_include(midgard_pool * pool, char * name, char * value, char * 
+type)
+{
+       midgard *mgd;
+
+       if ((mgd = mgd_handle()) == NULL) {
+               php_error(E_NOTICE, "Not a midgard request");
+               return NULL;
+       }
+
+       if(!pool && type[0]=='i') { /* inline */
+               return value;
+       }
+
+       if (!type) {
+               return mgd_format(mgd, pool, "$p", value);
+       }
+
+       if (strcmp(type, "u") == 0
+                       || strcmp(type, "url") == 0)
+               return mgd_format(mgd, pool, "$u", value);
+       else if (strcmp(type, "f") == 0
+                || strcmp(type, "format") == 0)
+               return mgd_format(mgd, pool, "$f", value);
+       else if (strcmp(type, "F") == 0
+                || strcmp(type, "format-more") == 0)
+               return mgd_format(mgd, pool, "$F", value);
+       else if (strcmp(type, "t") == 0
+                || strcmp(type, "text") == 0)
+               return mgd_format(mgd, pool, "$h", value);
+       else if (strcmp(type, "T") == 0
+                || strcmp(type, "quote-all") == 0)
+               return mgd_format(mgd, pool, "$p", value);
+       else if (strcmp(type, "h") == 0
+                || strcmp(type, "html") == 0)
+               return mgd_format(mgd, pool, "$H", value);
+       else
+               php_error(E_NOTICE, "Unknown format type %s", type);
+
+       return NULL;
+}
+
+char * php_midgard_template(midgard_pool * pool, char * name)
+{
+       char *value = NULL;
+       midgard_request_config *rcfg = mgd_rcfg();
+
+       if (mgd_handle() == NULL) {
+               php_error(E_ERROR, "Not a midgard request.");
+               return NULL;
+       }
+
+/* TODO: check this when enabling FTs
+       if (MGD_ENV.ft.elements) {
+               value = g_hash_table_lookup(MGD_ENV.ft.elements, name);
+       }
+*/
+
+       if (value == NULL && rcfg != NULL)
+               value = (char *)ap_table_get(rcfg->elements, name);
+
+       if (value == NULL) {
+               return NULL;
+       }
+
+       return value;
+}
+
+MGD_FUNCTION(template)
+{
+       zval **arg;
+       char *tmp;
+       midgard_pool * pool;
+
+       if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1,&arg)==FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+       convert_to_string_ex(arg);
+       pool = mgd_alloc_pool();
+       tmp = php_midgard_template(pool, (*arg)->value.str.val);
+
+       if( tmp== NULL ) {
+               RETVAL_STRING("",1);
+       } else {
+               RETVAL_STRING(tmp,1);
+       }
+
+       mgd_free_pool(pool);
+}
+
+char * php_midgard_variable(midgard_pool * pool, char * name, char * member, char * 
+type)
+{
+       zval **var;
+
+       if (mgd_handle() == NULL) {
+               php_error(E_ERROR, "Not a midgard request.");
+               return NULL;
+       }
+
+       if (zend_hash_find (EG(active_symbol_table), name, 
+                        strlen(name)+1, (void **) &var) == FAILURE) {
+               MGD_LOG_START("Uninitialized variable $%s")
+                       MGD_LOG_ARG(name)
+               MGD_LOG_END()
+               php_error(E_NOTICE, "Uninitialized variable $%s", name);
+               return NULL;
+       }
+
+       if (member) {
+
+               if (!(Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT)) {
+                       MGD_LOG_START("Not an object or array: $%s")
+                               MGD_LOG_ARG(name)
+                       MGD_LOG_END()
+                       php_error(E_NOTICE, "Not an object or array: $%s", name);
+                       return NULL;
+               }
+
+               if (!(Z_TYPE_PP(var) == IS_OBJECT)) {
+                       if(zend_hash_find((*var)->value.ht, member, strlen(member)+1,
+                                               (void **)&var)!= SUCCESS) {
+                               MGD_LOG_START("Uninitialized hash property $%s")
+                                       MGD_LOG_ARG(member)
+                               MGD_LOG_END()
+                               php_error(E_NOTICE, "Uninitialized hash property $%s", 
+member);
+                               return NULL;
+                       }
+               } else {
+                       if(!MGD_PROPFIND((*var), member, var)) {
+                               MGD_LOG_START("Uninitialized member variable $%s")
+                                       MGD_LOG_ARG(member)
+                               MGD_LOG_END()
+                               php_error(E_NOTICE, "Uninitialized member variable 
+$%s",
+                                                                       member);
+                               return NULL;
+                       }
+               }
+       }
+
+       if(type && type[0] == 'x') {/* User Defined Filter func. (UDF/Xtension) */
+               php_mgd_call_udf_function(type + 1, NULL, *var);
+               return NULL;
+       }
+
+       convert_to_string_ex(var);
+       return php_midgard_include(pool, name, (*var)->value.str.val, type);
+}
+
+MGD_FUNCTION(variable)
+{
+       zval **var, **arg, **rec;
+       char *tmp;
+       midgard_pool *pool=NULL;
+
+       if (ZEND_NUM_ARGS() == 1) {
+               if( zend_get_parameters_ex(1,&var) == FAILURE ) {
+                       WRONG_PARAM_COUNT;
+               } else {
+                       pool = mgd_alloc_pool();
+                       convert_to_string_ex(var);
+                       tmp = php_midgard_variable(pool, (*var)->value.str.val, NULL, 
+NULL);
+                       if( tmp== NULL ) {
+                               RETVAL_STRING("",1);
+                       } else {
+                               RETVAL_STRING(tmp,1);
+                       }
+               }
+       }
+
+       if (ZEND_NUM_ARGS() == 2) {
+               if( zend_get_parameters_ex(2,&var,&arg) == FAILURE ) {
+                       WRONG_PARAM_COUNT;
+               } else {
+                       pool = mgd_alloc_pool();
+                       convert_to_string_ex(var);
+                       convert_to_string_ex(arg);
+                       tmp = php_midgard_variable(pool, (*var)->value.str.val, NULL,
+                                                                                      
+  (*arg)->value.str.val);
+                       if( tmp== NULL ) {
+                               RETVAL_STRING("",1);
+                       } else {
+                               RETVAL_STRING(tmp,1);
+                       }
+               }
+       }
+
+       if (ZEND_NUM_ARGS() == 3) {
+               if( zend_get_parameters_ex(3,&var,&rec,&arg) == FAILURE ) {
+                       WRONG_PARAM_COUNT;
+               } else {
+                       pool = mgd_alloc_pool();
+                       convert_to_string_ex(var);
+                       convert_to_string_ex(arg);
+                       convert_to_string_ex(rec);
+                       if( (*arg)->value.str.val[0] == '\0' ) {
+                               tmp = php_midgard_variable(pool, (*var)->value.str.val,
+                                                                                      
+          (*rec)->value.str.val,
+                                                                                      
+          NULL);
+                       } else {
+                               tmp = php_midgard_variable(pool, (*var)->value.str.val,
+                                                                                      
+          (*rec)->value.str.val,
+                                                                                      
+          (*arg)->value.str.val);
+                       }
+                       if( tmp== NULL ) {
+                               RETVAL_STRING("",1);
+                       } else {
+                               RETVAL_STRING(tmp,1);
+                       }
+               }
+       }
+       mgd_free_pool(pool);
+}
+
+MGD_FUNCTION(snippet)
+{
+       zval **file;
+       char *part, *name;
+       midgard_res *res;
+       midgard_pool *pool;
+       int upval, idval;
+       midgard *mgd = mgd_handle(); // DG: GLOBAL(midgard_module_env).mgd;
+       midgard_request_config *rcfg = mgd_rcfg();
+       char *db = NULL;
+       
+       if (ZEND_NUM_ARGS() == 1) {
+               if( zend_get_parameters_ex(1,&file) == FAILURE ) {
+                       WRONG_PARAM_COUNT;
+               } else {
+                       convert_to_string_ex(file);
+               }
+       } else WRONG_PARAM_COUNT;
+
+       /* EEH: if the page database has been defined you will want to include 
+snippets from there too. */
+       if (rcfg->database.page && rcfg->database.page->handle
+                       && rcfg->database.page->handle->mgd) {
+               mgd_select_database(php_rqst, rcfg->database.page, rcfg);
+               db = rcfg->database.page->name; 
+               MGD_LOG_START("Midgard: fetching snippet '%s' from database %s")
+                       MGD_LOG_ARG((*file)->value.str.val)
+                       MGD_LOG_ARG(db)
+               MGD_LOG_END()
+       }
+       
+       if (MGD_PARSE_COMMON_PATH(mgd, (*file)->value.str.val,
+                                       "snippetdir", "snippet", &idval, &upval))
+               RETURN_STRING("",1);
+       
+
+       res = mgd_sitegroup_record(mgd, "code", "snippet", idval);
+       if (!res || !mgd_fetch(res)) {
+               if (res)
+                       mgd_release(res);
+               MGD_LOG_START("Midgard: snippet get record failed: %s")
+                       MGD_LOG_ARG((*file)->value.str.val)
+               MGD_LOG_END()
+               RETURN_STRING("",1);
+       }
+
+       pool = mgd_alloc_pool();
+       if (!pool) {
+               if (res)
+                       mgd_release(res);
+               MGD_LOG_START("Midgard: snippet no pool: %s")
+                       MGD_LOG_ARG((*file)->value.str.val)
+               MGD_LOG_END()
+               RETURN_STRING("",1);
+       }
+
+       part = mgd_strdup(pool, mgd_colvalue(res, 0));
+       name = mgd_strcat(pool, 2, "snippet://", (*file)->value.str.val);
+       mgd_release(res);
+       
+       if (db) {
+               MGD_LOG_START("Midgard: fetched snippet '%s' from database %s")
+                       MGD_LOG_ARG(name)
+                       MGD_LOG_ARG(db)
+               MGD_LOG_END()
+               mgd_select_database(php_rqst, rcfg->database.main, rcfg);
+       }
+
+       RETVAL_STRING(part,1);
+       mgd_free_pool(pool);
+}
+
+MGD_FUNCTION(eval)
+{
+       zval **string, **name;
+       char *tmp, *value;
+       midgard_pool *pool;
+
+       RETVAL_FALSE;
+       switch (ZEND_NUM_ARGS()) {
+               case 2:
+                       if (zend_get_parameters_ex(2, &string, &name) == SUCCESS) {
+                               convert_to_string_ex(string);
+                               convert_to_string_ex(name);
+                               tmp = (*name)->value.str.val;
+                               break;
+                       }
+               case 1:
+                       if (zend_get_parameters_ex(1, &string) == SUCCESS) {
+                               convert_to_string_ex(string);
+                               tmp = "mgd_eval()";
+                               break;
+                       }
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+       if((*string)->value.str.len) {
+#ifdef MGD_PREPARSER_LOG
+               zend_syntax_highlighter_ini syntax_highlighter_ini;
+               php_get_highlight_struct(&syntax_highlighter_ini);
+//             highlight_string(*string, &syntax_highlighter_ini, tmp);
+#endif
+               pool = mgd_alloc_pool();
+               value = php_eval_midgard(pool, tmp, (*string)->value.str.val, 0);
+#ifdef MGD_PREPARSER_LOG
+MGD_LOG_START("mgd_eval(%s) '%s'\n\n\n\n\n\n\n\n")
+       MGD_LOG_ARG(tmp)
+       MGD_LOG_ARG(value)
+MGD_LOG_END()
+#endif
+               if(zend_eval_string(value, NULL /* return_value */, tmp CLS_CC ELS_CC) 
+!= SUCCESS) {
+/* DG: we probably want to turn that off when stable and ready to release
+ * or at least offer the user an option to turn it off, as it exposes the
+ * PHP source (security issue here)
+ */
+                       zend_syntax_highlighter_ini syntax_highlighter_ini;
+                       php_get_highlight_struct(&syntax_highlighter_ini);
+                       highlight_string(*string, &syntax_highlighter_ini, tmp);
+                       mgd_free_pool(pool);
+                       zend_bailout(); //exit(0);
+               }
+               mgd_free_pool(pool);
+       }
+}
+
+MGD_FUNCTION(register_filter)
+{
+       zval **name, **function;
+       zval *func, **retval;
+       zval *udf;
+
+       RETVAL_FALSE;
+       udf = mgd_getudf();
+       switch (ZEND_NUM_ARGS()) {
+               case 2:
+                       if (zend_get_parameters_ex(2, &name, &function) == SUCCESS) {
+                               convert_to_string_ex(name);
+                               convert_to_string_ex(function);
+                               break;
+                       }
+               case 1:
+                       if (zend_get_parameters_ex(1, &name) == SUCCESS) {
+                               convert_to_string_ex(name);
+                               function = NULL;
+                               break;
+                       }
+               case 0:
+                       *return_value = *udf; zval_copy_ctor(return_value);
+                       return;
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+       if(function) {
+               if((*function)->value.str.len) {        /* registration */
+                       MAKE_STD_ZVAL(func);
+                       *func = **function; zval_copy_ctor(func);
+                       if(zend_hash_update(udf->value.ht, (*name)->value.str.val,
+                                                               
+(*name)->value.str.len+1,
+                                                               &func,
+                                                               sizeof(func), NULL) == 
+SUCCESS) {
+                               RETVAL_TRUE;
+                       }
+               } else {                /* unregistration */
+                       if(zend_hash_del(udf->value.ht, (*name)->value.str.val,
+                                                               
+(*name)->value.str.len+1) == SUCCESS) {
+                               RETVAL_TRUE;
+                       }
+               }
+       } else {
+               if(zend_hash_find(udf->value.ht, (*name)->value.str.val,
+                                                               
+(*name)->value.str.len+1,
+                                                               (void **)&retval) == 
+SUCCESS) {
+                       *return_value = **retval; zval_copy_ctor(return_value);
+               }
+       }
+}
+#endif /* HAVE_MIDGARD */
Index: php4/ext/midgard/sitegroup.c
diff -u /dev/null php4/ext/midgard/sitegroup.c:1.3
--- /dev/null   Sat Feb 17 15:21:54 2001
+++ php4/ext/midgard/sitegroup.c        Sat Feb 17 15:21:50 2001
@@ -0,0 +1,303 @@
+/* $Id: sitegroup.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(has_sitegroups)
+{
+#if HAVE_MIDGARD_SITEGROUPS
+       RETURN_TRUE;
+#else
+       RETURN_FALSE;
+#endif
+}
+
+#if HAVE_MIDGARD_SITEGROUPS
+MGD_FUNCTION(list_sitegroups)
+{
+  php_midgard_select(&MidgardSitegroup, return_value, "*", "sitegroup", NULL, "name");
+}
+
+MGD_FUNCTION(create_sitegroup)
+{
+       zval **zv_name, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if (!mgd_isroot(mgd_handle()))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "name", zv_name)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if ((ZEND_NUM_ARGS() != 1)
+                   || (zend_get_parameters_ex(1, &zv_name) !=
+                       SUCCESS)) WRONG_PARAM_COUNT;
+       }
+
+       convert_to_string_ex(zv_name);
+
+       /* no 'magic' chars in sitegroup name */
+       if (strpbrk((*zv_name)->value.str.val, MIDGARD_LOGIN_RESERVED_CHARS))
+               RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_NAME);
+
+       if (mgd_exists_bool
+           (mgd_handle(), "sitegroup", "name=$q",
+            (*zv_name)->value.str.val)) RETURN_FALSE_BECAUSE(MGD_ERR_DUPLICATE);
+
+       php_midgard_create(return_value, "sitegroup",
+                          "name,admingroup", "$q,$d", (*zv_name)->value.str.val,
+                          0);
+
+       PHP_CREATE_REPLIGARD("sitegroup", return_value->value.lval);
+}
+
+MGD_FUNCTION(get_sitegroup)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+               php_midgard_bless(return_value, &MidgardSitegroup);
+               mgd_object_init(return_value, "name", "admingroup", "realm", NULL);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+
+    php_midgard_sitegroup_get(&MidgardSitegroup, return_value, 0, "*", "sitegroup", 
+(*id)->value.lval);
+}
+
+MGD_FUNCTION(update_sitegroup)
+{
+       zval **zv_id, **zv_name, **zv_admingroup, **zv_realm, *self;
+       int group;
+       int id, admingroup;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if (!mgd_isroot(mgd_handle()))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "id", zv_id)
+                   || !MGD_PROPFIND(self, "name", zv_name)
+                   || !MGD_PROPFIND(self, "admingroup", zv_admingroup)
+                   || !MGD_PROPFIND(self, "realm", zv_realm)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if ((ZEND_NUM_ARGS() != 4)
+                   ||
+                   (zend_get_parameters_ex
+                    (4, &zv_id, &zv_name, &zv_admingroup,
+                     &zv_realm) != SUCCESS)) WRONG_PARAM_COUNT;
+       }
+
+       convert_to_string_ex(zv_name);
+       convert_to_string_ex(zv_realm);
+       convert_to_long_ex(zv_admingroup);
+       convert_to_long_ex(zv_id);
+
+       id = (*zv_id)->value.lval;
+       admingroup = (*zv_admingroup)->value.lval;
+
+       if (id == 0)
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       group = mgd_exists_id(mgd_handle(), "sitegroup", "name=$q",
+                               (*zv_name)->value.str.val);
+       if (group != 0 && group != id)
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       /* check admingroup == sitegroup || admingroup == 0 */
+       if (admingroup != 0
+           && !mgd_exists_bool(mgd_handle(), "grp", "id=$d and sitegroup=$d",
+                               admingroup, id)
+          )
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+
+       php_midgard_update(return_value,
+                          "sitegroup",
+                          "name=$q, admingroup=$d, realm=$q",
+                          id,
+                          (*zv_name)->value.str.val,
+                          admingroup, (*zv_realm)->value.str.val);
+       PHP_UPDATE_REPLIGARD("sitegroup", id);
+}
+
+MGD_FUNCTION(delete_sitegroup)
+{
+  IDINIT;
+  CHECK_MGD;
+
+  if (!mgd_isroot(mgd_handle())) RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+  if (mgd_global_exists(mgd_handle(), "sitegroup=$d", id)) 
+RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+  php_midgard_delete(return_value, "sitegroup", id);
+  PHP_DELETE_REPLIGARD("sitegroup", id);
+}
+
+MGD_FUNCTION(oop_sitegroup_get)
+{
+zval *self = NULL;
+zval **pv_table, **pv_id;
+int sitegroup;
+
+   CHECK_MGD;
+
+   if ((self=getThis()) == NULL) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+
+   if (zend_hash_find(self->value.obj.properties, "__table__", 10,
+         (void **) &pv_table) != SUCCESS) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+   if (zend_hash_find(self->value.obj.properties, "id", 3,
+         (void **) &pv_id) != SUCCESS) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+   convert_to_string_ex(pv_table);
+   convert_to_long_ex(pv_id);
+
+   if (strcmp((*pv_table)->value.str.val, "sitegroup") == 0) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+   }
+
+   if (ZEND_NUM_ARGS() != 0) { WRONG_PARAM_COUNT; }
+
+   sitegroup = mgd_idfield(mgd_handle(), "sitegroup",
+      (*pv_table)->value.str.val,(*pv_id)->value.lval);
+
+   php_midgard_sitegroup_get(&MidgardSitegroup, return_value,
+      0, "*", "sitegroup", sitegroup);
+}
+
+MGD_FUNCTION(oop_sitegroup_set)
+{
+   zval *self;
+   zval **zv_sitegroup;
+   zval **zv_table, **zv_id;
+
+   CHECK_MGD;
+
+       if (!mgd_isroot(mgd_handle())) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+   }
+
+       if ((self = getThis()) == NULL) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+
+   if (ZEND_NUM_ARGS() != 1) { WRONG_PARAM_COUNT; }
+
+   if (zend_hash_find(self->value.obj.properties, "__table__", 10,
+         (void **) &zv_table) != SUCCESS) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+   if (zend_hash_find(self->value.obj.properties, "id", 3,
+         (void **) &zv_id) != SUCCESS) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_NOT_OBJECT);
+   }
+
+   convert_to_string_ex(zv_table);
+   convert_to_long_ex(zv_id);
+
+   if (strcmp((*zv_table)->value.str.val, "sitegroup") == 0) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+   }
+
+   if (zend_get_parameters_ex(1, &zv_sitegroup) == FAILURE) {
+      WRONG_PARAM_COUNT;
+   }
+
+   convert_to_long_ex(zv_sitegroup);
+
+   if ((*zv_sitegroup)->value.lval != 0
+         && !mgd_exists_bool(mgd_handle(), "sitegroup", "id=$d",
+               (*zv_sitegroup)->value.lval)) {
+      RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+   }
+
+   php_midgard_update(return_value,
+      (*zv_table)->value.str.val,
+      "sitegroup=$d", (*zv_id)->value.lval,
+      (*zv_sitegroup)->value.lval);
+   PHP_UPDATE_REPLIGARD((*zv_table)->value.str.val, (*zv_id)->value.lval);
+}
+
+MidgardProperty MidgardSitegroupProperties [] = {
+       { IS_STRING,    "name"                  },
+       { IS_LONG,              "admingroup"    },
+       { IS_STRING,    "realm"                 },
+       { 0,                    NULL                    }
+};
+
+MIDGARD_HANDLERS_DECL(sitegroup)
+static zend_function_entry MidgardSitegroupMethods[] = {
+//      MidgardSitegroup class constructor
+//      PHP_FALIAS(midgardsitegroup,   mgd_ctor_sitegroup,  NULL)
+   PHP_FALIAS(create,  mgd_create_sitegroup,   NULL)
+   PHP_FALIAS(update,  mgd_update_sitegroup,   NULL)
+   PHP_FALIAS(delete,  mgd_delete_sitegroup,   NULL)
+   PHP_FALIAS(fetch,   mgd_oop_list_fetch,             NULL)
+   MIDGARD_OOP_PARAMETER_METHODS
+   MIDGARD_OOP_ATTACHMENT_METHODS
+   {  NULL,             NULL,                         NULL}
+};
+MidgardClass MidgardSitegroup = {
+   "MidgardSitegroup",
+   "sitegroup",
+   MidgardSitegroupMethods,
+   {},
+   mgd_sitegroup_call_function_handler,
+   mgd_sitegroup_get_property_handler,
+   mgd_sitegroup_set_property_handler,
+   MidgardSitegroupProperties,
+   NULL
+};
+MIDGARD_HANDLERS(MidgardSitegroup, sitegroup)
+
+#endif
Index: php4/ext/midgard/snippet.c
diff -u /dev/null php4/ext/midgard/snippet.c:1.3
--- /dev/null   Sat Feb 17 15:21:54 2001
+++ php4/ext/midgard/snippet.c  Sat Feb 17 15:21:50 2001
@@ -0,0 +1,315 @@
+/* $Id: snippet.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(snippet_exists)
+{
+       zval **file;
+       int upval, idval;
+       midgard *mgd = mgd_handle(); // DG: GLOBAL(midgard_module_env).mgd;
+       
+       RETVAL_FALSE;
+       if (ZEND_NUM_ARGS() == 1) {
+               if( zend_get_parameters_ex(1,&file) == FAILURE ) {
+                       WRONG_PARAM_COUNT;
+               } else {
+                       convert_to_string_ex(file);
+               }
+       } else WRONG_PARAM_COUNT;
+
+       if (MGD_PARSE_COMMON_PATH(mgd, (*file)->value.str.val,
+                                       "snippetdir", "snippet", &idval, &upval))
+               return;
+       
+       if(idval) RETURN_TRUE;
+}
+
+MGD_FUNCTION(list_snippets)
+{
+    IDINIT;
+       CHECK_MGD;
+    php_midgard_select(&MidgardSnippet, return_value, 
+"id,name,author,creator,created,revisor,revised,revision", "snippet", "up=$d", 
+"name", id);
+}
+
+MGD_FUNCTION(get_snippet)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+               php_midgard_bless(return_value, &MidgardSnippet);
+               mgd_object_init(return_value, "up", "name", "code", "doc", "author", 
+NULL);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+       if(!(*id)->value.lval)
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+    php_midgard_get(&MidgardSnippet, return_value, 
+"id,up,name,code,doc,author,creator,created,revisor,revised,revision", "snippet", 
+(*id)->value.lval);
+}
+
+MGD_FUNCTION(get_snippet_by_name)
+{
+    zval **snippetdir, **name;
+       CHECK_MGD;
+    if (ZEND_NUM_ARGS() != 2
+       || zend_get_parameters_ex(2, &snippetdir, &name) != SUCCESS)
+       WRONG_PARAM_COUNT;
+    convert_to_long_ex(snippetdir);
+    convert_to_string_ex(name);
+
+       if(!(*snippetdir)->value.lval || !(*name)->value.str.len)
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+    php_midgard_get_by_name(&MidgardSnippet, return_value, 
+"id,up,name,code,doc,author,creator,revisor,revised,revision", "snippet", "up",
+                           (*snippetdir)->value.lval,(*name)->value.str.val);
+}
+
+MGD_FUNCTION(create_snippet)
+{
+       zval **snippetdir, **name, **code, **doc, **author, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "up", snippetdir)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "code", code)
+                   || !MGD_PROPFIND(self, "doc", doc)
+                   || !MGD_PROPFIND(self, "author", author)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               self = NULL;
+               if (ZEND_NUM_ARGS() != 5
+                   || zend_get_parameters_ex(5, &snippetdir, &name, &code, &doc,
+                                    &author) == FAILURE)
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(snippetdir);
+       convert_to_string_ex(name);
+       convert_to_string_ex(code);
+       convert_to_string_ex(doc);
+       convert_to_string_ex(author);
+
+       if (!mgd_exists_id
+           (mgd_handle(), "snippetdir", "id=$d",
+            (*snippetdir)->value.lval)) RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* up must be in same SG or be 0 */
+       if ((*snippetdir)->value.lval != 0
+           && !mgd_exists_id(mgd_handle(), "snippetdir",
+                             "id=$d AND sitegroup IN (0,$d)",
+                             (*snippetdir)->value.lval,
+                             mgd_sitegroup(mgd_handle())))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+       if (!issnippetdirowner((*snippetdir)->value.lval)
+           || mgd_exists_id(mgd_handle(), "snippet", "up=$d AND name=$q",
+                            (*snippetdir)->value.lval, (*name)->value.str.val))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       php_midgard_create(return_value, "snippet",
+                          
+"up,name,code,doc,author,creator,created,revisor,revised,revision",
+                          "$d,$q,$q,$q,$q,$d,Now(),$d,Now(),0",
+                          (*snippetdir)->value.lval, (*name)->value.str.val,
+                          (*code)->value.str.val, (*doc)->value.str.val,
+                          (*author)->value.str.val, mgd_user(mgd_handle()),
+                          mgd_user(mgd_handle()));
+
+       PHP_CREATE_REPLIGARD("snippet", return_value->value.lval);
+}
+
+MGD_FUNCTION(update_snippet)
+{
+       zval **id, **name, **code, **doc, **author, *self;
+       int up;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "id", id)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "code", code)
+                   || !MGD_PROPFIND(self, "doc", doc)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+      
+       convert_to_long_ex(id);
+       convert_to_string_ex(name);
+       convert_to_string_ex(code);
+       convert_to_string_ex(doc);
+       author = NULL;
+      if (mgd_isadmin(mgd_handle())) {
+         if (!MGD_PROPFIND(self, "author", author)) {
+            RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+         }
+       convert_to_string_ex(author);
+      }
+       }
+       else {
+               switch (ZEND_NUM_ARGS()) {
+                       case 4:
+                               if (zend_get_parameters_ex
+                                   (4, &id, &name, &code, &doc) == FAILURE) {
+                                       WRONG_PARAM_COUNT;
+                               }
+                               convert_to_long_ex(id);
+                               convert_to_string_ex(name);
+                               convert_to_string_ex(code);
+                               convert_to_string_ex(doc);
+                               author = NULL;
+                               break;
+
+                       case 5:
+                               if (!mgd_isadmin(mgd_handle())
+                                   || zend_get_parameters_ex(5, &id, &name, &code,
+                                                    &doc, &author) == FAILURE) {
+                                       WRONG_PARAM_COUNT;
+                               }
+                               convert_to_long_ex(id);
+                               convert_to_string_ex(name);
+                               convert_to_string_ex(code);
+                               convert_to_string_ex(doc);
+                               convert_to_string_ex(author);
+                               break;
+
+                       default:
+                               WRONG_PARAM_COUNT;
+               }
+       }
+
+       if (!mgd_exists_id(mgd_handle(), "snippet", "id=$d", (*id)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_NOT_EXISTS);
+
+       if (!issnippetdirowner
+           (up =
+            mgd_idfield(mgd_handle(), "up", "snippet",
+                        (*id)->value.lval)))
+             RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       if (mgd_exists_id
+           (mgd_handle(), "snippet", "id!=$d AND up=$d AND name=$q",
+            (*id)->value.lval, up, (*name)->value.str.val))
+               RETURN_FALSE_BECAUSE(MGD_ERR_DUPLICATE);
+
+       if (author)
+               php_midgard_update(return_value, "snippet",
+                                  
+"name=$q,code=$q,doc=$q,author=$q,revisor=$d,revised=Now(),revision=revision+1",
+                                  (*id)->value.lval, (*name)->value.str.val,
+                                  (*code)->value.str.val, (*doc)->value.str.val,
+                                  (*author)->value.str.val,
+                                  mgd_user(mgd_handle()));
+       else
+               php_midgard_update(return_value, "snippet",
+                                  
+"name=$q,code=$q,doc=$q,revisor=$d,revised=Now(),revision=revision+1",
+                                  (*id)->value.lval, (*name)->value.str.val,
+                                  (*code)->value.str.val, (*doc)->value.str.val,
+                                  mgd_user(mgd_handle()));
+       PHP_UPDATE_REPLIGARD("snippet", (*id)->value.lval);
+}
+
+MGD_FUNCTION(delete_snippet)
+{
+       IDINIT;
+       CHECK_MGD;
+
+       if (mgd_has_dependants(mgd_handle(), id, "snippet"))
+               RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+       if (!issnippetdirowner(mgd_idfield(mgd_handle(), "up", "snippet", id)))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       php_midgard_delete(return_value, "snippet", id);
+       PHP_DELETE_REPLIGARD("snippet", id);
+}
+
+MGD_FUNCTION(copy_snippet)
+{
+       zval **id, **newsnippetdir;
+       RETVAL_FALSE;
+       CHECK_MGD;
+       switch (ZEND_NUM_ARGS()) {
+               case 2:
+                       if (zend_get_parameters_ex(2, &id, &newsnippetdir) !=
+                           SUCCESS) WRONG_PARAM_COUNT;
+                       break;
+               case 1:
+                       if (zend_get_parameters_ex(1, &id) != SUCCESS)
+                               WRONG_PARAM_COUNT;
+                       newsnippetdir = NULL;
+                       break;
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(id);
+       if (newsnippetdir)
+               convert_to_long_ex(newsnippetdir);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* newsnippetdir must be in same SG or be 0 */
+       if (newsnippetdir && !mgd_exists_bool(mgd_handle(), "snippetdir,snippet",
+                                   "snippetdir.id=$d AND snippet.id=$d"
+                                   " AND (snippetdir.sitegroup=snippet.sitegroup"
+                                   " OR snippetdir.sitegroup=0"
+                                   " OR snippet.sitegroup=0)",
+                                   (*newsnippetdir)->value.lval, (*id)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+       RETVAL_LONG(mgd_copy_snippet(mgd_handle(), (*id)->value.lval,
+                                    newsnippetdir ? (*newsnippetdir)->value.lval : 
+0));
+
+}
+
+MGD_MOVE_FUNCTION(snippet,snippetdir,snippet,up);
+
+MidgardProperty MidgardSnippetProperties [] = {
+       { IS_LONG,              "up"            },
+       { IS_STRING,    "name"          },
+       { IS_STRING,    "code"          },
+       { IS_STRING,    "doc"           },
+       { IS_STRING,    "author"        },
+       { 0,                    NULL            }
+};
+
+MIDGARD_CLASS(MidgardSnippet, snippet)
Index: php4/ext/midgard/snippetdir.c
diff -u /dev/null php4/ext/midgard/snippetdir.c:1.3
--- /dev/null   Sat Feb 17 15:21:54 2001
+++ php4/ext/midgard/snippetdir.c       Sat Feb 17 15:21:50 2001
@@ -0,0 +1,323 @@
+/* $Id: snippetdir.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(is_snippetdir_owner)
+{
+    IDINIT;
+    CHECK_MGD;
+    RETVAL_LONG(issnippetdirowner(id));
+}
+
+MGD_FUNCTION(list_snippetdirs)
+{
+    zval **id;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    if (ZEND_NUM_ARGS() != 1
+               || zend_get_parameters_ex(1, &id) != SUCCESS)
+               WRONG_PARAM_COUNT;
+    convert_to_long_ex(id);
+
+    php_midgard_select(&MidgardSnippetdir, return_value, "id,name", "snippetdir", 
+"up=$d", "name", (*id)->value.lval);
+}
+
+MGD_FUNCTION(get_snippetdir)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+               php_midgard_bless(return_value, &MidgardSnippetdir);
+               mgd_object_init(return_value, "name", "description", "owner", NULL);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+
+    php_midgard_get(&MidgardSnippetdir, return_value, "id,up,name,description,owner", 
+ "snippetdir", (*id)->value.lval);
+}
+
+MGD_FUNCTION(get_snippetdir_by_path)
+{
+       zval **path;
+       int id, up;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+               object_init(return_value);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &path) == SUCCESS) {
+                       convert_to_string_ex(path);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+    if(!MGD_PARSE_COMMON_PATH(mgd_handle(), (*path)->value.str.val, "snippetdir", 
+"snippetdir", &id, &up)) {
+        php_midgard_get(&MidgardSnippetdir, return_value, 
+"id,up,name,description,owner", "snippetdir", id);
+       return;
+    }
+}
+
+static int snippetdir_owner_id = 0;
+static int snippetdir_copy_hook(midgard *mgd, const char *table, const char *name, 
+int up, int id, int flag) {
+    if((flag == MIDGARD_PATH_ELEMENT_EXISTS)) {
+       return id;
+    }
+    if(flag == MIDGARD_PATH_ELEMENT_NOTEXISTS) {
+    if (!issnippetdirowner(up) || 
+       mgd_exists_id(mgd_handle(), "topic", "up=$d AND name=$q", up, name)) return 0;
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* up must be in same SG or be 0 */
+       if (up != 0 && !mgd_exists_id(mgd_handle(), "snippetdir",
+                       "id=$d",
+                       up)) return 0;
+       /* owner must be in same SG or be 0 */
+       /* TODO: should we in fact allow owner == 0 for non-root? */
+       if (snippetdir_owner_id != 0 && !mgd_exists_id(mgd_handle(), "grp",
+                       "id=$d",
+                       snippetdir_owner_id)) return 0;
+#endif
+        id = mgd_create(mgd, table, "name,up,owner", "$q,$d,$d", name,
+                       up,snippetdir_owner_id);
+       PHP_CREATE_REPLIGARD_VOID(table,id);
+       return id;
+    }
+    return 0;
+}
+
+MGD_FUNCTION(create_snippetdir)
+{
+       zval **up, **name, **description, **owner, *self;
+       int id;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       up = NULL;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "description", description)
+                   || !MGD_PROPFIND(self, "owner", owner)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+
+               if (!MGD_PROPFIND(self, "up", up))
+                       up = NULL;
+       }
+       else {
+               switch (ZEND_NUM_ARGS()) {
+                       case 3:
+                               if (zend_get_parameters_ex
+                                   (ht, 3, &name, &description,
+                                    &owner) != SUCCESS) WRONG_PARAM_COUNT;
+                               break;
+                       case 4:
+                               if (zend_get_parameters_ex
+                                   (4, &up, &name, &description,
+                                    &owner) != SUCCESS) WRONG_PARAM_COUNT;
+                               break;
+                       default:
+                               WRONG_PARAM_COUNT;
+               }
+       }
+       if (up)
+               convert_to_long_ex(up);
+       convert_to_string_ex(name);
+       convert_to_string_ex(description);
+       convert_to_long_ex(owner);
+       snippetdir_owner_id = (*owner)->value.lval;
+       if (up) {
+#if HAVE_MIDGARD_SITEGROUPS
+               /* up must be in same SG or be 0 */
+               if ((*up)->value.lval != 0
+                   && !mgd_exists_id(mgd_handle(), "snippetdir", "id=$d",
+                                     (*up)->value.lval))
+                          RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+               /* owner must be in same SG or be 0 */
+               /* TODO: should we in fact allow owner == 0 for non-root? */
+               if ((*owner)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "grp",
+                                                            "id=$d",
+                                                            (*owner)->value.lval))
+                          RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+               if (!issnippetdirowner((*up)->value.lval)
+                   || mgd_exists_id(mgd_handle(), "snippetdir",
+                                    "up=$d AND name=$q", (*up)->value.lval,
+                                    (*name)->value.str.val))
+                          RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+
+               php_midgard_create(return_value, "snippetdir",
+                                  "name,up,owner, description", "$q,$d,$d,$q",
+                                  (*name)->value.str.val, (*up)->value.lval,
+                                  snippetdir_owner_id,
+                                  (*description)->value.str.val);
+
+               PHP_CREATE_REPLIGARD("snippetdir", return_value->value.lval);
+       }
+       else {
+               if (!mgd_parse_path_with_hook
+                   (mgd_handle(), (*name)->value.str.val, "snippetdir", NULL, NULL,
+                    NULL, NULL, &id, snippetdir_copy_hook)) {
+
+                       RETURN_LONG(id);
+               }
+       }
+}
+
+MGD_FUNCTION(update_snippetdir)
+{
+       zval **id, **name, **description, **owner, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "id", id)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "description", description)
+                   || !MGD_PROPFIND(self, "owner", owner)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 4
+                   || zend_get_parameters_ex(4, &id, &name, &description,
+                                    &owner) != SUCCESS) WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(id);
+       convert_to_string_ex(name);
+       convert_to_string_ex(description);
+       convert_to_long_ex(owner);
+       if (!issnippetdirowner((*id)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       if (mgd_exists_id
+           (mgd_handle(), "snippetdir", "id!=$d AND up=$d AND name=$q",
+            (*id)->value.lval, mgd_idfield(mgd_handle(), "up", "snippetdir",
+                                        (*id)->value.lval),
+            (*name)->value.str.val)) RETURN_FALSE_BECAUSE(MGD_ERR_DUPLICATE);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* owner must be in same SG or be 0 */
+       /* should we in fact allow owner == 0 for non-root? */
+       if ((*owner)->value.lval != 0
+           && !mgd_exists_bool(mgd_handle(), "snippetdir,grp",
+                               "snippetdir.id=$d AND grp.id=$d"
+                               " AND (snippetdir.sitegroup=grp.sitegroup"
+                               " OR snippetdir.sitegroup=0"
+                               " OR grp.sitegroup=0)",
+                               (*id)->value.lval,
+                               (*owner)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+       php_midgard_update(return_value, "snippetdir",
+                          "name=$q, owner=$d, description=$q", (*id)->value.lval,
+                          (*name)->value.str.val, (*owner)->value.lval,
+                          (*description)->value.str.val);
+       PHP_UPDATE_REPLIGARD("snippetdir", (*id)->value.lval);
+}
+
+MGD_FUNCTION(delete_snippetdir)
+{
+    IDINIT;
+       CHECK_MGD;
+    if(mgd_has_dependants(mgd_handle(),id,"snippetdir"))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+    if (!issnippetdirowner(id)) RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+    if (mgd_exists_id(mgd_handle(), "snippetdir", "up=$d", id))
+           RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+    if (mgd_exists_id(mgd_handle(), "snippet", "up=$d", id))
+           RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+    php_midgard_delete(return_value, "snippetdir", id);
+    PHP_DELETE_REPLIGARD("snippetdir", id);
+}
+
+MGD_FUNCTION(delete_snippetdir_tree)
+{
+    IDINIT;
+    CHECK_MGD;
+    RETVAL_FALSE;
+    if (!issnippetdirowner(mgd_idfield(mgd_handle(), "up", "snippetdir", id))) 
+RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+    if(mgd_delete_snippetdir(mgd_handle(),  id)) { RETVAL_TRUE; }
+}
+
+MGD_FUNCTION(copy_snippetdir)
+{
+    zval **id, **path; int id_r, id_v;
+
+    RETVAL_FALSE;
+       CHECK_MGD;
+    if (ZEND_NUM_ARGS() != 2
+       || zend_get_parameters_ex(2, &id, &path) != SUCCESS)
+       WRONG_PARAM_COUNT;
+    convert_to_long_ex(id);
+    convert_to_string_ex(path);
+
+    /* Create destination snippetdir */
+    if(!mgd_parse_path_with_hook(mgd_handle(), (*path)->value.str.val, "snippetdir", 
+NULL, NULL, 
+                               NULL, NULL, &id_v, snippetdir_copy_hook)) {
+       id_r = mgd_copy_snippetdir(mgd_handle(),  (*id)->value.lval);
+       if(id_r) {
+           php_midgard_update(return_value, "snippetdir", "up=$i", id_r, id_v);
+           PHP_UPDATE_REPLIGARD("snippetdir",id_r);
+       }
+    }
+           
+}
+
+MGD_MOVE_FUNCTION(snippetdir,snippetdir,snippetdir,up);
+
+MidgardProperty MidgardSnippetdirProperties [] = {
+       { IS_LONG,              "up"                    },
+       { IS_STRING,    "name"                  },
+       { IS_STRING,    "description"   },
+       { IS_LONG,              "owner"                 },
+       { 0,                    NULL                    }
+};
+
+MIDGARD_CLASS(MidgardSnippetdir, snippetdir)
Index: php4/ext/midgard/style.c
diff -u /dev/null php4/ext/midgard/style.c:1.3
--- /dev/null   Sat Feb 17 15:21:54 2001
+++ php4/ext/midgard/style.c    Sat Feb 17 15:21:50 2001
@@ -0,0 +1,238 @@
+/* $Id: style.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(is_style_owner)
+{
+    IDINIT;
+    CHECK_MGD;
+    RETVAL_LONG(isstyleowner(id));
+}
+
+MGD_FUNCTION(list_styles)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+        php_midgard_select(&MidgardStyle, return_value, "id,name", "style", NULL, 
+"name");
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+    php_midgard_select(&MidgardStyle, return_value, "id,name", "style", "up=$d", 
+"name",
+                                                            (*id)->value.lval);
+}
+
+MGD_FUNCTION(get_style)
+{
+       zval **id;
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+       case 0:
+               php_midgard_bless(return_value, &MidgardStyle);
+               mgd_object_init(return_value, "up", "name", "owner", NULL);
+               return;
+       case 1:
+               if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                       convert_to_long_ex(id);
+                       break;
+               } /* else fall through */
+       default:
+               WRONG_PARAM_COUNT;
+       }
+    php_midgard_get(&MidgardStyle, return_value, "id,up,name,owner", "style", 
+(*id)->value.lval);
+}
+
+MGD_FUNCTION(get_style_by_name)
+{
+    zval **style;
+       CHECK_MGD;
+    if (ZEND_NUM_ARGS() != 1
+       || zend_get_parameters_ex(1, &style) != SUCCESS)
+       WRONG_PARAM_COUNT;
+    convert_to_string_ex(style);
+    php_midgard_get_by_name_only(&MidgardStyle, return_value, "id,up,name,owner", 
+"style", 
+                           (*style)->value.str.val);
+}
+
+MGD_FUNCTION(create_style)
+{
+       zval **up, **name, **owner, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "up", up)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "owner", owner)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 3
+                   || zend_get_parameters_ex(3, &up, &name, &owner) == FAILURE)
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(up);
+       convert_to_string_ex(name);
+       convert_to_long_ex(owner);
+
+       if (!isstyleowner((*up)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* up must be in same SG or be 0 */
+       if ((*up)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "style",
+                                                 "id=$d",
+                                                 (*up)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+       /* owner must be in same SG or be 0 */
+       if ((*owner)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "grp",
+                                                    "id=$d",
+                                                    (*owner)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+       php_midgard_create(return_value, "style", "up,name,owner", "$d,$q,$d",
+                          (*up)->value.lval, (*name)->value.str.val,
+                          (*owner)->value.lval);
+
+       PHP_CREATE_REPLIGARD("style", return_value->value.lval);
+}
+
+MGD_FUNCTION(update_style)
+{
+       zval **id, **name, **owner, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 0) {
+                       WRONG_PARAM_COUNT;
+               }
+
+               if (!MGD_PROPFIND(self, "id", id)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "owner", owner)
+                  ) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 3
+                   || zend_get_parameters_ex(3, &id, &name, &owner) == FAILURE)
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(id);
+       convert_to_string_ex(name);
+       convert_to_long_ex(owner);
+
+       if (!isstyleowner((*id)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* owner must be in same SG or be 0 */
+       if ((*owner)->value.lval != 0 && !mgd_exists_bool(mgd_handle(), "style,grp",
+                                                      "style.id=$d AND grp.id=$d"
+                                                      " AND 
+(style.sitegroup=grp.sitegroup"
+                                                      " OR style.sitegroup=0"
+                                                      " OR grp.sitegroup=0)",
+                                                      (*id)->value.lval,
+                                                      (*owner)->value.lval))
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+       php_midgard_update(return_value, "style", "name=$q,owner=$d",
+                          (*id)->value.lval, (*name)->value.str.val,
+                          (*owner)->value.lval);
+       PHP_UPDATE_REPLIGARD("style", (*id)->value.lval);
+}
+
+MGD_FUNCTION(delete_style)
+{
+    IDINIT;
+       CHECK_MGD;
+    if(mgd_has_dependants(mgd_handle(), id, "style"))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+    if(mgd_exists_id(mgd_handle(), "host", "style=$d", id))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+    if(mgd_exists_id(mgd_handle(), "page", "style=$d", id))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+    if(mgd_exists_id(mgd_handle(), "style", "up=$d", id))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+    if(mgd_exists_id(mgd_handle(), "element", "style=$d", id))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+    if (!isstyleowner(id)) RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+    php_midgard_delete(return_value, "style", id);
+    PHP_DELETE_REPLIGARD("style", id);
+}
+
+
+MGD_FUNCTION(copy_style)
+{
+    IDINIT;
+       CHECK_MGD;
+    RETVAL_LONG(mgd_copy_style(mgd_handle(),  id));
+}
+
+MGD_FUNCTION(delete_style_tree)
+{
+    IDINIT;
+       CHECK_MGD;
+    if (!isstyleowner(mgd_idfield(mgd_handle(), "up", "style", id)))
+       RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+    if(mgd_exists_id(mgd_handle(), "host", "style=$d", id))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+    if(mgd_exists_id(mgd_handle(), "page", "style=$d", id))
+       RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+    if(mgd_delete_style(mgd_handle(),  id))
+       RETVAL_TRUE;
+}
+
+MGD_MOVE_FUNCTION(style,style,style,up)
+
+MidgardProperty MidgardStyleProperties [] = {
+       { IS_LONG,              "up"            },
+       { IS_STRING,    "name"          },
+       { IS_LONG,              "owner"         },
+       { 0,                    NULL            }
+};
+
+MIDGARD_CLASS(MidgardStyle, style)
Index: php4/ext/midgard/topic.c
diff -u /dev/null php4/ext/midgard/topic.c:1.3
--- /dev/null   Sat Feb 17 15:21:54 2001
+++ php4/ext/midgard/topic.c    Sat Feb 17 15:21:50 2001
@@ -0,0 +1,464 @@
+/* $Id: topic.c,v 1.3 2001/02/17 23:21:50 emile Exp $
+Copyright (C) 1999 Jukka Zitting <[EMAIL PROTECTED]>
+Copyright (C) 2000 The Midgard Project ry
+Copyright (C) 2000 Emile Heyns, Aurora SA <[EMAIL PROTECTED]>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "mgd_internal.h"
+#include "mgd_oop.h"
+
+MGD_FUNCTION(is_topic_owner)
+{
+       IDINIT;
+       CHECK_MGD;
+       RETVAL_LONG(istopicowner(id));
+}
+
+static const char *topic_sort(const char *order)
+{
+       static struct
+       {
+               const char *order, *sort;
+       }
+       sort[] =
+       {
+               {
+               "alpha", "name ASC"}
+               , {
+               "reverse alpha", "name DESC"}
+               , {
+               "score", "score ASC,name ASC"}
+               , {
+               "reverse score", "score DESC,name ASC"}
+               , {
+               "revised", "revised ASC"}
+               , {
+               "reverse revised", "revised DESC"}
+               , {
+               "created", "created ASC"}
+               , {
+               "reverse created", "created DESC"}
+               , {
+               NULL, "score DESC,name"}
+       };
+       int i;
+
+       for (i = 0; sort[i].order; i++)
+               if (strcmp(order, sort[i].order) == 0)
+                       return sort[i].sort;
+
+       return sort[i].sort;
+}
+
+MGD_FUNCTION(list_topics)
+{
+       const char *sortv = NULL;
+       zval **id, **sortn;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+       switch (ZEND_NUM_ARGS()) {
+               case 2:
+                       if (zend_get_parameters_ex(2, &id, &sortn) == SUCCESS) {
+                               convert_to_long_ex(id);
+                               convert_to_string_ex(sortn);
+                               sortv = topic_sort((*sortn)->value.str.val);
+                               break;
+                       }
+               case 1:
+                       if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                               convert_to_long_ex(id);
+                               sortv = "score DESC,name";
+                               break;
+                       }
+               default:
+                       wrong_param_count();
+       }
+
+#if 0
+       if (!istopicreader(id))
+               return;
+#endif
+
+       php_midgard_select(&MidgardTopic, return_value,
+                          "id,score,name,owner,extra,description,code,created,"
+            "revised,creator,revisor",
+                          "topic", "up=$d", sortv, (*id)->value.lval);
+}
+
+MGD_FUNCTION(is_in_topic_tree)
+{
+       zval **root, **topic;
+       int *ids, i;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+       if (ZEND_NUM_ARGS() != 2
+           || zend_get_parameters_ex(2, &root, &topic) != SUCCESS)
+                  WRONG_PARAM_COUNT;
+       convert_to_long_ex(root);
+       convert_to_long_ex(topic);
+
+#if 0
+       if (!istopicreader((*topic)->value.lval))
+               return;
+#endif
+
+       ids = mgd_tree(mgd_handle(), "topic", (*root)->value.lval, 0, NULL);
+       if (ids)
+               for (i = 0; ids[i]; i++)
+                       if (ids[i] == (*topic)->value.lval)
+                               RETURN_TRUE;
+}
+
+MGD_FUNCTION(get_topic)
+{
+       zval **id, **name;
+
+       CHECK_MGD;
+
+       switch (ZEND_NUM_ARGS()) {
+               case 0:
+                       php_midgard_bless(return_value, &MidgardTopic);
+                       mgd_object_init(return_value, "id", "up", "name",
+                                        "extra", "owner", "score",
+                                        "description", "revised", "created",
+                                        "revisor", "creator", "revision",
+                                        "code", NULL);
+                       return;
+               case 1:
+                       if (zend_get_parameters_ex(1, &id) == SUCCESS) {
+                               convert_to_long_ex(id);
+                               php_midgard_get(&MidgardTopic,
+                                               return_value,
+                                               
+"id,up,score,name,description,extra,owner,code,"
+                                               "creator,Unix_timestamp(created) as 
+created,"
+                                               "revisor,Unix_timestamp(revised) as 
+revised,revision",
+                                               "topic", (*id)->value.lval);
+                       }
+                       else {
+                               WRONG_PARAM_COUNT;
+                       }
+                       break;
+               case 2:
+                       if (zend_get_parameters_ex(2, &id, &name) == SUCCESS) {
+                               convert_to_long_ex(id);
+                               convert_to_string_ex(name);
+                               php_midgard_get_by_name
+                                  (&MidgardTopic, return_value,
+                                   "id,up,score,name,description,extra,owner,code,"
+                                   "creator,Unix_timestamp(created) as created,"
+                                   "revisor,Unix_timestamp(revised) as revised,"
+                                   "revision", "topic", "up",
+                                   (*id)->value.lval, (*name)->value.str.val);
+                       }
+                       else {
+                               WRONG_PARAM_COUNT;
+                       }
+                       break;
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+}
+
+MGD_FUNCTION(get_topic_by_name)
+{
+   /* EEH: just an alias */
+   php_if_mgd_get_topic(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+}
+
+MGD_FUNCTION(create_topic)
+{
+       zval **up, **name, **description, **extra, **owner, **code;
+       zval *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (!MGD_PROPFIND(self, "up", up)
+                   || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "description", description)
+                   || !MGD_PROPFIND(self, "extra", extra)
+                   || !MGD_PROPFIND(self, "owner", owner)
+                   || !MGD_PROPFIND(self, "code", code)) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 6
+                   || zend_get_parameters_ex(6, &up, &name, &description,
+                                             &extra, &owner, &code) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(up);
+       convert_to_string_ex(name);
+       convert_to_string_ex(description);
+       convert_to_string_ex(extra);
+       convert_to_long_ex(owner);
+       convert_to_string_ex(code);
+
+       if (!istopicowner((*up)->value.lval)
+           || mgd_exists_id(mgd_handle(), "topic", "up=$d AND name=$q",
+                         (*up)->value.lval, (*name)->value.str.val)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       }
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* up must be in same SG or be 0 */
+       if ((*up)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "topic",
+                                                 "id=$d AND sitegroup IN (0,$d)",
+                                                 (*up)->value.lval,
+                                                 mgd_sitegroup(mgd_handle()))) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+       }
+       /* owner must be in same SG or be 0 */
+       /* TODO: should we in fact allow owner == 0 for non-root? */
+       if ((*owner)->value.lval != 0 && !mgd_exists_id(mgd_handle(), "grp",
+                                                    "id=$d AND sitegroup IN (0,$d)",
+                                                    (*owner)->value.lval,
+                                                    mgd_sitegroup(mgd_handle
+                                                                  ()))) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+       }
+#endif
+
+       php_midgard_create(return_value, "topic",
+                          "up,name,description,extra,owner,code,"
+                          "creator,created,revisor,revised,revision",
+                          "$d,$q,$q,$q,$d,$q,$d,Now(),$d,Now(),0",
+                          (*up)->value.lval, (*name)->value.str.val,
+                          (*description)->value.str.val,
+                          (*extra)->value.str.val, (*owner)->value.lval,
+                          (*code)->value.str.val, mgd_user(mgd_handle()),
+                          mgd_user(mgd_handle()));
+       PHP_CREATE_REPLIGARD("topic", return_value->value.lval);
+}
+
+MGD_FUNCTION(update_topic)
+{
+       zval **id, **name, **description, **extra, **owner, **code, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (!MGD_PROPFIND(self, "id", id)
+                       || !MGD_PROPFIND(self, "name", name)
+                   || !MGD_PROPFIND(self, "description", description)
+                   || !MGD_PROPFIND(self, "extra", extra)
+                   || !MGD_PROPFIND(self, "owner", owner)
+                   || !MGD_PROPFIND(self, "code", code)) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 6
+                   || zend_get_parameters_ex(6, &id, &name, &description,
+                                             &extra, &owner, &code) != SUCCESS) {
+                       WRONG_PARAM_COUNT;
+               }
+       }
+
+       convert_to_long_ex(id);
+       convert_to_string_ex(name);
+       convert_to_string_ex(description);
+       convert_to_string_ex(extra);
+       convert_to_string_ex(code);
+       convert_to_long_ex(owner);
+
+       if (!istopicowner((*id)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* owner must be in same SG or be 0 */
+       /* should we in fact allow owner == 0 for non-root? */
+       if ((*owner)->value.lval != 0
+           && !mgd_exists_bool(mgd_handle(), "topic,grp",
+                          "topic.id=$d AND grp.id=$d"
+                          " AND (topic.sitegroup=grp.sitegroup"
+                          " OR topic.sitegroup=0"
+                          " OR grp.sitegroup=0)",
+                          (*id)->value.lval,
+                          (*owner)->value.lval)) {
+                  RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+   }
+#endif
+
+       php_midgard_update(return_value, "topic",
+                          "name=$q,description=$q,extra=$q,owner=$d,code=$q,"
+                          "revisor=$d,revised=Now(),revision=revision+1",
+                          (*id)->value.lval, (*name)->value.str.val,
+                          (*description)->value.str.val,
+                          (*extra)->value.str.val, (*owner)->value.lval,
+                          (*code)->value.str.val, mgd_user(mgd_handle()));
+       PHP_UPDATE_REPLIGARD("topic", (*id)->value.lval);
+}
+
+MGD_FUNCTION(update_topic_score)
+{
+       zval **id, **score, *self;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+
+       if ((self = getThis()) != NULL) {
+               if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &score) !=
+                   SUCCESS) {
+                       WRONG_PARAM_COUNT;
+               }
+               if (!MGD_PROPFIND(self, "id", id)) {
+                       RETURN_FALSE_BECAUSE(MGD_ERR_INVALID_OBJECT);
+               }
+       }
+       else {
+               if (ZEND_NUM_ARGS() != 2
+                   || zend_get_parameters_ex(2, &id, &score) != SUCCESS)
+                       WRONG_PARAM_COUNT;
+       }
+
+       convert_to_long_ex(id);
+       convert_to_long_ex(score);
+
+       if (!istopicowner((*id)->value.lval))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+
+       php_midgard_update(return_value, "topic", "score=$d", (*id)->value.lval,
+                          (*score)->value.lval);
+       PHP_UPDATE_REPLIGARD("topic", (*id)->value.lval);
+}
+
+MGD_FUNCTION(delete_topic)
+{
+       IDINIT;
+       CHECK_MGD;
+       if (mgd_has_dependants(mgd_handle(), id, "topic"))
+               RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+       if (mgd_exists_id(mgd_handle(), "article", "topic=$d", id))
+               RETURN_FALSE_BECAUSE(MGD_ERR_HAS_DEPENDANTS);
+
+       if (!istopicowner(mgd_idfield(mgd_handle(), "up", "topic", id)))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       php_midgard_delete(return_value, "topic", id);
+       PHP_DELETE_REPLIGARD("topic", id);
+}
+
+MGD_FUNCTION(copy_topic)
+{
+       zval **id, **root;
+       int id_r;
+       int new_root;
+
+       RETVAL_FALSE;
+       CHECK_MGD;
+        switch (ZEND_NUM_ARGS()) {
+               case 2:
+                       if (zend_get_parameters_ex(2, &id, &root) !=
+                           SUCCESS) WRONG_PARAM_COUNT;
+                       convert_to_long_ex(root);
+                       new_root = (*root)->value.lval;    
+                       break;
+               case 1:
+                       if (zend_get_parameters_ex(1, &id) != SUCCESS)
+                               WRONG_PARAM_COUNT;
+             convert_to_long_ex(id);
+                       new_root =   mgd_idfield(mgd_handle(), "up", 
+"topic",(*id)->value.lval);
+                       break;
+               default:
+                       WRONG_PARAM_COUNT;
+       }
+       convert_to_long_ex(id);
+
+       /* if new_root is 0 or if not owner, access denied (unless isadmin) */
+       if (!istopicowner(new_root)) {
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+   }
+
+#if HAVE_MIDGARD_SITEGROUPS
+       /* root must be in same SG or be 0 */
+       if (new_root != 0 && 
+                       !mgd_exists_bool(mgd_handle(), "topic src, topic tgt",
+                          "src.id=$d AND tgt.id=$d"
+                          " AND (src.sitegroup=tgt.sitegroup"
+                          " OR src.sitegroup=0" " OR tgt.sitegroup=0)",
+                          (*id)->value.lval, new_root))
+               RETURN_FALSE_BECAUSE(MGD_ERR_SITEGROUP_VIOLATION);
+#endif
+
+       id_r = mgd_copy_topic(mgd_handle(), (*id)->value.lval);
+       if (id_r) {
+               php_midgard_update(return_value, "topic", "up=$i", id_r,
+                                  new_root);
+               PHP_UPDATE_REPLIGARD("topic", id_r);
+       }
+       RETVAL_LONG(new_root);
+}
+
+MGD_FUNCTION(delete_topic_tree)
+{
+       IDINIT;
+       CHECK_MGD;
+       if (!istopicowner(mgd_idfield(mgd_handle(), "up", "topic", id)))
+               RETURN_FALSE_BECAUSE(MGD_ERR_ACCESS_DENIED);
+       if (mgd_delete_topic(mgd_handle(), id))
+               RETVAL_TRUE;
+}
+
+MGD_MOVE_FUNCTION(topic, topic, topic, up)
+
+MidgardProperty MidgardTopicProperties [] = {
+       { IS_LONG,              "up"                    },
+       { IS_STRING,    "name"                  },
+       { IS_STRING,    "extra"                 },
+       { IS_STRING,    "description"   },
+       { IS_STRING,    "code"                  },
+       { IS_LONG,              "owner"                 },
+       { IS_LONG,              "score"                 },
+       { IS_LONG,              "revised"               },
+       { IS_LONG,              "created"               },
+       { IS_LONG,              "revisor"               },
+       { IS_LONG,              "creator"               },
+       { IS_LONG,              "revision"              },
+       { 0,                    NULL                    }
+};
+
+MIDGARD_HANDLERS_DECL(topic)
+static zend_function_entry MidgardTopicMethods[] = {
+   PHP_FALIAS(midgardtopic,   mgd_ctor_topic,       NULL)
+   PHP_FALIAS(create,   mgd_create_topic,       NULL)
+   PHP_FALIAS(update,   mgd_update_topic,       NULL)
+   PHP_FALIAS(delete,   mgd_delete_topic,       NULL)
+   PHP_FALIAS(setscore, mgd_update_topic_score, NULL)
+   PHP_FALIAS(fetch,    mgd_oop_list_fetch,     NULL)
+   MIDGARD_OOP_ATTACHMENT_METHODS
+   MIDGARD_OOP_SITEGROUP_METHODS
+   MIDGARD_OOP_PARAMETER_METHODS
+   {  NULL,             NULL,                   NULL}
+};
+MidgardClass MidgardTopic = {
+   "MidgardTopic",
+   "topic",
+   MidgardTopicMethods,
+   {},
+   mgd_topic_call_function_handler,
+   mgd_topic_get_property_handler,
+   mgd_topic_set_property_handler,
+   MidgardTopicProperties,
+   NULL
+};
+MIDGARD_HANDLERS(MidgardTopic, topic)

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]

Reply via email to