From 38500933d36e5d9eae50ce579356ec68d041b7e1 Mon Sep 17 00:00:00 2001 From: Ahmed Sarfraaz Date: Thu, 20 Oct 2005 06:03:50 +0000 Subject: [PATCH] Add the test files --- servers/exchange/lib/Makefile.am | 86 +++++ servers/exchange/lib/actest.c | 201 +++++++++++ servers/exchange/lib/cptest.c | 120 +++++++ servers/exchange/lib/davcat.c | 184 ++++++++++ servers/exchange/lib/ebrowse.c | 715 ++++++++++++++++++++++++++++++++++++++ servers/exchange/lib/fbtest.c | 146 ++++++++ servers/exchange/lib/gctest.c | 251 +++++++++++++ servers/exchange/lib/ruletest.c | 90 +++++ servers/exchange/lib/test-utils.c | 260 ++++++++++++++ servers/exchange/lib/test-utils.h | 25 ++ servers/exchange/lib/urltest.c | 158 +++++++++ 11 files changed, 2236 insertions(+) create mode 100644 servers/exchange/lib/actest.c create mode 100644 servers/exchange/lib/cptest.c create mode 100644 servers/exchange/lib/davcat.c create mode 100644 servers/exchange/lib/ebrowse.c create mode 100644 servers/exchange/lib/fbtest.c create mode 100644 servers/exchange/lib/gctest.c create mode 100644 servers/exchange/lib/ruletest.c create mode 100644 servers/exchange/lib/test-utils.c create mode 100644 servers/exchange/lib/test-utils.h create mode 100644 servers/exchange/lib/urltest.c diff --git a/servers/exchange/lib/Makefile.am b/servers/exchange/lib/Makefile.am index b119eee..c562bf6 100644 --- a/servers/exchange/lib/Makefile.am +++ b/servers/exchange/lib/Makefile.am @@ -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 index 0000000..3a2efa4 --- /dev/null +++ b/servers/exchange/lib/actest.c @@ -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 +#endif + +#include +#include +#include +#include + +#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 index 0000000..567c822 --- /dev/null +++ b/servers/exchange/lib/cptest.c @@ -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 +#endif + +#include +#include +#include +#include + +#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 index 0000000..d523998 --- /dev/null +++ b/servers/exchange/lib/davcat.c @@ -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 +#endif + +#include +#include +#include +#include +#include + +#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 index 0000000..a074132 --- /dev/null +++ b/servers/exchange/lib/ebrowse.c @@ -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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 \ +"" \ +"" \ +" " \ +" " \ +" " \ +"" + +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 index 0000000..8b09cf9 --- /dev/null +++ b/servers/exchange/lib/fbtest.c @@ -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 +#endif + +#include +#include +#include + +#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 index 0000000..e4ee914 --- /dev/null +++ b/servers/exchange/lib/gctest.c @@ -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 +#endif + +#include +#include +#include +#include +#include + +#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 index 0000000..85541e5 --- /dev/null +++ b/servers/exchange/lib/ruletest.c @@ -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 +#endif + +#include +#include + +#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 index 0000000..b13a07c --- /dev/null +++ b/servers/exchange/lib/test-utils.c @@ -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 +#endif + +#include +#include +#include + +#include +#include + +#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 index 0000000..9d2fa0b --- /dev/null +++ b/servers/exchange/lib/test-utils.h @@ -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 index 0000000..82d9969 --- /dev/null +++ b/servers/exchange/lib/urltest.c @@ -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 +#endif + +#include +#include +#include + +#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 (); +} -- 2.7.4