Index: pjproject/branches/1.0/pjsip/src/pjsip/sip_parser.c
===================================================================
--- pjproject/branches/1.0/pjsip/src/pjsip/sip_parser.c	(revision 2420)
+++ pjproject/branches/1.0/pjsip/src/pjsip/sip_parser.c	(revision 2538)
@@ -54,6 +54,4 @@
  */
 #define GENERIC_URI_CHARS   "#?;:@&=+-_.!~*'()%$,/" "%"
-
-#define PJSIP_VERSION		"SIP/2.0"
 
 #define UNREACHED(expr)
@@ -328,4 +326,12 @@
     pj_cis_del_str(&pconst.pjsip_TOKEN_SPEC_ESC, "%");
 
+    status = pj_cis_dup(&pconst.pjsip_VIA_PARAM_SPEC, &pconst.pjsip_TOKEN_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_add_str(&pconst.pjsip_VIA_PARAM_SPEC, ":");
+
+    status = pj_cis_dup(&pconst.pjsip_VIA_PARAM_SPEC_ESC, &pconst.pjsip_TOKEN_SPEC_ESC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_add_str(&pconst.pjsip_VIA_PARAM_SPEC, ":");
+
     status = pj_cis_dup(&pconst.pjsip_HOST_SPEC, &pconst.pjsip_ALNUM_SPEC);
     PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
@@ -773,4 +779,6 @@
     const char *line;
     int content_length = -1;
+    pj_str_t cur_msg;
+    const pj_str_t end_hdr = { "\n\r\n", 3};
 
     *msg_size = size;
@@ -782,6 +790,10 @@
 
 
-    /* Find the end of header area by finding an empty line. */
-    pos = pj_ansi_strstr(buf, "\n\r\n");
+    /* Find the end of header area by finding an empty line. 
+     * Don't use plain strstr() since we want to be able to handle
+     * NULL character in the message
+     */
+    cur_msg.ptr = (char*)buf; cur_msg.slen = size;
+    pos = pj_strstr(&cur_msg, &end_hdr);
     if (pos == NULL) {
 	return PJSIP_EPARTIALMSG;
@@ -792,5 +804,5 @@
 
     /* Find "Content-Length" header the hard way. */
-    line = pj_ansi_strchr(buf, '\n');
+    line = pj_strchr(&cur_msg, '\n');
     while (line && line < hdr_end) {
 	++line;
@@ -843,5 +855,7 @@
 
 	/* Go to next line. */
-	line = pj_ansi_strchr(line, '\n');
+	cur_msg.slen -= (line - cur_msg.ptr);
+	cur_msg.ptr = (char*)line;
+	line = pj_strchr(&cur_msg, '\n');
     }
 
@@ -894,4 +908,34 @@
 }
 
+/* SIP version */
+static void parse_sip_version(pj_scanner *scanner)
+{
+    pj_str_t SIP = { "SIP", 3 };
+    pj_str_t V2 = { "2.0", 3 };
+    pj_str_t sip, version;
+
+    pj_scan_get( scanner, &pconst.pjsip_ALPHA_SPEC, &sip);
+    if (pj_scan_get_char(scanner) != '/')
+	on_syntax_error(scanner);
+    pj_scan_get_n( scanner, 3, &version);
+    if (pj_stricmp(&sip, &SIP) || pj_stricmp(&version, &V2))
+	on_syntax_error(scanner);
+}
+
+static pj_bool_t is_next_sip_version(pj_scanner *scanner)
+{
+    pj_str_t SIP = { "SIP", 3 };
+    pj_str_t sip;
+    int c;
+
+    c = pj_scan_peek(scanner, &pconst.pjsip_ALPHA_SPEC, &sip);
+    /* return TRUE if it is "SIP" followed by "/" or space.
+     * we include space since the "/" may be separated by space,
+     * although this would mean it would return TRUE if it is a
+     * request and the method is "SIP"!
+     */
+    return c && (c=='/' || c==' ' || c=='\t') && pj_stricmp(&sip, &SIP)==0;
+}
+
 /* Internal function to parse SIP message */
 static pjsip_msg *int_parse_msg( pjsip_parse_ctx *ctx,
@@ -927,5 +971,5 @@
 
 	/* Parse request or status line */
-	if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION, 7) == 0) {
+	if (is_next_sip_version(scanner)) {
 	    msg = pjsip_msg_create(pool, PJSIP_RESPONSE_MSG);
 	    int_parse_status_line( scanner, &msg->line.status );
@@ -1126,5 +1170,5 @@
 
 
-/* Parse parameter (";" pname ["=" pvalue]) in header. */
+/* Parse parameter (";" pname ["=" pvalue]) in SIP header. */
 static void int_parse_param( pj_scanner *scanner, pj_pool_t *pool,
 			     pj_str_t *pname, pj_str_t *pvalue,
@@ -1514,7 +1558,5 @@
 
     req_line->uri = int_parse_uri(scanner, pool, PJ_TRUE);
-    if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION, 7) != 0)
-	PJ_THROW( PJSIP_SYN_ERR_EXCEPTION);
-    pj_scan_advance_n (scanner, 7, 1);
+    parse_sip_version(scanner);
     pj_scan_get_newline( scanner );
 }
@@ -1526,8 +1568,5 @@
     pj_str_t token;
 
-    if (pj_scan_stricmp_alnum(scanner, PJSIP_VERSION, 7) != 0)
-	PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
-    pj_scan_advance_n( scanner, 7, 1);
-
+    parse_sip_version(scanner);
     pj_scan_get( scanner, &pconst.pjsip_DIGIT_SPEC, &token);
     status_line->code = pj_strtoul(&token);
@@ -1619,10 +1658,30 @@
 /* Parse generic string header. */
 static void parse_generic_string_hdr( pjsip_generic_string_hdr *hdr,
-				      pj_scanner *scanner )
-{
-    if (pj_cis_match(&pconst.pjsip_NOT_NEWLINE, *scanner->curptr))
+				      pjsip_parse_ctx *ctx)
+{
+    pj_scanner *scanner = ctx->scanner;
+
+    hdr->hvalue.slen = 0;
+
+    /* header may be mangled hence the loop */
+    while (pj_cis_match(&pconst.pjsip_NOT_NEWLINE, *scanner->curptr)) {
+	pj_str_t next, tmp;
+
 	pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &hdr->hvalue);
-    else
-	hdr->hvalue.slen = 0;
+	if (pj_scan_is_eof(scanner) || IS_NEWLINE(*scanner->curptr))
+	    break;
+	/* mangled, get next fraction */
+	pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &next);
+	/* concatenate */
+	tmp.ptr = (char*)pj_pool_alloc(ctx->pool, 
+				       hdr->hvalue.slen + next.slen + 2);
+	tmp.slen = 0;
+	pj_strcpy(&tmp, &hdr->hvalue);
+	pj_strcat2(&tmp, " ");
+	pj_strcat(&tmp, &next);
+	tmp.ptr[tmp.slen] = '\0';
+
+	hdr->hvalue = tmp;
+    }
 
     parse_hdr_end(scanner);
@@ -1935,11 +1994,18 @@
 
 	//Parse with PARAM_CHAR instead, to allow IPv6
+	//No, back to using int_parse_param() for the "`" character!
 	//int_parse_param( scanner, pool, &pname, &pvalue, 0);
-	/* Get ';' character */
+	//parse_param_imp(scanner, pool, &pname, &pvalue, 
+	//		&pconst.pjsip_TOKEN_SPEC,
+	//		&pconst.pjsip_TOKEN_SPEC_ESC, 0);
+	//int_parse_param(scanner, pool, &pname, &pvalue, 0);
+	// This should be the correct one:
+	//  added special spec for Via parameter, basically token plus
+	//  ":" to allow IPv6 address in the received param.
 	pj_scan_get_char(scanner);
-
-	parse_param_imp(scanner, pool, &pname, &pvalue, 
-			&pconst.pjsip_PARAM_CHAR_SPEC,
-			&pconst.pjsip_PARAM_CHAR_SPEC_ESC, 0);
+	parse_param_imp(scanner, pool, &pname, &pvalue,
+			&pconst.pjsip_VIA_PARAM_SPEC,
+			&pconst.pjsip_VIA_PARAM_SPEC_ESC,
+			0);
 
 	if (!parser_stricmp(pname, pconst.pjsip_BRANCH_STR) && pvalue.slen) {
@@ -2076,8 +2142,7 @@
 	    pj_list_insert_before(first, hdr);
 
-	if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION "/", 8) != 0)
-	    PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
-
-	pj_scan_advance_n( scanner, 8, 1);
+	parse_sip_version(scanner);
+	if (pj_scan_get_char(scanner) != '/')
+	    on_syntax_error(scanner);
 
 	pj_scan_get( scanner, &pconst.pjsip_TOKEN_SPEC, &hdr->transport);
@@ -2120,5 +2185,5 @@
 
     hdr = pjsip_generic_string_hdr_create(ctx->pool, NULL, NULL);
-    parse_generic_string_hdr(hdr, ctx->scanner);
+    parse_generic_string_hdr(hdr, ctx);
     return (pjsip_hdr*)hdr;
 
