]> www.infradead.org Git - users/dwmw2/ews-sync.git/commitdiff
Add C version of autodiscover, using libsoup
authorDavid Woodhouse <dwmw2@infradead.org>
Sat, 17 Jul 2010 15:07:43 +0000 (16:07 +0100)
committerDavid Woodhouse <dwmw2@infradead.org>
Sat, 17 Jul 2010 15:07:43 +0000 (16:07 +0100)
Makefile
ews_autodiscover.c [new file with mode: 0644]

index fff23de6249bd2c20599a29c697b0ab94f259ba8..ffab257c13f01544f81839b0617a479c9d0ebd93 100644 (file)
--- 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 (file)
index 0000000..a0b5ff3
--- /dev/null
@@ -0,0 +1,155 @@
+#define _GNU_SOURCE
+
+#include <libsoup/soup.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+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 <email> <DOMAIN\\username> <password>\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 <Autodiscover> 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 <Response> 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 <Account> 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;
+}