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