Ejemplo n.º 1
0
bool XMLWrapper::nodeDump(xmlNodePtr node, std::string &content, bool trim)
{
	content.clear();

	if (!mDocument) {
		return false;
	}

	if (!node) {
		return false;
	}

	bool result = false;

	xmlBufferPtr buffer = xmlBufferCreate();
	if (buffer) {
		xmlOutputBufferPtr outputBuffer = xmlOutputBufferCreateBuffer(buffer, NULL);
		if (outputBuffer) {
			xmlNodeDumpOutput(outputBuffer, mDocument, node, 0, 0, "UTF8");
			xmlOutputBufferClose(outputBuffer);
			outputBuffer = NULL;

			result = convertToString(buffer->content, content);

			if (result && trim) {
				trimString(content);
			}
		}
		xmlBufferFree(buffer);
		buffer = NULL;
	}

	return result;
}
Ejemplo n.º 2
0
string Node::XMLString() const
{
    std::ostringstream stream;
    StreamOutputBuffer buf(stream);
    xmlNodeDumpOutput(buf, _xml->doc, _xml, 0, 0, nullptr);
    return xmlString(stream.str().c_str());
}
Ejemplo n.º 3
0
/**
 * xmlnode_to_pv:
 * @node: an xmlNode* object
 * @do_free: do we need to free the node after the conversion
 *
 * Return value: a newly allocated SV/PV or under.
 */
static SV*
xmlnode_to_pv(xmlNode *node, gboolean do_free)
{
	xmlOutputBufferPtr buf;
	SV *pestring = NULL;

	if (node == NULL) {
		return &PL_sv_undef;
	}

	buf = xmlAllocOutputBuffer(NULL);
	if (buf == NULL) {
		pestring = &PL_sv_undef;
	} else {
		xmlNodeDumpOutput(buf, NULL, node, 0, 1, NULL);
		xmlOutputBufferFlush(buf);
		if (buf->conv == NULL) {
			pestring = newSVpv((char*)buf->buffer->content, 0);
		} else {
			pestring = newSVpv((char*)buf->conv->content, 0);
		}
		xmlOutputBufferClose(buf);
	}
	if (do_free) {
		lasso_release_xml_node(node);
	}

	return pestring;
}
Ejemplo n.º 4
0
  void XMLNode::GetXML(std::string& out_xml_str, bool user_friendly) const {
    out_xml_str.resize(0);
    if (!node_) return;
    if (node_->type != XML_ELEMENT_NODE) return;
    xmlDocPtr doc = node_->doc;
    if (doc == NULL) return;
    // Printing non-root node omits namespaces defined at higher level.
    // So we need to create temporary namespace definitions and place them 
    // at node being printed
    std::map<xmlNsPtr,xmlNsPtr> extns;
    CollectExternalNamespaces(node_, extns);
    // It is easier to insert namespaces into final text. Hence 
    // allocating place for them.
    std::string ns_str;
    NamespacesToString(extns, ns_str);
    out_xml_str.append(ns_str.length(),' ');
/*
    xmlBufferPtr buf = xmlBufferCreate();
    xmlNodeDump(buf, doc, node_, 0, user_friendly ? 1 : 0);
    out_xml_str = (char*)(buf->content);
    xmlBufferFree(buf);
*/
    xmlOutputBufferPtr buf =
     xmlOutputBufferCreateIO(&write_to_string,&close_string,&out_xml_str,NULL);
    if(buf == NULL) return;
    xmlNodeDumpOutput(buf, doc, node_, 0, user_friendly ? 1 : 0, (const char*)(doc->encoding));
    xmlOutputBufferClose(buf);
    // Insert external namespaces into final string using allocated space
    InsertExternalNamespaces(out_xml_str, ns_str);
  }
Ejemplo n.º 5
0
extern "C" void DumpXMLString(xmlNodePtr node)
{
    xmlOutputBufferPtr buf = xmlOutputBufferCreateFile(stdout, nullptr);
    xmlNodeDumpOutput(buf, node->doc, node, 0, 0, nullptr);
    xmlOutputBufferClose(buf);
    fprintf(stdout, "\n\n");
}
Ejemplo n.º 6
0
string Node::XMLString() const
{
    std::ostringstream stream;
    
    StreamOutputBuffer buf(stream);
    xmlNodeDumpOutput(buf.xmlBuffer(), _xml->doc, _xml, 0, 1, "UTF-8");
    buf.flush();
    
    return xmlString(stream.str().c_str());
}
Ejemplo n.º 7
0
static VALUE rxml_node_to_s(int argc, VALUE *argv, VALUE self)
{
  VALUE result = Qnil;
  VALUE options = Qnil;
  xmlNodePtr xnode;
  xmlCharEncodingHandlerPtr encodingHandler;
  xmlOutputBufferPtr output;

  int level = 0;
  int indent = 1;
  const char *xencoding = "UTF-8";

  rb_scan_args(argc, argv, "01", &options);

  if (!NIL_P(options))
  {
    VALUE rencoding, rindent, rlevel;
    Check_Type(options, T_HASH);
    rencoding = rb_hash_aref(options, ID2SYM(rb_intern("encoding")));
    rindent = rb_hash_aref(options, ID2SYM(rb_intern("indent")));
    rlevel = rb_hash_aref(options, ID2SYM(rb_intern("level")));

    if (rindent == Qfalse)
      indent = 0;

    if (rlevel != Qnil)
      level = NUM2INT(rlevel);

    if (rencoding != Qnil)
    {
      xencoding = xmlGetCharEncodingName((xmlCharEncoding)NUM2INT(rencoding));
      if (!xencoding)
        rb_raise(rb_eArgError, "Unknown encoding value: %d", NUM2INT(rencoding));
    }
  }

  encodingHandler = xmlFindCharEncodingHandler(xencoding);
  output = xmlAllocOutputBuffer(encodingHandler);

  xnode = rxml_get_xnode(self);

  xmlNodeDumpOutput(output, xnode->doc, xnode, level, indent, xencoding);
  xmlOutputBufferFlush(output);

  if (output->conv)
    result = rxml_new_cstr((const char*) output->conv->content, xencoding);
  else
    result = rxml_new_cstr((const char*) output->buffer->content, xencoding);

  xmlOutputBufferClose(output);
  
  return result;
}
string BEXMLTextReader::raw_xml()
{
	xmlBufferPtr node_content = xmlBufferCreate();
	xmlOutputBufferPtr node = (xmlOutputBufferPtr) xmlMalloc ( sizeof(xmlOutputBuffer) );
	memset ( node, 0, (size_t) sizeof(xmlOutputBuffer) );
	node->buffer = node_content;
	
	xmlNodeDumpOutput ( node, xml_document, xmlTextReaderCurrentNode ( reader ), 0, true, "UTF-8" );
	const xmlChar * xml_data = xmlBufferContent ( (xmlBufferPtr)node_content );
	size_t xml_length = xmlBufferLength ( node_content );
	string xml_result ( (char *)xml_data, xml_length );
	
	xmlFree ( (xmlChar *)xml_data );
	
	return xml_result;
} // raw_xml
Ejemplo n.º 9
0
/* {{{ internalSubset	string
readonly=yes
URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-Core-DocType-internalSubset
Since: DOM Level 2
*/
int dom_documenttype_internal_subset_read(dom_object *obj, zval *retval)
{
	xmlDtdPtr dtdptr = (xmlDtdPtr) dom_object_get_node(obj);
	xmlDtdPtr intsubset;

	if (dtdptr == NULL) {
		php_dom_throw_error(INVALID_STATE_ERR, 0);
		return FAILURE;
	}

	if (dtdptr->doc != NULL && ((intsubset = xmlGetIntSubset(dtdptr->doc)) != NULL)) {
		smart_str ret_buf = {0};
		xmlNodePtr cur = intsubset->children;

		while (cur != NULL) {
			xmlOutputBuffer *buff = xmlAllocOutputBuffer(NULL);

			if (buff != NULL) {
				xmlNodeDumpOutput (buff, NULL, cur, 0, 0, NULL);
				xmlOutputBufferFlush(buff);

#ifdef LIBXML2_NEW_BUFFER
				smart_str_appendl(&ret_buf, (const char *) xmlOutputBufferGetContent(buff), xmlOutputBufferGetSize(buff));
#else
				smart_str_appendl(&ret_buf, (char *) buff->buffer->content, buff->buffer->use);
#endif

				(void)xmlOutputBufferClose(buff);
			}

			cur = cur->next;
		}

		if (ret_buf.s) {
			smart_str_0(&ret_buf);
			ZVAL_NEW_STR(retval, ret_buf.s);
			return SUCCESS;
		}
	}

	ZVAL_NULL(retval);

	return SUCCESS;

}
Ejemplo n.º 10
0
static VALUE rxml_node_to_s(int argc, VALUE *argv, VALUE self)
{
  VALUE options = Qnil;
  xmlNodePtr xnode;
  xmlCharEncodingHandlerPtr encodingHandler;
  xmlOutputBufferPtr output;

  int level = 0;
  int indent = 1;
  const char *encoding = "UTF-8";

  rb_scan_args(argc, argv, "01", &options);

  if (!NIL_P(options))
  {
    VALUE rencoding, rindent, rlevel;
    Check_Type(options, T_HASH);
    rencoding = rb_hash_aref(options, ID2SYM(rb_intern("encoding")));
    rindent = rb_hash_aref(options, ID2SYM(rb_intern("indent")));
    rlevel = rb_hash_aref(options, ID2SYM(rb_intern("level")));

    if (rindent == Qfalse)
      indent = 0;

    if (rlevel != Qnil)
      level = NUM2INT(rlevel);

    if (rencoding != Qnil)
      encoding = RSTRING_PTR(rxml_input_encoding_to_s(cXMLInput, rencoding));
  }

  encodingHandler = xmlFindCharEncodingHandler(encoding);
  output = xmlAllocOutputBuffer(encodingHandler);

  Data_Get_Struct(self, xmlNode, xnode);
  xmlNodeDumpOutput(output, xnode->doc, xnode, level, indent, encoding);
  xmlOutputBufferFlush(output);

  if (output->conv)
    return rb_str_new2((const char*) output->conv->content);
  else
    return rb_str_new2((const char*) output->buffer->content);
}
Ejemplo n.º 11
0
 void XMLNode::GetXML(std::string& out_xml_str, const std::string& encoding, bool user_friendly) const {
   out_xml_str.resize(0);
   if (!node_) return;
   if (node_->type != XML_ELEMENT_NODE) return;
   xmlDocPtr doc = node_->doc;
   if (doc == NULL) return;
   xmlCharEncodingHandlerPtr handler = NULL;
   handler = xmlFindCharEncodingHandler(encoding.c_str());
   if (handler == NULL) return;
   std::map<xmlNsPtr,xmlNsPtr> extns;
   CollectExternalNamespaces(node_, extns);
   std::string ns_str;
   NamespacesToString(extns, ns_str);
   out_xml_str.append(ns_str.length(),' ');
   //xmlOutputBufferPtr buf = xmlAllocOutputBuffer(handler);
   xmlOutputBufferPtr buf =
    xmlOutputBufferCreateIO(&write_to_string,&close_string,&out_xml_str,NULL);
   if(buf == NULL) return;
   xmlNodeDumpOutput(buf, doc, node_, 0, user_friendly ? 1 : 0, encoding.c_str());
   xmlOutputBufferFlush(buf);
   //out_xml_str = (char*)(buf->conv ? buf->conv->content : buf->buffer->content);
   xmlOutputBufferClose(buf);
   InsertExternalNamespaces(out_xml_str, ns_str);
 }
Ejemplo n.º 12
0
/**
 * xmlSecEncCtxXmlEncrypt:
 * @encCtx:             the pointer to <enc:EncryptedData/> processing context.
 * @tmpl:               the pointer to <enc:EncryptedData/> template node.
 * @node:               the pointer to node for encryption.
 *
 * Encrypts @node according to template @tmpl. If requested, @node is replaced
 * with result <enc:EncryptedData/> node.
 *
 * Returns: 0 on success or a negative value if an error occurs.
 */
int
xmlSecEncCtxXmlEncrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr tmpl, xmlNodePtr node) {
    xmlOutputBufferPtr output;
    int ret;

    xmlSecAssert2(encCtx != NULL, -1);
    xmlSecAssert2(encCtx->result == NULL, -1);
    xmlSecAssert2(tmpl != NULL, -1);
    xmlSecAssert2(node != NULL, -1);
    xmlSecAssert2(node->doc != NULL, -1);

    /* initialize context and add ID atributes to the list of known ids */
    encCtx->operation = xmlSecTransformOperationEncrypt;
    xmlSecAddIDs(tmpl->doc, tmpl, xmlSecEncIds);

    /* read the template and set encryption method, key, etc. */
    ret = xmlSecEncCtxEncDataNodeRead(encCtx, tmpl);
    if(ret < 0) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    NULL,
                    "xmlSecEncCtxEncDataNodeRead",
                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
                    XMLSEC_ERRORS_NO_MESSAGE);
        return(-1);
    }

    ret = xmlSecTransformCtxPrepare(&(encCtx->transformCtx), xmlSecTransformDataTypeBin);
    if(ret < 0) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    NULL,
                    "xmlSecTransformCtxPrepare",
                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
                    "type=bin");
        return(-1);
    }

    xmlSecAssert2(encCtx->transformCtx.first != NULL, -1);
    output = xmlSecTransformCreateOutputBuffer(encCtx->transformCtx.first,
             &(encCtx->transformCtx));
    if(output == NULL) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    xmlSecErrorsSafeString(xmlSecTransformGetName(encCtx->transformCtx.first)),
                    "xmlSecTransformCreateOutputBuffer",
                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
                    XMLSEC_ERRORS_NO_MESSAGE);
        return(-1);
    }

    /* push data thru */
    if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
        /* get the content of the node */
        xmlNodeDumpOutput(output, node->doc, node, 0, 0, NULL);
    } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
        xmlNodePtr cur;

        /* get the content of the nodes childs */
        for(cur = node->children; cur != NULL; cur = cur->next) {
            xmlNodeDumpOutput(output, node->doc, cur, 0, 0, NULL);
        }
    } else {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    NULL,
                    NULL,
                    XMLSEC_ERRORS_R_INVALID_TYPE,
                    "type=%s",
                    xmlSecErrorsSafeString(encCtx->type));
        xmlOutputBufferClose(output);
        return(-1);
    }

    /* close the buffer and flush everything */
    ret = xmlOutputBufferClose(output);
    if(ret < 0) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    NULL,
                    "xmlOutputBufferClose",
                    XMLSEC_ERRORS_R_XML_FAILED,
                    XMLSEC_ERRORS_NO_MESSAGE);
        return(-1);
    }

    encCtx->result = encCtx->transformCtx.result;
    xmlSecAssert2(encCtx->result != NULL, -1);

    ret = xmlSecEncCtxEncDataNodeWrite(encCtx);
    if(ret < 0) {
        xmlSecError(XMLSEC_ERRORS_HERE,
                    NULL,
                    "xmlSecEncCtxEncDataNodeWrite",
                    XMLSEC_ERRORS_R_XMLSEC_FAILED,
                    XMLSEC_ERRORS_NO_MESSAGE);
        return(-1);
    }

    /* now we need to update our original document */
    if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
        /* check if we need to return the replaced node */
        if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
            ret = xmlSecReplaceNodeAndReturn(node, tmpl, &(encCtx->replacedNodeList));
            if(ret < 0) {
                xmlSecError(XMLSEC_ERRORS_HERE,
                            NULL,
                            "xmlSecReplaceNode",
                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
                            "node=%s",
                            xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
                return(-1);
            }
        } else {
            ret = xmlSecReplaceNode(node, tmpl);
            if(ret < 0) {
                xmlSecError(XMLSEC_ERRORS_HERE,
                            NULL,
                            "xmlSecReplaceNode",
                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
                            "node=%s",
                            xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
                return(-1);
            }
        }

        encCtx->resultReplaced = 1;
    } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
        /* check if we need to return the replaced node */
        if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
            ret = xmlSecReplaceContentAndReturn(node, tmpl, &(encCtx->replacedNodeList));
            if(ret < 0) {
                xmlSecError(XMLSEC_ERRORS_HERE,
                            NULL,
                            "xmlSecReplaceContentAndReturn",
                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
                            "node=%s",
                            xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
                return(-1);
            }
        } else {
            ret = xmlSecReplaceContent(node, tmpl);
            if(ret < 0) {
                xmlSecError(XMLSEC_ERRORS_HERE,
                            NULL,
                            "xmlSecReplaceContent",
                            XMLSEC_ERRORS_R_XMLSEC_FAILED,
                            "node=%s",
                            xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
                return(-1);
            }
        }

        encCtx->resultReplaced = 1;
    } else {
        /* we should've catached this error before */
        xmlSecError(XMLSEC_ERRORS_HERE,
                    NULL,
                    NULL,
                    XMLSEC_ERRORS_R_INVALID_TYPE,
                    "type=%s",
                    xmlSecErrorsSafeString(encCtx->type));
        return(-1);
    }
    return(0);
}
Ejemplo n.º 13
0
extern "C" void DebugPrintNodeConst(std::shared_ptr<const ePub3::xml::Node> aNode)
{
    auto output = xmlOutputBufferCreateFile(stderr, nullptr);
    xmlNodeDumpOutput(output, aNode->Document()->xml(), aNode->xml(), 0, 1, "UTF-8");
    xmlOutputBufferClose(output);
}
Ejemplo n.º 14
0
/**
 * gdata_entry_new_from_xmlptr:
 * @doc: A xml document pointer
 * @ptr: A xml Node pointer
 **/
GDataEntry *
gdata_entry_new_from_xmlptr (xmlDocPtr doc, xmlNodePtr cur)
{
	GDataEntry *entry;
	GDataEntryPrivate *priv;
	xmlChar *value = NULL;
	xmlOutputBufferPtr buf;
	gchar *xmlString;

	g_return_val_if_fail(doc != NULL, NULL);
	g_return_val_if_fail(cur != NULL, NULL);

	if (xmlStrcmp(cur->name, (xmlChar *)"entry")) {
		return NULL;
	}

	entry = gdata_entry_new ();
	priv  = GDATA_ENTRY_GET_PRIVATE(entry);
	buf = xmlAllocOutputBuffer (NULL);

	if (buf == NULL) {
		xmlString = NULL;
	}
	else {
		xmlNodeDumpOutput (buf, NULL, cur, 0, 1, NULL);
		xmlOutputBufferFlush (buf);

		if (buf->conv == NULL)
			xmlString = g_strdup ((gchar *)buf->buffer->content);
		else
			xmlString = g_strdup ((gchar *)buf->conv->content);
		xmlOutputBufferClose (buf);
	}

	priv->entry_xml = g_strdup (xmlString);
	cur = cur->xmlChildrenNode;
	while (cur != NULL) {

		if (!xmlStrcmp(cur->name, (xmlChar *)"author")) {
			priv->authors = g_slist_prepend(priv->authors, xmlnode_to_author(doc, cur));
		}
		else if (!xmlStrcmp(cur->name, (xmlChar *)"link")) {
			priv->links = g_slist_prepend(priv->links, xmlnode_to_link(doc, cur));
		}
		else if (!xmlStrcmp(cur->name, (xmlChar *)"category")) {
			priv->categories = g_slist_prepend(priv->categories, xmlnode_to_category(doc, cur));
		}
		else if (!xmlStrcmp (cur->name, (xmlChar *)"where")) {
			priv->location = (gchar *)xmlGetProp (cur, (xmlChar *)"valueString");
		}
		else if (!xmlStrcmp (cur->name, (xmlChar *)"eventStatus")) {
			priv->status = (gchar *)xmlGetProp (cur, (xmlChar *)"value");
		}
		else if (!xmlStrcmp (cur->name, (xmlChar *)"visibility")) {
			priv->visibility = (gchar *)xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);
		}
		else if (!xmlStrcmp (cur->name, (xmlChar *)"when")) {
			priv->start_time = (gchar *)xmlGetProp (cur, (xmlChar *)"startTime");
			priv->end_time = (gchar *)xmlGetProp (cur, (xmlChar *)"endTime");
		}
		else if (!xmlStrcmp (cur->name, (xmlChar *)"recurrence")) {
			priv->is_recurrent = TRUE;
		}

		else if (!xmlStrcmp (cur->name, (xmlChar *)"who")) {
			priv->attendees = g_slist_prepend (priv->attendees, xmlnode_to_attendee (doc, cur));
			priv->has_attendees = TRUE;
		}
		else if (!xmlStrcmp (cur->name, (xmlChar *)"sendEventNotifications")) {
			priv->send_notification =(gchar *)xmlGetProp (cur, (xmlChar *)"value");
		}
		else if (!xmlStrcmp (cur->name, (xmlChar *)"comments")) {
			/*FIXME Call _comment_to_xml_node */
		}
		else if (!xmlStrcmp(cur->name, (xmlChar *)"email")) {
			priv->email_addresses = g_slist_prepend(priv->email_addresses, xmlnode_to_email_address(doc, cur));
		}
		else if (!xmlStrcmp(cur->name, (xmlChar *)"im")) {
			priv->im_addresses = g_slist_prepend(priv->im_addresses, xmlnode_to_im_address(doc, cur));
		}
		else if (!xmlStrcmp(cur->name, (xmlChar *)"organization")) {
			priv->organizations = g_slist_prepend(priv->organizations, xmlnode_to_organization(doc, cur));
		}
		else if (!xmlStrcmp(cur->name, (xmlChar *)"phoneNumber")) {
			priv->phone_numbers = g_slist_prepend(priv->phone_numbers, xmlnode_to_phone_number(doc, cur));
		}
		else if (!xmlStrcmp(cur->name, (xmlChar *)"postalAddress")) {
			priv->postal_addresses = g_slist_prepend(priv->postal_addresses, xmlnode_to_postal_address(doc, cur));
		}
		else if (!xmlStrcmp (cur->name, (xmlChar *)"deleted")) {
			priv->is_deleted = TRUE;
		}

		else {
			value = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
			g_hash_table_insert(priv->field_table, g_strdup((gchar *)cur->name),
					g_strdup((gchar *)value));
			xmlFree(value);
		}
		cur = cur->next;
	}

	return entry;
}
Ejemplo n.º 15
0
void
goa_ews_autodiscover (GoaObject *goa_object,
                      GCancellable *cancellable,
                      GAsyncReadyCallback callback,
                      gpointer user_data)
{
	GoaAccount *goa_account;
	GoaExchange *goa_exchange;
	GoaPasswordBased *goa_password;
	GSimpleAsyncResult *simple;
	AutodiscoverData *data;
	AutodiscoverAuthData *auth;
	gchar *url1;
	gchar *url2;
	xmlDoc *doc;
	xmlOutputBuffer *buf;
	gchar *email;
	gchar *host;
	gchar *password = NULL;
	GError *error = NULL;

	g_return_if_fail (GOA_IS_OBJECT (goa_object));

	goa_account = goa_object_get_account (goa_object);
	goa_exchange = goa_object_get_exchange (goa_object);
	goa_password = goa_object_get_password_based (goa_object);

	email = goa_account_dup_presentation_identity (goa_account);
	host = goa_exchange_dup_host (goa_exchange);

	doc = ews_create_autodiscover_xml (email);
	buf = xmlAllocOutputBuffer (NULL);
	xmlNodeDumpOutput (buf, doc, xmlDocGetRootElement (doc), 0, 1, NULL);
	xmlOutputBufferFlush (buf);

	url1 = g_strdup_printf (
		"https://%s/autodiscover/autodiscover.xml", host);
	url2 = g_strdup_printf (
		"https://autodiscover.%s/autodiscover/autodiscover.xml", host);

	g_free (host);
	g_free (email);

	/* http://msdn.microsoft.com/en-us/library/ee332364.aspx says we are
	* supposed to try $domain and then autodiscover.$domain. But some
	* people have broken firewalls on the former which drop packets
	* instead of rejecting connections, and make the request take ages
	* to time out. So run both queries in parallel and let the fastest
	* (successful) one win. */
	data = g_slice_new0 (AutodiscoverData);
	data->buf = buf;
	data->msgs[0] = ews_create_msg_for_url (url1, buf);
	data->msgs[1] = ews_create_msg_for_url (url2, buf);
	data->session = soup_session_async_new_with_options (
		SOUP_SESSION_USE_NTLM, TRUE,
		SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
		SOUP_SESSION_TIMEOUT, 90,
		SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE,
		NULL);
	if (G_IS_CANCELLABLE (cancellable)) {
		data->cancellable = g_object_ref (cancellable);
		data->cancellable_id = g_cancellable_connect (
			data->cancellable,
			G_CALLBACK (ews_autodiscover_cancelled_cb),
			data, NULL);
	}

	simple = g_simple_async_result_new (
		G_OBJECT (goa_object), callback,
		user_data, goa_ews_autodiscover);

	g_simple_async_result_set_check_cancellable (simple, cancellable);

	g_simple_async_result_set_op_res_gpointer (
		simple, data, (GDestroyNotify) ews_autodiscover_data_free);

	goa_password_based_call_get_password_sync (
		goa_password, "", &password, cancellable, &error);

	/* Sanity check */
	g_return_if_fail (
		((password != NULL) && (error == NULL)) ||
		((password == NULL) && (error != NULL)));

	if (error == NULL) {
		gchar *username;

		username = goa_account_dup_identity (goa_account);

		auth = g_slice_new0 (AutodiscoverAuthData);
		auth->username = username;  /* takes ownership */
		auth->password = password;  /* takes ownership */

		g_signal_connect_data (
			data->session, "authenticate",
			G_CALLBACK (ews_authenticate), auth,
			ews_autodiscover_auth_data_free, 0);

		soup_session_queue_message (
			data->session, data->msgs[0],
			ews_autodiscover_response_cb, simple);
		soup_session_queue_message (
			data->session, data->msgs[1],
			ews_autodiscover_response_cb, simple);
	} else {
		g_dbus_error_strip_remote_error (error);
		g_simple_async_result_take_error (simple, error);
		g_simple_async_result_complete_in_idle (simple);
		g_object_unref (simple);
	}

	g_free (url2);
	g_free (url1);
	xmlFreeDoc (doc);

	g_object_unref (goa_account);
	g_object_unref (goa_exchange);
	g_object_unref (goa_password);
}