Index: src/buf.c
===================================================================
RCS file: /data/cvs/libxen/src/buf.c,v
retrieving revision 1.2
diff -u -p -r1.2 buf.c
--- src/buf.c	29 Jun 2007 13:23:13 -0000	1.2
+++ src/buf.c	6 Jul 2007 13:31:34 -0000
@@ -185,6 +185,82 @@ virBufferVSprintf(virBufferPtr buf, cons
 }
 
 /**
+ * virBufferEscapeString:
+ * @buf:  the buffer to dump
+ * @format: a printf like format string but with only one %s parameter
+ * @str:  the string argument which need to be escaped
+ *
+ * Do a formatted print with a single string to an XML buffer. The string
+ * is escaped to avoid generating a not well-formed XML instance.
+ *
+ * Returns 0 successful, -1 in case of internal or API error.
+ */
+int
+virBufferEscapeString(virBufferPtr buf, const char *format, const char *str)
+{
+    int size, count, len;
+    char *escaped, *out;
+    const char *cur;
+
+    if ((format == NULL) || (buf == NULL) || (str == NULL)) {
+        return (-1);
+    }
+
+    len = strlen(str);
+    escaped = malloc(5 * len + 1);
+    if (escaped == NULL) {
+        return (-1);
+    }
+    cur = str;
+    out = escaped;
+    while (*cur != 0) {
+        if (*cur == '<') {
+	    *out++ = '&';
+	    *out++ = 'l';
+	    *out++ = 'l';
+	    *out++ = ';';
+	} else if (*cur == '>') {
+	    *out++ = '&';
+	    *out++ = 'g';
+	    *out++ = 't';
+	    *out++ = ';';
+	} else if (*cur == '&') {
+	    *out++ = '&';
+	    *out++ = 'a';
+	    *out++ = 'm';
+	    *out++ = 'p';
+	    *out++ = ';';
+	} else if ((*cur >= 0x20) || (*cur == '\n') || (*cur == '\t') ||
+	           (*cur == '\r')) {
+	    /*
+	     * default case, just copy !
+	     * Note that character over 0x80 are likely to give problem
+	     * with UTF-8 XML, but since our string don't have an encoding
+	     * it's hard to handle properly we have to assume it's UTF-8 too
+	     */
+	    *out++ = *cur;
+	}
+	cur++;
+    }
+    *out = 0;
+
+    size = buf->size - buf->use - 1;
+    while (((count = snprintf(&buf->content[buf->use], size, format,
+                              (char *)escaped)) < 0) || (count >= size - 1)) {
+        buf->content[buf->use] = 0;
+        if (virBufferGrow(buf, 1000) < 0) {
+	    free(escaped);
+            return (-1);
+        }
+        size = buf->size - buf->use - 1;
+    }
+    buf->use += count;
+    buf->content[buf->use] = 0;
+    free(escaped);
+    return (0);
+}
+
+/**
  * virBufferStrcat:
  * @buf:  the buffer to dump
  * @...:  the variable list of strings, the last argument must be NULL
Index: src/buf.h
===================================================================
RCS file: /data/cvs/libxen/src/buf.h,v
retrieving revision 1.1
diff -u -p -r1.1 buf.h
--- src/buf.h	26 Jun 2007 22:33:22 -0000	1.1
+++ src/buf.h	6 Jul 2007 13:31:34 -0000
@@ -33,5 +33,6 @@ int virBufferAdd(virBufferPtr buf, const
 int virBufferVSprintf(virBufferPtr buf, const char *format, ...)
   ATTRIBUTE_FORMAT(printf, 2, 3);
 int virBufferStrcat(virBufferPtr buf, ...);
+int virBufferEscapeString(virBufferPtr buf, const char *format, const char *str);
 
 #endif /* __VIR_BUFFER_H__ */
Index: src/xend_internal.c
===================================================================
RCS file: /data/cvs/libxen/src/xend_internal.c,v
retrieving revision 1.126
diff -u -p -r1.126 xend_internal.c
--- src/xend_internal.c	5 Jul 2007 16:04:12 -0000	1.126
+++ src/xend_internal.c	6 Jul 2007 13:31:34 -0000
@@ -1337,7 +1337,7 @@ xend_parse_sexp_desc_os(virConnectPtr xe
            virBufferVSprintf(buf, "    %s\n", tmp);
         tmp = sexpr_node(node, "domain/image/linux/args");
         if ((tmp != NULL) && (tmp[0] != 0))
-           virBufferVSprintf(buf, "    %s\n", tmp);
+           virBufferEscapeString(buf, "    %s\n", tmp);
     }
 
     virBufferAdd(buf, "  \n", 8);
@@ -1423,7 +1423,7 @@ xend_parse_sexp_desc(virConnectPtr conn,
         /*
          * Only insert bootloader_args if there is also a bootloader param
          */
-        virBufferVSprintf(&buf, "  %s\n", tmp);
+        virBufferEscapeString(&buf, "  %s\n", tmp);
     }
 
     if (domid != 0) {
Index: src/xm_internal.c
===================================================================
RCS file: /data/cvs/libxen/src/xm_internal.c,v
retrieving revision 1.34
diff -u -p -r1.34 xm_internal.c
--- src/xm_internal.c	4 Jul 2007 13:16:57 -0000	1.34
+++ src/xm_internal.c	6 Jul 2007 13:31:34 -0000
@@ -663,7 +663,7 @@ char *xenXMDomainFormatXML(virConnectPtr
         if (xenXMConfigGetString(conf, "bootloader", &str) == 0)
             virBufferVSprintf(buf, "  %s\n", str);
         if (xenXMConfigGetString(conf, "bootargs", &str) == 0)
-            virBufferVSprintf(buf, "  %s\n", str);
+            virBufferEscapeString(buf, "  %s\n", str);
         if (xenXMConfigGetString(conf, "kernel", &str) == 0) {
             virBufferAdd(buf, "  \n", -1);
             virBufferAdd(buf, "    linux\n", -1);
@@ -671,7 +671,7 @@ char *xenXMDomainFormatXML(virConnectPtr
             if (xenXMConfigGetString(conf, "ramdisk", &str) == 0)
                 virBufferVSprintf(buf, "    %s\n", str);
             if (xenXMConfigGetString(conf, "extra", &str) == 0)
-                virBufferVSprintf(buf, "    %s\n", str);
+                virBufferEscapeString(buf, "    %s\n", str);
             virBufferAdd(buf, "  \n", -1);
         }
     }