<commit_before>/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 */

#include <libedataserver/eds-version.h>

#include <string.h>
#include <libsoup/soup.h>
#include "e-soap-message.h"

G_DEFINE_TYPE (ESoapMessage, e_soap_message, SOUP_TYPE_MESSAGE)

typedef struct {
	/* Serialization fields */
	xmlParserCtxtPtr ctxt;
	xmlDocPtr doc;
	xmlNodePtr last_node;
	xmlNsPtr soap_ns;
	xmlNsPtr xsi_ns;
	xmlChar *env_prefix;
	xmlChar *env_uri;
	gboolean body_started;
	gchar *action;

	/* Content stealing */
	gchar *steal_node;
	gchar *steal_dir;
	gboolean steal_base64;

	gint steal_b64_state;
	guint steal_b64_save;
	int steal_fd;

	/* Progress callbacks */
	gsize response_size;
	gsize response_received;
	ESoapProgressFn progress_fn;
	gpointer progress_data;

} ESoapMessagePrivate;
#define E_SOAP_MESSAGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_SOAP_MESSAGE, ESoapMessagePrivate))

static void
finalize (GObject *object)
{
	ESoapMessagePrivate *priv = E_SOAP_MESSAGE_GET_PRIVATE (object);

	if (priv->ctxt) {
		if (priv->ctxt->myDoc)
			xmlFreeDoc (priv->ctxt->myDoc);
		xmlFreeParserCtxt (priv->ctxt);
	}
	if (priv->doc)
		xmlFreeDoc (priv->doc);
	if (priv->action)
		g_free (priv->action);
	if (priv->env_uri)
                xmlFree (priv->env_uri);
	if (priv->env_prefix)
                xmlFree (priv->env_prefix);

	g_free (priv->steal_node);
	g_free (priv->steal_dir);
	if (priv->steal_fd != -1)
		close (priv->steal_fd);
	G_OBJECT_CLASS (e_soap_message_parent_class)->finalize (object);
}

static void
e_soap_message_class_init (ESoapMessageClass *e_soap_message_class)
{
	GObjectClass *object_class = G_OBJECT_CLASS (e_soap_message_class);

	g_type_class_add_private (e_soap_message_class, sizeof (ESoapMessagePrivate));

	object_class->finalize = finalize;
}

static void
e_soap_message_init (ESoapMessage *msg)
{
	ESoapMessagePrivate *priv = E_SOAP_MESSAGE_GET_PRIVATE (msg);

	/* initialize XML structures */
	priv->doc = xmlNewDoc ((const xmlChar *)"1.0");
	priv->doc->standalone = FALSE;
	priv->doc->encoding = xmlCharStrdup ("UTF-8");
	priv->steal_fd = -1;
}

static xmlNsPtr
fetch_ns (ESoapMessage *msg, const gchar *prefix, const gchar *ns_uri)
{
	ESoapMessagePrivate *priv = E_SOAP_MESSAGE_GET_PRIVATE (msg);
        xmlNsPtr ns = NULL;

        if (prefix && ns_uri)
                ns = xmlNewNs (priv->last_node, (const xmlChar *)ns_uri, (const xmlChar *)prefix);
        else if (prefix && !ns_uri) {
                ns = xmlSearchNs (priv->doc, priv->last_node, (const xmlChar *)prefix);
                if (!ns)
			ns = xmlNewNs (priv->last_node, (const xmlChar *)"", (const xmlChar *)prefix);
        }

        return ns;
}

static void soap_got_headers (SoupMessage *msg, gpointer data)
{
	ESoapMessagePrivate *priv = E_SOAP_MESSAGE_GET_PRIVATE (msg);
	const char *size;

	size = soup_message_headers_get_one (msg->response_headers,
					     "Content-Length");

	if (size)
		priv->response_size = strtol(size, NULL, 10);
}

static void soap_restarted (SoupMessage *msg, gpointer data)
{
	ESoapMessagePrivate *priv = E_SOAP_MESSAGE_GET_PRIVATE (msg);

	priv->response_size = 0;
	priv->response_received = 0;

	/* Discard the existing context, if there is one, and start again */
	if (priv->ctxt) {
		if (priv->ctxt->myDoc)
			xmlFreeDoc (priv->ctxt->myDoc);
		xmlFreeParserCtxt (priv->ctxt);
		priv->ctxt = NULL;
	}
}

static void soap_sax_startElementNs (void * _ctxt, 
				     const xmlChar *localname, 
				     const xmlChar *prefix, 
				     const xmlChar *uri, 
				     int nb_namespaces, 
				     const xmlChar **namespaces, 
				     int nb_attributes, 
				     int nb_defaulted, 
				     const xmlChar **attributes)
{
	xmlParserCtxt *ctxt = _ctxt; 
	ESoapMessagePrivate *priv = ctxt->_private;
	gchar *fname;

	xmlSAX2StartElementNs (ctxt, localname, prefix, uri, nb_namespaces,
			       namespaces, nb_attributes, nb_defaulted,
			       attributes);

	if (!priv->steal_node || strcmp ((const char *)localname, priv->steal_node))
		return;

	fname = g_build_filename (priv->steal_dir, "XXXXXX", NULL);
	priv->steal_fd = g_mkstemp (fname);
	if (priv->steal_fd != -1) {
		if (priv->steal_base64) {
			gchar *enc = g_base64_encode ((guchar *)fname, strlen(fname));
			xmlSAX2Characters (ctxt, (xmlChar *)enc, strlen (enc));<commit_msg>Enable steal multiple XML nodes as it arrives<commit_after>/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 */

#include <libedataserver/eds-version.h>

#include <string.h>
#include <libsoup/soup.h>
#include "e-soap-message.h"

G_DEFINE_TYPE (ESoapMessage, e_soap_message, SOUP_TYPE_MESSAGE)

typedef struct {
	/* Serialization fields */
	xmlParserCtxtPtr ctxt;
	xmlDocPtr doc;
	xmlNodePtr last_node;
	xmlNsPtr soap_ns;
	xmlNsPtr xsi_ns;
	xmlChar *env_prefix;
	xmlChar *env_uri;
	gboolean body_started;
	gchar *action;

	/* Content stealing */
	gchar *steal_node;
	gchar *steal_dir;
	gboolean steal_base64;

	gint steal_b64_state;
	guint steal_b64_save;
	int steal_fd;

	/* Progress callbacks */
	gsize response_size;
	gsize response_received;
	ESoapProgressFn progress_fn;
	gpointer progress_data;

} ESoapMessagePrivate;
#define E_SOAP_MESSAGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), E_TYPE_SOAP_MESSAGE, ESoapMessagePrivate))

static void
finalize (GObject *object)
{
	ESoapMessagePrivate *priv = E_SOAP_MESSAGE_GET_PRIVATE (object);

	if (priv->ctxt) {
		if (priv->ctxt->myDoc)
			xmlFreeDoc (priv->ctxt->myDoc);
		xmlFreeParserCtxt (priv->ctxt);
	}
	if (priv->doc)
		xmlFreeDoc (priv->doc);
	if (priv->action)
		g_free (priv->action);
	if (priv->env_uri)
                xmlFree (priv->env_uri);
	if (priv->env_prefix)
                xmlFree (priv->env_prefix);

	g_free (priv->steal_node);
	g_free (priv->steal_dir);
	if (priv->steal_fd != -1)
		close (priv->steal_fd);
	G_OBJECT_CLASS (e_soap_message_parent_class)->finalize (object);
}

static void
e_soap_message_class_init (ESoapMessageClass *e_soap_message_class)
{
	GObjectClass *object_class = G_OBJECT_CLASS (e_soap_message_class);

	g_type_class_add_private (e_soap_message_class, sizeof (ESoapMessagePrivate));

	object_class->finalize = finalize;
}

static void
e_soap_message_init (ESoapMessage *msg)
{
	ESoapMessagePrivate *priv = E_SOAP_MESSAGE_GET_PRIVATE (msg);

	/* initialize XML structures */
	priv->doc = xmlNewDoc ((const xmlChar *)"1.0");
	priv->doc->standalone = FALSE;
	priv->doc->encoding = xmlCharStrdup ("UTF-8");
	priv->steal_fd = -1;
}

static xmlNsPtr
fetch_ns (ESoapMessage *msg, const gchar *prefix, const gchar *ns_uri)
{
	ESoapMessagePrivate *priv = E_SOAP_MESSAGE_GET_PRIVATE (msg);
        xmlNsPtr ns = NULL;

        if (prefix && ns_uri)
                ns = xmlNewNs (priv->last_node, (const xmlChar *)ns_uri, (const xmlChar *)prefix);
        else if (prefix && !ns_uri) {
                ns = xmlSearchNs (priv->doc, priv->last_node, (const xmlChar *)prefix);
                if (!ns)
			ns = xmlNewNs (priv->last_node, (const xmlChar *)"", (const xmlChar *)prefix);
        }

        return ns;
}

static void soap_got_headers (SoupMessage *msg, gpointer data)
{
	ESoapMessagePrivate *priv = E_SOAP_MESSAGE_GET_PRIVATE (msg);
	const char *size;

	size = soup_message_headers_get_one (msg->response_headers,
					     "Content-Length");

	if (size)
		priv->response_size = strtol(size, NULL, 10);
}

static void soap_restarted (SoupMessage *msg, gpointer data)
{
	ESoapMessagePrivate *priv = E_SOAP_MESSAGE_GET_PRIVATE (msg);

	priv->response_size = 0;
	priv->response_received = 0;

	/* Discard the existing context, if there is one, and start again */
	if (priv->ctxt) {
		if (priv->ctxt->myDoc)
			xmlFreeDoc (priv->ctxt->myDoc);
		xmlFreeParserCtxt (priv->ctxt);
		priv->ctxt = NULL;
	}
}

static void soap_sax_startElementNs (void * _ctxt, 
				     const xmlChar *localname, 
				     const xmlChar *prefix, 
				     const xmlChar *uri, 
				     int nb_namespaces, 
				     const xmlChar **namespaces, 
				     int nb_attributes, 
				     int nb_defaulted, 
				     const xmlChar **attributes)
{
	xmlParserCtxt *ctxt = _ctxt; 
	ESoapMessagePrivate *priv = ctxt->_private;
	gchar *fname;

	xmlSAX2StartElementNs (ctxt, localname, prefix, uri, nb_namespaces,
			       namespaces, nb_attributes, nb_defaulted,
			       attributes);

	/* steal_node can contain multiple node name separated by " " */
	if (priv->steal_node && *priv->steal_node) {
		gchar **prop = g_strsplit (priv->steal_node, " ", 0);
		gint i = 0;
		gboolean isnode = FALSE;

		while (prop[i]) {
			if (strcmp ((const char *)localname, prop [i]) == 0) {
				isnode = TRUE;
				break;
			}
			i++;
		}
		g_strfreev (prop);

		if (!isnode) return;
	} else
		return;

	fname = g_build_filename (priv->steal_dir, "XXXXXX", NULL);
	priv->steal_fd = g_mkstemp (fname);
	if (priv->steal_fd != -1) {
		if (priv->steal_base64) {
			gchar *enc = g_base64_encode ((guchar *)fname, strlen(fname));
			xmlSAX2Characters (ctxt, (xmlChar *)enc, strlen (enc));
{'fraction_non_alphanumeric': 0.12585183556825677, 'fraction_numerical': 0.007364255880413278, 'mean_word_length': 3.929035752979415, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 106, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 72}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3487924', 'n_tokens_mistral': 3582, 'n_tokens_neox': 3364, 'n_words': 749}