Index: subversion/include/svn_xml.h =================================================================== --- subversion/include/svn_xml.h (revision 4679) +++ subversion/include/svn_xml.h (working copy) @@ -61,27 +61,53 @@ /** 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. + * suitable for output as character data. * 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); - -/** 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); - -/** 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); +void svn_xml_escape_cdata_stringbuf (svn_stringbuf_t **outstr, + const svn_stringbuf_t *string, + apr_pool_t *pool); + +/** Same as @c svn_xml_escape_cdata_stringbuf, but @a string is an + * @c svn_string_t. + */ +void svn_xml_escape_cdata_string (svn_stringbuf_t **outstr, + const svn_string_t *string, + apr_pool_t *pool); +/** Same as @c svn_xml_escape_cdata_stringbuf, but @a string is a + * null-terminated C string. + */ +void svn_xml_escape_cdata_cstring (svn_stringbuf_t **outstr, + const char *string, + apr_pool_t *pool); + + +/** 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 an attribute value. + * If @a *outstr is @c NULL, store a new stringbuf, else append to the + * existing stringbuf there. + */ +void svn_xml_escape_attr_stringbuf (svn_stringbuf_t **outstr, + const svn_stringbuf_t *string, + apr_pool_t *pool); + +/** Same as @c svn_xml_escape_attr_stringbuf, but @a string is an + * @c svn_string_t. + */ +void svn_xml_escape_attr_string (svn_stringbuf_t **outstr, + const svn_string_t *string, + apr_pool_t *pool); + +/** Same as @c svn_xml_escape_attr_stringbuf, but @a string is a + * null-terminated C string. + */ +void svn_xml_escape_attr_cstring (svn_stringbuf_t **outstr, + const char *string, + apr_pool_t *pool); /*---------------------------------------------------------------*/ Index: subversion/libsvn_subr/xml.c =================================================================== --- subversion/libsvn_subr/xml.c (revision 4679) +++ subversion/libsvn_subr/xml.c (working copy) @@ -29,10 +29,10 @@ /*** XML escaping. ***/ static void -xml_escape (svn_stringbuf_t **outstr, - const char *data, - apr_size_t len, - apr_pool_t *pool) +xml_escape_cdata (svn_stringbuf_t **outstr, + const char *data, + apr_size_t len, + apr_pool_t *pool) { const char *end = data + len; const char *p = data, *q; @@ -47,8 +47,48 @@ quoted if it follows ]], but it's easier to quote it all the time. */ q = p; + while (q end *q != '' *q != '' *q != '') + q++; + svn_stringbuf_appendbytes (*outstr, p, q - p); + + /* We may already be a winner. */ + if (q == end) + break; + + /* Append the entity reference for the character. */ + if (*q == '') + svn_stringbuf_appendcstr (*outstr, ); + else if (*q == '') + svn_stringbuf_appendcstr (*outstr, ); + else if (*q == '') + svn_stringbuf_appendcstr (*outstr, ); + + p = q + 1; + } +} + +/* Essentially the same as xml_escape_cdata, with the addition of + whitespace and quote characters. */ +static void +xml_escape_attr (svn_stringbuf_t **outstr, + const char *data, + apr_size_t len, + apr_pool_t *pool) +{ + const char *end = data + len; + const char *p = data, *q; + + if (*outstr == NULL) + *outstr = svn_stringbuf_create (, pool); + + while (1) + { + /* Find a character which needs to be quoted and append bytes up + to that point. */ + q = p; while (q end *q != '' *q != '' *q != '' - *q != '' *q != '\'') + *q != '' *q != '\'' *q != '\r' + *q != '\n' *q != '\t') q++; svn_stringbuf_appendbytes (*outstr, p, q - p); @@ -67,6 +107,12 @@ svn_stringbuf_appendcstr (*outstr, ); else if (*q == '\'') svn_stringbuf_appendcstr (*outstr, ); + else if (*q == '\r') + svn_stringbuf_appendcstr (*outstr, ); + else if (*q == '\n') + svn_stringbuf_appendcstr (*outstr, ); + else if (*q == '\t') + svn_stringbuf_appendcstr (*outstr, ); p = q + 1; } @@ -74,29 +120,56 @@ void -svn_xml_escape_stringbuf (svn_stringbuf_t **outstr, - const svn_stringbuf_t *string, - apr_pool_t *pool) +svn_xml_escape_cdata_stringbuf (svn_stringbuf_t **outstr, + const svn_stringbuf_t *string, + apr_pool_t *pool) +{ + xml_escape_cdata (outstr, string-data, string-len, pool); +} + + +void +svn_xml_escape_cdata_string (svn_stringbuf_t **outstr, + const svn_string_t *string, + apr_pool_t *pool) +{ + xml_escape_cdata (outstr, string-data, string-len, pool); +} + + +void +svn_xml_escape_cdata_cstring (svn_stringbuf_t **outstr, + const char *string, + apr_pool_t *pool) +{ + xml_escape_cdata (outstr, string, (apr_size_t) strlen (string), pool); +} + + +void +svn_xml_escape_attr_stringbuf (svn_stringbuf_t **outstr, + const svn_stringbuf_t *string, + apr_pool_t *pool) { - xml_escape (outstr, string-data, string-len, pool); + xml_escape_attr (outstr, string-data, string-len, pool); } void -svn_xml_escape_string (svn_stringbuf_t **outstr, - const svn_string_t *string, - apr_pool_t *pool) +svn_xml_escape_attr_string (svn_stringbuf_t **outstr, + const svn_string_t *string, + apr_pool_t *pool) { - xml_escape (outstr, string-data, string-len, pool); + xml_escape_attr (outstr, string-data, string-len, pool); } void -svn_xml_escape_cstring (svn_stringbuf_t **outstr, - const char *string, - apr_pool_t *pool) +svn_xml_escape_attr_cstring (svn_stringbuf_t **outstr, + const char *string, + apr_pool_t *pool) { - xml_escape (outstr, string, (apr_size_t) strlen (string), pool); + xml_escape_attr (outstr, string, (apr_size_t) strlen (string), pool); } @@ -339,7 +412,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_attr_cstring (str, val, pool); svn_stringbuf_appendcstr (*str, \); } Index: subversion/mod_dav_svn/deadprops.c =================================================================== --- subversion/mod_dav_svn/deadprops.c (revision 4679) +++ 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_cdata_string(xmlsafe, propval, db-resource-pool); #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 4679) +++ 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_cdata_cstring (sb, author, pool); 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_cdata_cstring (sb, date, pool); svn_xml_make_close_tag (sb, pool, date); if (changed_paths) @@ -385,7 +385,8 @@ { /* 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_attr_cstring (escpath, + log_item-copyfrom_path, pool); 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 +401,7 @@ action, action, NULL); } /* xxx/path */ - svn_xml_escape_cstring (sb, path, pool); + svn_xml_escape_cdata_cstring (sb, path, pool); svn_xml_make_close_tag (sb, pool, path); } @@ -419,7 +420,7 @@ NULL, /* no keywords */ FALSE, /* no expansion */ pool)); - svn_xml_escape_cstring (sb, msg_native_eol, pool); + svn_xml_escape_cdata_cstring (sb, msg_native_eol, pool); svn_xml_make_close_tag (sb, pool, msg); /* /logentry */ Index: subversion/libsvn_ra_dav/commit.c =================================================================== --- subversion/libsvn_ra_dav/commit.c (revision 4679) +++ subversion/libsvn_ra_dav/commit.c (working copy) @@ -515,7 +515,7 @@ if (r-prop_changes == NULL) r-prop_changes = apr_table_make(pool, 5); - svn_xml_escape_string(escaped, value, pool); + svn_xml_escape_cdata_string(escaped, value, pool); apr_table_set(r-prop_changes, name, escaped-data); } else @@ -1257,7 +1257,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_cdata_cstring(xml_data, log_msg, cc-ras-pool); 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 4679) +++ subversion/libsvn_ra_dav/fetch.c (working copy) @@ -2232,7 +2232,7 @@ const char *entry; svn_stringbuf_t *qpath = NULL; - svn_xml_escape_cstring (qpath, path, pool); + svn_xml_escape_cdata_cstring (qpath, path, pool); entry = apr_psprintf(pool, S:entry rev=\% SVN_REVNUM_T_FMT @@ -2273,8 +2273,8 @@ pool)); - svn_xml_escape_cstring (qpath, path, pool); - svn_xml_escape_cstring (qlinkpath, bc_relative.data, pool); + svn_xml_escape_cdata_cstring (qpath, path, pool); + svn_xml_escape_attr_cstring (qlinkpath, bc_relative.data, pool); entry = apr_psprintf(pool, S:entry rev=\% SVN_REVNUM_T_FMT \ linkpath=\/%s\%s/S:entry DEBUG_CR, @@ -2302,7 +2302,7 @@ const char *s; svn_stringbuf_t *qpath = NULL; - svn_xml_escape_cstring (qpath, path, pool); + svn_xml_escape_cdata_cstring (qpath, path, pool); s = apr_psprintf(pool, S:missing%s/S:missing DEBUG_CR, qpath-data); @@ -2504,7 +2504,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_cdata_cstring (dst_path_str, dst_path, ras-pool); s = apr_psprintf(ras-pool, S:dst-path%s/S:dst-path, dst_path_str-data);