From b21d4d433b77b4be2497ad675aa904dd7288b97c Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 17 Jul 2010 16:07:43 +0100 Subject: [PATCH] Add C version of autodiscover, using libsoup --- Makefile | 12 ++++ ews_autodiscover.c | 155 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 ews_autodiscover.c diff --git a/Makefile b/Makefile index fff23de..ffab257 100644 --- a/Makefile +++ b/Makefile @@ -11,10 +11,22 @@ ifeq ($(XML2_LDFLAGS),) $(error "No libxml2 support. Cannot continue"); endif +SOUP_CFLAGS += $(shell pkg-config libsoup-2.4 --cflags) +SOUP_LDFLAGS += $(shell pkg-config libsoup-2.4 --libs) +ifeq ($(SOUP_LDFLAGS),) +$(error "No libsoup support. Cannot continue"); +endif + CFLAGS := $(OPT_FLAGS) $(XML2_CFLAGS) +CFLAGS_ews_autodiscover.o := $(SOUP_CFLAGS) %.o: %.c $(CC) -c -o $@ $(CFLAGS) $(CFLAGS_$@) $< -MD -MF .$@.dep +all: ews_autodiscover ews2ical + ews2ical: ews2ical.o $(CC) -o $@ $< $(LDFLAGS) $(XML2_LDFLAGS) + +ews_autodiscover: ews_autodiscover.o + $(CC) -o $@ $< $(LDFLAGS) $(XML2_LDFLAGS) $(SOUP_LDFLAGS) diff --git a/ews_autodiscover.c b/ews_autodiscover.c new file mode 100644 index 0000000..a0b5ff3 --- /dev/null +++ b/ews_autodiscover.c @@ -0,0 +1,155 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +struct ews_auth { + const char *username; + const char *password; +}; +static int parse_protocol(xmlNode *node); + +static void souptest_authenticate(SoupSession *sess, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + struct ews_auth *authdata = data; + soup_auth_authenticate (auth, authdata->username, authdata->password); +} + +int main(int argc, char **argv) +{ + SoupSession *sess; + SoupMessage *msg; + xmlDoc *doc; + xmlNode *node, *child; + guint status; + xmlOutputBuffer *buf; + struct ews_auth auth; + char *domain; + char *url; + + if (argc != 4) { + usage: + fprintf(stderr, "Usage: ews_autodiscover \n"); + fprintf(stderr, "Sorry, no Kerberos auth support yet (https://bugzilla.gnome.org/587145)\n"); + exit (1); + } + auth.username = argv[2]; + auth.password = argv[3]; + + domain = strchr(argv[1], '@'); + if (!domain) { + fprintf(stderr, "No @ sign in email address\n"); + goto usage; + } + domain++; + + if (!strchr(argv[2], '\\')) { + fprintf(stderr, "No domain in username (https://bugzilla.gnome.org/624613)\n"); + goto usage; + } + + g_thread_init (NULL); + g_type_init (); + asprintf(&url, "https://autodiscover.%s/autodiscover/autodiscover.xml", domain); + + sess = soup_session_sync_new_with_options(SOUP_SESSION_USE_NTLM, TRUE, NULL); + g_signal_connect (sess, "authenticate", + G_CALLBACK(souptest_authenticate), &auth); + + if (getenv("EWS_DEBUG")) { + SoupLogger *logger; + logger = soup_logger_new(SOUP_LOGGER_LOG_BODY, -1); + soup_session_add_feature(sess, SOUP_SESSION_FEATURE(logger)); + } + + printf("url is %s\n", url); + msg = soup_message_new("GET", url); + + soup_message_headers_append (msg->request_headers, + "User-Agent", "libews/0.1"); + + doc = xmlNewDoc((xmlChar *) "1.0"); + node = xmlNewDocNode(doc, NULL, (xmlChar *)"Autodiscover", NULL); + xmlNewProp(node, (xmlChar *)"xmlns", (xmlChar *)"http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006"); + xmlDocSetRootElement(doc, node); + + node = xmlNewChild(node, NULL, (xmlChar *)"Request", NULL); + child = xmlNewChild(node, NULL, (xmlChar *)"EMailAddress", + (xmlChar *)argv[1]); + child = xmlNewChild(node, NULL, (xmlChar *)"AcceptableResponseSchema", + (xmlChar *)"http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a"); + + buf = xmlAllocOutputBuffer(NULL); + xmlNodeDumpOutput(buf, doc, xmlDocGetRootElement(doc), 0, 1, NULL); + xmlOutputBufferFlush(buf); + + soup_message_set_request(msg, "application/xml", SOUP_MEMORY_COPY, + (gchar *)buf->buffer->content, + buf->buffer->use); + + status = soup_session_send_message(sess, msg); + + xmlOutputBufferClose (buf); + xmlFreeDoc (doc); + + if (status != 200) { + fprintf(stderr, "Unexpected response from server: %d\n", status); + exit(1); + } + + doc = xmlReadMemory (msg->response_body->data, msg->response_body->length, + "autodiscover.xml", NULL, 0); + if (!doc) { + fprintf(stderr, "Failed to parse autodiscover response XML\n"); + exit(1); + } + node = xmlDocGetRootElement(doc); + if (strcmp((char *)node->name, "Autodiscover")) { + fprintf(stderr, "Failed to find element\n"); + exit (1); + } + for (node = node->children; node; node = node->next) { + if (node->type == XML_ELEMENT_NODE && + !strcmp((char *)node->name, "Response")) + break; + } + if (!node) { + fprintf(stderr, "Failed to find element\n"); + exit (1); + } + for (node = node->children; node; node = node->next) { + if (node->type == XML_ELEMENT_NODE && + !strcmp((char *)node->name, "Account")) + break; + } + if (!node) { + fprintf(stderr, "Failed to find element\n"); + exit (1); + } + for (node = node->children; node; node = node->next) { + if (node->type == XML_ELEMENT_NODE && + !strcmp((char *)node->name, "Protocol") && + parse_protocol(node)) + break; + } + return 0; +} +static int parse_protocol(xmlNode *node) +{ + for (node = node->children; node; node = node->next) { + if (node->type == XML_ELEMENT_NODE && + !strcmp((char *)node->name, "ASUrl")) { + char *asurl = (char *)xmlNodeGetContent(node); + if (asurl) { + printf("Got ASUrl %s\n", asurl); + return 1; + } + } + } + return 0; +} -- 2.50.1