Index: pjproject/trunk/pjsip/src/pjsip/sip_parser.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_parser.c	(revision 54)
+++ pjproject/trunk/pjsip/src/pjsip/sip_parser.c	(revision 64)
@@ -24,4 +24,5 @@
 #include <pjsip/sip_transport.h>        /* rdata structure */
 #include <pjlib-util/scanner.h>
+#include <pjlib-util/string.h>
 #include <pj/except.h>
 #include <pj/log.h>
@@ -33,14 +34,18 @@
 #include <pj/assert.h>
 
-#define RESERVED    ";/?:@&=+$,"
-#define MARK	    "-_.!~*'()"
-#define ESCAPED	    "%"
-#define USER	    "&=+$,;?/"
-#define PASS	    "&=+$,"
-#define TOKEN	    "-.!%*_=`'~+"   /* '+' is because of application/pidf+xml
-                                     * in Content-Type! */
-#define HOST	    "_-."
-#define HEX_DIGIT   "abcdefABCDEF"
-#define PARAM_CHAR  "[]/:&+$" MARK "%"
+#define ALNUM
+#define RESERVED	    ";/?:@&=+$,"
+#define MARK		    "-_.!~*'()"
+#define UNRESERVED	    ALNUM MARK
+#define ESCAPED		    "%"
+#define USER_UNRESERVED	    "&=+$,;?/"
+#define PASS		    "&=+$,"
+#define TOKEN		    "-.!%*_=`'~+"   /* '+' is because of app/pidf+xml
+					     * in Content-Type! */
+#define HOST		    "_-."
+#define HEX_DIGIT	    "abcdefABCDEF"
+#define PARAM_CHAR	    "[]/:&+$" UNRESERVED ESCAPED
+#define HNV_UNRESERVED	    "[]/?:+$"
+#define HDR_CHAR	    HNV_UNRESERVED UNRESERVED ESCAPED
 
 #define PJSIP_VERSION		"SIP/2.0"
@@ -93,4 +98,5 @@
 	    pjsip_PARAM_CHAR_SPEC,      /* For scanning pname (or pvalue when
                                          * it's not quoted.) */
+	    pjsip_HDR_CHAR_SPEC,	/* Chars in hname or hvalue */
 	    pjsip_PROBE_USER_HOST_SPEC, /* Hostname characters. */
 	    pjsip_PASSWD_SPEC,	        /* Password. */
@@ -110,4 +116,7 @@
 				     pj_str_t *pname, 
 				     pj_str_t *pvalue);
+static void	    int_parse_hparam( pj_scanner *scanner,
+				      pj_str_t *hname,
+				      pj_str_t *hvalue );
 static void         int_parse_req_line( pj_scanner *scanner, 
 					pj_pool_t *pool,
@@ -272,7 +281,11 @@
     pj_cis_add_str(&pjsip_PARAM_CHAR_SPEC, PARAM_CHAR);
 
+    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_USER_SPEC, &pjsip_ALNUM_SPEC);
     PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
-    pj_cis_add_str( &pjsip_USER_SPEC, MARK ESCAPED USER );
+    pj_cis_add_str( &pjsip_USER_SPEC, ESCAPED USER_UNRESERVED );
 
     status = pj_cis_dup(&pjsip_PASSWD_SPEC, &pjsip_ALNUM_SPEC);
@@ -859,4 +872,5 @@
     /* pname */
     pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pname);
+    pj_str_unescape(pname);
 
     /* pvalue, if any */
@@ -872,4 +886,5 @@
 	} else {
 	    pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pvalue);
+	    pj_str_unescape(pvalue);
 	}
     } else {
@@ -890,4 +905,26 @@
 }
 
+/* Parse header parameter. */
+static void int_parse_hparam( pj_scanner *scanner,
+			      pj_str_t *hname, pj_str_t *hvalue )
+{
+    /* Get '?' or '&' character. */
+    pj_scan_get_char(scanner);
+
+    /* hname */
+    pj_scan_get(scanner, &pjsip_HDR_CHAR_SPEC, hname);
+    pj_str_unescape(hname);
+
+    /* pvalue, if any */
+    if (*scanner->curptr == '=') {
+	pj_scan_get_char(scanner);
+	pj_scan_get(scanner, &pjsip_HDR_CHAR_SPEC, hvalue);
+	pj_str_unescape(hvalue);
+    } else {
+	hvalue->ptr = NULL;
+	hvalue->slen = 0;
+    }
+}
+
 /* Parse host:port in URI. */
 static void int_parse_uri_host_port( pj_scanner *scanner, 
@@ -895,8 +932,10 @@
 {
     pj_scan_get( scanner, &pjsip_HOST_SPEC, host);
+    /* RFC3261 section 19.1.2: host don't need to be unescaped */
     if (*scanner->curptr == ':') {
 	pj_str_t port;
 	pj_scan_get_char(scanner);
 	pj_scan_get(scanner, &pjsip_DIGIT_SPEC, &port);
+	pj_str_unescape(&port);
 	*p_port = pj_strtoul(&port);
     } else {
@@ -927,7 +966,10 @@
 {
     pj_scan_get( scanner, &pjsip_USER_SPEC, user);
+    pj_str_unescape(user);
+
     if ( *scanner->curptr == ':') {
 	pj_scan_get_char( scanner );
 	pj_scan_get( scanner, &pjsip_PASSWD_SPEC, pass);
+	pj_str_unescape(pass);
     } else {
 	pass->ptr = NULL;
@@ -945,4 +987,7 @@
     pjsip_uri *uri;
     int is_name_addr = 0;
+
+    /* Exhaust any whitespaces. */
+    pj_scan_skip_whitespace(scanner);
 
     if (*scanner->curptr=='"' || *scanner->curptr=='<') {
@@ -1035,4 +1080,5 @@
     int colon;
     int skip_ws = scanner->skip_ws;
+    int hsep = '?';
     scanner->skip_ws = 0;
 
@@ -1090,12 +1136,18 @@
 
 	} else {
-	    concat_param(&url->other_param, pool, &pname, &pvalue);
+	    pjsip_param *p = pj_pool_alloc(pool, sizeof(pjsip_param));
+	    p->name = pname;
+	    p->value = pvalue;
+	    pj_list_insert_before(&url->other_param, p);
 	}
     }
 
     /* Get header params. */
-    if (parse_params && *scanner->curptr == '?') {
-	pj_scan_get_until(scanner, &pjsip_NEWLINE_OR_EOF_SPEC, 
-                          &url->header_param);
+    while (parse_params && *scanner->curptr == hsep) {
+	pjsip_param *param;
+	param = pj_pool_alloc(pool, sizeof(pjsip_param));
+	int_parse_hparam(scanner, &param->name, &param->value);
+	pj_list_insert_before(&url->header_param, param);
+	hsep = '&';
     }
 
