diff options
Diffstat (limited to 'dev-libs/libstrophe/files/libstrophe-xml-escape.patch')
-rw-r--r-- | dev-libs/libstrophe/files/libstrophe-xml-escape.patch | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/dev-libs/libstrophe/files/libstrophe-xml-escape.patch b/dev-libs/libstrophe/files/libstrophe-xml-escape.patch new file mode 100644 index 0000000..4b97099 --- /dev/null +++ b/dev-libs/libstrophe/files/libstrophe-xml-escape.patch @@ -0,0 +1,121 @@ +commit c0b1e5b7fe51c6b7018116d96ea98b7912374385 +Author: Alexandre Erwin Ittner <alexandre@ittner.com.br> +Date: Sun Sep 23 17:18:53 2012 -0300 + + Fix escaping of XML text and attributes + + There was a bug in xmpp_send which caused XML special characters to be + sent to the server verbatim, implying in invalid stanzas and making the + server drop the connection. This commit fixed the bug escaping such + characters with the usual rules. + + Bugs: The code now do several (de)allocation operations in every send, + this may have a negative effect on performance when used with slow + memory managers. + + License: This code is distributed under the same license used by strophe + (i.e., GPLv3 or MIT). + +diff --git a/src/stanza.c b/src/stanza.c +index 6bf11b8..4ecc558 100644 +--- a/src/stanza.c ++++ b/src/stanza.c +@@ -206,6 +206,64 @@ int xmpp_stanza_is_tag(xmpp_stanza_t * const stanza) + return (stanza && stanza->type == XMPP_STANZA_TAG); + } + ++/* Escape a string with for use in a XML text node or attribute. Assumes that ++ * the input string is encoded in UTF-8. On sucess, returns a pointer to a ++ * buffer with the resulting data which must be xmpp_free()'d by the caller. ++ * On failure, returns NULL. ++ */ ++ ++static char *_escape_xml(xmpp_ctx_t * const ctx, char *text) ++{ ++ size_t len = 0; ++ char *src; ++ char *dst; ++ char *buf; ++ for (src = text; *src != '\0'; src++) { ++ switch (*src) { ++ case '<': /* "<" */ ++ case '>': /* ">" */ ++ len += 4; ++ break; ++ case '&': /* "&" */ ++ len += 5; ++ break; ++ case '"': ++ len += 6; /*""" */ ++ break; ++ default: ++ len++; ++ } ++ } ++ if ((buf = xmpp_alloc(ctx, (len+1) * sizeof(char))) == NULL) ++ return NULL; /* Error */ ++ dst = buf; ++ for (src = text; *src != '\0'; src++) { ++ switch (*src) { ++ case '<': ++ strcpy(dst, "<"); ++ dst += 4; ++ break; ++ case '>': ++ strcpy(dst, ">"); ++ dst += 4; ++ break; ++ case '&': ++ strcpy(dst, "&"); ++ dst += 5; ++ break; ++ case '"': ++ strcpy(dst, """); ++ dst += 6; ++ break; ++ default: ++ *dst = *src; ++ dst++; ++ } ++ } ++ *dst = '\0'; ++ return buf; ++} ++ + /* small helper function */ + static inline void _render_update(int *written, const int length, + const int lastwrite, +@@ -236,6 +294,7 @@ static int _render_stanza_recursive(xmpp_stanza_t *stanza, + xmpp_stanza_t *child; + hash_iterator_t *iter; + const char *key; ++ char *tmp; + + written = 0; + +@@ -244,7 +303,10 @@ static int _render_stanza_recursive(xmpp_stanza_t *stanza, + if (stanza->type == XMPP_STANZA_TEXT) { + if (!stanza->data) return XMPP_EINVOP; + +- ret = xmpp_snprintf(ptr, left, "%s", stanza->data); ++ tmp = _escape_xml(stanza->ctx, stanza->data); ++ if (tmp == NULL) return XMPP_EMEM; ++ ret = xmpp_snprintf(ptr, left, "%s", tmp); ++ xmpp_free(stanza->ctx, tmp); + if (ret < 0) return XMPP_EMEM; + _render_update(&written, buflen, ret, &left, &ptr); + } else { /* stanza->type == XMPP_STANZA_TAG */ +@@ -258,8 +320,11 @@ static int _render_stanza_recursive(xmpp_stanza_t *stanza, + if (stanza->attributes && hash_num_keys(stanza->attributes) > 0) { + iter = hash_iter_new(stanza->attributes); + while ((key = hash_iter_next(iter))) { +- ret = xmpp_snprintf(ptr, left, " %s=\"%s\"", key, +- (char *)hash_get(stanza->attributes, key)); ++ tmp = _escape_xml(stanza->ctx, ++ (char *)hash_get(stanza->attributes, key)); ++ if (tmp == NULL) return XMPP_EMEM; ++ ret = xmpp_snprintf(ptr, left, " %s=\"%s\"", key, tmp); ++ xmpp_free(stanza->ctx, tmp); + if (ret < 0) return XMPP_EMEM; + _render_update(&written, buflen, ret, &left, &ptr); + } |