]> www.infradead.org Git - users/dwmw2/ews-sync.git/commitdiff
Clean up fetch item code to be more like I want it
authorDavid Woodhouse <dwmw2@infradead.org>
Thu, 22 Jul 2010 15:40:05 +0000 (16:40 +0100)
committerDavid Woodhouse <dwmw2@infradead.org>
Thu, 22 Jul 2010 15:40:05 +0000 (16:40 +0100)
ews_syncfolder.c

index 5b7c267dbbce1cc6ea72b8e7a0fa7946270c00b4..5335d556eae0d4463e3f674563572d47468b62a7 100644 (file)
@@ -23,9 +23,9 @@ struct item_change {
 };
 
 int process_changes(xmlNode *node, struct item_change **changes);
-int fetch_xml_item(SoupSession *sess, char *url, const char *itemid,
-                  const char *xml_filename, const char *ics_filename,
-                  const char *parent_id, icaltimezone *parent_zone);
+icalcomponent *fetch_xml_item(SoupSession *sess, char *url, const char *itemid,
+                             const char *xml_filename, const char *parent_id,
+                             icaltimezone *parent_zone, GError **error);
 
 struct ews_auth {
        const char *username;
@@ -59,7 +59,7 @@ soup_ews_message_new(const gchar *url, const gchar *request)
        soup_soap_message_start_body(msg);
        soup_soap_message_add_namespace(msg, "types", 
                                       "http://schemas.microsoft.com/exchange/services/2006/types");
-       soup_soap_message_start_element(msg, "SyncFolderItems", NULL, NULL);
+       soup_soap_message_start_element(msg, request, NULL, NULL);
        soup_soap_message_set_default_namespace(msg, "http://schemas.microsoft.com/exchange/services/2006/messages");
        return msg;
 }
@@ -242,10 +242,23 @@ int main(int argc, char **argv)
                        unlink(xml_filename);
                        unlink(ics_filename);
                } else {
-                       if (fetch_xml_item(sess, url, this->itemid,
-                                          xml_filename, ics_filename,
-                                          NULL, NULL))
-                               return -1;
+                       GError *error = NULL;
+                       icalcomponent *comp;
+
+                       comp = fetch_xml_item(sess, url, this->itemid,
+                                             xml_filename, NULL, NULL, &error);
+                       if (!comp) {
+                               fprintf(stderr, "Fetch error: %s\n", error->message);
+                               g_clear_error(&error);
+                       } else {
+                               char *outbuf;
+                               outbuf = icalcomponent_as_ical_string_r(comp);
+
+                               g_file_set_contents(ics_filename, outbuf, strlen(outbuf), NULL);
+                               printf("Got ICS file %s\n", ics_filename);
+                               free(outbuf);
+                               icalcomponent_free(comp);
+                       }
                }
                changes = this->next;
                free(this);
@@ -256,171 +269,130 @@ int main(int argc, char **argv)
        return 0;
 }
 
-int fetch_xml_item(SoupSession *sess, char *url, const char *itemid,
-                  const char *xml_filename, const char *ics_filename,
-                  const char *parent_id, icaltimezone *parent_zone)
+icalcomponent *fetch_xml_item(SoupSession *sess, char *url, const char *itemid,
+                             const char *xml_filename, const char *parent_id,
+                             icaltimezone *parent_zone, GError **error)
 {
-       GError *error = NULL;
-       SoupMessage *msg;
-       xmlDoc *doc;
-       xmlNode *node, *child;
-       xmlNs *soap_ns, *types_ns, *messages_ns;
-       xmlOutputBuffer *buf;
+       SoupSoapMessage *msg;
+       SoupSoapResponse *resp;
+       xmlNode *node;
        int status;
        char *responseclass;
-       icalcomponent *calcomp;
-       char *outbuf;
+       icalcomponent *calcomp = NULL;
 
-       msg = soup_message_new("POST", url);
+       msg = soup_ews_message_new(url, "GetItem");
 
-       soup_message_headers_append (msg->request_headers,
-                                    "User-Agent", "libews/0.1");
+       soup_soap_message_start_element(msg, "ItemShape", NULL, NULL);
+               
+       soup_soap_message_start_element(msg, "BaseShape", "types", NULL);
+       soup_soap_message_write_string(msg, "AllProperties");
+       soup_soap_message_end_element(msg);
 
-       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 *)"GetItem", 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 *)"AllProperties");
-       xmlNewTextChild(child, types_ns, (xmlChar *)"BodyType", (xmlChar *)"Text");
-       child = xmlNewChild (node, messages_ns, (xmlChar *)"ItemIds", NULL);
-       xmlNewProp(xmlNewChild(child, types_ns, (xmlChar *)"ItemId", NULL),
-                      (xmlChar *)"Id", (xmlChar *)itemid);
-
-
-       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);
-       }
-       g_file_set_contents(xml_filename, msg->response_body->data,
-                           msg->response_body->length, NULL);
-       printf("Got XML file %s\n", itemid);
-       doc = xmlReadMemory (msg->response_body->data, msg->response_body->length,
-                            "syncresponse.xml", NULL, 0);
-       if (!doc) {
-               fprintf(stderr, "Failed to parse GetItem 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;
+       soup_soap_message_start_element(msg, "BodyType", "types", NULL);
+       soup_soap_message_write_string(msg, "Text");
+       soup_soap_message_end_element(msg);
+
+       soup_soap_message_end_element(msg); /* ItemShape */
+
+       soup_soap_message_start_element(msg, "ItemIds", NULL, NULL);
+       soup_soap_message_start_element(msg, "ItemId", "types", NULL);
+       soup_soap_message_add_attribute(msg, "Id", itemid, NULL, NULL);
+       soup_soap_message_end_element(msg);
+       soup_soap_message_end_element(msg);
+
+       soup_soap_message_end_element(msg); /* SyncFolderItems */
+       soup_soap_message_end_body(msg);
+       soup_soap_message_end_envelope(msg);
+
+       soup_soap_message_persist(msg);
+
+       status = soup_session_send_message(sess, SOUP_MESSAGE(msg));
+
+       if (!SOUP_STATUS_IS_SUCCESSFUL(status)) {
+               const gchar *errtxt = soup_status_get_phrase(status);
+               if (!errtxt)
+                       errtxt = "Unknown error";
+
+               g_set_error(error, EWS_ERROR, EWS_ERROR_SOAP,
+                           "GetItem message failed: %s\n", errtxt);
+               return NULL;
        }
-       if (!node) {
-               fprintf(stderr, "Failed to find SOAP <Body> element\n");
-               exit (1);
+
+       if (xml_filename) {
+               g_file_set_contents(xml_filename, SOUP_MESSAGE(msg)->response_body->data,
+                                   SOUP_MESSAGE(msg)->response_body->length, NULL);
+
+               printf("Got XML file %s\n", xml_filename);
        }
-       for (node = node->children; node; node = node->next) {
-               if (node->type == XML_ELEMENT_NODE &&
-                   !strcmp((char *)node->name, "GetItemResponse"))
-                       break;
+
+       resp = soup_soap_message_parse_response(msg);
+       g_object_unref(msg);
+       if (!resp) {
+               g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                           "Failed to parse GetItem response");
+               return NULL;
        }
+
+       node = soup_soap_response_get_first_parameter_by_name(resp, "ResponseMessages");
        if (!node) {
-               fprintf(stderr, "Failed to find <GetItemResponse> element\n");
-               exit (1);
-       }
-       for (node = node->children; node; node = node->next) {
-               if (node->type == XML_ELEMENT_NODE &&
-                   !strcmp((char *)node->name, "ResponseMessages"))
-                       break;
+               g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                           "No <ResponseMessages> element in GetItems reply");
+               goto out;
        }
+
+       node = soup_soap_parameter_get_first_child_by_name(node, "GetItemResponseMessage");
        if (!node) {
-               fprintf(stderr, "Failed to find <ResponseMessages> element\n");
-               exit (1);
+               g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                           "No <GetItemResponseMessage> element in GetItem reply");
+               goto out;
        }
-       for (node = node->children; node; node = node->next) {
-               if (node->type == XML_ELEMENT_NODE &&
-                   !strcmp((char *)node->name, "GetItemResponseMessage"))
-                       break;
-       }
-       responseclass = (char *)xmlGetProp(node, (xmlChar *)"ResponseClass");
+       
+       responseclass = soup_soap_parameter_get_property(node, "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));
-                       }
-               }
-               /* Don't abort the whole sync run just for this */
-               xmlFreeDoc(doc);
-               return 0;
+               gchar *msgtext = NULL;
+               gchar *respcode = NULL;
+               xmlNode *n2;
+
+               n2 = soup_soap_parameter_get_first_child_by_name(node, "MessageText");
+               if (n2)
+                       msgtext = soup_soap_parameter_get_string_value(n2);
+
+               n2 = soup_soap_parameter_get_first_child_by_name(node, "ResponseCode");
+               if (n2)
+                       respcode = soup_soap_parameter_get_string_value(n2);
+
+               g_set_error(error, EWS_ERROR, EWS_ERROR_SERVER,
+                           "Server returned error: %s (ResponseCode %s)",
+                           msgtext, respcode);
+               goto out;
        } else if (strcmp(responseclass, "Success")) {
-               fprintf(stderr, "Unknown response class '%s' from server\n",
-                       responseclass);
-               exit(1);
+               g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                           "Unknown response class '%s' from server",
+                           responseclass);
+               goto out;
        }
 
-       for (node = node->children; node; node = node->next) {
-               if (node->type == XML_ELEMENT_NODE &&
-                   !strcmp((char *)node->name, "Items"))
-                       break;
-       }
+       node = soup_soap_parameter_get_first_child_by_name(node, "Items");
        if (!node) {
-               fprintf(stderr, "Failed to find <Items> element\n");
-               exit (1);
+               g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                           "No <Items> element in GetItem reply");
+               goto out;
        }
 
-       for (node = node->children; node; node = node->next) {
-               if (node->type == XML_ELEMENT_NODE &&
-                   !strcmp((char *)node->name, "CalendarItem"))
-                       break;
-       }
+       node = soup_soap_parameter_get_first_child_by_name(node, "CalendarItem");
        if (!node) {
-               fprintf(stderr, "Failed to find <CalendarItem> element\n");
-               exit (1);
+               g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                           "Failed to find <CalendarItem> element in GetItem reply");
+               goto out;
        }
 
-       calcomp = ews_calitem_to_ical(node, parent_id, parent_zone, NULL, NULL, &error);
-       if (!calcomp) {
-               printf("Failed to parse calendar: %s\n", error->message);
-               g_clear_error(&error);
-               return 0;
-       }
-       outbuf = icalcomponent_as_ical_string_r(calcomp);
-
-       g_file_set_contents(ics_filename, outbuf, strlen(outbuf), NULL);
-       printf("Got ICS file %s\n", ics_filename);
-       free(outbuf);
-
-
-       xmlFreeDoc(doc);
-
+       calcomp = ews_calitem_to_ical(node, parent_id, parent_zone, NULL, NULL, error);
+ out:
+       g_object_unref(resp);
 
-       return 0;
+       return calcomp;
 }
+
 int process_changes(xmlNode *node, struct item_change **changes)
 {
        xmlNode *node2;