Index: /pjproject/trunk/pjlib-util/include/pjlib-util/scanner.h
===================================================================
--- /pjproject/trunk/pjlib-util/include/pjlib-util/scanner.h	(revision 582)
+++ /pjproject/trunk/pjlib-util/include/pjlib-util/scanner.h	(revision 583)
@@ -333,4 +333,17 @@
 
 /** 
+ * Just like #pj_scan_get(), but additionally performs unescaping when
+ * escaped ('%') character is found. The input spec MUST NOT contain the
+ * specification for '%' characted.
+ *
+ * @param scanner   The scanner.
+ * @param spec	    The spec to match input string.
+ * @param out	    String to store the result.
+ */
+PJ_DECL(void) pj_scan_get_unescape( pj_scanner *scanner,
+				    const pj_cis_t *spec, pj_str_t *out);
+
+
+/** 
  * Get characters between quotes. If current input doesn't match begin_quote,
  * syntax error will be thrown. Note that the resulting string will contain
Index: /pjproject/trunk/pjlib-util/src/pjlib-util/scanner.c
===================================================================
--- /pjproject/trunk/pjlib-util/src/pjlib-util/scanner.c	(revision 582)
+++ /pjproject/trunk/pjlib-util/src/pjlib-util/scanner.c	(revision 583)
@@ -18,4 +18,5 @@
  */
 #include <pjlib-util/scanner.h>
+#include <pj/ctype.h>
 #include <pj/string.h>
 #include <pj/except.h>
@@ -283,4 +284,62 @@
 
 
+PJ_DEF(void) pj_scan_get_unescape( pj_scanner *scanner,
+				   const pj_cis_t *spec, pj_str_t *out)
+{
+    register char *s = scanner->curptr;
+    char *dst = s;
+
+    pj_assert(pj_cis_match(spec,0)==0);
+
+    /* Must not match character '%' */
+    pj_assert(pj_cis_match(spec,'%')==0);
+
+    /* EOF is detected implicitly */
+    if (!pj_cis_match(spec, *s) && *s != '%') {
+	pj_scan_syntax_err(scanner);
+	return;
+    }
+
+    out->ptr = s;
+    do {
+	if (*s == '%') {
+	    if (s+3 <= scanner->end) {
+		/* This doesn't check if the hex digits are valid.
+		 * If they dont' it will produce garbage characters, but
+		 * no harm is done to the application (e.g. no illegal
+		 * memory access.
+		 */
+		*dst = (pj_uint8_t) ((pj_hex_digit_to_val(*(s+1)) << 4) +
+				      pj_hex_digit_to_val(*(s+2)));
+		++dst;
+		s += 3;
+	    } else {
+		*dst++ = *s++;
+		*dst++ = *s++;
+		break;
+	    }
+	}
+	
+	if (pj_cis_match(spec, *s)) {
+	    char *start = s;
+	    do {
+		++s;
+	    } while (pj_cis_match(spec, *s));
+
+	    if (dst != start) pj_memmove(dst, start, s-start);
+	    dst += (s-start);
+	} 
+	
+    } while (*s == '%');
+
+    scanner->curptr = s;
+    out->slen = (dst - out->ptr);
+
+    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
+	pj_scan_skip_whitespace(scanner);    
+    }
+}
+
+
 PJ_DEF(void) pj_scan_get_quote( pj_scanner *scanner,
 				 int begin_quote, int end_quote, 
Index: /pjproject/trunk/pjlib-util/src/pjlib-util/scanner_cis_uint.c
===================================================================
--- /pjproject/trunk/pjlib-util/src/pjlib-util/scanner_cis_uint.c	(revision 582)
+++ /pjproject/trunk/pjlib-util/src/pjlib-util/scanner_cis_uint.c	(revision 583)
@@ -27,8 +27,10 @@
 {
     /* Do nothing. */
+    PJ_UNUSED_ARG(cis_buf);
 }
 
 PJ_DEF(pj_status_t) pj_cis_init(pj_cis_buf_t *cis_buf, pj_cis_t *cis)
 {
+    PJ_UNUSED_ARG(cis_buf);
     pj_bzero(cis->cis_buf, sizeof(cis->cis_buf));
     return PJ_SUCCESS;
Index: /pjproject/trunk/pjlib/src/pj/hash.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/hash.c	(revision 582)
+++ /pjproject/trunk/pjlib/src/pj/hash.c	(revision 583)
@@ -76,8 +76,19 @@
     long i;
 
+#if defined(PJ_HASH_USE_OWN_TOLOWER) && PJ_HASH_USE_OWN_TOLOWER != 0
+    for (i=0; i<key->slen; ++i) {
+	pj_uint8_t c = key->ptr[i];
+	if (c & 64)
+	    result[i] = (char)(c | 32);
+	else
+	    result[i] = (char)c;
+	hval = hval * PJ_HASH_MULTIPLIER + result[i];
+    }
+#else
     for (i=0; i<key->slen; ++i) {
 	result[i] = (char)pj_tolower(key->ptr[i]);
 	hval = hval * PJ_HASH_MULTIPLIER + result[i];
     }
+#endif
 
     return hval;
Index: /pjproject/trunk/pjsip-apps/build/sample_debug.dsp
===================================================================
--- /pjproject/trunk/pjsip-apps/build/sample_debug.dsp	(revision 582)
+++ /pjproject/trunk/pjsip-apps/build/sample_debug.dsp	(revision 583)
@@ -43,5 +43,5 @@
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "../../pjsip/include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../../pjmedia/include" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /I "../../pjsip/include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../../pjmedia/include" /D PJ_WIN32=1 /D PJ_M_I386=1 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
 # SUBTRACT CPP /YX
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
@@ -52,5 +52,6 @@
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 ole32.lib user32.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /map /machine:I386 /out:"../bin/samples/sampledebug_vc6.exe"
+# ADD LINK32 ole32.lib user32.lib dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /map /debug /machine:I386 /out:"../bin/samples/sampledebug_vc6.exe" /fixed:no
+# SUBTRACT LINK32 /pdb:none
 
 !ELSEIF  "$(CFG)" == "sample_debug - Win32 Debug"
Index: /pjproject/trunk/pjsip/build/test_pjsip.dsp
===================================================================
--- /pjproject/trunk/pjsip/build/test_pjsip.dsp	(revision 582)
+++ /pjproject/trunk/pjsip/build/test_pjsip.dsp	(revision 583)
@@ -52,5 +52,5 @@
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib netapi32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /map /debug /machine:I386 /out:"..\bin\test-pjsip-i386-win32-vc6-release.exe"
+# ADD LINK32 dsound.lib dxguid.lib netapi32.lib mswsock.lib ws2_32.lib kernel32.lib netapi32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /map /debug /machine:I386 /out:"..\bin\test-pjsip-i386-win32-vc6-release.exe" /fixed:no
 
 !ELSEIF  "$(CFG)" == "test_pjsip - Win32 Debug"
Index: /pjproject/trunk/pjsip/include/pjsip/sip_config.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsip/sip_config.h	(revision 582)
+++ /pjproject/trunk/pjsip/include/pjsip/sip_config.h	(revision 583)
@@ -128,4 +128,21 @@
 #ifndef PJSIP_SAFE_MODULE
 #   define PJSIP_SAFE_MODULE		1
+#endif
+
+
+/**
+ * If non-zero, SIP parser will unescape the escape characters ('%')
+ * in the original message, which means that it will modify the
+ * original message. Otherwise the parser will create a copy of
+ * the string and store the unescaped string to the new location.
+ *
+ * Unescaping in-place is faster, but less elegant (and it may
+ * break certain applications). So normally it's disabled, unless
+ * when benchmarking (to show off big performance).
+ *
+ * Default: 0
+ */
+#ifndef PJSIP_UNESCAPE_IN_PLACE
+#   define PJSIP_UNESCAPE_IN_PLACE	0
 #endif
 
Index: /pjproject/trunk/pjsip/include/pjsip/sip_parser.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsip/sip_parser.h	(revision 582)
+++ /pjproject/trunk/pjsip/include/pjsip/sip_parser.h	(revision 583)
@@ -316,8 +316,12 @@
     pjsip_PARAM_CHAR_SPEC,      /**< For scanning pname (or pvalue when it's 
 				     not quoted.) */
+    pjsip_PARAM_CHAR_SPEC_ESC,	/**< Variant without the escape ('%') char */
     pjsip_HDR_CHAR_SPEC,	/**< Chars in hname/havalue in URL. */
+    pjsip_HDR_CHAR_SPEC_ESC,	/**< Variant without the escape ('%') char */
     pjsip_PROBE_USER_HOST_SPEC, /**< Hostname characters. */
     pjsip_PASSWD_SPEC,		/**< Password. */
+    pjsip_PASSWD_SPEC_ESC,	/**< Variant without the escape ('%') char */
     pjsip_USER_SPEC,		/**< User */
+    pjsip_USER_SPEC_ESC,	/**< Variant without the escape ('%') char */
     pjsip_NOT_NEWLINE,		/**< For eating up header, basicly any chars
 				     except newlines or zero. */
Index: /pjproject/trunk/pjsip/src/pjsip/sip_msg.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_msg.c	(revision 582)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_msg.c	(revision 583)
@@ -197,5 +197,7 @@
     int i;
     for (i=0; i<PJ_ARRAY_SIZE(method_names); ++i) {
-	if (pj_stricmp(str, method_names[i])==0) {
+	if (pj_memcmp(str->ptr, method_names[i]->ptr, str->slen)==0 || 
+	    pj_stricmp(str, method_names[i])==0) 
+	{
 	    m->id = (pjsip_method_e)i;
 	    m->name = *method_names[i];
Index: /pjproject/trunk/pjsip/src/pjsip/sip_parser.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_parser.c	(revision 582)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_parser.c	(revision 583)
@@ -116,8 +116,12 @@
 	    pjsip_PARAM_CHAR_SPEC,      /* For scanning pname (or pvalue when
                                          * it's not quoted.) */
+	    pjsip_PARAM_CHAR_SPEC_ESC,	/* The variant without escaped char */
 	    pjsip_HDR_CHAR_SPEC,	/* Chars in hname or hvalue */
+	    pjsip_HDR_CHAR_SPEC_ESC,	/* Variant without escaped char */
 	    pjsip_PROBE_USER_HOST_SPEC, /* Hostname characters. */
 	    pjsip_PASSWD_SPEC,	        /* Password. */
+	    pjsip_PASSWD_SPEC_ESC,	/* Variant without escaped char */
 	    pjsip_USER_SPEC,	        /* User */
+	    pjsip_USER_SPEC_ESC,	/* Variant without escaped char */
 	    pjsip_NOT_COMMA_OR_NEWLINE, /* Array separator. */
 	    pjsip_NOT_NEWLINE,		/* For eating up header.*/
@@ -202,5 +206,24 @@
 
 /* Case insensitive comparison */
-#define parser_stricmp(s1, s2)  (pj_stricmp_alnum(&s1, &s2))
+#define parser_stricmp(s1, s2)  (s1.slen!=s2.slen || pj_stricmp_alnum(&s1, &s2))
+
+
+/* Get a token and unescape */
+PJ_INLINE(void) parser_get_and_unescape(pj_scanner *scanner, pj_pool_t *pool,
+					const pj_cis_t *spec, 
+					const pj_cis_t *unesc_spec,
+					pj_str_t *token)
+{
+#if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0
+    PJ_UNUSED_ARG(pool);
+    PJ_UNUSED_ARG(spec);
+    pj_scan_get_unescape(scanner, unesc_spec, token);
+#else
+    PJ_UNUSED_ARG(unesc_spec);
+    pj_scan_get(scanner, spec, token);
+    *token = pj_str_unescape(pool, token);
+#endif
+}
+
 
 
@@ -314,15 +337,31 @@
     pj_cis_add_str(&pjsip_PARAM_CHAR_SPEC, PARAM_CHAR);
 
+    status = pj_cis_dup(&pjsip_PARAM_CHAR_SPEC_ESC, &pjsip_PARAM_CHAR_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_del_str(&pjsip_PARAM_CHAR_SPEC_ESC, ESCAPED);
+
     status = pj_cis_dup(&pjsip_HDR_CHAR_SPEC, &pjsip_ALNUM_SPEC);
     PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
     pj_cis_add_str(&pjsip_HDR_CHAR_SPEC, HDR_CHAR);
 
+    status = pj_cis_dup(&pjsip_HDR_CHAR_SPEC_ESC, &pjsip_HDR_CHAR_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_del_str(&pjsip_HDR_CHAR_SPEC_ESC, ESCAPED);
+
     status = pj_cis_dup(&pjsip_USER_SPEC, &pjsip_ALNUM_SPEC);
     PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
     pj_cis_add_str( &pjsip_USER_SPEC, UNRESERVED ESCAPED USER_UNRESERVED );
 
+    status = pj_cis_dup(&pjsip_USER_SPEC_ESC, &pjsip_USER_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_del_str( &pjsip_USER_SPEC_ESC, ESCAPED);
+
     status = pj_cis_dup(&pjsip_PASSWD_SPEC, &pjsip_ALNUM_SPEC);
     PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
     pj_cis_add_str( &pjsip_PASSWD_SPEC, UNRESERVED ESCAPED PASS);
+
+    status = pj_cis_dup(&pjsip_PASSWD_SPEC_ESC, &pjsip_PASSWD_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_del_str( &pjsip_PASSWD_SPEC, ESCAPED);
 
     status = pj_cis_init(&cis_buf, &pjsip_PROBE_USER_HOST_SPEC);
@@ -460,5 +499,5 @@
 
     /* Equal length and equal hash. compare the strings. */
-    return pj_ansi_strcmp(r1->hname, name);
+    return pj_memcmp(r1->hname, name, name_len);
 }
 
@@ -469,7 +508,7 @@
     unsigned	pos;
     handler_rec rec;
-    unsigned	i;
 
     if (handler_count >= PJ_ARRAY_SIZE(handler)) {
+	pj_assert(!"Too many handlers!");
 	return PJ_ETOOMANY;
     }
@@ -482,11 +521,10 @@
 	return PJ_ENAMETOOLONG;
     }
-    /* Name is copied in lowercase. */
-    for (i=0; i<rec.hname_len; ++i) {
-	rec.hname[i] = (char)pj_tolower(name[i]);
-    }
-    rec.hname[i] = '\0';
-    /* Hash value is calculated from the lowercase name. */
-    rec.hname_hash = pj_hash_calc(0, rec.hname, PJ_HASH_KEY_STRING);
+    /* Copy name. */
+    pj_memcpy(rec.hname, name, rec.hname_len);
+    rec.hname[rec.hname_len] = '\0';
+
+    /* Calculate hash value. */
+    rec.hname_hash = pj_hash_calc(0, rec.hname, rec.hname_len);
 
     /* Get the pos to insert the new handler. */
@@ -523,10 +561,35 @@
 					       pjsip_parse_hdr_func *fptr)
 {
+    unsigned i, len;
+    char hname_lcase[PJSIP_MAX_HNAME_LEN+1];
     pj_status_t status;
 
+    /* Check that name is not too long */
+    len = pj_ansi_strlen(hname);
+    if (len > PJSIP_MAX_HNAME_LEN) {
+	pj_assert(!"Header name is too long!");
+	return PJ_ENAMETOOLONG;
+    }
+
+    /* Register the normal Mixed-Case name */
     status = int_register_parser(hname, fptr);
     if (status != PJ_SUCCESS) {
 	return status;
     }
+
+    /* Get the lower-case name */
+    for (i=0; i<len; ++i) {
+	hname_lcase[i] = (char)pj_tolower(hname[i]);
+    }
+    hname_lcase[len] = '\0';
+
+    /* Register the lower-case version of the name */
+    status = int_register_parser(hname_lcase, fptr);
+    if (status != PJ_SUCCESS) {
+	return status;
+    }
+    
+
+    /* Register the shortname version of the name */
     if (hshortname) {
         status = int_register_parser(hshortname, fptr);
@@ -537,23 +600,12 @@
 }
 
+
 /* Find handler to parse the header name. */
-static pjsip_parse_hdr_func * find_handler(const pj_str_t *hname)
+static pjsip_parse_hdr_func * find_handler_imp(pj_uint32_t  hash, 
+					       const pj_str_t *hname)
 {
     handler_rec *first;
-    char	 hname_copy[PJSIP_MAX_HNAME_LEN];
-    pj_uint32_t  hash;
     int		 comp;
     unsigned	 n;
-
-    if (hname->slen >= PJSIP_MAX_HNAME_LEN) {
-	/* Guaranteed not to be able to find handler. */
-        return NULL;
-    }
-
-    /* Calculate hash value while converting the header to lowercase. 
-     * Don't assume that 'hname' is NULL terminated.
-     */
-    hash = pj_hash_calc_tolower(0, hname_copy, hname);
-    hname_copy[hname->slen] = '\0';
 
     /* Binary search for the handler. */
@@ -565,5 +617,5 @@
 	handler_rec *mid = first + half;
 
-	comp = compare_handler(mid, hname_copy, hname->slen, hash);
+	comp = compare_handler(mid, hname->ptr, hname->slen, hash);
 	if (comp < 0) {
 	    first = ++mid;
@@ -580,4 +632,35 @@
 }
 
+
+/* Find handler to parse the header name. */
+static pjsip_parse_hdr_func* find_handler(const pj_str_t *hname)
+{
+    pj_uint32_t hash;
+    char hname_copy[PJSIP_MAX_HNAME_LEN];
+    pj_str_t tmp;
+    pjsip_parse_hdr_func *handler;
+
+    if (hname->slen >= PJSIP_MAX_HNAME_LEN) {
+	/* Guaranteed not to be able to find handler. */
+        return NULL;
+    }
+
+    /* First, common case, try to find handler with exact name */
+    hash = pj_hash_calc(0, hname->ptr, hname->slen);
+    handler = find_handler_imp(hash, hname);
+    if (handler)
+	return handler;
+
+
+    /* If not found, try converting the header name to lowercase and
+     * search again.
+     */
+    hash = pj_hash_calc_tolower(0, hname_copy, hname);
+    tmp.ptr = hname_copy;
+    tmp.slen = hname->slen;
+    return find_handler_imp(hash, &tmp);
+}
+
+
 /* Find URI handler. */
 static pjsip_parse_uri_func* find_uri_handler(const pj_str_t *scheme)
@@ -585,5 +668,5 @@
     unsigned i;
     for (i=0; i<uri_handler_count; ++i) {
-	if (pj_stricmp_alnum(&uri_handler[i].scheme, scheme)==0)
+	if (parser_stricmp(uri_handler[i].scheme, (*scheme))==0)
 	    return uri_handler[i].parse;
     }
@@ -962,6 +1045,6 @@
 {
     /* pname */
-    pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pname);
-    *pname = pj_str_unescape(pool, pname);
+    parser_get_and_unescape(scanner, pool, &pjsip_PARAM_CHAR_SPEC,
+			    &pjsip_PARAM_CHAR_SPEC_ESC, pname);
 
     /* init pvalue */
@@ -981,6 +1064,6 @@
 		}
 	    } else if(pj_cis_match(&pjsip_PARAM_CHAR_SPEC, *scanner->curptr)) {
-		pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pvalue);
-		*pvalue = pj_str_unescape(pool, pvalue);
+		parser_get_and_unescape(scanner, pool, &pjsip_PARAM_CHAR_SPEC, 
+					&pjsip_PARAM_CHAR_SPEC_ESC, pvalue);
 	    }
 	}
@@ -1008,6 +1091,6 @@
 
     /* hname */
-    pj_scan_get(scanner, &pjsip_HDR_CHAR_SPEC, hname);
-    *hname = pj_str_unescape(pool, hname);
+    parser_get_and_unescape(scanner, pool, &pjsip_HDR_CHAR_SPEC, 
+			    &pjsip_HDR_CHAR_SPEC_ESC, hname);
 
     /* Init hvalue */
@@ -1021,6 +1104,6 @@
 	    pj_cis_match(&pjsip_HDR_CHAR_SPEC, *scanner->curptr))
 	{
-	    pj_scan_get(scanner, &pjsip_HDR_CHAR_SPEC, hvalue);
-	    *hvalue = pj_str_unescape(pool, hvalue);
+	    parser_get_and_unescape(scanner, pool, &pjsip_HDR_CHAR_SPEC,
+				    &pjsip_HDR_CHAR_SPEC, hvalue);
 	}
     }
@@ -1064,11 +1147,11 @@
 				 pj_str_t *user, pj_str_t *pass)
 {
-    pj_scan_get( scanner, &pjsip_USER_SPEC, user);
-    *user = pj_str_unescape(pool, user);
+    parser_get_and_unescape(scanner, pool, &pjsip_USER_SPEC, 
+			    &pjsip_USER_SPEC_ESC, user);
 
     if ( *scanner->curptr == ':') {
 	pj_scan_get_char( scanner );
-	pj_scan_get( scanner, &pjsip_PASSWD_SPEC, pass);
-	*pass = pj_str_unescape(pool, pass);
+	parser_get_and_unescape(scanner, pool, &pjsip_PASSWD_SPEC,
+				&pjsip_PASSWD_SPEC_ESC, pass);
     } else {
 	pass->ptr = NULL;
@@ -1436,5 +1519,5 @@
 	int_parse_param( scanner, pool, &pname, &pvalue);
 	if (!parser_stricmp(pname, pjsip_Q_STR) && pvalue.slen) {
-	    char *dot_pos = memchr(pvalue.ptr, '.', pvalue.slen);
+	    char *dot_pos = pj_memchr(pvalue.ptr, '.', pvalue.slen);
 	    if (!dot_pos) {
 		hdr->q1000 = pj_strtoul(&pvalue);
Index: /pjproject/trunk/pjsip/src/pjsip/sip_tel_uri.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_tel_uri.c	(revision 582)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_tel_uri.c	(revision 583)
@@ -374,6 +374,10 @@
 
     /* Get the phone number. */
+#if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0
+    pj_scan_get_unescape(scanner, &pjsip_TEL_NUMBER_SPEC, &uri->number);
+#else
     pj_scan_get(scanner, &pjsip_TEL_NUMBER_SPEC, &uri->number);
     uri->number = pj_str_unescape(pool, &uri->number);
+#endif
 
     /* Get all parameters. */
Index: /pjproject/trunk/pjsip/src/pjsip/sip_uri.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_uri.c	(revision 582)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_uri.c	(revision 583)
@@ -104,4 +104,6 @@
     endbuf = buf + size;
 
+    PJ_UNUSED_ARG(pname_spec);
+
     do {
 	*buf++ = (char)sep;
Index: /pjproject/trunk/pjsip/src/test-pjsip/msg_test.c
===================================================================
--- /pjproject/trunk/pjsip/src/test-pjsip/msg_test.c	(revision 582)
+++ /pjproject/trunk/pjsip/src/test-pjsip/msg_test.c	(revision 583)
@@ -51,5 +51,5 @@
     /* 'Normal' message with all headers. */
     "INVITE sip:user@foo SIP/2.0\n"
-    "From: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=123457890123456\r"
+    "from: Hi I'm Joe <sip:joe.user@bar.otherdomain.com>;tag=123457890123456\r"
     "To: Fellow User <sip:user@foo.bar.domain.com>\r\n"
     "Call-ID: 12345678901234567890@bar\r\n"
@@ -791,5 +791,4 @@
     pj_status_t status;
 
-
     status = simple_test();
     if (status != PJ_SUCCESS)
