Index: subversion/include/svn_xml.h =================================================================== --- subversion/include/svn_xml.h (revision 4632) +++ subversion/include/svn_xml.h (working copy) @@ -61,26 +61,30 @@ /** Create or append in @a *outstr an xml-escaped version of @a string. * * Create or append in @a *outstr an xml-escaped version of @a string, - * suitable for output as character data or as an attribute value. - * If @a *outstr is @c NULL, store a new stringbuf, else append to the - * existing stringbuf there. + * suitable for output as character data. If @a is_attribute is true, + * then @a *outstr will additionally be suitable for output as an + * attribute value. If @a *outstr is @c NULL, store a new stringbuf, + * else append to the existing stringbuf there. */ void svn_xml_escape_stringbuf (svn_stringbuf_t **outstr, const svn_stringbuf_t *string, - apr_pool_t *pool); + apr_pool_t *pool, + svn_boolean_t is_attribute); /** Same as @c svn_xml_escape_stringbuf, but @a string is an @c svn_string_t. */ void svn_xml_escape_string (svn_stringbuf_t **outstr, const svn_string_t *string, - apr_pool_t *pool); + apr_pool_t *pool, + svn_boolean_t is_attribute); /** Same as @c svn_xml_escape_stringbuf, but @a string is a null-terminated * C string. */ void svn_xml_escape_cstring (svn_stringbuf_t **outstr, const char *string, - apr_pool_t *pool); + apr_pool_t *pool, + svn_boolean_t is_attribute); /** Create or append in @a *outstr the unescaped version of the Index: subversion/libsvn_subr/xml.c =================================================================== --- subversion/libsvn_subr/xml.c (revision 4632) +++ subversion/libsvn_subr/xml.c (working copy) @@ -32,7 +32,8 @@ xml_escape (svn_stringbuf_t **outstr, const char *data, apr_size_t len, - apr_pool_t *pool) + apr_pool_t *pool, + svn_boolean_t is_attribute) { const char *end = data + len; const char *p = data, *q; @@ -48,7 +49,9 @@ the time. */ q = p; while (q end *q != '' *q != '' *q != '' - *q != '' *q != '\'') + (!is_attribute || *q != ' ' *q != '' + *q != '\'' *q != '\n' + *q != '\r' *q != '\t')) q++; svn_stringbuf_appendbytes (*outstr, p, q - p); @@ -67,6 +70,19 @@ svn_stringbuf_appendcstr (*outstr, ); else if (*q == '\'') svn_stringbuf_appendcstr (*outstr, ); + else if (*q == '\n') + svn_stringbuf_appendcstr (*outstr, ); + else if (*q == '\r') + svn_stringbuf_appendcstr (*outstr, ); + else if (*q == '\t') + svn_stringbuf_appendcstr (*outstr, ); + + /* Escaping normal spaces is technically unnecessary, but I'm + including this for (1) completeness, and (2) if ever support + is added for non-CDATA attribute types, this will become + necessary. */ + else if (*q == ' ') + svn_stringbuf_appendcstr (*outstr, ); p = q + 1; } @@ -165,27 +181,30 @@ void svn_xml_escape_stringbuf (svn_stringbuf_t **outstr, const svn_stringbuf_t *string, - apr_pool_t *pool) + apr_pool_t *pool, + svn_boolean_t is_attribute) { - xml_escape (outstr, string-data, string-len, pool); + xml_escape (outstr, string-data, string-len, pool, is_attribute); } void svn_xml_escape_string (svn_stringbuf_t **outstr, const svn_string_t *string, - apr_pool_t *pool) + apr_pool_t *pool, + svn_boolean_t is_attribute) { - xml_escape (outstr, string-data, string-len, pool); + xml_escape (outstr, string-data, string-len, pool, is_attribute); } void svn_xml_escape_cstring (svn_stringbuf_t **outstr, const char *string, - apr_pool_t *pool) + apr_pool_t *pool, + svn_boolean_t is_attribute) { - xml_escape (outstr, string, (apr_size_t) strlen (string), pool); + xml_escape (outstr, string, (apr_size_t) strlen (string), pool, is_attribute); } @@ -455,7 +474,7 @@ svn_stringbuf_appendcstr (*str, \n ); svn_stringbuf_appendcstr (*str, key); svn_stringbuf_appendcstr (*str, =\); - svn_xml_escape_cstring (str, val, pool); + svn_xml_escape_cstring (str, val, pool, TRUE); svn_stringbuf_appendcstr (*str, \); } Index: subversion/mod_dav_svn/deadprops.c =================================================================== --- subversion/mod_dav_svn/deadprops.c (revision 4632) +++ subversion/mod_dav_svn/deadprops.c (working copy) @@ -261,7 +261,7 @@ return NULL; /* XML-escape our properties before sending them across the wire. */ - svn_xml_escape_string(xmlsafe, propval, db-resource-pool); + svn_xml_escape_string(xmlsafe, propval, db-resource-pool, FALSE); #ifdef SVN_DAV_FEATURE_USE_OLD_NAMESPACES if (strcmp(name-ns, SVN_PROP_CUSTOM_PREFIX) == 0) Index: subversion/clients/cmdline/log-cmd.c =================================================================== --- subversion/clients/cmdline/log-cmd.c (revision 4632) +++ subversion/clients/cmdline/log-cmd.c (working copy) @@ -345,7 +345,7 @@ /* authorxxx/author */ svn_xml_make_open_tag (sb, pool, svn_xml_protect_pcdata, author, NULL); - svn_xml_escape_cstring (sb, author, pool); + svn_xml_escape_cstring (sb, author, pool, FALSE); svn_xml_make_close_tag (sb, pool, author); if (date == NULL) @@ -355,7 +355,7 @@ /* datexxx/date */ svn_xml_make_open_tag (sb, pool, svn_xml_protect_pcdata, date, NULL); - svn_xml_escape_cstring (sb, date, pool); + svn_xml_escape_cstring (sb, date, pool, FALSE); svn_xml_make_close_tag (sb, pool, date); if (changed_paths) @@ -385,7 +385,7 @@ { /* path action=X copyfrom-path=aaa copyfrom-rev= */ svn_stringbuf_t *escpath = svn_stringbuf_create (, pool); - svn_xml_escape_cstring (escpath, log_item-copyfrom_path, pool); + svn_xml_escape_cstring (escpath, log_item-copyfrom_path, pool, TRUE); revstr = apr_psprintf (pool, % SVN_REVNUM_T_FMT, log_item-copyfrom_rev); svn_xml_make_open_tag (sb, pool, svn_xml_protect_pcdata, path, @@ -400,7 +400,7 @@ action, action, NULL); } /* xxx/path */ - svn_xml_escape_cstring (sb, path, pool); + svn_xml_escape_cstring (sb, path, pool, FALSE); svn_xml_make_close_tag (sb, pool, path); } @@ -419,7 +419,7 @@ NULL, /* no keywords */ FALSE, /* no expansion */ pool)); - svn_xml_escape_cstring (sb, msg_native_eol, pool); + svn_xml_escape_cstring (sb, msg_native_eol, pool, FALSE); svn_xml_make_close_tag (sb, pool, msg); /* /logentry */ Index: subversion/libsvn_ra_dav/commit.c =================================================================== --- subversion/libsvn_ra_dav/commit.c (revision 4632) +++ subversion/libsvn_ra_dav/commit.c (working copy) @@ -515,7 +515,10 @@ if (r-prop_changes == NULL) r-prop_changes = apr_table_make(pool, 5); - svn_xml_escape_string(escaped, value, pool); + /* Not sure whether this will eventually be output as an XML + attribute, but it can't hurt to escape it if + not. --pediddle */ + svn_xml_escape_string(escaped, value, pool, TRUE); apr_table_set(r-prop_changes, name, escaped-data); } else @@ -1257,7 +1260,7 @@ /* XML-Escape the log message. */ xml_data = NULL; /* Required by svn_xml_escape_*. */ - svn_xml_escape_cstring(xml_data, log_msg, cc-ras-pool); + svn_xml_escape_cstring(xml_data, log_msg, cc-ras-pool, FALSE); po[0].name = log_message_prop; po[0].type = ne_propset; Index: subversion/libsvn_ra_dav/fetch.c =================================================================== --- subversion/libsvn_ra_dav/fetch.c (revision 4632) +++ subversion/libsvn_ra_dav/fetch.c (working copy) @@ -2231,7 +2231,7 @@ const char *entry; svn_stringbuf_t *qpath = NULL; - svn_xml_escape_cstring (qpath, path, pool); + svn_xml_escape_cstring (qpath, path, pool, FALSE); entry = apr_psprintf(pool, S:entry rev=\% SVN_REVNUM_T_FMT @@ -2272,8 +2272,8 @@ pool)); - svn_xml_escape_cstring (qpath, path, pool); - svn_xml_escape_cstring (qlinkpath, bc_relative.data, pool); + svn_xml_escape_cstring (qpath, path, pool, FALSE); + svn_xml_escape_cstring (qlinkpath, bc_relative.data, pool, TRUE); entry = apr_psprintf(pool, S:entry rev=\% SVN_REVNUM_T_FMT \ linkpath=\/%s\%s/S:entry DEBUG_CR, @@ -2301,7 +2301,7 @@ const char *s; svn_stringbuf_t *qpath = NULL; - svn_xml_escape_cstring (qpath, path, pool); + svn_xml_escape_cstring (qpath, path, pool, FALSE); s = apr_psprintf(pool, S:missing%s/S:missing DEBUG_CR, qpath-data); @@ -2503,7 +2503,7 @@ if (dst_path) { svn_stringbuf_t *dst_path_str = NULL; - svn_xml_escape_cstring (dst_path_str, dst_path, ras-pool); + svn_xml_escape_cstring (dst_path_str, dst_path, ras-pool, FALSE); s = apr_psprintf(ras-pool, S:dst-path%s/S:dst-path, dst_path_str-data);