]> www.infradead.org Git - users/dwmw2/ews-sync.git/commitdiff
Update process_changes() to process the whole SoupSoapResponse
authorDavid Woodhouse <dwmw2@infradead.org>
Fri, 23 Jul 2010 16:59:51 +0000 (17:59 +0100)
committerDavid Woodhouse <dwmw2@infradead.org>
Fri, 23 Jul 2010 16:59:51 +0000 (17:59 +0100)
ews_syncfolder.c

index d47506bc48248b2df31b89d1f1fba13b54260dab..75133913b3fe592ef6d09d0119131a4571407b9b 100644 (file)
@@ -24,7 +24,9 @@ struct item_change {
 
 void combine_ical_files(void);
 
-int process_changes(xmlNode *node, struct item_change **changes);
+gboolean process_changes(SoupSoapResponse *resp, struct item_change **changes,
+                        gboolean *last, gchar **syncstate, GError **error);
+
 icalcomponent *fetch_xml_item(SoupSession *sess, char *url, const char *itemid,
                              const char *xml_filename, const char *parent_id,
                              icaltimezone *parent_zone, GError **error);
@@ -68,14 +70,13 @@ soup_ews_message_new(const gchar *url, const gchar *request)
 
 int main(int argc, char **argv)
 {
+       GError *error = NULL;
        SoupSession *sess;
        SoupSoapMessage *msg;
        SoupSoapResponse *resp;
-       xmlNode *node;
        guint status;
        struct ews_auth auth;
        char *url;
-       char *str;
        struct item_change *changes = NULL;
        gchar *syncstate = NULL;
        gboolean last_in_range = TRUE;
@@ -116,7 +117,6 @@ int main(int argc, char **argv)
  again:
        msg = soup_ews_message_new(url, "SyncFolderItems");
 
-
        soup_soap_message_start_element(msg, "ItemShape", NULL, NULL);
 
        soup_soap_message_start_element(msg, "BaseShape", "types", NULL);
@@ -158,79 +158,19 @@ int main(int argc, char **argv)
                if (!error)
                        error = "Unknown error";
 
-               fprintf(stderr, "SyncFolderChanges message failed: %s\n", error);
+               fprintf(stderr, "SyncFolderItems message failed: %s\n", error);
                exit(1);
        }
 
        resp = soup_soap_message_parse_response(msg);
        if (!resp) {
-               fprintf(stderr, "Failed to parse SyncFolderChanges response\n");
-               exit(1);
-       }
-       node = soup_soap_response_get_first_parameter_by_name(resp, "ResponseMessages");
-       if (!node) {
-               fprintf(stderr, "No <ResponseMessages> element in SyncFolderChanges reply\n");
-               exit(1);
-       }
-       node = soup_soap_parameter_get_first_child_by_name(node, "SyncFolderItemsResponseMessage");
-       if (!node) {
-               fprintf(stderr, "No <SyncFolderItemsResponseMessage> element in SyncFolderChanges reply\n");
-               exit(1);
-       }
-       str = soup_soap_parameter_get_property(node, "ResponseClass");
-       if (!strcmp(str, "Error")) {
-               gchar *msgtext = NULL;
-               gchar *respcode = NULL;
-
-               xmlNode *n2 = soup_soap_parameter_get_first_child_by_name(node, "MessageText");
-               if (n2) {
-                       msgtext = soup_soap_parameter_get_string_value(n2);
-                       fprintf(stderr, "Server returned error: %s\n",
-                               msgtext);
-               } else
-                       fprintf(stderr, "Server returned erorr without MessageText\n");
-
-               n2 = soup_soap_parameter_get_first_child_by_name(node, "ResponseCode");
-               if (n2) {
-                       respcode = soup_soap_parameter_get_string_value(n2);
-                       fprintf(stderr, "Response Code: %s\n", respcode);
-               }
-               g_free(msgtext);
-               g_free(respcode);
-               g_free(str);
-               exit(1);
-       } else if (strcmp(str, "Success")) {
-               fprintf(stderr, "Unknown response class '%s' from server\n",
-                       str);
-               g_free(str);
+               fprintf(stderr, "Failed to parse SyncFolderItems response\n");
                exit(1);
        }
-       g_free(str);
-       str = get_child_string(node, "IncludesLastItemInRange");
-       if (!str) {
-               fprintf(stderr, "No LastItemInRange element in SyncFolderItems response\n");
-               exit (1);
-       }
-       if (!strcmp(str, "true"))
-               last_in_range = TRUE;
-       else if (!strcmp(str, "false"))
-               last_in_range = FALSE;
-       else {
-               fprintf(stderr, "Invalid value for <IncludesLastItemInRange>: %s\n",
-                       str);
-               g_free(str);
+       if (!process_changes(resp, &changes, &last_in_range, &syncstate, &error)) {
+               fprintf(stderr, "Process changes failed: %s\n", error->message);
                exit(1);
        }
-       g_free(str);
-
-       syncstate = (gchar *)get_child_string(node, "SyncState");
-       if (!syncstate) {
-               fprintf(stderr, "No SyncState element in SyncFolderItems response\n");
-               exit (1);
-       }
-       node = soup_soap_parameter_get_first_child_by_name(node, "Changes");
-       if (node && process_changes(node, &changes))
-               exit(1);
 
        g_object_unref(resp);
 
@@ -266,7 +206,7 @@ int main(int argc, char **argv)
                changes = this->next;
                free(this);
        }
-               
+
        g_file_set_contents(statefilename, syncstate, strlen(syncstate), NULL);
        if (!last_in_range) {
                printf("Not last in range; restarting\n");
@@ -340,7 +280,7 @@ icalcomponent *fetch_xml_item(SoupSession *sess, char *url, const char *itemid,
                        errtxt = "Unknown error";
 
                g_set_error(error, EWS_ERROR, EWS_ERROR_SOAP,
-                           "GetItem message failed: %s\n", errtxt);
+                           "GetItem message failed: %s", errtxt);
                return NULL;
        }
 
@@ -390,11 +330,15 @@ icalcomponent *fetch_xml_item(SoupSession *sess, char *url, const char *itemid,
                g_set_error(error, EWS_ERROR, EWS_ERROR_SERVER,
                            "Server returned error: %s (ResponseCode %s)",
                            msgtext, respcode);
+               g_free(responseclass);
+               g_free(msgtext);
+               g_free(respcode);
                goto out;
        } else if (strcmp(responseclass, "Success")) {
                g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
                            "Unknown response class '%s' from server",
                            responseclass);
+               g_free(responseclass);
                goto out;
        }
 
@@ -419,66 +363,142 @@ icalcomponent *fetch_xml_item(SoupSession *sess, char *url, const char *itemid,
        return calcomp;
 }
 
-int process_changes(xmlNode *node, struct item_change **changes)
+gboolean process_changes(SoupSoapResponse *resp, struct item_change **changes,
+                        gboolean *last, gchar **syncstate, GError **error)
 {
-       xmlNode *node2;
+       xmlNode *node, *node2;
+       char *str;
 
-       for (node = node->children; node; node = node->next) {
-               int type;
-               char *itemid;
+       node = soup_soap_response_get_first_parameter_by_name(resp, "ResponseMessages");
+       if (!node) {
+               g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                           "No <ResponseMessages> element in SyncFolderItems reply");
+               return FALSE;
+       }
+       node = soup_soap_parameter_get_first_child_by_name(node, "SyncFolderItemsResponseMessage");
+       if (!node) {
+               g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                           "No <SyncFolderItemsResponseMessage> element in SyncFolderItems reply");
+               return FALSE;
+       }
+       str = soup_soap_parameter_get_property(node, "ResponseClass");
+       if (!str) {
+               g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                           "No ResponseClass parameter in SyncFolderItems reply");
+               return FALSE;
+       }
+       if (!strcmp(str, "Error")) {
+               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);
+               g_free(msgtext);
+               g_free(respcode);
+               g_free(str);
+               return FALSE;
+       } else if (strcmp(str, "Success")) {
+               g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                           "Unknown response class '%s' from server",
+                           str);
+               g_free(str);
+               return FALSE;
+       }
+       g_free(str);
+       str = get_child_string(node, "IncludesLastItemInRange");
+       if (!str) {
+               g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                           "No LastItemInRange element in SyncFolderItems response");
+               return FALSE;
+       }
+       if (!strcmp(str, "true"))
+               *last = TRUE;
+       else if (!strcmp(str, "false"))
+               *last = FALSE;
+       else {
+               g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                           "Invalid value for <IncludesLastItemInRange>: %s",
+                           str);
+               g_free(str);
+               return FALSE;
+       }
+       g_free(str);
+
+       *syncstate = (gchar *)get_child_string(node, "SyncState");
+       if (!*syncstate) {
+               g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                           "No SyncState element in SyncFolderItems response");
+               return FALSE;
+       }
+       node = soup_soap_parameter_get_first_child_by_name(node, "Changes");
+       if (!node)
+               return TRUE;
+
+       for (node = soup_soap_parameter_get_first_child(node);
+            node; node = soup_soap_parameter_get_next_child(node)) {
                struct item_change *new_change;
+               char *itemid;
+               int type;
 
-               if (node->type != XML_ELEMENT_NODE)
-                       continue;
-               if (!strcmp((char *)node->name, "Create"))
+               if (!strcmp((char *)node->name, "Create")) {
                        type = ITEM_CREATE;
-               else if (!strcmp((char *)node->name, "Delete")) {
+               } else if (!strcmp((char *)node->name, "Update")) {
+                       type = ITEM_UPDATE;
+               } else if (!strcmp((char *)node->name, "Delete")) {
                        type = ITEM_DELETE;
                        node2 = node;
                        goto itemid;
-               } else if (!strcmp((char *)node->name, "Update"))
-                       type = ITEM_UPDATE;
-               else {
-                       fprintf(stderr, "Unknown change type '%s'\n", 
-                               node->name);
-                       return -1;
-               }
-               for (node2 = node->children; node2; node2 = node2->next) {
-                       if (node2->type != XML_ELEMENT_NODE)
-                               continue;
-                       if (!strcmp((char *)node2->name, "CalendarItem"))
-                               break;
+               } else {
+                       g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                                   "Unknown change type '%s'", 
+                                   node->name);
+               err_changes:
+                       while (*changes) {
+                               new_change = *changes;
+                               *changes = new_change->next;
+                               g_free(new_change);
+                       }
+                       return FALSE;
                }
+               node2 = soup_soap_parameter_get_first_child_by_name(node, "CalendarItem");
                if (!node2) {
-                       fprintf(stderr, "<%s> node has no <CalendarItem> child\n",
-                               node->name);
-                       return -1;
+                       g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                                   "<%s> node has no <CalendarItem> child",
+                                   node->name);
+                       goto err_changes;
                }
        itemid:
-               for (node2 = node2->children; node2; node2 = node2->next) {
-                       if (node2->type != XML_ELEMENT_NODE)
-                               continue;
-                       if (!strcmp((char *)node2->name, "ItemId"))
-                               break;
-               }
+               node2 = soup_soap_parameter_get_first_child_by_name(node2, "ItemId");
                if (!node2) {
-                       fprintf(stderr, "<%s> node has no <ItemId> child\n",
-                               node->name);
-                       return -1;
+                       g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                                   "<%s> node has no <ItemId> child",
+                                   node->name);
+                       goto err_changes;
                }
                itemid = (char *)xmlGetProp(node2, (xmlChar *)"Id");
 
                new_change = malloc(sizeof(*new_change) + strlen(itemid) + 1);
                if (!new_change) {
-                       fprintf(stderr, "Out of memory\n");
-                       return -1;
+                       g_set_error(error, EWS_ERROR, EWS_ERROR_PARSE,
+                                   "Out of memory");
+                       goto err_changes;
                }
                new_change->next = *changes;
                new_change->type = type;
                strcpy(new_change->itemid, itemid);
                *changes = new_change;
        }
-       return 0;
+       return TRUE;
 }
 
 void combine_ical_files(void)