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 \
--- /dev/null
+/* -*- 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 ();
+}
--- /dev/null
+/* -*- 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 ();
+}
--- /dev/null
+/* -*- 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 ();
+}
--- /dev/null
+/* -*- 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 ();
+ }
+}
--- /dev/null
+/* -*- 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 ();
+}
--- /dev/null
+/* -*- 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);
+}
--- /dev/null
+/* -*- 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 ();
+}
--- /dev/null
+/* -*- 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;
+}
--- /dev/null
+/* -*- 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 */
--- /dev/null
+/* -*- 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 ();
+}