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);
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;
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);
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);
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");
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;
}
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;
}
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)