Add the test files
authorAhmed Sarfraaz <sarfraaz@src.gnome.org>
Thu, 20 Oct 2005 06:03:50 +0000 (06:03 +0000)
committerAhmed Sarfraaz <sarfraaz@src.gnome.org>
Thu, 20 Oct 2005 06:03:50 +0000 (06:03 +0000)
servers/exchange/lib/Makefile.am
servers/exchange/lib/actest.c [new file with mode: 0644]
servers/exchange/lib/cptest.c [new file with mode: 0644]
servers/exchange/lib/davcat.c [new file with mode: 0644]
servers/exchange/lib/ebrowse.c [new file with mode: 0644]
servers/exchange/lib/fbtest.c [new file with mode: 0644]
servers/exchange/lib/gctest.c [new file with mode: 0644]
servers/exchange/lib/ruletest.c [new file with mode: 0644]
servers/exchange/lib/test-utils.c [new file with mode: 0644]
servers/exchange/lib/test-utils.h [new file with mode: 0644]
servers/exchange/lib/urltest.c [new file with mode: 0644]

index b119eee..c562bf6 100644 (file)
@@ -142,6 +142,92 @@ libexchangeinclude_HEADERS =                                       \
        e2k-xml-utils.h                                         \
        mapi.h
 
+noinst_PROGRAMS =                                              \
+       ebrowse                                                 \
+       davcat                                                  \
+       actest                                                  \
+       fbtest                                                  \
+       gctest                                                  \
+       ruletest                                                \
+       cptest                                                  \
+       urltest
+
+progs_libadd =                                                 \
+       libexchange.la                                          \
+       $(top_builddir)/servers/exchange/xntlm/libxntlm.la      \
+       $(top_builddir)/libedataserverui/libedataserverui-$(API_VERSION).la     \
+       $(E_DATA_SERVER_LIBS)                                   \
+       $(LDAP_LIBS)                                            \
+       $(SOUP_LIBS)                                            \
+       $(KRB5_LIBS)
+
+ebrowse_SOURCES =                                              \
+       ebrowse.c                                               \
+       test-utils.c
+
+ebrowse.c: e2k-propnames.c
+
+ebrowse_LDADD =                                                        \
+       $(progs_libadd)
+
+davcat_SOURCES =                                               \
+       davcat.c                                                \
+       test-utils.c                                            \
+       test-utils.h
+
+davcat_LDADD =                                                 \
+       $(progs_libadd)
+
+gctest_SOURCES =                                               \
+       gctest.c                                                \
+       test-utils.c                                            \
+       test-utils.h
+
+gctest_LDADD =                                                 \
+       $(progs_libadd)
+
+actest_SOURCES =                                               \
+       actest.c                                                \
+       test-utils.c                                            \
+       test-utils.h
+
+actest_LDADD =                                                 \
+       $(progs_libadd)
+
+fbtest_SOURCES =                                               \
+        fbtest.c                                               \
+       test-utils.c                                            \
+       test-utils.h
+
+fbtest_LDADD =                                                 \
+       $(progs_libadd)                                         \
+       $(EVOLUTION_CALENDAR_LIBS)
+
+ruletest_SOURCES =                                             \
+       ruletest.c                                              \
+       test-utils.c                                            \
+       test-utils.h
+
+ruletest_LDADD =                                               \
+       $(progs_libadd)
+
+cptest_SOURCES =                                               \
+       cptest.c                                                \
+       test-utils.c                                            \
+       test-utils.h
+
+cptest_LDADD =                                                         \
+       $(progs_libadd)
+
+urltest_SOURCES =                                              \
+       urltest.c                                               \
+       test-utils.c                                            \
+       test-utils.h
+
+urltest_LDADD =                                                        \
+       $(progs_libadd)
+
+
 EXTRA_DIST =                                                   \
        e2k-marshal.list                                        \
        mapi-properties                                         \
diff --git a/servers/exchange/lib/actest.c b/servers/exchange/lib/actest.c
new file mode 100644 (file)
index 0000000..3a2efa4
--- /dev/null
@@ -0,0 +1,201 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/* Copyright (C) 2003, 2004 Novell, Inc.
+ *
+ * This  program is free  software; you  can redistribute  it and/or
+ * modify it under the terms of version 2  of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/* Autoconfig test program */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "e2k-autoconfig.h"
+#include "test-utils.h"
+
+const char *test_program_name = "actest";
+
+static E2kOperation op;
+
+static void *
+cancel (void *data)
+{
+       e2k_operation_cancel (&op);
+       return NULL;
+}
+
+static void
+quit (int sig)
+{
+       static pthread_t cancel_thread;
+
+       if (!cancel_thread) {
+               pthread_create (&cancel_thread, NULL, cancel, NULL);
+       } else
+               exit (0);
+}
+
+void
+test_main (int argc, char **argv)
+{
+       E2kAutoconfig *ac;
+       E2kAutoconfigResult result;
+       const char *username, *password, *owa_uri, *gc_server;
+
+       signal (SIGINT, quit);
+
+       if (argc < 2 || argc > 4) {
+               fprintf (stderr, "Usage: %s username [OWA URL] [Global Catalog server]\n", argv[0]);
+               exit (1);
+       }
+
+       username = argv[1];
+       password = test_get_password (username, NULL);
+
+       owa_uri = argc > 2 ? argv[2] : NULL;
+       gc_server = argc > 3 ? argv[3] : NULL;
+
+       e2k_operation_init (&op);
+       ac = e2k_autoconfig_new (owa_uri, username, password,
+                                E2K_AUTOCONFIG_USE_EITHER);
+
+       if (ac->owa_uri) {
+               if (!owa_uri)
+                       printf ("[Default OWA URI: %s]\n", ac->owa_uri);
+       } else {
+               printf ("No default OWA URI available. Must specify on commandline.\n");
+               goto done;
+       }
+
+       if (ac->gc_server)
+               printf ("[Default GC: %s]\n", ac->gc_server);
+       if (ac->nt_domain)
+               printf ("[Default NT Domain: %s]\n", ac->nt_domain);
+       if (ac->w2k_domain)
+               printf ("[Default W2k Domain: %s]\n", ac->w2k_domain);
+       printf ("\n");
+
+       if (gc_server)
+               e2k_autoconfig_set_gc_server (ac, gc_server, -1);
+
+       result = e2k_autoconfig_check_exchange (ac, &op);
+       if (result != E2K_AUTOCONFIG_OK) {
+               const char *msg;
+               switch (result) {
+               case E2K_AUTOCONFIG_CANT_RESOLVE:
+                       msg = "Could not resolve hostname";
+                       break;
+               case E2K_AUTOCONFIG_CANT_CONNECT:
+                       msg = "Could not connect to server";
+                       break;
+               case E2K_AUTOCONFIG_REDIRECT:
+                       msg = "Multiple redirection";
+                       break;
+               case E2K_AUTOCONFIG_AUTH_ERROR:
+                       msg = "Authentication error. Password incorrect?";
+                       break;
+               case E2K_AUTOCONFIG_AUTH_ERROR_TRY_DOMAIN:
+                       msg = "Authentication error. Password incorrect, or try DOMAIN\\username?";
+                       break;
+               case E2K_AUTOCONFIG_AUTH_ERROR_TRY_BASIC:
+                       msg = "Authentication error. Password incorrect, or try Basic auth?";
+                       break;
+               case E2K_AUTOCONFIG_AUTH_ERROR_TRY_NTLM:
+                       msg = "Authentication error. Password incorrect, or try NTLM auth?";
+                       break;
+               case E2K_AUTOCONFIG_TRY_SSL:
+                       msg = "Need to use SSL";
+                       break;
+               case E2K_AUTOCONFIG_EXCHANGE_5_5:
+                       msg = "This is an Exchange 5.5 server";
+                       break;
+               case E2K_AUTOCONFIG_NOT_EXCHANGE:
+                       msg = "Server does not appear to be Exchange";
+                       break;
+               case E2K_AUTOCONFIG_NO_OWA:
+                       msg = "Did not find OWA at given URL";
+                       break;
+               case E2K_AUTOCONFIG_NO_MAILBOX:
+                       msg = "You don't seem to have a mailbox here";
+                       break;
+               case E2K_AUTOCONFIG_CANT_BPROPFIND:
+                       msg = "Server does not allow BPROPFIND";
+                       break;
+               case E2K_AUTOCONFIG_CANCELLED:
+                       msg = "Cancelled";
+                       break;
+               case E2K_AUTOCONFIG_FAILED:
+               default:
+                       msg = "Unknown error";
+                       break;
+               }
+
+               printf ("Exchange check to %s failed:\n  %s\n",
+                       ac->owa_uri, msg);
+               goto done;
+       }
+
+       result = e2k_autoconfig_check_global_catalog (ac, &op);
+       if (result != E2K_AUTOCONFIG_OK) {
+               const char *msg;
+               switch (result) {
+               case E2K_AUTOCONFIG_CANT_RESOLVE:
+                       msg = "Could not resolve GC server";
+                       break;
+               case E2K_AUTOCONFIG_NO_MAILBOX:
+                       msg = "No data for user";
+                       break;
+               case E2K_AUTOCONFIG_AUTH_ERROR_TRY_DOMAIN:
+                       msg = "Authentication error. Try DOMAIN\\username?";
+                       break;
+               case E2K_AUTOCONFIG_CANCELLED:
+                       msg = "Cancelled";
+                       break;
+               case E2K_AUTOCONFIG_FAILED:
+               default:
+                       msg = "Unknown error";
+                       break;
+               }
+
+               printf ("\nGlobal Catalog check failed: %s\n", msg);
+               if (!ac->gc_server) {
+                       if (ac->w2k_domain)
+                               printf ("got domain=%s but ", ac->w2k_domain);
+                       printf ("could not autodetect.\nSpecify GC on command-line.\n");
+               }
+               goto done;
+       }
+
+       printf ("%s is an Exchange Server %s\n\n", ac->exchange_server,
+               ac->version == E2K_EXCHANGE_2000 ? "2000" :
+               ac->version == E2K_EXCHANGE_2003 ? "2003" :
+               "[Unknown version]");
+
+       printf ("Name: %s\nEmail: %s\nTimezone: %s\nAccount URL: %s\n\n",
+               ac->display_name, ac->email, ac->timezone, ac->account_uri);
+
+       if (!ac->pf_server)
+               printf ("Warning: public folder server was defaulted\n\n");
+ done:
+       e2k_operation_free (&op);
+       e2k_autoconfig_free (ac);
+       test_quit ();
+}
diff --git a/servers/exchange/lib/cptest.c b/servers/exchange/lib/cptest.c
new file mode 100644 (file)
index 0000000..567c822
--- /dev/null
@@ -0,0 +1,120 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/* Copyright (C) 2003, 2004 Novell, Inc.
+ *
+ * This  program is free  software; you  can redistribute  it and/or
+ * modify it under the terms of version 2  of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/* Change password test program */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "e2k-kerberos.h"
+#include "test-utils.h"
+
+const char *test_program_name = "cptest";
+
+static void
+krb_error (E2kKerberosResult result, const char *failed)
+{
+       switch (result) {
+       case E2K_KERBEROS_USER_UNKNOWN:
+               fprintf (stderr, "Unknown user\n");
+               exit (1);
+
+       case E2K_KERBEROS_PASSWORD_INCORRECT:
+               fprintf (stderr, "Password incorrect\n");
+               exit (1);
+
+       case E2K_KERBEROS_PASSWORD_EXPIRED:
+               printf ("Note: password has expired\n");
+               break;
+
+       case E2K_KERBEROS_KDC_UNREACHABLE:
+               fprintf (stderr, "KDC unreachable (network problem or no such domain)\n");
+               exit (1);
+
+       case E2K_KERBEROS_TIME_SKEW:
+               fprintf (stderr, "Client/server time skew is too large.\n");
+               exit (1);
+
+       case E2K_KERBEROS_PASSWORD_TOO_WEAK:
+               fprintf (stderr, "Server rejected new password\n");
+               exit (1);
+
+       case E2K_KERBEROS_FAILED:
+               if (failed) {
+                       fprintf (stderr, "%s\n", failed);
+                       exit (1);
+               }
+               /* else fall through */                 
+
+       default:
+               fprintf (stderr, "Unknown error.\n");
+               exit (1);
+       }
+}
+
+void
+test_main (int argc, char **argv)
+{
+       char *domain, *at, *prompt, *password;
+       char *newpass1, *newpass2;
+       const char *user;
+       int res;
+
+       if (argc != 2) {
+               fprintf (stderr, "Usage: %s [user@]domain\n", argv[0]);
+               exit (1);
+       }
+
+       domain = argv[1];
+       at = strchr (domain, '@');
+       if (at) {
+               user = g_strndup (domain, at - domain);
+               domain = at + 1;
+       } else
+               user = g_get_user_name ();
+
+       prompt = g_strdup_printf ("Password for %s@%s", user, domain);
+       password = test_ask_password (prompt);
+       g_free (prompt);
+
+       res = e2k_kerberos_check_password (user, domain, password);
+       if (res != E2K_KERBEROS_OK)
+               krb_error (res, NULL);
+
+       newpass1 = test_ask_password ("New password");
+       newpass2 = test_ask_password ("Confirm");
+
+       if (!newpass1 || !newpass2 || strcmp (newpass1, newpass2) != 0) {
+               fprintf (stderr, "Passwords do not match.\n");
+               exit (1);
+       }
+
+       res = e2k_kerberos_change_password (user, domain, password, newpass1);
+       if (res != E2K_KERBEROS_OK)
+               krb_error (res, "Could not change password");
+
+       printf ("Password changed\n");
+       test_quit ();
+}
diff --git a/servers/exchange/lib/davcat.c b/servers/exchange/lib/davcat.c
new file mode 100644 (file)
index 0000000..d523998
--- /dev/null
@@ -0,0 +1,184 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/* Copyright (C) 2003, 2004 Novell, Inc.
+ *
+ * This  program is free  software; you  can redistribute  it and/or
+ * modify it under the terms of version 2  of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/* Generic WebDAV test program */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "e2k-context.h"
+#include "e2k-uri.h"
+#include "e2k-utils.h"
+#include "e2k-xml-utils.h"
+
+#include "test-utils.h"
+
+static void
+print_header (gpointer name, gpointer value, gpointer data)
+{
+       gboolean *isxml = data;
+
+       printf ("%s: %s\n", (char *)name, (char *)value);
+       if (!g_ascii_strcasecmp (name, "Content-Type") &&
+           strstr (value, "/xml"))
+               *isxml = TRUE;
+}
+
+const char *test_program_name = "davcat";
+
+void
+test_main (int argc, char **argv)
+{
+       E2kContext *ctx;
+       SoupMessage *msg;
+       GByteArray *input;
+       char buf[1024], *base_uri, *root_uri, *eol, *vers, *p;
+       char *method, *path, *uri;
+       char *name, *value;
+       int nread;
+       gboolean isxml = FALSE;
+
+       if (argc != 2) {
+               fprintf (stderr, "usage: %s URI\n", argv[0]);
+               exit (1);
+       }
+       base_uri = argv[1];
+       ctx = test_get_context (base_uri);
+
+       input = g_byte_array_new ();
+       do {
+               nread = read (STDIN_FILENO, buf, sizeof (buf));
+               if (nread > 0)
+                       g_byte_array_append (input, buf, nread);
+       } while (nread > 0 || (nread == -1 && errno == EINTR));
+       g_byte_array_append (input, "", 1);
+
+       method = input->data;
+       eol = strchr (method, '\n');
+       p = strchr (method, ' ');
+       if (!eol || !p || p > eol) {
+               fprintf (stderr, "Could not parse request method\n");
+               exit (1);
+       }
+       *p = '\0';
+
+       path = p + 1;
+       if (*path == '/')
+               path++;
+       p = strchr (path, ' ');
+       if (!p || p > eol)
+               p = eol;
+       *p = '\0';
+       if (p < eol)
+               vers = p + 1;
+       else
+               vers = NULL;
+
+       root_uri = g_strdup (base_uri);
+       p = strstr (root_uri, "://");
+       if (p) {
+               p = strchr (p + 3, '/');
+               if (p)
+                       *p = '\0';
+       }
+       uri = e2k_uri_concat (root_uri, path);
+       g_free (root_uri);
+       msg = e2k_soup_message_new (ctx, uri, method);
+       if (!msg) {
+               fprintf (stderr, "Could not create message to %s\n", uri);
+               exit (1);
+       }
+       g_free (uri);
+
+       if (vers) {
+               if (strncmp (vers, "HTTP/1.", 7) != 0 ||
+                   (vers[7] != '0' && vers[7] != '1')) {
+                       fprintf (stderr, "Could not parse HTTP version\n");
+                       exit (1);
+               }
+               if (vers[7] == '0')
+                       soup_message_set_http_version (msg, SOUP_HTTP_1_0);
+       }
+
+       while (1) {
+               name = eol + 1;
+               eol = strchr (name, '\n');
+               p = strchr (name, ':');
+               if (!eol || eol == name || !p || p > eol || p[1] != ' ')
+                       break;
+               *p = '\0';
+               value = p + 2;
+               *eol = '\0';
+               if (eol[-1] == '\r')
+                       eol[-1] = '\0';
+               soup_message_add_header (msg->request_headers, name, value);
+       }
+
+       p = name;
+       if (*p == '\r')
+               p++;
+       if (*p == '\n')
+               p++;
+
+       if (*p) {
+               msg->request.body = e2k_lf_to_crlf (p);
+               msg->request.length = strlen (msg->request.body);
+               msg->request.owner = SOUP_BUFFER_SYSTEM_OWNED;
+
+               if (!soup_message_get_header (msg->request_headers, "Content-Type")) {
+                       soup_message_add_header (msg->request_headers,
+                                                "Content-Type", "text/xml");
+               }
+       }
+
+       e2k_context_send_message (ctx, NULL, msg);
+
+       printf ("%d %s\n", msg->status_code, msg->reason_phrase);
+       if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code))
+               exit (1);
+
+       soup_message_foreach_header (msg->response_headers,
+                                    print_header, &isxml);
+       printf ("\n");
+
+       if (isxml) {
+               xmlDoc *doc;
+
+               doc = e2k_parse_xml (msg->response.body, msg->response.length);
+               if (doc) {
+                       xmlDocFormatDump (stdout, doc, 1);
+                       xmlFreeDoc (doc);
+               } else
+                       fwrite (msg->response.body, 1, msg->response.length, stdout);
+       } else
+               fwrite (msg->response.body, 1, msg->response.length, stdout);
+       printf ("\n");
+
+       g_object_unref (msg);
+       g_byte_array_free (input, TRUE);
+       g_object_unref (ctx);
+       test_quit ();
+}
diff --git a/servers/exchange/lib/ebrowse.c b/servers/exchange/lib/ebrowse.c
new file mode 100644 (file)
index 0000000..a074132
--- /dev/null
@@ -0,0 +1,715 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/* Copyright (C) 2001-2004 Novell, Inc.
+ *
+ * This  program is free  software; you  can redistribute  it and/or
+ * modify it under the terms of version 2  of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/* WebDAV test program / utility */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <libsoup/soup-misc.h>
+
+#include "e2k-context.h"
+#include "e2k-restriction.h"
+#include "e2k-security-descriptor.h"
+#include "e2k-sid.h"
+#include "e2k-xml-utils.h"
+
+#include "e2k-propnames.h"
+#include "e2k-propnames.c"
+
+#include "test-utils.h"
+
+static E2kContext *ctx;
+static E2kOperation op;
+
+static const char *folder_tree_props[] = {
+       E2K_PR_DAV_DISPLAY_NAME,
+       E2K_PR_EXCHANGE_FOLDER_CLASS
+};
+static const int n_folder_tree_props = sizeof (folder_tree_props) / sizeof (folder_tree_props[0]);
+
+static void
+display_folder_tree (E2kContext *ctx, char *top)
+{
+       E2kRestriction *rn;
+       E2kResultIter *iter;
+       E2kResult *result;
+       int status;
+       const char *name, *class;
+
+       e2k_operation_init (&op);
+       rn = e2k_restriction_prop_bool (E2K_PR_DAV_IS_COLLECTION,
+                                       E2K_RELOP_EQ, TRUE);
+       iter = e2k_context_search_start (ctx, &op, top,
+                                        folder_tree_props,
+                                        n_folder_tree_props,
+                                        rn, NULL, TRUE);
+       e2k_restriction_unref (rn);
+
+       while ((result = e2k_result_iter_next (iter))) {
+               name = e2k_properties_get_prop (result->props,
+                                               E2K_PR_DAV_DISPLAY_NAME);
+               class = e2k_properties_get_prop (result->props,
+                                                E2K_PR_EXCHANGE_FOLDER_CLASS);
+
+               printf ("%s:\n    %s, %s\n", result->href,
+                       name, class ? class : "(No Outlook folder class)");
+       }
+       status = e2k_result_iter_free (iter);
+       e2k_operation_free (&op);
+
+       test_abort_if_http_error (status);
+       test_quit ();
+}
+
+static void
+list_contents (E2kContext *ctx, char *top, gboolean reverse)
+{
+       E2kRestriction *rn;
+       E2kResultIter *iter;
+       E2kResult *result;
+       const char *prop;
+       int status;
+
+       e2k_operation_init (&op);
+       prop = E2K_PR_DAV_DISPLAY_NAME;
+       rn = e2k_restriction_prop_bool (E2K_PR_DAV_IS_COLLECTION,
+                                       E2K_RELOP_EQ, FALSE);
+       iter = e2k_context_search_start (ctx, &op, top, &prop, 1,
+                                        rn, NULL, !reverse);
+       e2k_restriction_unref (rn);
+
+       while ((result = e2k_result_iter_next (iter))) {
+               printf ("%3d %s (%s)\n", e2k_result_iter_get_index (iter),
+                       result->href,
+                       (char *)e2k_properties_get_prop (result->props,
+                                                        E2K_PR_DAV_DISPLAY_NAME));
+       }
+       status = e2k_result_iter_free (iter);
+       e2k_operation_free (&op);
+
+       test_abort_if_http_error (status);
+       test_quit ();
+}
+
+static int
+mp_compar (const void *k, const void *m)
+{
+       const char *key = k;
+       struct mapi_proptag *mp = (void *)m;
+
+       return strncmp (key, mp->proptag, 5);
+}
+
+static void
+print_propname (const char *propname)
+{
+       struct mapi_proptag *mp;
+
+       printf ("  %s", propname);
+
+       if (!strncmp (propname, E2K_NS_MAPI_PROPTAG, sizeof (E2K_NS_MAPI_PROPTAG) - 1)) {
+               mp = bsearch (propname + 42, mapi_proptags, nmapi_proptags,
+                             sizeof (struct mapi_proptag), mp_compar);
+               if (mp)
+                       printf (" (%s)", mp->name);
+       }
+
+       printf (":\n");
+}
+
+static void
+print_binary (GByteArray *data)
+{
+       unsigned char *start, *end, *p;
+
+       end = data->data + data->len;
+       for (start = data->data; start < end; start += 16) {
+               printf ("    ");
+               for (p = start; p < end && p < start + 16; p++)
+                       printf ("%02x ", *p);
+               while (p++ < start + 16)
+                       printf ("   ");
+               printf ("   ");
+               for (p = start; p < end && p < start + 16; p++)
+                       printf ("%c", isprint (*p) ? *p : '.');
+               printf ("\n");
+       }
+}
+
+typedef struct {
+       const char *propname;
+       E2kPropType type;
+       gpointer value;
+} EBrowseProp;
+
+static int
+prop_compar (const void *a, const void *b)
+{
+       EBrowseProp **pa = (void *)a;
+       EBrowseProp **pb = (void *)b;
+
+       return strcmp ((*pa)->propname, (*pb)->propname);
+}
+
+static void
+print_prop (EBrowseProp *prop)
+{
+       print_propname (prop->propname);
+
+       switch (prop->type) {
+       case E2K_PROP_TYPE_BINARY:
+               print_binary (prop->value);
+               break;
+
+       case E2K_PROP_TYPE_STRING_ARRAY:
+       case E2K_PROP_TYPE_INT_ARRAY:
+       {
+               GPtrArray *array = prop->value;
+               int i;
+
+               for (i = 0; i < array->len; i++)
+                       printf ("    %s\n", (char *)array->pdata[i]);
+               break;
+       }
+
+       case E2K_PROP_TYPE_BINARY_ARRAY:
+       {
+               GPtrArray *array = prop->value;
+               int i;
+
+               for (i = 0; i < array->len; i++) {
+                       print_binary (array->pdata[i]);
+                       printf ("\n");
+               }
+               break;
+       }
+
+       case E2K_PROP_TYPE_XML:
+               printf ("    (xml)\n");
+               break;
+
+       case E2K_PROP_TYPE_STRING:
+       default:
+               printf ("    %s\n", (char *)prop->value);
+               break;
+       }
+}
+
+static void
+add_prop (const char *propname, E2kPropType type, gpointer value, gpointer props)
+{
+       EBrowseProp *prop;
+
+       prop = g_new0 (EBrowseProp, 1);
+       prop->propname = propname;
+       prop->type = type;
+       prop->value = value;
+       g_ptr_array_add (props, prop);
+}
+
+static void
+print_properties (E2kResult *results, int nresults)
+{
+       GPtrArray *props;
+       int i;
+
+       if (nresults != 1) {
+               printf ("Got %d results?\n", nresults);
+               test_quit ();
+               return;
+       }
+
+       printf ("%s\n", results[0].href);
+       props = g_ptr_array_new ();
+       e2k_properties_foreach (results[0].props, add_prop, props);
+       qsort (props->pdata, props->len, sizeof (gpointer), prop_compar); 
+
+       for (i = 0; i < props->len; i++)
+               print_prop (props->pdata[i]);
+
+       test_quit ();
+}
+
+static void
+got_all_properties (SoupMessage *msg, gpointer ctx)
+{
+       E2kResult *results;
+       int nresults;
+
+       test_abort_if_http_error (msg->status_code);
+
+       e2k_results_from_multistatus (msg, &results, &nresults);
+       test_abort_if_http_error (msg->status_code);
+       print_properties (results, nresults);
+       e2k_results_free (results, nresults);
+}
+
+
+#define ALL_PROPS \
+"<?xml version=\"1.0\" encoding=\"utf-8\" ?>" \
+"<propfind xmlns=\"DAV:\" xmlns:e=\"http://schemas.microsoft.com/exchange/\">" \
+"  <allprop>" \
+"    <e:allprop/>" \
+"  </allprop>" \
+"</propfind>"
+
+static void
+get_all_properties (E2kContext *ctx, char *uri)
+{
+       SoupMessage *msg;
+
+       msg = e2k_soup_message_new_full (ctx, uri, "PROPFIND",
+                                        "text/xml", SOUP_BUFFER_USER_OWNED,
+                                        ALL_PROPS, strlen (ALL_PROPS));
+       soup_message_add_header (msg->request_headers, "Brief", "t");
+       soup_message_add_header (msg->request_headers, "Depth", "0");
+
+       e2k_context_queue_message (ctx, msg, got_all_properties, ctx);
+}
+
+static void
+get_property (E2kContext *ctx, char *uri, char *prop)
+{
+       E2kHTTPStatus status;
+       E2kResult *results;
+       int nresults, i;
+
+       if (!strncmp (prop, "PR_", 3)) {
+               for (i = 0; i < nmapi_proptags; i++)
+                       if (!strcmp (mapi_proptags[i].name, prop)) {
+                               prop = g_strconcat (E2K_NS_MAPI_PROPTAG,
+                                                   mapi_proptags[i].proptag,
+                                                   NULL);
+                               break;
+                       }
+       }
+
+       e2k_operation_init (&op);
+       status = e2k_context_propfind (ctx, &op, uri,
+                                      (const char **)&prop, 1,
+                                      &results, &nresults);
+       e2k_operation_free (&op);
+       test_abort_if_http_error (status);
+       print_properties (results, nresults);
+       e2k_results_free (results, nresults);
+}
+
+static void
+get_fav_properties(E2kContext *ctx, char *uri)
+{
+       E2kRestriction *rn;
+       E2kResultIter *iter;
+       E2kResult *result;
+       const char *prop;
+       int status;
+       char *eml_str, *top = uri, fav_uri[1024];
+
+       
+       /* list the contents and search for the favorite properties */
+       e2k_operation_init (&op);
+       prop = E2K_PR_DAV_DISPLAY_NAME;
+       rn = e2k_restriction_prop_bool (E2K_PR_DAV_IS_COLLECTION,
+                                       E2K_RELOP_EQ, FALSE);
+       iter = e2k_context_search_start (ctx, &op, top, &prop, 1,
+                                         rn, NULL, FALSE);
+       e2k_restriction_unref (rn);
+
+       while ((result = e2k_result_iter_next (iter))) {
+               strcpy(fav_uri, uri);
+               eml_str = strstr(result->href, "Shortcuts");
+               eml_str = eml_str + strlen("Shortcuts");
+
+               strcat(fav_uri, eml_str);
+
+               printf("\nNAME:\n");
+               get_property (ctx, fav_uri, PR_FAV_DISPLAY_NAME);
+               printf("\nALIAS:\n");
+               get_property (ctx, fav_uri, PR_FAV_DISPLAY_ALIAS);
+               printf("\nPUBLIC SOURCE KEY:\n");
+               get_property (ctx, fav_uri, PR_FAV_PUBLIC_SOURCE_KEY);
+               printf("\nPARENT SOURCE KEY:\n");
+               get_property (ctx, fav_uri, PR_FAV_PARENT_SOURCE_KEY);
+               printf("\nAUTO SUBFOLDERS:\n");
+               get_property (ctx, fav_uri, PR_FAV_AUTOSUBFOLDERS);
+               printf("\nLEVEL MASK:\n");
+               get_property (ctx, fav_uri, PR_FAV_LEVEL_MASK);
+               printf("\nINHERIT AUTO:\n");
+               get_property (ctx, fav_uri, PR_FAV_INHERIT_AUTO);
+               printf("\nDEL SUBS:\n");
+               get_property (ctx, fav_uri, PR_FAV_DEL_SUBS);
+               printf("\n\t\t=================================================\n");
+
+               memset(fav_uri, 0, 1024);
+       }
+       status = e2k_result_iter_free (iter);
+       e2k_operation_free (&op);
+
+       test_abort_if_http_error (status);
+       test_quit ();
+}
+
+static void
+get_sd (E2kContext *ctx, char *uri)
+{
+       const char *props[] = {
+               E2K_PR_EXCHANGE_SD_BINARY,
+               E2K_PR_EXCHANGE_SD_XML,
+       };
+       E2kHTTPStatus status;
+       E2kResult *results;
+       int nresults;
+       xmlNodePtr xml_form;
+       GByteArray *binary_form;
+       E2kSecurityDescriptor *sd;
+       E2kPermissionsRole role;
+       guint32 perms;
+       GList *sids, *s;
+       E2kSid *sid;
+
+       e2k_operation_init (&op);
+       status = e2k_context_propfind (ctx, &op, uri, props, 2,
+                                      &results, &nresults);
+       e2k_operation_free (&op);
+       test_abort_if_http_error (status);
+
+       if (nresults == 0)
+               goto done;
+
+       xml_form = e2k_properties_get_prop (results[0].props,
+                                           E2K_PR_EXCHANGE_SD_XML);
+       binary_form = e2k_properties_get_prop (results[0].props,
+                                              E2K_PR_EXCHANGE_SD_BINARY);
+       if (!xml_form || !binary_form)
+               goto done;
+
+       xmlElemDump (stdout, NULL, xml_form);
+       printf ("\n");
+
+       print_binary (binary_form);
+       printf ("\n");
+
+       sd = e2k_security_descriptor_new (xml_form, binary_form);
+       if (!sd) {
+               printf ("(Could not parse)\n");
+               goto done;
+       }
+
+       sids = e2k_security_descriptor_get_sids (sd);
+       for (s = sids; s; s = s->next) {
+               sid = s->data;
+               perms = e2k_security_descriptor_get_permissions (sd, sid);
+               role = e2k_permissions_role_find (perms);
+               printf ("%s: %s (0x%lx)\n",
+                       e2k_sid_get_display_name (sid),
+                       e2k_permissions_role_get_name (role),
+                       (unsigned long)perms);
+       }
+       g_list_free (sids);
+
+       if (!e2k_security_descriptor_to_binary (sd))
+               printf ("\nSD is malformed.\n");
+       g_object_unref (sd);
+
+ done:
+       test_quit ();
+}
+
+static void
+get_body (E2kContext *ctx, char *uri)
+{
+       E2kHTTPStatus status;
+       char *body;
+       int len;
+
+       e2k_operation_init (&op);
+       status = e2k_context_get (ctx, &op, uri, NULL, &body, &len);
+       e2k_operation_free (&op);
+       test_abort_if_http_error (status);
+
+       fwrite (body, 1, len, stdout);
+       test_quit ();
+}
+
+static void
+delete (E2kContext *ctx, char *uri)
+{
+       E2kHTTPStatus status;
+
+       e2k_operation_init (&op);
+       status = e2k_context_delete (ctx, &op, uri);
+       e2k_operation_free (&op);
+       test_abort_if_http_error (status);
+       test_quit ();
+}
+
+static void
+notify (E2kContext *ctx, const char *uri,
+       E2kContextChangeType type, gpointer user_data)
+{
+       switch (type) {
+       case E2K_CONTEXT_OBJECT_CHANGED:
+               printf ("Changed\n");
+               break;
+       case E2K_CONTEXT_OBJECT_ADDED:
+               printf ("Added\n");
+               break;
+       case E2K_CONTEXT_OBJECT_REMOVED:
+               printf ("Removed\n");
+               break;
+       case E2K_CONTEXT_OBJECT_MOVED:
+               printf ("Moved\n");
+               break;
+       }
+}
+
+static void
+subscribe (E2kContext *ctx, char *uri)
+{
+       e2k_context_subscribe (ctx, uri,
+                              E2K_CONTEXT_OBJECT_CHANGED, 0,
+                              notify, NULL);
+       e2k_context_subscribe (ctx, uri,
+                              E2K_CONTEXT_OBJECT_ADDED, 0,
+                              notify, NULL);
+       e2k_context_subscribe (ctx, uri,
+                              E2K_CONTEXT_OBJECT_REMOVED, 0,
+                              notify, NULL);
+       e2k_context_subscribe (ctx, uri,
+                              E2K_CONTEXT_OBJECT_MOVED, 0,
+                              notify, NULL);
+}
+
+static void
+move (E2kContext *ctx, char *from, char *to, gboolean delete)
+{
+       GPtrArray *source_hrefs;
+       E2kResultIter *iter;
+       E2kResult *result;
+       E2kHTTPStatus status;
+
+       source_hrefs = g_ptr_array_new ();
+       g_ptr_array_add (source_hrefs, "");
+
+       e2k_operation_init (&op);
+       iter = e2k_context_transfer_start (ctx, &op, from, to,
+                                          source_hrefs, delete);
+       g_ptr_array_free (source_hrefs, TRUE);
+
+       result = e2k_result_iter_next (iter);
+       if (result) {
+               if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (result->status))
+                       printf ("Failed: %d\n", result->status);
+               else {
+                       printf ("moved to %s\n",
+                               (char *)e2k_properties_get_prop (result->props,
+                                                                E2K_PR_DAV_LOCATION));
+               }
+       }
+       status = e2k_result_iter_free (iter);
+       e2k_operation_free (&op);
+
+       test_abort_if_http_error (status);
+       test_quit ();
+}
+
+static void
+name (E2kContext *ctx, char *alias, char *uri_prefix)
+{
+       E2kHTTPStatus status;
+       char *uri, *body;
+       int len;
+       xmlDoc *doc;
+       xmlNode *item, *node;
+       char *data;
+
+       uri = g_strdup_printf ("%s?Cmd=galfind&AN=%s", uri_prefix, alias);
+       e2k_operation_init (&op);
+       status = e2k_context_get_owa (ctx, &op, uri, TRUE, &body, &len);
+       e2k_operation_free (&op);
+       test_abort_if_http_error (status);
+
+       doc = e2k_parse_xml (body, len);
+
+       if ((node = e2k_xml_find (doc->children, "error")))
+               printf ("Error: %s\n", xmlNodeGetContent (node));
+       else {
+               item = doc->children;
+               while ((item = e2k_xml_find (item, "item"))) {
+                       for (node = item->children; node; node = node->next) {
+                               if (node->type == XML_ELEMENT_NODE) {
+                                       data = xmlNodeGetContent (node);
+                                       if (data && *data)
+                                               printf ("%s: %s\n", node->name, data);
+                                       xmlFree (data);
+                               }
+                       }
+               }
+       }
+
+       xmlFreeDoc (doc);
+       test_quit ();
+}
+
+static void
+put (E2kContext *ctx, const char *file, const char *uri)
+{
+       struct stat st;
+       char *buf;
+       int fd;
+       E2kHTTPStatus status;
+
+       fd = open (file, O_RDONLY);
+       if (fd == -1 || fstat (fd, &st) == -1) {
+               fprintf (stderr, "%s\n", strerror (errno));
+               exit (1);
+       }
+       buf = g_malloc (st.st_size);
+       read (fd, buf, st.st_size);
+       close (fd);
+
+       e2k_operation_init (&op);
+       status = e2k_context_put (ctx, &op, uri,
+                                 "message/rfc822", buf, st.st_size,
+                                 NULL);
+       e2k_operation_free (&op);
+       test_abort_if_http_error (status);
+       test_quit ();
+}
+
+static void *
+cancel (void *op)
+{
+       e2k_operation_cancel (op);
+       return NULL;
+}
+
+static void
+quit (int sig)
+{
+       static pthread_t cancel_thread;
+
+       /* Can't cancel from here because we might be
+        * inside a malloc.
+        */
+       if (!cancel_thread) {
+               pthread_create (&cancel_thread, NULL, cancel, &op);
+       } else
+               exit (0);
+}
+
+static void
+usage (void)
+{
+       printf ("usage: ebrowse -t URI                       (shallow folder tree)\n");
+       printf ("       ebrowse [-l | -L ] URI               (contents listing [back/forward])\n");
+       printf ("       ebrowse [ -p | -P prop ] URI         (look up all/one prop)\n");
+       printf ("       ebrowse -S URI                       (look up security descriptor)\n");
+       printf ("       ebrowse -b URI                       (fetch body)\n");
+       printf ("       ebrowse -q FILE URI                  (put body)\n");
+       printf ("       ebrowse -d URI                       (delete)\n");
+       printf ("       ebrowse -s URI                       (subscribe and listen)\n");
+       printf ("       ebrowse [ -m | -c ] SRC DEST         (move/copy)\n");
+       printf ("       ebrowse -n ALIAS URI                 (lookup name)\n");
+       printf ("       ebrowse -f URI                       (lookup favorite folder props)\n");
+       exit (1);
+}
+
+const char *test_program_name = "ebrowse";
+
+void
+test_main (int argc, char **argv)
+{
+       char *uri;
+
+       signal (SIGINT, quit);
+
+       uri = argv[argc - 1];
+       ctx = test_get_context (uri);
+
+       switch (argv[1][1]) {
+       case 't':
+               display_folder_tree (ctx, uri);
+               break;
+
+       case 'l':
+               list_contents (ctx, uri, FALSE);
+               break;
+
+       case 'L':
+               list_contents (ctx, uri, TRUE);
+               break;
+
+       case 'b':
+               get_body (ctx, uri);
+               break;
+
+       case 'd':
+               delete (ctx, uri);
+               break;
+
+       case 'p':
+               get_all_properties (ctx, uri);
+               break;
+
+       case 'P':
+               get_property (ctx, uri, argv[2]);
+               break;
+
+       case 'S':
+               get_sd (ctx, uri);
+               break;
+
+       case 's':
+               subscribe (ctx, uri);
+               break;
+
+       case 'm':
+       case 'c':
+               move (ctx, argv[2], uri, argv[1][1] == 'm');
+               break;
+
+       case 'n':
+               name (ctx, argv[2], uri);
+               break;
+
+       case 'q':
+               put (ctx, argv[2], uri);
+               break;
+
+       case 'f':
+               get_fav_properties(ctx, uri);
+               break;
+
+       default:
+               usage ();
+       }
+}
diff --git a/servers/exchange/lib/fbtest.c b/servers/exchange/lib/fbtest.c
new file mode 100644 (file)
index 0000000..8b09cf9
--- /dev/null
@@ -0,0 +1,146 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/* Copyright (C) 2002-2004 Novell, Inc.
+ *
+ * This  program is free  software; you  can redistribute  it and/or
+ * modify it under the terms of version 2  of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/* Free/Busy test program. Note though that this uses the code in
+ * e2k-freebusy.c, which is not currently used by Connector itself.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "e2k-freebusy.h"
+#include "e2k-global-catalog.h"
+#include "test-utils.h"
+
+const char *test_program_name = "fbtest";
+
+void
+test_main (int argc, char **argv)
+{
+       E2kGlobalCatalog *gc;
+       E2kGlobalCatalogStatus status;
+       E2kGlobalCatalogEntry *entry;
+       const char *server, *email;
+       E2kContext *ctx;
+       E2kFreebusy *fb;
+       E2kFreebusyEvent event;
+       int ti, bi, oi;
+       char *public_uri;
+       struct tm tm;
+       time_t t;
+
+       if (argc != 3) {
+               fprintf (stderr, "Usage: %s server email-addr\n", argv[0]);
+               exit (1);
+       }
+
+       server = argv[1];
+       email = argv[2];
+
+       gc = test_get_gc (server);
+
+       status = e2k_global_catalog_lookup (
+               gc, NULL, E2K_GLOBAL_CATALOG_LOOKUP_BY_EMAIL,
+               email, E2K_GLOBAL_CATALOG_LOOKUP_LEGACY_EXCHANGE_DN,
+               &entry);
+
+       if (status != E2K_GLOBAL_CATALOG_OK) {
+               fprintf (stderr, "Lookup failed: %d\n", status);
+               test_quit ();
+               return;
+       }
+
+       public_uri = g_strdup_printf ("http://%s/public", server);
+       ctx = test_get_context (public_uri);
+       fb = e2k_freebusy_new (ctx, public_uri, entry->legacy_exchange_dn);
+       g_free (public_uri);
+       g_object_unref (ctx);
+
+       if (!fb) {
+               fprintf (stderr, "Could not get fb props\n");
+               test_quit ();
+               return;
+       }
+
+       if (!fb->events[E2K_BUSYSTATUS_ALL]->len) {
+               printf ("No data\n");
+               test_quit ();
+               return;
+       }
+
+       printf ("                         6am      9am      noon     3pm      6pm\n");
+
+       ti = bi = oi = 0;
+       for (t = fb->start; t < fb->end; t += 30 * 60) {
+               if ((t - fb->start) % (24 * 60 * 60) == 0) {
+                       tm = *localtime (&t);
+                       printf ("\n%02d-%02d: ", tm.tm_mon + 1, tm.tm_mday);
+               }
+
+               for (; oi < fb->events[E2K_BUSYSTATUS_OOF]->len; oi++) {
+                       event = g_array_index (fb->events[E2K_BUSYSTATUS_OOF],
+                                              E2kFreebusyEvent, oi);
+                       if (event.end <= t)
+                               continue;
+                       if (event.start < t + (30 * 60)) {
+                               printf ("O");
+                               goto next;
+                       }
+                       if (event.start > t)
+                               break;
+               }
+               for (; bi < fb->events[E2K_BUSYSTATUS_BUSY]->len; bi++) {
+                       event = g_array_index (fb->events[E2K_BUSYSTATUS_BUSY],
+                                              E2kFreebusyEvent, bi);
+                       if (event.end <= t)
+                               continue;
+                       if (event.start < t + (30 * 60)) {
+                               printf ("X");
+                               goto next;
+                       }
+                       if (event.start > t)
+                               break;
+               }
+               for (; ti < fb->events[E2K_BUSYSTATUS_TENTATIVE]->len; ti++) {
+                       event = g_array_index (fb->events[E2K_BUSYSTATUS_TENTATIVE],
+                                              E2kFreebusyEvent, ti);
+                       if (event.end <= t)
+                               continue;
+                       if (event.start < t + (30 * 60)) {
+                               printf ("t");
+                               goto next;
+                       }
+                       if (event.start > t)
+                               break;
+               }
+               printf (".");
+
+       next:
+               if ((t - fb->start) % (60 * 60))
+                       printf (" ");
+       }
+       printf ("\n");
+
+       test_quit ();
+}
diff --git a/servers/exchange/lib/gctest.c b/servers/exchange/lib/gctest.c
new file mode 100644 (file)
index 0000000..e4ee914
--- /dev/null
@@ -0,0 +1,251 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/* Copyright (C) 2002-2004 Novell, Inc.
+ *
+ * This  program is free  software; you  can redistribute  it and/or
+ * modify it under the terms of version 2  of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/* Global Catalog test program */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "e2k-global-catalog.h"
+#include "e2k-sid.h"
+#include "test-utils.h"
+
+E2kGlobalCatalog *gc;
+E2kOperation op;
+
+static void
+do_lookup (E2kGlobalCatalog *gc, const char *user)
+{
+       E2kGlobalCatalogStatus status;
+       E2kGlobalCatalogEntry *entry;
+       E2kGlobalCatalogLookupType type;
+       guint32 flags;
+       int i, pwd_exp_days; 
+       double maxAge;
+
+       if (*user == '/')
+               type = E2K_GLOBAL_CATALOG_LOOKUP_BY_LEGACY_EXCHANGE_DN;
+       else if (strchr (user, '@'))
+               type = E2K_GLOBAL_CATALOG_LOOKUP_BY_EMAIL;
+       else
+               type = E2K_GLOBAL_CATALOG_LOOKUP_BY_DN;
+
+       flags = E2K_GLOBAL_CATALOG_LOOKUP_SID |
+               E2K_GLOBAL_CATALOG_LOOKUP_EMAIL |
+               E2K_GLOBAL_CATALOG_LOOKUP_MAILBOX |
+               E2K_GLOBAL_CATALOG_LOOKUP_LEGACY_EXCHANGE_DN |
+               E2K_GLOBAL_CATALOG_LOOKUP_DELEGATES |
+               E2K_GLOBAL_CATALOG_LOOKUP_DELEGATORS |
+               E2K_GLOBAL_CATALOG_LOOKUP_QUOTA |
+               E2K_GLOBAL_CATALOG_LOOKUP_ACCOUNT_CONTROL;
+
+       e2k_operation_init (&op);
+       status = e2k_global_catalog_lookup (gc, &op, type, user, flags, &entry);
+       // e2k_operation_free (&op);
+
+       switch (status) {
+       case E2K_GLOBAL_CATALOG_OK:
+               break;
+       case E2K_GLOBAL_CATALOG_NO_SUCH_USER:
+               printf ("No entry for %s\n", user);
+               test_quit ();
+               return;
+       case E2K_GLOBAL_CATALOG_NO_DATA:
+               printf ("Entry for %s contains no data\n", user);
+               test_quit ();
+               return;
+       case E2K_GLOBAL_CATALOG_AUTH_FAILED:
+               printf ("Authentication failed (try DOMAIN\\username)\n");
+               test_quit ();
+               return;
+       default:
+               printf ("Error looking up user\n");
+               test_quit ();
+               return;
+       }
+
+       printf ("%s (%s)\n", entry->display_name, entry->dn);
+       if (entry->email)
+               printf ("  email: %s\n", entry->email);
+       if (entry->mailbox)
+               printf ("  mailbox: %s on %s\n", entry->mailbox, entry->exchange_server);
+       if (entry->legacy_exchange_dn)
+               printf ("  Exchange 5.5 DN: %s\n", entry->legacy_exchange_dn);
+       if (entry->sid)
+               printf ("  sid: %s\n", e2k_sid_get_string_sid (entry->sid));
+       if (entry->delegates) {
+               printf ("  delegates:\n");
+               for (i = 0; i < entry->delegates->len; i++)
+                       printf ("    %s\n", (char *)entry->delegates->pdata[i]);
+       }
+       if (entry->delegators) {
+               printf ("  delegators:\n");
+               for (i = 0; i < entry->delegators->len; i++)
+                       printf ("    %s\n", (char *)entry->delegators->pdata[i]);
+       }
+
+       if (entry->quota_warn || entry->quota_nosend || entry->quota_norecv )
+               printf ("  Mail Quota Info:\n");
+       if (entry->quota_warn)  
+               printf ("    Issue Quota warning at : %d\n", entry->quota_warn);
+       if (entry->quota_nosend)
+               printf ("    Stop sending mails at  : %d\n", entry->quota_nosend);
+       if (entry->quota_norecv)
+               printf ("    Stop sending and recieving mails at : %d\n", entry->quota_norecv);
+       if (entry->user_account_control)
+               printf ("    user_account_control : %d\n", entry->user_account_control);
+       
+
+       maxAge = lookup_passwd_max_age (gc, &op);
+       printf("Password max age is %f \n", maxAge);
+       pwd_exp_days = (maxAge * 0.000000100)/86400 ;
+       printf("Password expiery period is %d \n", pwd_exp_days);
+
+       e2k_operation_free (&op);
+
+       e2k_global_catalog_entry_free (gc, entry);
+       test_quit ();
+}
+
+static char *
+lookup_dn (E2kGlobalCatalog *gc, const char *id)
+{
+       E2kGlobalCatalogEntry *entry;
+       E2kGlobalCatalogLookupType type;
+       E2kGlobalCatalogStatus status;
+       char *dn;
+
+       if (id[0] == '/')
+               type = E2K_GLOBAL_CATALOG_LOOKUP_BY_LEGACY_EXCHANGE_DN;
+       else if (strchr (id, '@'))
+               type = E2K_GLOBAL_CATALOG_LOOKUP_BY_EMAIL;
+       else
+               return g_strdup (id);
+
+       e2k_operation_init (&op);
+       status = e2k_global_catalog_lookup (gc, &op, type, id, 0, &entry);
+       e2k_operation_free (&op);
+
+       switch (status) {
+       case E2K_GLOBAL_CATALOG_OK:
+               break;
+       case E2K_GLOBAL_CATALOG_NO_SUCH_USER:
+               printf ("No entry for %s\n", id);
+               exit (1);
+               break;
+       default:
+               printf ("Error looking up user %s\n", id);
+               exit (1);
+               break;
+       }
+
+       dn = g_strdup (entry->dn);
+       e2k_global_catalog_entry_free (gc, entry);
+
+       return dn;
+}
+
+static void
+do_modify (E2kGlobalCatalog *gc, const char *user,
+          int deleg_op, const char *delegate)
+{
+       char *self_dn, *deleg_dn;
+       E2kGlobalCatalogStatus status;
+
+       self_dn = lookup_dn (gc, user);
+       deleg_dn = lookup_dn (gc, delegate);
+
+       e2k_operation_init (&op);
+       if (deleg_op == '+')
+               status = e2k_global_catalog_add_delegate (gc, &op, self_dn, deleg_dn);
+       else
+               status = e2k_global_catalog_remove_delegate (gc, &op, self_dn, deleg_dn);
+       e2k_operation_free (&op);
+
+       switch (status) {
+       case E2K_GLOBAL_CATALOG_OK:
+               printf ("Done\n");
+               break;
+       case E2K_GLOBAL_CATALOG_BAD_DATA:
+               printf ("Invalid delegate DN\n");
+               break;
+       case E2K_GLOBAL_CATALOG_NO_DATA:
+               printf ("No such delegate to remove\n");
+               break;
+       case E2K_GLOBAL_CATALOG_EXISTS:
+               printf ("That user is already a delegate\n");
+               break;
+       default:
+               printf ("Failed\n");
+               break;
+       }
+
+       test_quit ();
+}
+
+static void *
+cancel (void *data)
+{
+       e2k_operation_cancel (&op);
+       return NULL;
+}
+
+static void
+quit (int sig)
+{
+       static pthread_t cancel_thread;
+
+       if (!cancel_thread) {
+               pthread_create (&cancel_thread, NULL, cancel, NULL);
+       } else
+               exit (0);
+}
+
+const char *test_program_name = "gctest";
+
+void
+test_main (int argc, char **argv)
+{
+       const char *server;
+
+       if (argc < 3 || argc > 4 ||
+           (argc == 4 && argv[3][0] != '+' && argv[3][0] != '-')) {
+               fprintf (stderr, "Usage: %s server email-or-dn [[+|-]delegate]\n", argv[0]);
+               exit (1);
+       }
+
+       signal (SIGINT, quit);
+
+       server = argv[1];
+       gc = test_get_gc (server);
+
+       if (argc == 3)
+               do_lookup (gc, argv[2]);
+       else
+               do_modify (gc, argv[2], argv[3][0], argv[3] + 1);
+
+       g_object_unref (gc);
+}
diff --git a/servers/exchange/lib/ruletest.c b/servers/exchange/lib/ruletest.c
new file mode 100644 (file)
index 0000000..85541e5
--- /dev/null
@@ -0,0 +1,90 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/* Copyright (C) 2003-2004 Novell, Inc.
+ *
+ * This  program is free  software; you  can redistribute  it and/or
+ * modify it under the terms of version 2  of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/* Server-side rule test program */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <string.h>
+
+#include "e2k-context.h"
+#include "e2k-propnames.h"
+#include "e2k-rule.h"
+#include "e2k-rule-xml.h"
+#include "test-utils.h"
+
+const char *test_program_name = "ruletest";
+
+static const char *rules_props[] = {
+       PR_RULES_DATA,
+};
+static const int n_rules_props = sizeof (rules_props) / sizeof (rules_props[0]);
+
+void
+test_main (int argc, char **argv)
+{
+       const char *url;
+       E2kContext *ctx;
+       E2kHTTPStatus status;
+       E2kResult *results;
+       int nresults;
+       GByteArray *ba;
+       E2kRules *rules;
+       xmlDoc *doc;
+
+       if (argc != 2) {
+               fprintf (stderr, "Usage: %s URL\n", argv[0]);
+               exit (1);
+       }
+       url = argv[1];
+
+       ctx = test_get_context (url);
+       status = e2k_context_propfind (ctx, NULL, url,
+                                      rules_props, n_rules_props,
+                                      &results, &nresults);
+       test_abort_if_http_error (status);
+
+       ba = e2k_properties_get_prop (results[0].props, PR_RULES_DATA);
+       if (!ba) {
+               printf ("No rules\n");
+               goto done;
+       }
+
+       rules = e2k_rules_from_binary (ba);
+       if (!rules) {
+               printf ("Could not parse rules\n");
+               goto done;
+       }
+
+       doc = e2k_rules_to_xml (rules);
+       if (doc) {
+               xmlDocFormatDump (stdout, doc, TRUE);
+               xmlFreeDoc (doc);
+       } else
+               printf ("Could not convert normal rules to XML\n");
+
+       e2k_rules_free (rules);
+       e2k_results_free (results, nresults);
+
+ done:
+       test_quit ();
+}
diff --git a/servers/exchange/lib/test-utils.c b/servers/exchange/lib/test-utils.c
new file mode 100644 (file)
index 0000000..b13a07c
--- /dev/null
@@ -0,0 +1,260 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/* Copyright (C) 2001-2004 Novell, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include <libedataserverui/e-passwords.h>
+#include <libgnome/gnome-util.h>
+
+#include "e2k-context.h"
+#include "e2k-global-catalog.h"
+#include "e2k-uri.h"
+
+#include "test-utils.h"
+
+extern const char *test_program_name;
+
+/**
+ * test_ask_password:
+ * @prompt: prompt string
+ *
+ * Prints @prompt followed by ": " and waits for the user to type
+ * a password (with echoing disabled).
+ *
+ * Return value: the password (or %NULL if stdin is not a tty).
+ **/
+char *
+test_ask_password (const char *prompt)
+{
+       char *password;
+       struct termios t;
+       int old_lflag;
+       char buf[80];
+
+       if (tcgetattr (STDIN_FILENO, &t) != 0)
+               return NULL;
+
+       old_lflag = t.c_lflag;
+       t.c_lflag = (t.c_lflag | ICANON | ECHONL) & ~ECHO;
+       tcsetattr (STDIN_FILENO, TCSANOW, &t);
+
+       fprintf (stderr, "%s: ", prompt);
+       fflush (stdout);
+
+       /* For some reason, fgets can return EINTR on
+        * Linux if ECHO is false...
+        */
+       do
+               password = fgets (buf, sizeof (buf), stdin);
+       while (password == NULL && errno == EINTR);
+
+       t.c_lflag = old_lflag;
+       tcsetattr (STDIN_FILENO, TCSANOW, &t);
+
+       if (!password)
+               exit (1);
+       return g_strndup (password, strcspn (password, "\n"));
+}
+
+/**
+ * test_get_password:
+ * @user: username to get the password for
+ * @host: Exchange (or global catalog) server name
+ *
+ * Tries to get a password for @user on @host, by looking it up in
+ * the Evolution password database or by prompting the user.
+ *
+ * Return value: the password, or %NULL if it could not be determined.
+ **/
+const char *
+test_get_password (const char *user, const char *host)
+{
+       static char *password = NULL;
+       char *prompt;
+
+       if (password)
+               return password;
+
+       if (host) {
+               char *key;
+
+               key = g_strdup_printf ("exchange://%s@%s", user, host);
+               password = e_passwords_get_password ("Exchange", key);
+               g_free (key);
+       }
+
+       if (!password) {
+               if (host) {
+                       prompt = g_strdup_printf ("Password for %s@%s",
+                                                 user, host);
+               } else
+                       prompt = g_strdup_printf ("Password for %s", user);
+
+               password = test_ask_password (prompt);
+               g_free (prompt);
+       }
+
+       return password;
+}
+
+/**
+ * test_get_context:
+ * @uri: an Exchange HTTP/HTTPS URI
+ *
+ * Creates an %E2kContext based on @uri. If @uri does not contain a
+ * username, the user's local username will be used. If it does not
+ * contain a password, test_get_password() will be called to get one.
+ *
+ * Return value: the new %E2kContext (always; if an error occurs,
+ * test_get_context() will exit the program).
+ **/
+E2kContext *
+test_get_context (const char *uri)
+{
+       E2kContext *ctx;
+       E2kUri *euri;
+
+       ctx = e2k_context_new (uri);
+       if (!ctx) {
+               fprintf (stderr, "Could not parse %s as URI\n", uri);
+               exit (1);
+       }
+
+       euri = e2k_uri_new (uri);
+       if (!euri->user)
+               euri->user = g_strdup (g_get_user_name ());
+       if (!euri->passwd)
+               euri->passwd = g_strdup (test_get_password (euri->user, euri->host));
+
+       e2k_context_set_auth (ctx, euri->user, euri->domain,
+                             euri->authmech, euri->passwd);
+
+       e2k_uri_free (euri);
+       return ctx;
+}
+
+/**
+ * test_get_gc:
+ * @server: the global catalog server to contact
+ *
+ * Creates an %E2kGlobalCatalog for the server @server.
+ * test_get_password() will be called to get a password.
+ *
+ * Return value: the new %E2kGlobalCatalog (always; if an error occurs,
+ * test_get_gc() will exit the program).
+ **/
+E2kGlobalCatalog *
+test_get_gc (const char *server)
+{
+       E2kGlobalCatalog *gc;
+       const char *password;
+       char *user, *p;
+
+       if (strchr (server, '@')) {
+               user = g_strdup (server);
+               p = strchr (user, '@');
+               *p = '\0';
+               server = p + 1;
+       } else
+               user = g_strdup (g_get_user_name ());
+
+       password = test_get_password (user, server);
+       gc = e2k_global_catalog_new (server, -1, user, NULL, password);
+       if (!gc) {
+               fprintf (stderr, "Could not create GC\n");
+               exit (1);
+       }
+       g_free (user);
+
+       return gc;
+}
+
+static char **global_argv;
+static int global_argc;
+static GMainLoop *loop;
+
+/**
+ * test_main:
+ * @argc: argc
+ * @argv: argv
+ *
+ * test-utils.o includes a main() function that calls various
+ * initialization routines, starts the main loop, and then calls
+ * test_main(). So test_main() is the entry point for a
+ * test-utils-using program.
+ **/
+
+/**
+ * test_quit:
+ *
+ * Cleanly quits a test program.
+ **/
+void
+test_quit (void)
+{
+       g_main_loop_quit (loop);
+}
+
+/**
+ * test_abort_if_http_error:
+ * @status: an HTTP status code
+ *
+ * Checks if @status is an HTTP or libsoup error, and if so, prints
+ * the error message and exits.
+ **/
+void
+test_abort_if_http_error (E2kHTTPStatus status)
+{
+       if (E2K_HTTP_STATUS_IS_TRANSPORT_ERROR (status)) {
+               fprintf (stderr, "\n%s\n", soup_status_get_phrase (status));
+               exit (1);
+       } else if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
+               fprintf (stderr, "\n%d\n", status);
+               exit (1);
+       }
+}
+
+static gboolean
+idle_run (gpointer data)
+{
+       test_main (global_argc, global_argv);
+       return FALSE;
+}
+
+int
+main (int argc, char **argv)
+{
+       gnome_program_init (test_program_name, VERSION, LIBGNOME_MODULE,
+                           argc, argv, NULL);
+
+       global_argc = argc;
+       global_argv = argv;
+
+       loop = g_main_loop_new (NULL, TRUE);
+       g_idle_add (idle_run, NULL);
+       g_main_loop_run (loop);
+
+       return 0;
+}
diff --git a/servers/exchange/lib/test-utils.h b/servers/exchange/lib/test-utils.h
new file mode 100644 (file)
index 0000000..9d2fa0b
--- /dev/null
@@ -0,0 +1,25 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* Copyright (C) 2001-2004 Novell, Inc. */
+
+#ifndef TEST_UTILS_H
+#define TEST_UTILS_H
+
+#include "e2k-types.h"
+#include "e2k-http-utils.h"
+
+void              test_main                (int             argc,
+                                           char          **argv);
+void              test_quit                (void);
+
+const char       *test_get_password        (const char     *user,
+                                           const char     *host);
+E2kContext       *test_get_context         (const char     *uri);
+E2kGlobalCatalog *test_get_gc              (const char     *server);
+
+void              test_abort_if_http_error (E2kHTTPStatus   status);
+
+
+/* lower-level util */
+char             *test_ask_password        (const char     *prompt);
+
+#endif /* TEST_UTILS_H */
diff --git a/servers/exchange/lib/urltest.c b/servers/exchange/lib/urltest.c
new file mode 100644 (file)
index 0000000..82d9969
--- /dev/null
@@ -0,0 +1,158 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/* Copyright (C) 2002-2004 Novell, Inc.
+ *
+ * This  program is free  software; you  can redistribute  it and/or
+ * modify it under the terms of version 2  of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * This program takes account URL as input and dups E2KUri structure
+ * values
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "e2k-uri.h"
+#include "test-utils.h"
+
+const char *test_program_name = "urltest";
+
+static void
+dump_uri (E2kUri *euri) {
+       const char *temp;
+
+       printf ("URI contents \n");
+       printf ("==================== \n");
+
+       if (euri->protocol)
+               printf("Protocol : %s \n", euri->protocol);
+       else 
+               printf ("Protocol : NULL \n");  
+       if (euri->user)
+               printf("User : %s \n", euri->user);
+       else 
+               printf ("User : NULL \n");      
+       if (euri->domain)
+               printf("Domain : %s \n", euri->domain);
+       else 
+               printf ("Domain : NULL \n");    
+       if (euri->authmech)
+               printf("Authmech : %s \n", euri->authmech);
+       else 
+               printf ("Authmech : NULL \n");  
+       if (euri->passwd)
+               printf("Password : %s \n", euri->passwd);
+       else 
+               printf ("Password : NULL \n");  
+       if (euri->host)
+               printf("Host : %s \n", euri->host);
+       else 
+               printf ("Host : NULL \n");      
+       if (euri->port)
+               printf("Port : %d \n", euri->port);
+       else 
+               printf ("Port : NULL \n");      
+       if (euri->path)
+               printf("Path : %s \n", euri->path);
+       else 
+               printf ("Path : NULL \n");      
+       if (euri->params) {
+               printf("\nParams : \n");
+               temp = e2k_uri_get_param (euri, "ad_server"); 
+               if (temp) printf ("\tAd server = %s\n", temp);
+               else printf ("\tAd server = NULL \n");
+
+               temp = e2k_uri_get_param (euri, "ad_limit"); 
+               if (temp) printf ("\tAd Limit = %s\n", temp);
+               else printf ("\tAd Limit = NULL\n");
+
+               temp = e2k_uri_get_param (euri, "passwd_exp_warn_period"); 
+               if (temp) printf ("\tPasswd expiry warn period = %s\n", temp);
+               else printf ("\tPasswd expiry warn period = NULL \n");
+
+               temp = e2k_uri_get_param (euri, "offline_sync"); 
+               if (temp) printf ("\tOffline Sync = %s\n", temp);
+               else printf ("\tOffline Sync = NULL \n");
+
+               temp = e2k_uri_get_param (euri, "owa_path"); 
+               if (temp) printf ("\tOwa path = %s\n", temp);
+               else printf ("\tOwa path = NULL \n");
+
+               temp = e2k_uri_get_param (euri, "pf_server"); 
+               if (temp) printf ("\tPf server = %s\n", temp);
+               else printf ("\tPf server = NULL \n");
+
+               temp = e2k_uri_get_param (euri, "use_ssl"); 
+               if (temp) printf ("\tSSL = %s\n", temp);
+               else printf ("\tSSL = NULL\n");
+
+               temp = e2k_uri_get_param (euri, "mailbox"); 
+               if (temp) printf ("\tMailbox = %s\n", temp);
+               else printf ("\tMailbox = NULL \n");
+
+               temp = e2k_uri_get_param (euri, "filter"); 
+               if (temp) printf ("\tFilter = %s\n", temp);
+               else printf ("\tFilter = NULL \n");
+
+               temp = e2k_uri_get_param (euri, "filter_junk"); 
+               if (temp) printf ("\tFilter junk = %s\n", temp);
+               else printf ("\tFilter junk = NULL \n");
+
+               temp = e2k_uri_get_param (euri, "filter_junk_inbox"); 
+               if (temp) printf ("\tFilter junk inbox = %s\n", temp);
+               else printf ("\tFilter junk inbox = NULL \n");
+
+               temp = e2k_uri_get_param (euri, "owa_protocol"); 
+               if (temp) printf ("\tOwa protocol = %s\n", temp);
+               else printf ("\tOwa protocol = NULL \n");
+
+               temp = e2k_uri_get_param (euri, "owa_url"); 
+               if (temp) printf ("\tOwa url = %s\n", temp);
+               else printf ("\tOwa url = NULL \n");
+       }
+       else 
+               printf ("Params : NULL \n");    
+       if (euri->query)
+               printf("Query : %s \n", euri->query);
+       else 
+               printf ("Query : NULL \n");     
+       if (euri->fragment)
+               printf("Fragment : %s \n", euri->fragment);
+       else 
+               printf ("Fragment : NULL \n");  
+}
+
+void
+test_main (int argc, char **argv)
+{
+       const char *url;
+       E2kUri *euri;
+
+       if (argc != 2) {
+               fprintf (stderr, "Usage: %s url \n", argv[0]);
+               exit (1);
+       }
+
+       url = argv[1];
+       euri = e2k_uri_new (url);
+       dump_uri (euri);
+       test_quit ();
+}