aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--filter/ChangeLog8
-rw-r--r--filter/rule-context.c313
2 files changed, 317 insertions, 4 deletions
diff --git a/filter/ChangeLog b/filter/ChangeLog
index 1c24bc393b..c1b4f2d613 100644
--- a/filter/ChangeLog
+++ b/filter/ChangeLog
@@ -1,3 +1,11 @@
+2002-08-05 Jeffrey Stedfast <fejj@ximian.com>
+
+ * rule-context.c (xml_doc_save): New internal function to replace
+ xmlSaveFile. Does proper error checking and so forth to ensure
+ that the resulting file does not ever get truncated.
+ (save): Cal xml_doc_save rather than xmlSaveFile. Fixes bug
+ #25980.
+
2002-08-02 Not Zed <NotZed@Ximian.com>
* filter.glade: Added a datespec editor window.
diff --git a/filter/rule-context.c b/filter/rule-context.c
index 490c169d05..03f89b8c71 100644
--- a/filter/rule-context.c
+++ b/filter/rule-context.c
@@ -1,3 +1,4 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2000 Ximian Inc.
*
@@ -18,6 +19,7 @@
* Boston, MA 02111-1307, USA.
*/
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -26,8 +28,13 @@
#include <alloca.h>
#endif
-#include <errno.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
#include <gtk/gtksignal.h>
#include <libgnomeui/gnome-dialog.h>
#include <libgnomeui/gnome-stock.h>
@@ -374,6 +381,304 @@ rule_context_save (RuleContext *f, const char *user)
return ((RuleContextClass *) ((GtkObject *) f)->klass)->save(f, user);
}
+
+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;
+ }
+ }
+}
+
+static int
+xml_doc_save (xmlDocPtr doc, const char *filename)
+{
+ 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;
+}
+
static int
save (RuleContext *f, const char *user)
{
@@ -384,7 +689,7 @@ save (RuleContext *f, const char *user)
struct _rule_set_map *map;
char *usersav, *userbak, *slash;
int ret;
-
+
doc = xmlNewDoc ("1.0");
root = xmlNewDocNode (doc, NULL, "filteroptions", NULL);
xmlDocSetRootElement (doc, root);
@@ -401,7 +706,7 @@ save (RuleContext *f, const char *user)
}
l = g_list_next (l);
}
-
+
usersav = alloca(strlen(user)+5);
userbak = alloca(strlen(user)+5);
slash = strrchr(user, '/');
@@ -411,7 +716,7 @@ save (RuleContext *f, const char *user)
sprintf(usersav, ".#%s", user);
sprintf(userbak, "%s~", user);
printf("saving rules to '%s' then backup '%s'\n", usersav, userbak);
- ret = xmlSaveFile(usersav, doc);
+ ret = xml_doc_save (doc, usersav);
if (ret != -1) {
rename(user, userbak);
ret = rename(usersav, user);