]> www.infradead.org Git - users/dwmw2/ews-sync.git/commitdiff
Start implementing syncfolder in C with libsoup
authorDavid Woodhouse <dwmw2@infradead.org>
Mon, 19 Jul 2010 22:00:41 +0000 (23:00 +0100)
committerDavid Woodhouse <dwmw2@infradead.org>
Mon, 19 Jul 2010 22:01:45 +0000 (23:01 +0100)
Makefile
ews_syncfolder.c [new file with mode: 0644]

index 7cad3403c23e1222a1ef709d4b2348e0d11a40a3..c61fe84b615c98d22f8c8cd4d932a04c36d400ec 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -39,13 +39,14 @@ endif
 
 
 CFLAGS := $(OPT_FLAGS) $(XML2_CFLAGS) $(GLIB_CFLAGS)
+CFLAGS_ews_syncfolder.o := $(SOUP_CFLAGS)
 CFLAGS_ews_autodiscover.o := $(SOUP_CFLAGS)
 CFLAGS_ews2ical.o := $(ICAL_CFLAGS)
 
 %.o: %.c
        $(CC) -c -o $@ $(CFLAGS) $(CFLAGS_$@) $< -MD -MF .$@.dep
 
-PROGS := ews_autodiscover ews2ical
+PROGS := ews_syncfolder ews_autodiscover ews2ical
 
 all: $(PROGS)
 
@@ -57,3 +58,6 @@ ews2ical: ews2ical.o
 
 ews_autodiscover: ews_autodiscover.o
        $(CC) -o $@ $< $(LDFLAGS) $(XML2_LDFLAGS) $(SOUP_LDFLAGS) $(GLIB_LDFLAGS)
+
+ews_syncfolder: ews_syncfolder.o
+       $(CC) -o $@ $< $(LDFLAGS) $(XML2_LDFLAGS) $(SOUP_LDFLAGS) $(GLIB_LDFLAGS)
diff --git a/ews_syncfolder.c b/ews_syncfolder.c
new file mode 100644 (file)
index 0000000..63a4cb4
--- /dev/null
@@ -0,0 +1,176 @@
+#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 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;
+       xmlNs *soap_ns, *types_ns, *messages_ns;
+       guint status;
+       xmlOutputBuffer *buf;
+       struct ews_auth auth;
+       char *url;
+       char *responseclass;
+
+       if (argc != 4) {
+       usage:
+               fprintf(stderr, "Usage: ews_syncfolder <ews_url> <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];
+
+       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 ();
+
+       url = argv[1];
+
+       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));
+       }
+
+       msg = soup_message_new("POST", url);
+
+       soup_message_headers_append (msg->request_headers,
+                                    "User-Agent", "libews/0.1");
+
+       doc = xmlNewDoc((xmlChar *) "1.0");
+       node = xmlNewDocNode(doc, NULL, (xmlChar *)"Envelope", NULL);
+       xmlDocSetRootElement(doc, node);
+       
+       soap_ns = xmlNewNs (node, (xmlChar *)"http://schemas.xmlsoap.org/soap/envelope/",
+                           (xmlChar *)"soap");
+       xmlSetNs(node, soap_ns);
+       types_ns = xmlNewNs (node, (xmlChar *)"http://schemas.microsoft.com/exchange/services/2006/types",
+                            (xmlChar *)"types");
+       node = xmlNewChild(node, soap_ns, (xmlChar *)"Body", NULL);
+       node = xmlNewChild(node, NULL, (xmlChar *)"SyncFolderItems", NULL);
+
+       messages_ns = xmlNewNs (node, (xmlChar *)"http://schemas.microsoft.com/exchange/services/2006/messages", NULL);
+       xmlSetNs(node, messages_ns);
+       child = xmlNewChild (node, messages_ns, (xmlChar *)"ItemShape", NULL);
+       xmlNewTextChild(child, types_ns, (xmlChar *)"BaseShape", (xmlChar *)"IdOnly");
+       child = xmlNewChild (node, messages_ns, (xmlChar *)"SyncFolderId", NULL);
+       xmlNewProp(xmlNewChild(child, types_ns, (xmlChar *)"DistinguishedFolderId", NULL),
+                      (xmlChar *)"Id", (xmlChar *)"calendar");
+       child = xmlNewTextChild (node, messages_ns, (xmlChar *)"MaxChangesReturned",
+                                (xmlChar *)"5");
+
+       buf = xmlAllocOutputBuffer(NULL);
+       xmlNodeDumpOutput(buf, doc, xmlDocGetRootElement(doc), 0, 1, NULL);
+       xmlOutputBufferFlush(buf);
+
+       soup_message_set_request(msg, "text/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,
+                            "syncresponse.xml", NULL, 0);
+       if (!doc) {
+               fprintf(stderr, "Failed to parse autodiscover response XML\n");
+               exit(1);
+       }
+       node = xmlDocGetRootElement(doc);
+       if (strcmp((char *)node->name, "Envelope")) {
+               fprintf(stderr, "Failed to find SOAP <Envelope> element\n");
+               exit (1);
+       }
+       for (node = node->children; node; node = node->next) {
+               if (node->type == XML_ELEMENT_NODE &&
+                   !strcmp((char *)node->name, "Body"))
+                       break;
+       }
+       if (!node) {
+               fprintf(stderr, "Failed to find SOAP <Body> element\n");
+               exit (1);
+       }
+       for (node = node->children; node; node = node->next) {
+               if (node->type == XML_ELEMENT_NODE &&
+                   !strcmp((char *)node->name, "SyncFolderItemsResponse"))
+                       break;
+       }
+       if (!node) {
+               fprintf(stderr, "Failed to find <SyncFolderItemsResponse> element\n");
+               exit (1);
+       }
+       for (node = node->children; node; node = node->next) {
+               if (node->type == XML_ELEMENT_NODE &&
+                   !strcmp((char *)node->name, "ResponseMessages"))
+                       break;
+       }
+       if (!node) {
+               fprintf(stderr, "Failed to find <ResponseMessages> element\n");
+               exit (1);
+       }
+       for (node = node->children; node; node = node->next) {
+               if (node->type == XML_ELEMENT_NODE &&
+                   !strcmp((char *)node->name, "SyncFolderItemsResponseMessage"))
+                       break;
+       }
+       if (!node) {
+               fprintf(stderr, "Failed to find <SyncFolderItemsResponseMessage> element\n");
+               exit (1);
+       }
+       responseclass = (char *)xmlGetProp(node, (xmlChar *)"ResponseClass");
+       if (!strcmp(responseclass, "Error")) {
+               for (node = node->children; node; node = node->next) {
+                       if (node->type != XML_ELEMENT_NODE)
+                               continue;
+                       if (!strcmp((char *)node->name, "MessageText")) {
+                               fprintf(stderr, "Server returned error: %s\n",
+                                       xmlNodeGetContent(node));
+                       } else if (!strcmp((char *)node->name, "ResponseCode")) {
+                               fprintf(stderr, "Response code: %s\n",
+                                       xmlNodeGetContent(node));
+                       }
+               }
+               exit(1);
+       } else if (strcmp(responseclass, "Success")) {
+               fprintf(stderr, "Unknown response class '%s' from server\n",
+                       responseclass);
+               exit(1);
+       }
+       fprintf(stderr, "WRITE ME\n");
+
+       return 0;
+}