From 0a32a2c245d1cd4930a5fbeb14c25d3a5b3198fa Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 19 Jul 2010 23:00:41 +0100 Subject: [PATCH] Start implementing syncfolder in C with libsoup --- Makefile | 6 +- ews_syncfolder.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 ews_syncfolder.c diff --git a/Makefile b/Makefile index 7cad340..c61fe84 100644 --- 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 index 0000000..63a4cb4 --- /dev/null +++ b/ews_syncfolder.c @@ -0,0 +1,176 @@ +#include +#include +#include +#include +#include +#include + +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 \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 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 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 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 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 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; +} -- 2.49.0