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); } }