]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Adds ast_escape_encoded utility to properly handle escaping of quoted field before...
authorJonathan Rose <jrose@digium.com>
Thu, 9 Jun 2011 14:06:42 +0000 (14:06 +0000)
committerJonathan Rose <jrose@digium.com>
Thu, 9 Jun 2011 14:06:42 +0000 (14:06 +0000)
This commit backports a feature in trunk affecting initreqprep so that display name won't
be encoded improperly. Also includes unit tests for the ast_escape_quoted function.
This patch gives 1.8 a much improved outlook in countries which don't use standard
ASCII characters.

(closes issue ASTERISK-16949)
Reported by: Örn Arnarson
Review: https://reviewboard.asterisk.org/r/1235/

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@322585 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c
include/asterisk/utils.h
main/utils.c
tests/test_utils.c

index 457b088d4d73609c90d710313387bb236b244596..ad8997e8bf3afb4412bc744f7a5148172437a4e3 100644 (file)
@@ -11537,7 +11537,7 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
                ast_string_field_set(p, fromname, n);
 
        if (sip_cfg.pedanticsipchecking) {
-               ast_uri_encode(n, tmp_n, sizeof(tmp_n), 0);
+               ast_escape_quoted(n, tmp_n, sizeof(tmp_n));
                n = tmp_n;
                ast_uri_encode(l, tmp_l, sizeof(tmp_l), 0);
                l = tmp_l;
index 7b75db808fc6b5f79561536b4f88d6d16f7abc93..ed71441e5c1035024b15772885352edc2e9d43a0 100644 (file)
@@ -273,6 +273,19 @@ char *ast_uri_encode(const char *string, char *outbuf, int buflen, int do_specia
  */
 void ast_uri_decode(char *s);
 
+/*!
+ * \brief Escape characters found in a quoted string.
+ *
+ * \note This function escapes quoted characters based on the 'qdtext' set of
+ * allowed characters from RFC 3261 section 25.1.
+ *
+ * \param string string to be escaped
+ * \param outbuf resulting escaped string
+ * \param buflen size of output buffer
+ * \return a pointer to the escaped string
+ */
+char *ast_escape_quoted(const char *string, char *outbuf, int buflen);
+
 static force_inline void ast_slinear_saturated_add(short *input, short *value)
 {
        int res;
index bd6805b16d6a11b4080e8a46135bf13e069bcbaf..0872876f5bdfb985af39e67982c5e84387b5d3f7 100644 (file)
@@ -415,6 +415,37 @@ char *ast_uri_encode(const char *string, char *outbuf, int buflen, int do_specia
        return outbuf;
 }
 
+/*! \brief escapes characters specified for quoted portions of sip messages */
+char *ast_escape_quoted(const char *string, char *outbuf, int buflen)
+{
+       const char *ptr  = string;
+       char *out = outbuf;
+       char *allow = "\t\v !"; /* allow LWS (minus \r and \n) and "!" */
+
+       while (*ptr && out - outbuf < buflen - 1) {
+               if (!(strchr(allow, *ptr))
+                       && !(*ptr >= '#' && *ptr <= '[') /* %x23 - %x5b */
+                       && !(*ptr >= ']' && *ptr <= '~') /* %x5d - %x7e */
+                       && !((unsigned char) *ptr > 0x7f)) {             /* UTF8-nonascii */
+
+                       if (out - outbuf >= buflen - 2) {
+                               break;
+                       }
+                       out += sprintf(out, "\\%c", (unsigned char) *ptr);
+               } else {
+                       *out = *ptr;
+                       out++;
+               }
+               ptr++;
+       }
+
+       if (buflen) {
+               *out = '\0';
+       }
+
+       return outbuf;
+}
+
 /*! \brief  ast_uri_decode: Decode SIP URI, URN, URL (overwrite the string)  */
 void ast_uri_decode(char *s) 
 {
index b7a368a7d0b2f9212167bb0d3fc699233ca1491f..a4852f6b34c67afe3471d641aaa61dbb40076e47 100644 (file)
@@ -102,6 +102,54 @@ AST_TEST_DEFINE(uri_encode_decode_test)
        return res;
 }
 
+AST_TEST_DEFINE(quoted_escape_test)
+{
+       int res = AST_TEST_PASS;
+       const char *in = "a\"bcdefg\"hijkl\\mnopqrs tuv\twxyz";
+       char out[256] = { 0 };
+       char small[4] = { 0 };
+       int i;
+
+       static struct {
+               char *buf;
+               const size_t buflen;
+
+               const char *output;
+       } tests[] = {
+               {0, sizeof(out),
+                       "a\\\"bcdefg\\\"hijkl\\\\mnopqrs tuv\twxyz"},
+               {0, sizeof(small),
+                       "a\\\""},
+       };
+
+       tests[0].buf = out;
+       tests[1].buf = small;
+
+       switch (cmd) {
+       case TEST_INIT:
+               info->name = "quoted_escape_test";
+               info->category = "/main/utils/";
+               info->summary = "escape a quoted string";
+               info->description = "Escape a string to be quoted and check the result.";
+               return AST_TEST_NOT_RUN;
+       case TEST_EXECUTE:
+               break;
+       }
+
+       for (i = 0; i < ARRAY_LEN(tests); i++) {
+               ast_escape_quoted(in, tests[i].buf, tests[i].buflen);
+               if (strcmp(tests[i].output, tests[i].buf)) {
+                       ast_test_status_update(test, "ESCAPED DOES NOT MATCH EXPECTED, FAIL\n");
+                       ast_test_status_update(test, "original: %s\n", in);
+                       ast_test_status_update(test, "expected: %s\n", tests[i].output);
+                       ast_test_status_update(test, "result: %s\n", tests[i].buf);
+                       res = AST_TEST_FAIL;
+               }
+       }
+
+       return res;
+}
+
 AST_TEST_DEFINE(md5_test)
 {
        static const struct {
@@ -348,6 +396,7 @@ AST_TEST_DEFINE(agi_loaded_test)
 static int unload_module(void)
 {
        AST_TEST_UNREGISTER(uri_encode_decode_test);
+       AST_TEST_UNREGISTER(quoted_escape_test);
        AST_TEST_UNREGISTER(md5_test);
        AST_TEST_UNREGISTER(sha1_test);
        AST_TEST_UNREGISTER(base64_test);
@@ -360,6 +409,7 @@ static int unload_module(void)
 static int load_module(void)
 {
        AST_TEST_REGISTER(uri_encode_decode_test);
+       AST_TEST_REGISTER(quoted_escape_test);
        AST_TEST_REGISTER(md5_test);
        AST_TEST_REGISTER(sha1_test);
        AST_TEST_REGISTER(base64_test);