Index: channels/chan_sip.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v
retrieving revision 1.759
diff -u -u -r1.759 chan_sip.c
--- channels/chan_sip.c	9 Jun 2005 22:41:18 -0000	1.759
+++ channels/chan_sip.c	13 Jun 2005 22:27:13 -0000
@@ -728,6 +728,8 @@
 static int clear_realm_authentication(struct sip_auth *authlist);                            /* Clear realm authentication list (at reload) */
 static struct sip_auth *add_realm_authentication(struct sip_auth *authlist, char *configuration, int lineno);   /* Add realm authentication in list */
 static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, char *realm);         /* Find authentication for a specific realm */
+static int sip_escape_uri(char *uri, char *buf, size_t len);
+static int sip_unescape_uri(char *uri);
 
 /* Definition of this channel for channel registration */
 static const struct ast_channel_tech sip_tech = {
@@ -1338,6 +1340,7 @@
 	struct ast_variable *var;
 	struct ast_variable *tmp;
 	char *newpeername = (char *) peername;
+	char *fullcontact = NULL;
 	char iabuf[80] = "";
 
 	/* First check on peer name */
@@ -1362,6 +1365,10 @@
 		} else if (!newpeername && !strcasecmp(tmp->name, "name")) {
 			newpeername = tmp->value;
 		}
+		if (!strcasecmp(tmp->name, "fullcontact")) {
+			fullcontact = ast_strdupa(tmp->value);
+			sip_unescape_uri(fullcontact);
+		}
 		tmp = tmp->next;
 	}
 	
@@ -1373,6 +1380,9 @@
 		
 	/* Peer found in realtime, now build it in memory */
 	peer = build_peer(newpeername, var, !ast_test_flag((&global_flags_page2), SIP_PAGE2_RTCACHEFRIENDS));
+	if (fullcontact) {
+		ast_copy_string(peer->fullcontact, fullcontact, sizeof(peer->fullcontact));
+	}
 
 	if (!peer) {
 		ast_variables_destroy(var);
@@ -4955,8 +4965,14 @@
 	int port;
 	char *scan, *addr, *port_str, *expiry_str, *username, *contact;
 
-	if (ast_db_get("SIP/Registry", peer->name, data, sizeof(data)))
-		return;
+
+	if (!(ast_test_flag(peer, SIP_REALTIME) && ast_test_flag((&peer->flags_page2), SIP_PAGE2_RTCACHEFRIENDS))) {
+		if (ast_db_get("SIP/Registry", peer->name, data, sizeof(data))) {
+			return;
+		}
+	} else {
+		ast_copy_string(data, peer->fullcontact, sizeof(data));
+	}
 
 	scan = data;
 	addr = strsep(&scan, ":");
@@ -5137,6 +5153,11 @@
 		return 0;
 	}
 	ast_copy_string(p->fullcontact, c, sizeof(p->fullcontact));
+	if (!ast_test_flag((&global_flags_page2), SIP_PAGE2_RTNOUPDATE)) {
+		char buf[128];
+		sip_escape_uri(c, buf, sizeof(buf));
+		ast_update_realtime("sippeers", "name", p->name, "fullcontact", buf, NULL);
+	}
 	/* For the 200 OK, we should use the received contact */
 	snprintf(pvt->our_contact, sizeof(pvt->our_contact) - 1, "<%s>", c);
 	/* Make sure it's a SIP URL */
@@ -5197,8 +5218,13 @@
 		p->expire = -1;
 	pvt->expiry = expiry;
 	snprintf(data, sizeof(data), "%s:%d:%d:%s:%s", ast_inet_ntoa(iabuf, sizeof(iabuf), p->addr.sin_addr), ntohs(p->addr.sin_port), expiry, p->username, p->fullcontact);
-	if (!(ast_test_flag(p, SIP_REALTIME) && ast_test_flag((&p->flags_page2), SIP_PAGE2_RTCACHEFRIENDS)))
+	if (!(ast_test_flag(p, SIP_REALTIME) && ast_test_flag((&p->flags_page2), SIP_PAGE2_RTCACHEFRIENDS))) {
 		ast_db_put("SIP/Registry", p->name, data);
+	} else {
+		char buf[128];
+		sip_escape_uri(data, buf, sizeof(buf));
+		ast_update_realtime("sippeers", "name", p->name, "fullcontact", buf, NULL);
+	}
 	manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Registered\r\n", p->name);
 	if (inaddrcmp(&p->addr, &oldsin)) {
 		sip_poke_peer(p);
@@ -5797,7 +5823,28 @@
 	return sip_pvt_ptr;
 }
 
-/*--- sip_unescape_uri: Turn %XX into and ascii char ---*/
+/*--- sip_escape_uri: Turn an ascii char into %XX---*/
+static int sip_escape_uri(char *uri, char *buf, size_t len)
+{
+    char *p;
+    int x = 0;
+    const char urlunsafe[] = " \"#%&+:;<=>?@[\\]^`{|}";
+    const char hex[] = "0123456789ABCDEF";
+
+    memset(buf, 0, len);
+    for( p = uri ; *p ; p++) {
+        if (*p < ' ' || *p > '~' || strchr(urlunsafe, *p)) {
+            buf[x++] = '%';
+            buf[x++] = hex[*p >> 4];
+            buf[x++] = hex[*p & 0x0f];
+        } else {
+            buf[x++] = *p;
+        }
+    }
+	return x;
+}
+
+/*--- sip_unescape_uri: Turn %XX into an ascii char ---*/
 static int sip_unescape_uri(char *uri) 
 {
 	char *ptr = uri;
@@ -10454,12 +10501,15 @@
 			continue;
 		}
 
-		if (realtime && !strcasecmp(v->name, "regseconds")) {
+		if (!strcasecmp(v->name, "regseconds")) {
 			if (sscanf(v->value, "%li", &regseconds) != 1)
 				regseconds = 0;
-		} else if (realtime && !strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) {
+		} else if (!strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) {
 			inet_aton(v->value, &(peer->addr.sin_addr));
-		} else if (realtime && !strcasecmp(v->name, "name"))
+			if (ast_test_flag((&global_flags_page2), SIP_PAGE2_RTIGNOREREGEXPIRE)) {
+				found++;
+			}
+		} else if (!strcasecmp(v->name, "name"))
 			ast_copy_string(peer->name, v->value, sizeof(peer->name));
 		else if (!strcasecmp(v->name, "secret")) 
 			ast_copy_string(peer->secret, v->value, sizeof(peer->secret));
@@ -10525,7 +10575,7 @@
 			maskfound++;
 			inet_aton(v->value, &peer->mask);
 		} else if (!strcasecmp(v->name, "port")) {
-			if (!realtime && ast_test_flag(peer, SIP_DYNAMIC))
+			if (ast_test_flag(peer, SIP_DYNAMIC))
 				peer->defaddr.sin_port = htons(atoi(v->value));
 			else
 				peer->addr.sin_port = htons(atoi(v->value));
@@ -10609,12 +10659,14 @@
 		 */
 		v=v->next;
 	}
-	if (realtime && !ast_test_flag((&global_flags_page2), SIP_PAGE2_RTIGNOREREGEXPIRE) && ast_test_flag(peer, SIP_DYNAMIC)) {
+
+	if (!ast_test_flag((&global_flags_page2), SIP_PAGE2_RTIGNOREREGEXPIRE) && ast_test_flag(peer, SIP_DYNAMIC)) {
 		time_t nowtime;
 
 		time(&nowtime);
 		if ((nowtime - regseconds) > 0) {
 			memset(&peer->addr, 0, sizeof(peer->addr));
+			ast_update_realtime("sippeers", "name", peer->name, "fullcontact", "", NULL);
 			if (option_debug)
 				ast_log(LOG_DEBUG, "Bah, we're expired (%ld/%ld/%ld)!\n", nowtime - regseconds, regseconds, nowtime);
 		}
