Example #1
0
static SoupMessage *
ews_create_msg_for_url (const gchar *url,
                        xmlOutputBuffer *buf)
{
	SoupMessage *msg;
	gconstpointer buf_content;
	gsize buf_size;

	msg = soup_message_new (buf != NULL ? "POST" : "GET", url);
	soup_message_headers_append (
		msg->request_headers, "User-Agent", "libews/0.1");

	if (buf != NULL) {
		buf_content = compat_libxml_output_buffer_get_content (buf, &buf_size);
		soup_message_set_request (
			msg, "text/xml; charset=utf-8",
			SOUP_MEMORY_COPY,
			buf_content, buf_size);
		g_signal_connect (
			msg, "restarted",
			G_CALLBACK (ews_post_restarted_cb), buf);
	}

	soup_buffer_free (
		soup_message_body_flatten (
		SOUP_MESSAGE (msg)->request_body));

	g_debug ("The request headers");
	g_debug ("===================");
	g_debug ("%s", SOUP_MESSAGE (msg)->request_body->data);

	return msg;
}
Example #2
0
SoupSoapMessage *
e_gw_message_new_with_header (const gchar *uri, const gchar *session_id, const gchar *method_name)
{
	SoupSoapMessage *msg;

	msg = soup_soap_message_new (SOUP_METHOD_POST, uri, FALSE, NULL, NULL, NULL);
	if (!msg) {
		g_warning (G_STRLOC ": Could not build SOAP message");
		return NULL;
	}

	soup_message_headers_append (SOUP_MESSAGE (msg)->request_headers, "Content-Type", "text/xml");
	soup_message_headers_append (SOUP_MESSAGE (msg)->request_headers, "User-Agent",
				     "Evolution/" VERSION);
	soup_message_headers_append (SOUP_MESSAGE (msg)->request_headers,"Connection",  "Keep-Alive");
	soup_message_headers_append (SOUP_MESSAGE (msg)->request_headers, "SOAPAction", method_name);

	soup_soap_message_start_envelope (msg);
	if (session_id && *session_id) {
		soup_soap_message_start_element (msg, "Header","SOAP-ENV", NULL);
		soup_soap_message_add_attribute (msg, "encodingStyle", "", "SOAP-ENV", NULL);
		/* FIXME: cannot use e_gw_message_write_string_parameter as it sets prefix -types*/
		soup_soap_message_start_element (msg, "session", NULL, NULL);
		soup_soap_message_write_string (msg, session_id);
		soup_soap_message_end_element (msg);
		soup_soap_message_end_element (msg);
	}
	soup_soap_message_start_body (msg);
	soup_soap_message_add_attribute (msg, "encodingStyle", "", "SOAP-ENV", NULL);
	soup_soap_message_add_namespace (msg, "types", "http://schemas.novell.com/2003/10/NCSP/types.xsd");

	soup_soap_message_start_element (msg, method_name, NULL, NULL);

	return msg;
}
Example #3
0
ESoapMessage *
e_ews_message_new_with_header (const gchar *uri,
                               const gchar *method_name,
                               const gchar *attribute_name,
                               const gchar *attribute_value,
                               EwsServerVersion server_info)
{
	ESoapMessage *msg;
	const gchar *server_ver;

	msg = e_soap_message_new (SOUP_METHOD_POST, uri, FALSE, NULL, NULL, NULL);
	if (!msg) {
		g_warning (G_STRLOC ": Could not build SOAP message");
		return NULL;
	}

	soup_message_headers_append (SOUP_MESSAGE (msg)->request_headers, "Content-Type", "text/xml; charset=utf-8");
	soup_message_headers_append (SOUP_MESSAGE (msg)->request_headers, "User-Agent",
				     "Evolution/" VERSION);
	soup_message_headers_append (SOUP_MESSAGE (msg)->request_headers,"Connection",  "Keep-Alive");

	e_soap_message_start_envelope (msg);

	/* server info */
	if (server_info == EWS_EXCHANGE_2007_SP1)
		server_ver = "Exchange2007_SP1";
	else
		server_ver = "Exchange2007";

	e_soap_message_start_header (msg);

	e_soap_message_start_element (msg, "RequestServerVersion", "types",
					"http://schemas.microsoft.com/exchange/services/2006/types");
	e_soap_message_add_attribute (msg, "Version", server_ver, NULL, NULL);
	e_soap_message_end_element (msg);

	e_soap_message_end_header (msg);

	e_soap_message_start_body (msg);
	e_soap_message_add_namespace(msg, "messages",
				       "http://schemas.microsoft.com/exchange/services/2006/messages");
	e_soap_message_start_element(msg, method_name, "messages", NULL);
	e_soap_message_set_default_namespace (msg,
						"http://schemas.microsoft.com/exchange/services/2006/types");
	if (attribute_name)
		e_soap_message_add_attribute (msg, attribute_name, attribute_value, NULL, NULL);
	return msg;
}
Example #4
0
/**
 * e_soap_message_new:
 * @method: the HTTP method for the created request.
 * @uri_string: the destination endpoint (as a string).
 * @standalone: ??? FIXME
 * @xml_encoding: ??? FIXME
 * @env_prefix: ??? FIXME
 * @env_uri: ??? FIXME
 *
 * Creates a new empty #ESoapMessage, which will connect to @uri_string.
 *
 * Returns: the new #ESoapMessage (or %NULL if @uri_string could not be
 * parsed).
 *
 * Since: 2.92
 */
ESoapMessage *
e_soap_message_new (const gchar *method,
                    const gchar *uri_string,
                    gboolean standalone,
                    const gchar *xml_encoding,
                    const gchar *env_prefix,
                    const gchar *env_uri)
{
	ESoapMessage *msg;
	SoupURI *uri;

	uri = soup_uri_new (uri_string);
	if (!uri)
		return NULL;

	msg = e_soap_message_new_from_uri (method, uri, standalone,
					   xml_encoding, env_prefix, env_uri);

	soup_uri_free (uri);

	/* Don't accumulate body data into a huge buffer.
	 * Instead, parse it as it arrives. */
	soup_message_body_set_accumulate (SOUP_MESSAGE (msg)->response_body,
					  FALSE);
	g_signal_connect (msg, "got-headers", G_CALLBACK (soap_got_headers), NULL);
	g_signal_connect (msg, "got-chunk", G_CALLBACK (soap_got_chunk), NULL);
	g_signal_connect (msg, "restarted", G_CALLBACK (soap_restarted), NULL);

	return msg;
}
Example #5
0
int
main (int argc, char **argv)
{
	SoupSession *session;
	SoupURI *proxy = NULL;
	SoupMessage *msg;
	const char *uri = "http://bugzilla.redhat.com/bugzilla/xmlrpc.cgi";
	int opt, bug;

	g_thread_init (NULL);
	g_type_init ();

	while ((opt = getopt (argc, argv, "p:")) != -1) {
		switch (opt) {
		case 'p':
			proxy = soup_uri_new (optarg);
			if (!proxy) {
				fprintf (stderr, "Could not parse %s as URI\n",
					 optarg);
				exit (1);
			}
			break;

		case '?':
			usage ();
			break;
		}
	}
	argc -= optind;
	argv += optind;

	if (argc > 1) {
		uri = argv[0];
		argc--;
		argv++;
	}

	if (argc != 1 || (bug = atoi (argv[0])) == 0)
		usage ();

	session = soup_session_async_new_with_options (
		SOUP_SESSION_PROXY_URI, proxy,
		NULL);

	msg = soup_xmlrpc_request_new (uri, "bugzilla.getBug",
				       G_TYPE_INT, bug,
				       G_TYPE_INVALID);
	if (!msg) {
		fprintf (stderr, "Could not create web service request to '%s'\n", uri);
		exit (1);
	}
	soup_session_queue_message (session, SOUP_MESSAGE (msg),
				    got_response, NULL);

	loop = g_main_loop_new (NULL, TRUE);
	g_main_loop_run (loop);
	g_main_loop_unref (loop);

	return 0;
}
Example #6
0
void
e_gw_message_write_footer (SoupSoapMessage *msg)
{
	soup_soap_message_end_element (msg);
	soup_soap_message_end_body (msg);
	soup_soap_message_end_envelope (msg);

	soup_soap_message_persist (msg);

	if (g_getenv ("GROUPWISE_DEBUG") && (atoi (g_getenv ("GROUPWISE_DEBUG")) == 1)) {
		const gchar *header = soup_message_headers_get (SOUP_MESSAGE (msg)->request_headers, "SOAPAction");

		soup_buffer_free (soup_message_body_flatten (SOUP_MESSAGE (msg)->request_body));
		if (header && g_str_equal (header, "loginRequest")) {
			gchar *body;
			gchar *begin = NULL;
			gchar *end = NULL;

			body = g_strdup (SOUP_MESSAGE (msg)->request_body->data);
			begin = g_strrstr (body, "<types:password>");
			if (begin)
				begin = begin + strlen ("<types:password>");
			end = g_strrstr (body , "</types:password>");
			if (begin && end) {
				gchar *tmp;
				for (tmp = begin; tmp < end; tmp++)
					*tmp='X';

			}
			fputc ('\n', stdout);
			fputs (body, stdout);
			fputc ('\n', stdout);
			g_free (body);
		}
		else {

			/* print request's body */
			fputc ('\n', stdout);
			fputs (SOUP_MESSAGE (msg)->request_body->data, stdout);
			fputc ('\n', stdout);
		}
	}
}
Example #7
0
static VALUE
WebNetworkResponse_message(VALUE self)
{
  VALUE __p_retval = Qnil;
  WebKitNetworkResponse *_self = ((WebKitNetworkResponse*)RVAL2GOBJ(self));

#line 217 "/home/geoff/Projects/gtk-webkit-ruby/ext/webkit/webkit.cr"
  do { __p_retval = GOBJ2RVAL(SOUP_MESSAGE(webkit_network_response_get_message(_self))); goto out; } while(0);
out:
  return __p_retval;
}
static void webkit_network_request_set_property(GObject* object, guint propertyID, const GValue* value, GParamSpec* pspec)
{
    WebKitNetworkRequest* request = WEBKIT_NETWORK_REQUEST(object);
    WebKitNetworkRequestPrivate* priv = request->priv;

    switch(propertyID) {
    case PROP_URI:
        webkit_network_request_set_uri(request, g_value_get_string(value));
        break;
    case PROP_MESSAGE:
        priv->message = SOUP_MESSAGE(g_value_dup_object(value));
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyID, pspec);
    }
}
Example #9
0
/**
 * e_soap_message_persist:
 * @msg: the #ESoapMessage.
 *
 * Writes the serialized XML tree to the #SoupMessage's buffer.
 *
 * Since: 2.92
 */
void
e_soap_message_persist (ESoapMessage *msg)
{
	ESoapMessagePrivate *priv;
	xmlChar *body;
	gint len;

	g_return_if_fail (E_IS_SOAP_MESSAGE (msg));
	priv = E_SOAP_MESSAGE_GET_PRIVATE (msg);

	xmlDocDumpMemory (priv->doc, &body, &len);

	/* serialize to SoupMessage class */
	soup_message_set_request (SOUP_MESSAGE (msg), "text/xml; charset=utf-8",
				  SOUP_MEMORY_TAKE, (gchar *) body, len);
}
static gboolean _soup_xmlrpc_call(gchar * method, SyncNetAction * sna,
				  SoupMessageCallbackFn callback)
{
    SoupXmlrpcMessage *msg;

    sna->error = NULL;

    msg = soup_xmlrpc_message_new(XMLRPC_SERVER_URI);
    if (!msg)
	return FALSE;

    DEBUG("calling xmlrpc method %s", method);
    soup_xmlrpc_message_start_call(msg, method);
    soup_xmlrpc_message_end_call(msg);

    soup_xmlrpc_message_persist(msg);

    soup_session_queue_message(session, SOUP_MESSAGE(msg), callback, sna);
    g_main_run(loop);

    return TRUE;
}
Example #11
0
static gboolean
send_chunks (gpointer user_data)
{
  SoupMessage *msg = SOUP_MESSAGE (user_data);
  char *s;
  SoupBuffer *buf;

  s = g_strdup_printf ("%d %d %d %d\n",
                       server_count, server_count,
                       server_count, server_count);
  buf = soup_buffer_new (SOUP_MEMORY_TAKE, s, strlen (s));

  soup_message_body_append_buffer (msg->response_body, buf);
  soup_server_unpause_message (server, msg);

  if (++server_count == NUM_CHUNKS)
  {
    soup_message_body_complete (msg->response_body);
    return FALSE;
  } else {
    return TRUE;
  }
}
static gboolean _soup_xmlrpc_call_with_parameters(gchar * method,
						  SyncNetAction * sna,
						  SoupMessageCallbackFn
						  callback, ...)
{
    SoupXmlrpcMessage *msg;
    gchar *argument;
    va_list ap;

    sna->error = NULL;

    msg = soup_xmlrpc_message_new(XMLRPC_SERVER_URI);
    if (!msg)
	return FALSE;

    DEBUG("calling xmlrpc method %s", method);
    soup_xmlrpc_message_start_call(msg, method);

    va_start(ap, callback);
    while ((argument = va_arg(ap, gchar *))) {
	soup_xmlrpc_message_start_param(msg);
	soup_xmlrpc_message_write_string(msg, argument);
	soup_xmlrpc_message_end_param(msg);

	DEBUG("with parameter: %s", argument);
    }
    va_end(ap);

    soup_xmlrpc_message_end_call(msg);
    soup_xmlrpc_message_persist(msg);

    soup_session_queue_message(session, SOUP_MESSAGE(msg), callback, sna);
    g_main_run(loop);

    return TRUE;
}
Example #13
0
static void
ews_autodiscover_response_cb (SoupSession *session,
                              SoupMessage *msg,
                              gpointer user_data)
{
	GSimpleAsyncResult *simple;
	AutodiscoverData *data;
	gboolean success = FALSE;
	guint status;
	gint idx;
	gsize size;
	xmlDoc *doc;
	xmlNode *node;
	GError *error = NULL;

	simple = G_SIMPLE_ASYNC_RESULT (user_data);
	data = g_simple_async_result_get_op_res_gpointer (simple);

	status = msg->status_code;
	if (status == SOUP_STATUS_CANCELLED)
		return;

	size = sizeof (data->msgs) / sizeof (data->msgs[0]);

	for (idx = 0; idx < size; idx++) {
		if (data->msgs[idx] == msg)
			break;
	}
	if (idx == size)
		return;

	data->msgs[idx] = NULL;

	if (status != SOUP_STATUS_OK) {
		g_set_error (
			&error, GOA_ERROR,
			GOA_ERROR_FAILED, /* TODO: more specific */
			_("Code: %u — Unexpected response from server"),
			status);
		goto out;
	}

	soup_buffer_free (
		soup_message_body_flatten (
		SOUP_MESSAGE (msg)->response_body));

	g_debug ("The response headers");
	g_debug ("===================");
	g_debug ("%s", SOUP_MESSAGE (msg)->response_body->data);

	doc = xmlReadMemory (
		msg->response_body->data,
		msg->response_body->length,
		"autodiscover.xml", NULL, 0);
	if (doc == NULL) {
		g_set_error (
			&error, GOA_ERROR,
			GOA_ERROR_FAILED, /* TODO: more specific */
			_("Failed to parse autodiscover response XML"));
		goto out;
	}

	node = xmlDocGetRootElement (doc);
	if (g_strcmp0 ((gchar *) node->name, "Autodiscover") != 0) {
		g_set_error (
			&error, GOA_ERROR,
			GOA_ERROR_FAILED, /* TODO: more specific */
			_("Failed to find Autodiscover element"));
		goto out;
	}

	for (node = node->children; node; node = node->next) {
		if (ews_check_node (node, "Response"))
			break;
	}
	if (node == NULL) {
		g_set_error (
			&error, GOA_ERROR,
			GOA_ERROR_FAILED, /* TODO: more specific */
			_("Failed to find Response element"));
		goto out;
	}

	for (node = node->children; node; node = node->next) {
		if (ews_check_node (node, "Account"))
			break;
	}
	if (node == NULL) {
		g_set_error (
			&error, GOA_ERROR,
			GOA_ERROR_FAILED, /* TODO: more specific */
			_("Failed to find Account element"));
		goto out;
	}

	for (node = node->children; node; node = node->next) {
		if (ews_check_node (node, "Protocol")) {
			success = ews_autodiscover_parse_protocol (node, data);
			break;
		}
	}
	if (!success) {
		g_set_error (
			&error, GOA_ERROR,
			GOA_ERROR_FAILED, /* TODO: more specific */
			_("Failed to find ASUrl and OABUrl in autodiscover response"));
			goto out;
	}

	for (idx = 0; idx < size; idx++) {
		if (data->msgs[idx] != NULL) {
			/* Since we are cancelling from the same thread
			 * that we queued the message, the callback (ie.
			 * this function) will be invoked before
			 * soup_session_cancel_message returns. */
			soup_session_cancel_message (
				data->session, data->msgs[idx],
				SOUP_STATUS_CANCELLED);
			data->msgs[idx] = NULL;
		}
	}

out:
	if (error != NULL) {
		for (idx = 0; idx < size; idx++) {
			if (data->msgs[idx] != NULL) {
				/* There's another request outstanding.
				 * Hope that it has better luck. */
				g_clear_error (&error);
				return;
			}
		}
		g_simple_async_result_take_error (simple, error);
	}

	g_simple_async_result_complete_in_idle (simple);
	g_object_unref (simple);
}
                                "text/xml; charset=utf-8",
                                SOUP_MEMORY_COPY,
#ifdef LIBXML2_NEW_BUFFER
                                (gchar *) xmlOutputBufferGetContent(buf),
                                xmlOutputBufferGetSize(buf));
#else
                                (gchar *) buf->buffer->content,
                                buf->buffer->use);
#endif
      g_signal_connect (msg, "restarted", G_CALLBACK (ews_client_post_restarted_cb), buf);
    }

  soup_buffer_free (soup_message_body_flatten (SOUP_MESSAGE (msg)->request_body));
  g_debug ("The request headers");
  g_debug ("===================");
  g_debug ("%s", SOUP_MESSAGE (msg)->request_body->data);

  return msg;
}

void
goa_ews_client_autodiscover (GoaEwsClient        *client,
                             const gchar         *email,
                             const gchar         *password,
                             const gchar         *username,
                             const gchar         *server,
                             gboolean             accept_ssl_errors,
                             GCancellable        *cancellable,
                             GAsyncReadyCallback  callback,
                             gpointer             user_data)
{
Example #15
0
// fetch contents of inventory folder
void fetch_system_folders(simgroup_ctx *sgrp, user_ctx *user,
			  void *user_priv) {
  uuid_t u; char tmp[40]; char uri[256];
  GRID_PRIV_DEF_SGRP(sgrp);
  USER_PRIV_DEF(user_priv);
  xmlTextWriterPtr writer;
  xmlBufferPtr buf;
  SoupMessage *msg;
  inv_items_req *req;
  
  assert(grid->inventory_server != NULL);

  buf = xmlBufferCreate();
  if(buf == NULL) goto fail;
  writer = xmlNewTextWriterMemory(buf, 0);
  if(writer == NULL) goto free_fail_1;
  
  if(xmlTextWriterStartDocument(writer,NULL,"UTF-8",NULL) < 0) 
    goto free_fail;
  if(xmlTextWriterStartElement(writer, BAD_CAST "RestSessionObjectOfGuid") < 0) 
    goto free_fail;
  user_get_session_id(user, u);
  uuid_unparse(u, tmp);
  if(xmlTextWriterWriteFormatElement(writer,BAD_CAST "SessionID",
				       "%s",tmp) < 0) goto free_fail;


  user_get_uuid(user, u);
  uuid_unparse(u, tmp);
  if(xmlTextWriterWriteFormatElement(writer,BAD_CAST "AvatarID",
				       "%s",tmp) < 0) goto free_fail;

  if(xmlTextWriterWriteFormatElement(writer,BAD_CAST "Body",
				       "%s",tmp) < 0) goto free_fail;
  if(xmlTextWriterEndElement(writer) < 0) 
    goto free_fail;

  if(xmlTextWriterEndDocument(writer) < 0) {
    printf("DEBUG: couldn't end XML document\n"); goto fail;
  }

  // FIXME - don't use fixed-length buffer, and handle missing trailing /
  snprintf(uri, 256, "%sSystemFolders/", grid->inventory_server);
  printf("DEBUG: sending inventory request to %s\n", uri);
  msg = soup_message_new ("POST", uri);
  // FIXME - avoid unnecessary strlen
  soup_message_set_request (msg, "application/xml",
			    SOUP_MEMORY_COPY, (char*)buf->content, 
			    strlen ((char*)buf->content));
  req = new inv_items_req();
  req->user_glue = user_glue; 
  user_grid_glue_ref(user_glue);
  caj_queue_soup_message(sgrp, SOUP_MESSAGE(msg),
			 got_system_folders_resp, req);
    
  xmlFreeTextWriter(writer);  
  xmlBufferFree(buf);
  return;

 free_fail:
  xmlFreeTextWriter(writer);  
 free_fail_1:
  xmlBufferFree(buf);
 fail:
  printf("DEBUG: ran into issues sending inventory request\n");
  // FIXME - handle this
}
Example #16
0
void add_inventory_item(simgroup_ctx *sgrp, user_ctx *user,
			void *user_priv, inventory_item *inv,
			void(*cb)(void* priv, int success, uuid_t item_id),
			void *cb_priv) {
  uuid_t u, user_id; char tmp[40]; char uri[256];
  GRID_PRIV_DEF_SGRP(sgrp);
  USER_PRIV_DEF(user_priv);
  xmlTextWriterPtr writer;
  xmlBufferPtr buf;
  SoupMessage *msg;
  add_inv_item_req *req;
  struct os_inv_item invitem;
  
  assert(grid->inventory_server != NULL);

  buf = xmlBufferCreate();
  if(buf == NULL) goto fail;
  writer = xmlNewTextWriterMemory(buf, 0);
  if(writer == NULL) goto free_fail_1;
  
  if(xmlTextWriterStartDocument(writer,NULL,"UTF-8",NULL) < 0) 
    goto free_fail;
  if(xmlTextWriterStartElement(writer, BAD_CAST "RestSessionObjectOfInventoryItemBase") < 0) 
    goto free_fail;
  user_get_session_id(user, u);
  uuid_unparse(u, tmp);
  if(xmlTextWriterWriteFormatElement(writer,BAD_CAST "SessionID",
				       "%s",tmp) < 0) goto free_fail;


  user_get_uuid(user, user_id);
  uuid_unparse(user_id, tmp);
  if(xmlTextWriterWriteFormatElement(writer,BAD_CAST "AvatarID",
				       "%s",tmp) < 0) goto free_fail;

  if(xmlTextWriterStartElement(writer,BAD_CAST "Body") < 0) 
    goto free_fail;

  inv_item_to_opensim(inv, invitem);
  osglue_serialise_xml(writer, deserialise_inv_item, &invitem);

  if(xmlTextWriterEndElement(writer) < 0) 
    goto free_fail;

  if(xmlTextWriterEndElement(writer) < 0) 
    goto free_fail;

  if(xmlTextWriterEndDocument(writer) < 0) {
    printf("DEBUG: couldn't end XML document\n"); goto fail;
  }

  // FIXME - don't use fixed-length buffer, and handle missing trailing /
  // (note: not AddNewItem, as that's not meant for sim use!)
  snprintf(uri, 256, "%sNewItem/", grid->inventory_server);
  printf("DEBUG: sending inventory add request to %s\n", uri);
  msg = soup_message_new ("POST", uri);
  // FIXME - avoid unnecessary strlen
  soup_message_set_request (msg, "text/xml",
			    SOUP_MEMORY_COPY, (char*)buf->content, 
			    strlen ((char*)buf->content));
  req = new add_inv_item_req();
  req->user_glue = user_glue; req->cb = cb;
  req->cb_priv = cb_priv;
  uuid_copy(req->item_id, inv->item_id);
  user_grid_glue_ref(user_glue);
  caj_queue_soup_message(sgrp, SOUP_MESSAGE(msg),
			 got_add_inv_item_resp, req);
    
  xmlFreeTextWriter(writer);  
  xmlBufferFree(buf);
  return;

 free_fail:
  xmlFreeTextWriter(writer);  
 free_fail_1:
  xmlBufferFree(buf);
 fail:
  printf("DEBUG: ran into issues sending inventory NewItem request\n");
  uuid_clear(u); cb(cb_priv, FALSE, u);
}
Example #17
0
void fetch_inventory_item(simgroup_ctx *sgrp, user_ctx *user,
			    void *user_priv, const uuid_t item_id,
			    void(*cb)(struct inventory_item* item, 
				      void* priv),
			    void *cb_priv) {
  uuid_t u, user_id; char tmp[40]; char uri[256];
  GRID_PRIV_DEF_SGRP(sgrp);
  USER_PRIV_DEF(user_priv);
  xmlTextWriterPtr writer;
  xmlBufferPtr buf;
  SoupMessage *msg;
  inv_item_req *req;
  struct os_inv_item invitem; // don't ask. Please.
  
  assert(grid->inventory_server != NULL);

  buf = xmlBufferCreate();
  if(buf == NULL) goto fail;
  writer = xmlNewTextWriterMemory(buf, 0);
  if(writer == NULL) goto free_fail_1;
  
  if(xmlTextWriterStartDocument(writer,NULL,"UTF-8",NULL) < 0) 
    goto free_fail;
  if(xmlTextWriterStartElement(writer, BAD_CAST "RestSessionObjectOfInventoryItemBase") < 0) 
    goto free_fail;
  user_get_session_id(user, u);
  uuid_unparse(u, tmp);
  if(xmlTextWriterWriteFormatElement(writer,BAD_CAST "SessionID",
				       "%s",tmp) < 0) goto free_fail;


  user_get_uuid(user, user_id);
  uuid_unparse(user_id, tmp);
  if(xmlTextWriterWriteFormatElement(writer,BAD_CAST "AvatarID",
				       "%s",tmp) < 0) goto free_fail;

  // okay, this is just painful... we have to serialise an entire complex
  // object in this cruddy .Net XML serialisation format... and the only bit
  // they actually use or need is a single UUID. Bletch  *vomit*.
  if(xmlTextWriterStartElement(writer,BAD_CAST "Body") < 0) 
    goto free_fail;
  memset(&invitem, 0, sizeof(invitem));
  invitem.name = invitem.description = const_cast<char*>("");
  invitem.creator_id = const_cast<char*>("");
  uuid_copy(invitem.owner_id, user_id);
  uuid_copy(invitem.item_id, item_id);

  osglue_serialise_xml(writer, deserialise_inv_item, &invitem);

  if(xmlTextWriterEndElement(writer) < 0) 
    goto free_fail;

  // now we should be done serialising the XML crud.

  if(xmlTextWriterEndElement(writer) < 0) 
    goto free_fail;

  if(xmlTextWriterEndDocument(writer) < 0) {
    printf("DEBUG: couldn't end XML document\n"); goto fail;
  }

  // FIXME - don't use fixed-length buffer, and handle missing trailing /
  snprintf(uri, 256, "%sQueryItem/", grid->inventory_server);
  printf("DEBUG: sending inventory request to %s\n", uri);
  msg = soup_message_new ("POST", uri);
  // FIXME - avoid unnecessary strlen
  soup_message_set_request (msg, "text/xml",
			    SOUP_MEMORY_COPY, (char*)buf->content, 
			    strlen ((char*)buf->content));
  req = new inv_item_req();
  req->user_glue = user_glue; req->cb = cb;
  req->cb_priv = cb_priv;
  uuid_copy(req->item_id, item_id);
  user_grid_glue_ref(user_glue);
  caj_queue_soup_message(sgrp, SOUP_MESSAGE(msg),
			 got_inventory_item_resp, req);
    
  xmlFreeTextWriter(writer);  
  xmlBufferFree(buf);
  return;

 free_fail:
  xmlFreeTextWriter(writer);  
 free_fail_1:
  xmlBufferFree(buf);
 fail:
  printf("DEBUG: ran into issues sending inventory QueryItem request\n");
  cb(NULL, cb_priv);
  // FIXME - handle this
  
}
static void
ews_client_autodiscover_response_cb (SoupSession *session, SoupMessage *msg, gpointer user_data)
{
  GError *error;
  AutodiscoverData *data = user_data;
  gboolean op_res;
  guint status;
  gint idx;
  gsize size;
  xmlDoc *doc;
  xmlNode *node;

  error = NULL;
  op_res = FALSE;
  size = sizeof (data->msgs) / sizeof (data->msgs[0]);

  for (idx = 0; idx < size; idx++)
    {
      if (data->msgs[idx] == msg)
        break;
    }
  if (idx == size || data->pending == 0)
    return;

  data->msgs[idx] = NULL;
  status = msg->status_code;

  /* status == SOUP_STATUS_CANCELLED, if we are being aborted by the
   * GCancellable, an SSL error or another message that was
   * successful.
   */
  if (status == SOUP_STATUS_CANCELLED)
    goto out;
  else if (status != SOUP_STATUS_OK)
    {
      g_set_error (&error,
                   GOA_ERROR,
                   GOA_ERROR_FAILED, /* TODO: more specific */
                   _("Code: %u — Unexpected response from server"),
                   status);
      goto out;
    }

  soup_buffer_free (soup_message_body_flatten (SOUP_MESSAGE (msg)->response_body));
  g_debug ("The response headers");
  g_debug ("===================");
  g_debug ("%s", SOUP_MESSAGE (msg)->response_body->data);

  doc = xmlReadMemory (msg->response_body->data, msg->response_body->length, "autodiscover.xml", NULL, 0);
  if (doc == NULL)
    {
      g_set_error (&error,
                   GOA_ERROR,
                   GOA_ERROR_FAILED, /* TODO: more specific */
                   _("Failed to parse autodiscover response XML"));
      goto out;
    }

  node = xmlDocGetRootElement (doc);
  if (g_strcmp0 ((gchar *) node->name, "Autodiscover"))
    {
      g_set_error (&error,
                   GOA_ERROR,
                   GOA_ERROR_FAILED, /* TODO: more specific */
                   /* Translators: the parameter is an XML element name. */
                   _("Failed to find ‘%s’ element"), "Autodiscover");
      goto out;
    }

  for (node = node->children; node; node = node->next)
    {
      if (ews_client_check_node (node, "Response"))
        break;
    }
  if (node == NULL)
    {
      g_set_error (&error,
                   GOA_ERROR,
                   GOA_ERROR_FAILED, /* TODO: more specific */
                   /* Translators: the parameter is an XML element name. */
                   _("Failed to find ‘%s’ element"), "Response");
      goto out;
    }

  for (node = node->children; node; node = node->next)
    {
      if (ews_client_check_node (node, "Account"))
        break;
    }
  if (node == NULL)
    {
      g_set_error (&error,
                   GOA_ERROR,
                   GOA_ERROR_FAILED, /* TODO: more specific */
                   /* Translators: the parameter is an XML element name. */
                   _("Failed to find ‘%s’ element"), "Account");
      goto out;
    }

  for (node = node->children; node; node = node->next)
    {
      if (ews_client_check_node (node, "Protocol"))
        {
          op_res = ews_client_autodiscover_parse_protocol (node);
          /* Since the server may send back multiple <Protocol> nodes
           * don't break unless we found the one we want.
           */
          if (op_res)
            break;
        }
    }
  if (!op_res)
    {
      g_set_error (&error,
                   GOA_ERROR,
                   GOA_ERROR_FAILED, /* TODO: more specific*/
                   _("Failed to find ASUrl and OABUrl in autodiscover response"));
      goto out;
    }

  for (idx = 0; idx < size; idx++)
    {
      if (data->msgs[idx] != NULL)
        {
          /* The callback (ie. this function) will be invoked after we
           * have returned to the main loop.
           */
          soup_session_cancel_message (data->session, data->msgs[idx], SOUP_STATUS_CANCELLED);
        }
    }

 out:
  /* error == NULL, if we are being aborted by the GCancellable, an
   * SSL error or another message that was successful.
   */
  if (!op_res)
    {
      /* There's another request outstanding.
       * Hope that it has better luck.
       */
      if (data->pending > 1)
        g_clear_error (&error);

      if (error != NULL)
        g_simple_async_result_take_error (data->res, error);
    }

  data->pending--;
  if (data->pending == 0)
    {
      GMainContext *context;
      GSource *source;

      g_simple_async_result_set_op_res_gboolean (data->res, op_res);

      source = g_idle_source_new ();
      g_source_set_priority (source, G_PRIORITY_DEFAULT_IDLE);
      g_source_set_callback (source, ews_client_autodiscover_data_free, data, NULL);
      g_source_set_name (source, "[goa] ews_client_autodiscover_data_free");

      context = g_main_context_get_thread_default ();
      g_source_attach (source, context);
      g_source_unref (source);
    }
}