diff options
-rw-r--r-- | e-util/e-xml-utils.c | 310 | ||||
-rw-r--r-- | e-util/e-xml-utils.h | 3 |
2 files changed, 312 insertions, 1 deletions
diff --git a/e-util/e-xml-utils.c b/e-util/e-xml-utils.c index 98c089074b..7e3560fdfb 100644 --- a/e-util/e-xml-utils.c +++ b/e-util/e-xml-utils.c @@ -21,13 +21,21 @@ * 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H #include <config.h> +#endif #include "e-xml-utils.h" +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> #include <locale.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> #include <math.h> -#include <string.h> #include <parser.h> #include <xmlmemory.h> @@ -425,3 +433,303 @@ e_xml_get_translated_string_prop_by_name (const xmlNode *parent, const xmlChar * return ret_val; } + + +/* Replacement for xmlSaveFile */ + +static void xmlNodeDump (xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, int format); + + +static void +xmlAttrDump (xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) +{ + xmlChar *value; + + if (cur == NULL) { +#ifdef DEBUG_TREE + fprintf(stderr, "xmlAttrDump : property == NULL\n"); +#endif + return; + } + + xmlBufferWriteChar (buf, " "); + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + xmlBufferWriteCHAR (buf, cur->ns->prefix); + xmlBufferWriteChar (buf, ":"); + } + + xmlBufferWriteCHAR (buf, cur->name); + value = xmlNodeListGetString (doc, cur->val, 0); + if (value) { + xmlBufferWriteChar (buf, "="); + xmlBufferWriteQuotedString (buf, value); + xmlFree (value); + } else { + xmlBufferWriteChar (buf, "=\"\""); + } +} + +static void +xmlAttrListDump (xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) +{ + if (cur == NULL) { +#ifdef DEBUG_TREE + fprintf(stderr, "xmlAttrListDump : property == NULL\n"); +#endif + return; + } + + while (cur != NULL) { + xmlAttrDump (buf, doc, cur); + cur = cur->next; + } +} + +static void +xmlNodeListDump (xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, int format) +{ + int i; + + if (cur == NULL) { +#ifdef DEBUG_TREE + fprintf(stderr, "xmlNodeListDump : node == NULL\n"); +#endif + return; + } + + while (cur != NULL) { + if ((format) && (xmlIndentTreeOutput) && + (cur->type == XML_ELEMENT_NODE)) + for (i = 0; i < level; i++) + xmlBufferWriteChar (buf, " "); + xmlNodeDump (buf, doc, cur, level, format); + if (format) { + xmlBufferWriteChar (buf, "\n"); + } + cur = cur->next; + } +} + +static void +xmlNodeDump (xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, int format) +{ + int i; + xmlNodePtr tmp; + + if (cur == NULL) { +#ifdef DEBUG_TREE + fprintf(stderr, "xmlNodeDump : node == NULL\n"); +#endif + return; + } + + if (cur->type == XML_TEXT_NODE) { + if (cur->content != NULL) { + xmlChar *buffer; + +#ifndef XML_USE_BUFFER_CONTENT + buffer = xmlEncodeEntitiesReentrant (doc, cur->content); +#else + buffer = xmlEncodeEntitiesReentrant (doc, xmlBufferContent (cur->content)); +#endif + if (buffer != NULL) { + xmlBufferWriteCHAR (buf, buffer); + xmlFree (buffer); + } + } + return; + } + + if (cur->type == XML_PI_NODE) { + if (cur->content != NULL) { + xmlBufferWriteChar (buf, "<?"); + xmlBufferWriteCHAR (buf, cur->name); + if (cur->content != NULL) { + xmlBufferWriteChar (buf, " "); +#ifndef XML_USE_BUFFER_CONTENT + xmlBufferWriteCHAR (buf, cur->content); +#else + xmlBufferWriteCHAR (buf, xmlBufferContent (cur->content)); +#endif + } + xmlBufferWriteChar (buf, "?>"); + } + return; + } + + if (cur->type == XML_COMMENT_NODE) { + if (cur->content != NULL) { + xmlBufferWriteChar (buf, "<!--"); +#ifndef XML_USE_BUFFER_CONTENT + xmlBufferWriteCHAR (buf, cur->content); +#else + xmlBufferWriteCHAR (buf, xmlBufferContent (cur->content)); +#endif + xmlBufferWriteChar (buf, "-->"); + } + return; + } + + if (cur->type == XML_ENTITY_REF_NODE) { + xmlBufferWriteChar (buf, "&"); + xmlBufferWriteCHAR (buf, cur->name); + xmlBufferWriteChar (buf, ";"); + return; + } + + if (cur->type == XML_CDATA_SECTION_NODE) { + xmlBufferWriteChar (buf, "<![CDATA["); + if (cur->content != NULL) +#ifndef XML_USE_BUFFER_CONTENT + xmlBufferWriteCHAR (buf, cur->content); +#else + xmlBufferWriteCHAR (buf, xmlBufferContent(cur->content)); +#endif + xmlBufferWriteChar (buf, "]]>"); + return; + } + + if (format == 1) { + tmp = cur->childs; + while (tmp != NULL) { + if ((tmp->type == XML_TEXT_NODE) || + (tmp->type == XML_ENTITY_REF_NODE)) { + format = 0; + break; + } + tmp = tmp->next; + } + } + + xmlBufferWriteChar (buf, "<"); + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + xmlBufferWriteCHAR (buf, cur->ns->prefix); + xmlBufferWriteChar (buf, ":"); + } + + xmlBufferWriteCHAR (buf, cur->name); + + if (cur->properties != NULL) + xmlAttrListDump (buf, doc, cur->properties); + + if ((cur->content == NULL) && (cur->childs == NULL) && + (!xmlSaveNoEmptyTags)) { + xmlBufferWriteChar (buf, "/>"); + return; + } + + xmlBufferWriteChar (buf, ">"); + if (cur->content != NULL) { + xmlChar *buffer; + +#ifndef XML_USE_BUFFER_CONTENT + buffer = xmlEncodeEntitiesReentrant (doc, cur->content); +#else + buffer = xmlEncodeEntitiesReentrant (doc, xmlBufferContent (cur->content)); +#endif + if (buffer != NULL) { + xmlBufferWriteCHAR (buf, buffer); + xmlFree (buffer); + } + } + + if (cur->childs != NULL) { + if (format) + xmlBufferWriteChar (buf, "\n"); + + xmlNodeListDump (buf, doc, cur->childs, (level >= 0 ? level + 1 : -1), format); + if ((xmlIndentTreeOutput) && (format)) + for (i = 0; i < level; i++) + xmlBufferWriteChar (buf, " "); + } + + xmlBufferWriteChar (buf, "</"); + if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { + xmlBufferWriteCHAR (buf, cur->ns->prefix); + xmlBufferWriteChar (buf, ":"); + } + + xmlBufferWriteCHAR (buf, cur->name); + xmlBufferWriteChar (buf, ">"); +} + +static void +xmlDocContentDump (xmlBufferPtr buf, xmlDocPtr cur) +{ + xmlBufferWriteChar (buf, "<?xml version="); + + if (cur->version != NULL) + xmlBufferWriteQuotedString (buf, cur->version); + else + xmlBufferWriteChar (buf, "\"1.0\""); + + if ((cur->encoding != NULL) && + (strcasecmp (cur->encoding, "UTF-8") != 0)) { + xmlBufferWriteChar (buf, " encoding="); + xmlBufferWriteQuotedString (buf, cur->encoding); + } + + switch (cur->standalone) { + case 1: + xmlBufferWriteChar (buf, " standalone=\"yes\""); + break; + } + + xmlBufferWriteChar (buf, "?>\n"); + if (cur->root != NULL) { + xmlNodePtr child = cur->root; + + while (child != NULL) { + xmlNodeDump (buf, cur, child, 0, 1); + xmlBufferWriteChar (buf, "\n"); + child = child->next; + } + } +} + +int +e_xml_save_file (const char *filename, xmlDocPtr doc) +{ + size_t n, written = 0; + xmlBufferPtr buf; + int errnosave; + ssize_t w; + int fd; + + fd = open (filename, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd == -1) + return -1; + + if (!(buf = xmlBufferCreate ())) { + close (fd); + unlink (filename); + errno = ENOMEM; + return -1; + } + + xmlDocContentDump (buf, doc); + + n = buf->use; + do { + do { + w = write (fd, buf->content + written, n - written); + } while (w == -1 && errno == EINTR); + + if (w > 0) + written += w; + } while (w != -1 && written < n); + + xmlBufferFree (buf); + + if (written < n || fsync (fd) == -1) { + errnosave = errno; + close (fd); + unlink (filename); + errno = errnosave; + return -1; + } + + close (fd); + + return 0; +} diff --git a/e-util/e-xml-utils.h b/e-util/e-xml-utils.h index 54981c96e6..b0811da013 100644 --- a/e-util/e-xml-utils.h +++ b/e-util/e-xml-utils.h @@ -95,6 +95,9 @@ void e_xml_set_string_prop_by_name (xmlNode *parent, gchar *e_xml_get_translated_string_prop_by_name (const xmlNode *parent, const xmlChar *prop_name); + +int e_xml_save_file (const char *filename, xmlDocPtr doc); + END_GNOME_DECLS #endif /* __E_XML_UTILS__ */ |