Index: utils.c
===================================================================
RCS file: /usr/cvsroot/asterisk/utils.c,v
retrieving revision 1.48
diff -u -r1.48 utils.c
--- utils.c	6 Jun 2005 22:12:18 -0000	1.48
+++ utils.c	7 Jun 2005 13:57:43 -0000
@@ -37,15 +37,50 @@
 static char base64[64];
 static char b2a[256];
 
-char *ast_strip(char *s)
+/*
+ * Advance the pointer past the 'blanks' (chars <= 33).
+ * A NULL argument is acceptable, it returns NULL in case.
+ */
+char *ast_skip_blanks(char *c)
+{
+	while (*c && *c < 33)
+		c++;
+	return c;
+}
+ 
+/*
+ * Remove trailing blanks. A NULL arg is acceptable.
+ */
+char *ast_trim_blanks(char *c)
 {
-	char *e;
+	if (c) {
+		c += strlen(c) - 1;
+		while (*c && *c < 33)
+			c--;
+		*(++c) = '\0'; /* terminate string */
+	}
+	return c;
+}
 
-	while (*s && (*s < 33)) s++;
-	e = s + strlen(s) - 1;
-	while ((e > s) && (*e < 33)) e--;
-	*++e = '\0';
+/*
+ * Skip all non-blank characters.
+ */
+char *ast_skip_nonblanks(char *c)
+{
+	while (*c && *c > 32)
+		c++;
+	return c;
+}
 
+/*
+ * Strip leading and trailing blanks.
+ * NULL argument is acceptable.
+ */
+char *ast_strip(char *s)
+{
+	s = ast_skip_blanks(s);
+	if (s)
+		ast_trim_blanks(s);
 	return s;
 } 
 
Index: channels/chan_sip.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v
retrieving revision 1.755
diff -u -r1.755 chan_sip.c
--- channels/chan_sip.c	6 Jun 2005 22:12:19 -0000	1.755
+++ channels/chan_sip.c	7 Jun 2005 13:58:03 -0000
@@ -761,6 +762,24 @@
 	return res;
 }
 
+/*
+ * If there is a string in <brackets>, strip everything around and return
+ * the content. Otherwise return the original argument.
+ */
+static char *get_in_brackets(char *c)
+{
+	char *n = strchr(c, '<');
+
+	if (n) {
+		c = n + 1;
+		n = strchr(c, '>');
+		/* Lose the part after the > */
+		if (n) 
+			*n = '\0';
+	}
+	return c;
+}
+
 /*--- sip_debug_test_addr: See if we pass debug IP filter */
 static inline int sip_debug_test_addr(struct sockaddr_in *addr) 
 {
@@ -1070,8 +1089,7 @@
 		}
 		cur = p->packets;
 		ast_copy_string(method, p->packets->data, sizeof(method));
-		c = method;
-		while(*c && (*c < 33)) c++;
+		c = ast_skip_blanks(method); /* XXX what ? */
 		*c = '\0';
 		__sip_ack(p, p->packets->seqno, (ast_test_flag(p->packets, FLAG_RESPONSE)), find_sip_method(method));
 	}
@@ -1181,27 +1199,19 @@
 	return res;
 }
 
-/*--- url_decode: Decode SIP URL  ---*/
+/*--- url_decode: Decode SIP URL (overwrite the string)  ---*/
 static void url_decode(char *s) 
 {
-	char *o = s;
+	char *o;
 	unsigned int tmp;
-	while(*s) {
-		switch(*s) {
-		case '%':
-			if (strlen(s) > 2) {
-				if (sscanf(s + 1, "%2x", &tmp) == 1) {
-					*o = tmp;
-					s += 2;	/* Will be incremented once more when we break out */
-					break;
-				}
-			}
-			/* Fall through if something wasn't right with the formatting */
-		default:
+
+	for (o = s; *s; s++, o++) {
+		if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) {
+			/* have '%', two chars and correct parsing */
+			*o = tmp;
+			s += 2;	/* Will be incremented once more when we break out */
+		} else /* all other cases, just copy */
 			*o = *s;
-		}
-		s++;
-		o++;
 	}
 	*o = '\0';
 }
@@ -2465,10 +2475,7 @@
 static char* get_sdp_by_line(char* line, char *name, int nameLen)
 {
 	if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=') {
-		char* r = line + nameLen + 1;
-		while (*r && (*r < 33)) 
-			++r;
-		return r;
+		return ast_skip_blanks(line + nameLen + 1);
 	}
 	return "";
 }
@@ -2509,49 +2516,45 @@
 	return "";
 }
 
-static char *__get_header(struct sip_request *req, char *name, int *start)
+static char *find_alias(const char *name, char *_default)
 {
 	int x;
-	int len = strlen(name);
-	char *r;
-	if (pedanticsipchecking) {
-		/* Technically you can place arbitrary whitespace both before and after the ':' in
-		   a header, although RFC3261 clearly says you shouldn't before, and place just
-		   one afterwards.  If you shouldn't do it, what absolute idiot decided it was 
-		   a good idea to say you can do it, and if you can do it, why in the hell would 
-		   you say you shouldn't.  */
+	for (x=0;x<sizeof(aliases) / sizeof(aliases[0]); x++) 
+		if (!strcasecmp(aliases[x].fullname, name))
+			return aliases[x].shortname;
+	return _default;
+}
+
+static char *__get_header(struct sip_request *req, char *name, int *start)
+{
+	int pass;
+
+	/*
+	 * Technically you can place arbitrary whitespace both before and after the ':' in
+	 * a header, although RFC3261 clearly says you shouldn't before, and place just
+	 * one afterwards.  If you shouldn't do it, what absolute idiot decided it was 
+	 * a good idea to say you can do it, and if you can do it, why in the hell would.
+	 * you say you shouldn't.
+	 * Anyways, pedanticsipchecking controls whether we allow spaces before ':',
+	 * and we always allow spaces after that for compatibility.
+	 */
+	for (pass = 0; name && pass < 2;pass++) {
+		int x, len = strlen(name);
 		for (x=*start; x<req->headers; x++) {
 			if (!strncasecmp(req->header[x], name, len)) {
-				r = req->header[x] + len;
-				while(*r && (*r < 33))
-					r++;
+				char *r = req->header[x] + len;	/* skip name */
+				if (pedanticsipchecking)
+					r = ast_skip_blanks(r);
+
 				if (*r == ':') {
-					r++ ;
-					while(*r && (*r < 33))
-						r++;
 					*start = x+1;
-					return r;
+					return ast_skip_blanks(r+1);
 				}
 			}
 		}
-	} else {
-		/* We probably shouldn't even bother counting whitespace afterwards but
-		   I guess for backwards compatibility we will */
-		for (x=*start;x<req->headers;x++) {
-			if (!strncasecmp(req->header[x], name, len) && 
-					(req->header[x][len] == ':')) {
-				r = req->header[x] + len + 1;
-				while(*r && (*r < 33))
-					r++;
-				*start = x+1;
-				return r;
-			}
-		}
+		if (pass == 0) /* Try aliases */
+			name = find_alias(name, NULL);
 	}
-	/* Try aliases */
-	for (x=0;x<sizeof(aliases) / sizeof(aliases[0]); x++) 
-		if (!strcasecmp(aliases[x].fullname, name))
-			return __get_header(req, aliases[x].shortname, start);
 
 	/* Don't return NULL, so get_header is always a valid pointer */
 	return "";
@@ -3050,9 +3053,7 @@
 				if (debug)
 					ast_verbose("Found RTP audio format %d\n", codec);
 				ast_rtp_set_m_type(p->rtp, codec);
-				codecs += len;
-				/* Skip over any whitespace */
-				while(*codecs && (*codecs < 33)) codecs++;
+				codecs = ast_skip_blanks(codecs + len);
 			}
 		}
 		if (p->vrtp)
@@ -3072,9 +3073,7 @@
 				if (debug)
 					ast_verbose("Found video format %s\n", ast_getformatname(codec));
 				ast_rtp_set_m_type(p->vrtp, codec);
-				codecs += len;
-				/* Skip over any whitespace */
-				while(*codecs && (*codecs < 33)) codecs++;
+				codecs = ast_skip_blanks(codecs + len);
 			}
 		}
 		if (!found )
@@ -3613,19 +3612,9 @@
 		c = p->uri;
 	} else {
 		/* We have no URI, use To: or From:  header as URI (depending on direction) */
-		if (ast_test_flag(p, SIP_OUTGOING))
-			ast_copy_string(stripped, get_header(orig, "To"), sizeof(stripped));
-		else
-			ast_copy_string(stripped, get_header(orig, "From"), sizeof(stripped));
-		
-		c = strchr(stripped, '<');
-		if (c) 
-			c++;
-		else
-			c = stripped;
-		n = strchr(c, '>');
-		if (n)
-			*n = '\0';
+		c = get_header(orig, (ast_test_flag(p, SIP_OUTGOING)) ? "To" : "From");
+		ast_copy_string(stripped, c, sizeof(stripped));
+		c = get_in_brackets(stripped);
 		n = strchr(c, ';');
 		if (n)
 			*n = '\0';
@@ -4010,29 +3999,17 @@
 	char *e, *cmd;
 	int len;
   
-	cmd = req->header[0];
-	while(*cmd && (*cmd < 33)) {
-		cmd++;
-	}
-	if (!*cmd) {
+	cmd = ast_skip_blanks(req->header[0]);
+	if (!*cmd)
 		return -1;
-	}
-	e = cmd;
-	while(*e && (*e > 32)) {
-		e++;
-	}
-	/* Get the command */
-	if (*e) {
-		*e = '\0';
-		e++;
-	}
 	req->rlPart1 = cmd;
-	while( *e && ( *e < 33 ) ) {
-		e++; 
-	}
-	if ( !*e ) {
+	e = ast_skip_nonblanks(cmd);
+	/* Get the command */
+	if (*e)
+		*e++ = '\0';
+	e = ast_skip_blanks(e);
+	if ( !*e )
 		return -1;
-	}
     
 	if ( !strcasecmp(cmd, "SIP/2.0") ) {
 		/* We have a response */
@@ -4041,11 +4018,7 @@
 		if ( len < 2 ) { 
 			return -1;
 		}
-		e+= len - 1;
-		while( *e && *e < 33 ) {
-			e--; 
-		}
-		*(++e)= '\0';
+		ast_trim_blanks(e);
 	} else {
 		/* We have a request */
 		if ( *e == '<' ) { 
@@ -4058,6 +4031,7 @@
 		if ( ( e= strrchr( req->rlPart2, 'S' ) ) == NULL ) {
 			return -1;
 		}
+		/* XXX maybe trim_blanks() ? */
 		while( isspace( *(--e) ) ) {}
 		if ( *e == '>' ) {
 			*e = '\0';
@@ -4102,14 +4076,7 @@
 	char stripped[256]="";
 	char *c, *n;
 	ast_copy_string(stripped, get_header(req, "Contact"), sizeof(stripped));
-	c = strchr(stripped, '<');
-	if (c) 
-		c++;
-	else
-		c = stripped;
-	n = strchr(c, '>');
-	if (n)
-		*n = '\0';
+	c = get_in_brackets(stripped);
 	n = strchr(c, ';');
 	if (n)
 		*n = '\0';
@@ -4999,16 +4966,7 @@
 
 	/* Look for brackets */
 	ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
-	c = contact;
-	
-	if ((n=strchr(c, '<'))) {
-		c = n + 1;
-		n = strchr(c, '>');
-		/* Lose the part after the > */
-		if (n) 
-			*n = '\0';
-	}
-
+	c = get_in_brackets(contact);
 
 	/* Save full contact to call pvt for later bye or re-invite */
 	ast_copy_string(pvt->fullcontact, c, sizeof(pvt->fullcontact));	
@@ -5093,15 +5051,8 @@
 	}
 	/* Look for brackets */
 	ast_copy_string(contact, get_header(req, "Contact"), sizeof(contact));
-	c = contact;
-	
-	if ((n=strchr(c, '<'))) {
-		c = n + 1;
-		n = strchr(c, '>');
-		/* Lose the part after the > */
-		if (n) 
-			*n = '\0';
-	}
+	c = get_in_brackets(contact);
+
 	if (!strcasecmp(c, "*") || !expiry) {	/* Unregister this peer */
 		/* This means remove all registrations and return OK */
 		memset(&p->addr, 0, sizeof(p->addr));
@@ -5416,7 +5367,7 @@
 		c = tmp;
 
 		while(c) {
-			while (*c && (*c < 33)) c++;
+			c = ast_skip_blanks(c);
 			if (!*c)
 				break;
 			if (!strncasecmp(c, "response=", strlen("response="))) {
@@ -5738,19 +5689,6 @@
 	return -1;
 }
 
-/*--- hex2int: Convert hex code to integer ---*/
-static int hex2int(char a)
-{
-	if ((a >= '0') && (a <= '9')) {
-		return a - '0';
-	} else if ((a >= 'a') && (a <= 'f')) {
-		return a - 'a' + 10;
-	} else if ((a >= 'A') && (a <= 'F')) {
-		return a - 'A' + 10;
-	}
-	return 0;
-}
-
 /*--- get_sip_pvt_byid_locked: Lock interface lock and find matching pvt lock  ---*/
 static struct sip_pvt *get_sip_pvt_byid_locked(char *callid) 
 {
@@ -5780,27 +5718,6 @@
 	return sip_pvt_ptr;
 }
 
-/*--- sip_unescape_uri: Turn %XX into and ascii char ---*/
-static int sip_unescape_uri(char *uri) 
-{
-	char *ptr = uri;
-	int replaced = 0;
-
-	while ((ptr = strchr(ptr, '%'))) {
-		/* un-escape urlencoded text */
-		if (strlen(ptr) < 3)
-			break;
-		*ptr = hex2int(ptr[1]) * 16 + hex2int(ptr[2]);
-		memmove(ptr+1, ptr+3, strlen(ptr+3) + 1);
-		ptr++;
-		replaced++;
-	}
-
-	return replaced;
-}
-
-
-
 /*--- get_refer_info: Call transfer support (the REFER method) ---*/
 static int get_refer_info(struct sip_pvt *sip_pvt, struct sip_request *outgoing_req)
 {
@@ -5851,19 +5768,21 @@
 		*ptr = '\0';
 		ptr++;
 		if (!strncasecmp(ptr, "REPLACES=", 9)) {
+			char *p;
 			replace_callid = ast_strdupa(ptr + 9);
 			/* someday soon to support invite/replaces properly!
 			   replaces_header = ast_strdupa(replace_callid); 
 			   -anthm
 			*/
-			sip_unescape_uri(replace_callid);
+			url_decode(replace_callid);
 			if ((ptr = strchr(replace_callid, '%'))) 
 				*ptr = '\0';
 			if ((ptr = strchr(replace_callid, ';'))) 
 				*ptr = '\0';
-			/* Skip leading whitespace */
-			while(replace_callid[0] && (replace_callid[0] < 33))
-				memmove(replace_callid, replace_callid+1, strlen(replace_callid));
+			/* Skip leading whitespace XXX memmove behaviour with overlaps ? */
+			p = ast_skip_blanks(replace_callid);
+			if (p != replace_callid)
+				memmove(replace_callid, p, strlen(p));
 		}
 	}
 	
@@ -5989,18 +5908,14 @@
 	c = strchr(via, ' ');
 	if (c) {
 		*c = '\0';
-		c++;
-		while(*c && (*c < 33))
-			c++;
+		c = ast_skip_blanks(c+1);
 		if (strcmp(via, "SIP/2.0/UDP")) {
 			ast_log(LOG_WARNING, "Don't know how to respond via '%s'\n", via);
 			return -1;
 		}
 		pt = strchr(c, ':');
-		if (pt) {
-			*pt = '\0';
-			pt++;
-		}
+		if (pt)
+			*pt++ = '\0';	/* remeber port pointer */
 		hp = ast_gethostbyname(c, &ahp);
 		if (!hp) {
 			ast_log(LOG_WARNING, "'%s' is not a valid host\n", c);
@@ -6011,13 +5926,11 @@
 		memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr));
 		p->sa.sin_port = htons(pt ? atoi(pt) : DEFAULT_SIP_PORT);
 		c = strstr(via, ";rport");
-		if (c && (c[6] != '='))
+		if (c && (c[6] != '='))	/* XXX some special hack ? */
 			ast_set_flag(p, SIP_NAT_ROUTE);
 		if (sip_debug_test_pvt(p)) {
-			if (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)
-				ast_verbose("Sending to %s : %d (NAT)\n", ast_inet_ntoa(iabuf, sizeof(iabuf), p->sa.sin_addr), ntohs(p->sa.sin_port));
-			else
-				ast_verbose("Sending to %s : %d (non-NAT)\n", ast_inet_ntoa(iabuf, sizeof(iabuf), p->sa.sin_addr), ntohs(p->sa.sin_port));
+			c = (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE) ? "NAT" : "non-NAT";
+			ast_verbose("Sending to %s : %d (%s)\n", ast_inet_ntoa(iabuf, sizeof(iabuf), p->sa.sin_addr), ntohs(p->sa.sin_port), c);
 		}
 	}
 	return 0;
@@ -6046,8 +5959,7 @@
 	} else {
 		/* we didn't find "name" */
 		/* clear the empty characters in the begining*/
-		while(*input && (*input < 33))
-			input++;
+		input = ast_skip_blanks(input);
 		/* clear the empty characters in the end */
 		while(*end && (*end < 33) && end > input)
 			end--;
@@ -9371,8 +9283,7 @@
 		ast_log(LOG_DEBUG, "No seqno in '%s'\n", cmd);
 		return -1;
 	}
-	/* Get the command */
-	cseq += len;
+	/* Get the command XXX */
 
 	cmd = req->rlPart1;
 	e = req->rlPart2;
@@ -9399,8 +9310,7 @@
 		}
 	
 		extract_uri(p, req);
-		while(*e && (*e < 33)) 
-			e++;
+		e = ast_skip_blanks(e);
 		if (sscanf(e, "%d %n", &respid, &len) != 1) {
 			ast_log(LOG_WARNING, "Invalid response: '%s'\n", e);
 		} else {
@@ -9408,7 +9318,7 @@
 		}
 		return 0;
 	}
-
+	/* XXX what if not SIP/2.0 ? */
 	/* New SIP request coming in 
 	   (could be new request in existing SIP dialog as well...) 
 	 */			
Index: include/asterisk/utils.h
===================================================================
RCS file: /usr/cvsroot/asterisk/include/asterisk/utils.h,v
retrieving revision 1.31
diff -u -r1.31 utils.h
--- include/asterisk/utils.h	20 May 2005 16:30:13 -0000	1.31
+++ include/asterisk/utils.h	7 Jun 2005 13:58:13 -0000
@@ -17,6 +17,7 @@
 #endif
 
 #include <netinet/in.h>
+#include <arpa/inet.h>	/* we want to override inet_ntoa */
 #include <netdb.h>
 #include <pthread.h>
 #include <limits.h>
@@ -129,6 +130,22 @@
 	struct hostent hp;
 	char buf[1024];
 };
+
+/*!
+ Advance the pointer past the 'blanks' (chars <= 33).
+ A NULL argument is acceptable, it returns NULL in case.
+*/
+char *ast_skip_blanks(char *c);
+
+/*!
+   Remove trailing blanks. A NULL arg is acceptable.
+ */
+char *ast_trim_blanks(char *c);
+
+/*!
+   Skip all non-blank characters.
+*/
+char *ast_skip_nonblanks(char *c);
 
 /*!
   \brief Strip leading/trailing whitespace from a string.
