diff --git a/linphone/coreapi/Makefile.am b/linphone/coreapi/Makefile.am
index 562cf8d1d001d6ab55a2946242c981696d427549..c0a28ade3f4c1c539773f1804fb7fa2e221c183a 100644
--- a/linphone/coreapi/Makefile.am
+++ b/linphone/coreapi/Makefile.am
@@ -17,6 +17,7 @@ liblinphone_la_SOURCES=\
 	linphonecore.c linphonecore.h private.h\
 	exevents.c exevents.h \
 	misc.c  \
+	address.c \
 	enum.c enum.h \
 	sdphandler.c sdphandler.h \
 	presence.c \
diff --git a/linphone/coreapi/address.c b/linphone/coreapi/address.c
new file mode 100644
index 0000000000000000000000000000000000000000..36f6de9035a21db954e0906e3f74f81533edf058
--- /dev/null
+++ b/linphone/coreapi/address.c
@@ -0,0 +1,184 @@
+/*
+linphone
+Copyright (C) 2009  Simon MORLAT (simon.morlat@linphone.org)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#include "linphonecore.h"
+#include "lpconfig.h"
+#include "private.h"
+#include <eXosip2/eXosip.h>
+
+/**
+ * @addtogroup linphone_address
+ * @{
+**/
+
+/**
+ * Constructs a LinphoneAddress object by parsing the user supplied address,
+ * given as a string.
+**/
+LinphoneAddress * linphone_address_new(const char *uri){
+	osip_from_t *from;
+	osip_from_init(&from);
+	if (osip_from_parse(from,uri)!=0){
+		osip_from_free(from);
+		return NULL;
+	}
+	return from;
+}
+
+/**
+ * Clones a LinphoneAddress object.
+**/
+LinphoneAddress * linphone_address_clone(const LinphoneAddress *uri){
+	osip_from_t *ret=NULL;
+	osip_from_clone(uri,&ret);
+	return ret;
+}
+
+#define null_if_empty(s) (((s)!=NULL && (s)[0]!='\0') ? (s) : NULL )
+
+/**
+ * Returns the address scheme, normally "sip".
+**/
+const char *linphone_address_get_scheme(const LinphoneAddress *u){
+	return null_if_empty(u->url->scheme);
+}
+
+/**
+ * Returns the display name.
+**/
+const char *linphone_address_get_display_name(const LinphoneAddress* u){
+	return null_if_empty(u->displayname);
+}
+
+/**
+ * Returns the username.
+**/
+const char *linphone_address_get_username(const LinphoneAddress *u){
+	return null_if_empty(u->url->username);
+}
+
+/**
+ * Returns the domain name.
+**/
+const char *linphone_address_get_domain(const LinphoneAddress *u){
+	return null_if_empty(u->url->host);
+}
+
+/**
+ * Sets the display name.
+**/
+void linphone_address_set_display_name(LinphoneAddress *u, const char *display_name){
+	if (u->displayname!=NULL){
+		osip_free(u->displayname);
+		u->displayname=NULL;
+	}
+	if (display_name!=NULL)
+		u->displayname=osip_strdup(display_name);
+}
+
+/**
+ * Sets the username.
+**/
+void linphone_address_set_username(LinphoneAddress *uri, const char *username){
+	if (uri->url->username!=NULL){
+		osip_free(uri->url->username);
+		uri->url->username=NULL;
+	}
+	if (username)
+		uri->url->username=osip_strdup(username);
+}
+
+/**
+ * Sets the domain.
+**/
+void linphone_address_set_domain(LinphoneAddress *uri, const char *host){
+	if (uri->url->host!=NULL){
+		osip_free(uri->url->host);
+		uri->url->host=NULL;
+	}
+	if (host)
+		uri->url->host=osip_strdup(host);
+}
+
+/**
+ * Sets the port number.
+**/
+void linphone_address_set_port(LinphoneAddress *uri, const char *port){
+	if (uri->url->port!=NULL){
+		osip_free(uri->url->port);
+		uri->url->port=NULL;
+	}
+	if (port)
+		uri->url->port=osip_strdup(port);
+}
+
+/**
+ * Sets the port number.
+**/
+void linphone_address_set_port_int(LinphoneAddress *uri, int port){
+	char tmp[12];
+	if (port==5060){
+		/*this is the default, special case to leave the port field blank*/
+		linphone_address_set_port(uri,NULL);
+		return;
+	}
+	snprintf(tmp,sizeof(tmp),"%i",port);
+	linphone_address_set_port(uri,tmp);
+}
+
+/**
+ * Removes address's tags and uri headers so that it is displayable to the user.
+**/
+void linphone_address_clean(LinphoneAddress *uri){
+	osip_generic_param_freelist(&uri->gen_params);
+}
+
+/**
+ * Returns the address as a string.
+ * The returned char * must be freed by the application. Use ms_free().
+**/
+char *linphone_address_as_string(const LinphoneAddress *u){
+	char *tmp,*ret;
+	osip_from_to_str(u,&tmp);
+	ret=ms_strdup(tmp);
+	osip_free(tmp);
+	return ret;
+}
+
+/**
+ * Returns the SIP uri only as a string, that is display name is removed.
+ * The returned char * must be freed by the application. Use ms_free().
+**/
+char *linphone_address_as_string_uri_only(const LinphoneAddress *u){
+	char *tmp=NULL,*ret;
+	osip_uri_to_str(u->url,&tmp);
+	ret=ms_strdup(tmp);
+	osip_free(tmp);
+	return ret;
+}
+
+/**
+ * Destroys a LinphoneAddress object.
+**/
+void linphone_address_destroy(LinphoneAddress *u){
+	osip_from_free(u);
+}
+
+
+/** @} */
diff --git a/linphone/coreapi/enum.c b/linphone/coreapi/enum.c
index deb8caff30155ae047906e314b6205b6ec828d0d..8818ae6ee6094e057fd94749423a722f28d7c52d 100644
--- a/linphone/coreapi/enum.c
+++ b/linphone/coreapi/enum.c
@@ -1,6 +1,6 @@
 /*
 linphone
-Copyright (C) 2000  Simon MORLAT (simon.morlat@linphone.org)
+Copyright (C) 2000-2009  Simon MORLAT (simon.morlat@linphone.org)
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
@@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #define DNS_ANSWER_MAX_SIZE 2048
 
 
-char *create_enum_domain(const char *number){
+static char *create_enum_domain(const char *number){
 	int len=strlen(number);
 	char *domain=ms_malloc((len*2)+10);
 	int i,j;
@@ -47,7 +47,7 @@ char *create_enum_domain(const char *number){
 }
 
 
-bool_t is_a_number(const char *str){
+static bool_t is_a_number(const char *str){
 	char *p=(char *)str;
 	bool_t res=FALSE;
 	bool_t space_found=FALSE;
diff --git a/linphone/coreapi/linphonecore.c b/linphone/coreapi/linphonecore.c
index 7665069b2f5612364359c4e5e58e12ee65430d8f..a0c442ad605f071e47747ccdbba66815cf5e812e 100644
--- a/linphone/coreapi/linphonecore.c
+++ b/linphone/coreapi/linphonecore.c
@@ -646,6 +646,7 @@ static void sip_config_read(LinphoneCore *lc)
 			break;
 		}
 	}
+	
 	/*for test*/
 	lc->sip_conf.sdp_200_ack=lp_config_get_int(lc->config,"sip","sdp_200_ack",0);
 	lc->sip_conf.only_one_codec=lp_config_get_int(lc->config,"sip","only_one_codec",0);
@@ -1648,12 +1649,16 @@ bool_t linphone_core_interpret_url(LinphoneCore *lc, const char *url, LinphoneAd
 			/* append the proxy domain suffix */
 			LinphoneAddress *uri;
 			const char *identity=linphone_proxy_config_get_identity(proxy);
+			char normalized_username[128];
 			uri=linphone_address_new(identity);
 			if (uri==NULL){
 				return FALSE;
 			}
 			linphone_address_set_display_name(uri,NULL);
-			linphone_address_set_username(uri,url);
+			linphone_proxy_config_normalize_number(proxy,url,normalized_username,
+			    					sizeof(normalized_username));
+			linphone_address_set_username(uri,normalized_username);
+										
 			if (real_parsed_url!=NULL) *real_parsed_url=uri;
 #if 0
 			/*if the prompted uri was auto-suffixed with proxy domain,
@@ -3477,162 +3482,3 @@ void linphone_core_destroy(LinphoneCore *lc){
 	ms_free(lc);
 }
 
-/**
- * @addtogroup linphone_address
- * @{
-**/
-
-/**
- * Constructs a LinphoneAddress object by parsing the user supplied address,
- * given as a string.
-**/
-LinphoneAddress * linphone_address_new(const char *uri){
-	osip_from_t *from;
-	osip_from_init(&from);
-	if (osip_from_parse(from,uri)!=0){
-		osip_from_free(from);
-		return NULL;
-	}
-	return from;
-}
-
-/**
- * Clones a LinphoneAddress object.
-**/
-LinphoneAddress * linphone_address_clone(const LinphoneAddress *uri){
-	osip_from_t *ret=NULL;
-	osip_from_clone(uri,&ret);
-	return ret;
-}
-
-#define null_if_empty(s) (((s)!=NULL && (s)[0]!='\0') ? (s) : NULL )
-
-/**
- * Returns the address scheme, normally "sip".
-**/
-const char *linphone_address_get_scheme(const LinphoneAddress *u){
-	return null_if_empty(u->url->scheme);
-}
-
-/**
- * Returns the display name.
-**/
-const char *linphone_address_get_display_name(const LinphoneAddress* u){
-	return null_if_empty(u->displayname);
-}
-
-/**
- * Returns the username.
-**/
-const char *linphone_address_get_username(const LinphoneAddress *u){
-	return null_if_empty(u->url->username);
-}
-
-/**
- * Returns the domain name.
-**/
-const char *linphone_address_get_domain(const LinphoneAddress *u){
-	return null_if_empty(u->url->host);
-}
-
-/**
- * Sets the display name.
-**/
-void linphone_address_set_display_name(LinphoneAddress *u, const char *display_name){
-	if (u->displayname!=NULL){
-		osip_free(u->displayname);
-		u->displayname=NULL;
-	}
-	if (display_name!=NULL)
-		u->displayname=osip_strdup(display_name);
-}
-
-/**
- * Sets the username.
-**/
-void linphone_address_set_username(LinphoneAddress *uri, const char *username){
-	if (uri->url->username!=NULL){
-		osip_free(uri->url->username);
-		uri->url->username=NULL;
-	}
-	if (username)
-		uri->url->username=osip_strdup(username);
-}
-
-/**
- * Sets the domain.
-**/
-void linphone_address_set_domain(LinphoneAddress *uri, const char *host){
-	if (uri->url->host!=NULL){
-		osip_free(uri->url->host);
-		uri->url->host=NULL;
-	}
-	if (host)
-		uri->url->host=osip_strdup(host);
-}
-
-/**
- * Sets the port number.
-**/
-void linphone_address_set_port(LinphoneAddress *uri, const char *port){
-	if (uri->url->port!=NULL){
-		osip_free(uri->url->port);
-		uri->url->port=NULL;
-	}
-	if (port)
-		uri->url->port=osip_strdup(port);
-}
-
-/**
- * Sets the port number.
-**/
-void linphone_address_set_port_int(LinphoneAddress *uri, int port){
-	char tmp[12];
-	if (port==5060){
-		/*this is the default, special case to leave the port field blank*/
-		linphone_address_set_port(uri,NULL);
-		return;
-	}
-	snprintf(tmp,sizeof(tmp),"%i",port);
-	linphone_address_set_port(uri,tmp);
-}
-
-/**
- * Removes address's tags and uri headers so that it is displayable to the user.
-**/
-void linphone_address_clean(LinphoneAddress *uri){
-	osip_generic_param_freelist(&uri->gen_params);
-}
-
-/**
- * Returns the address as a string.
- * The returned char * must be freed by the application. Use ms_free().
-**/
-char *linphone_address_as_string(const LinphoneAddress *u){
-	char *tmp,*ret;
-	osip_from_to_str(u,&tmp);
-	ret=ms_strdup(tmp);
-	osip_free(tmp);
-	return ret;
-}
-
-/**
- * Returns the SIP uri only as a string, that is display name is removed.
- * The returned char * must be freed by the application. Use ms_free().
-**/
-char *linphone_address_as_string_uri_only(const LinphoneAddress *u){
-	char *tmp=NULL,*ret;
-	osip_uri_to_str(u->url,&tmp);
-	ret=ms_strdup(tmp);
-	osip_free(tmp);
-	return ret;
-}
-
-/**
- * Destroys a LinphoneAddress object.
-**/
-void linphone_address_destroy(LinphoneAddress *u){
-	osip_from_free(u);
-}
-
-/** @} */
diff --git a/linphone/coreapi/linphonecore.h b/linphone/coreapi/linphonecore.h
index 50aa8f1d1b7c8cb998255f4900a35fd6ac3b039c..94d15c258f78182ffccf4240df117b918d24f97f 100644
--- a/linphone/coreapi/linphonecore.h
+++ b/linphone/coreapi/linphonecore.h
@@ -334,10 +334,12 @@ typedef struct _LinphoneProxyConfig
 	int auth_failures;
 	char *contact_addr; /* our IP address as seen by the proxy, read from via 's received= parameter*/
 	int contact_port; /*our IP port as seen by the proxy, read from via's rport= parameter */
+	char *dial_prefix;
 	bool_t commit;
 	bool_t reg_sendregister;
 	bool_t registered;
 	bool_t publish;
+	bool_t dial_escape_plus;
 } LinphoneProxyConfig;
 
 LinphoneProxyConfig *linphone_proxy_config_new(void);
diff --git a/linphone/coreapi/private.h b/linphone/coreapi/private.h
index bc23b80e7d36036a929bce9524340958c6e32e64..e9809dc83eb811f809a980c7ab68196561d2225f 100644
--- a/linphone/coreapi/private.h
+++ b/linphone/coreapi/private.h
@@ -192,4 +192,6 @@ int linphone_core_get_local_ip_for(const char *dest, char *result);
 LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(struct _LpConfig *config, int index);
 void linphone_proxy_config_write_to_config_file(struct _LpConfig* config,LinphoneProxyConfig *obj, int index);
 
+int linphone_proxy_config_normalize_number(LinphoneProxyConfig *cfg, const char *username, char *result, size_t result_len);
+
 #endif /* _PRIVATE_H */
diff --git a/linphone/coreapi/proxy.c b/linphone/coreapi/proxy.c
index 46d0bf1c7c4ca22b80bbe160de416ad2a7b5ad96..b836feb53fc0dce0cacfb87d24756e3acd48f2e4 100644
--- a/linphone/coreapi/proxy.c
+++ b/linphone/coreapi/proxy.c
@@ -25,6 +25,10 @@ Copyright (C) 2000  Simon MORLAT (simon.morlat@linphone.org)
 #include "lpconfig.h"
 #include "private.h"
 
+
+#include <ctype.h>
+
+
 void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc){
 	MSList *elem;
 	int i;
@@ -69,6 +73,7 @@ void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){
 	if (obj->realm!=NULL) ms_free(obj->realm);
 	if (obj->type!=NULL) ms_free(obj->type);
 	if (obj->contact_addr!=NULL) ms_free(obj->contact_addr);
+	if (obj->dial_prefix!=NULL) ms_free(obj->dial_prefix);
 }
 
 /**
@@ -334,6 +339,130 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
 	}
 }
 
+
+/**
+ * Sets a dialing prefix to be automatically prepended when inviting a number with 
+ * #linphone_core_invite.
+ *
+**/
+void linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig *cfg, const char *prefix){
+	if (cfg->dial_prefix!=NULL){
+		ms_free(cfg->dial_prefix);
+		cfg->dial_prefix=NULL;
+	}
+	if (prefix) cfg->dial_prefix=ms_strdup(prefix);
+}
+
+/**
+ * Returns dialing prefix.
+ *
+ * 
+**/
+const char *linphone_proxy_config_get_dial_prefix(const LinphoneProxyConfig *cfg){
+	return cfg->dial_prefix;
+}
+
+/**
+ * Sets whether liblinphone should replace "+" by "00" in dialed numbers (passed to
+ * #linphone_core_invite ).
+ *
+**/
+void linphone_proxy_config_set_dial_escape_plus(LinphoneProxyConfig *cfg, bool_t val){
+	cfg->dial_escape_plus=val;
+}
+
+/**
+ * Returns whether liblinphone should replace "+" by "00" in dialed numbers (passed to
+ * #linphone_core_invite ).
+ *
+**/
+bool_t linphone_proxy_config_get_dial_escape_plus(const LinphoneProxyConfig *cfg){
+	return cfg->dial_escape_plus;
+}
+
+
+static bool_t is_a_phone_number(const char *username){
+	const char *p;
+	for(p=username;*p!='\0';++p){
+		if (isdigit(*p) || 
+		    *p==' ' ||
+		    *p=='-' ||
+		    *p==')' ||
+			*p=='(' ||
+			*p=='/' ||
+			*p=='+') continue;
+		else return FALSE;
+	}
+	return TRUE;
+}
+
+static char *flatten_number(const char *number){
+	char *result=ms_malloc0(strlen(number)+1);
+	char *w=result;
+	const char *r;
+	for(r=number;*r!='\0';++r){
+		if (*r=='+' || isdigit(*r)){
+			*w++=*r;
+		}
+	}
+	*w++='\0';
+	return result;
+}
+
+static void copy_result(const char *src, char *dest, size_t destlen, bool_t escape_plus){
+	int i=0;
+	
+	if (escape_plus && src[0]=='+' && destlen>2){
+		dest[0]='0';
+		dest[1]='0';
+		src++;
+		i=2;
+	}
+	
+	for(;i<destlen-1;++i){
+		dest[i]=*src;
+		src++;
+	}
+	dest[i]='\0';
+}
+
+
+static char *append_prefix(const char *number, const char *prefix){
+	char *res=ms_malloc(strlen(number)+strlen(prefix)+1);
+	strcpy(res,prefix);
+	return strcat(res,number);
+}
+
+int linphone_proxy_config_normalize_number(LinphoneProxyConfig *proxy, const char *username, char *result, size_t result_len){
+	char *flatten;
+	int numlen;
+	if (is_a_phone_number(username)){
+		flatten=flatten_number(username);
+		ms_message("Flattened number is '%s'",flatten);
+		numlen=strlen(flatten);
+		if (numlen>10 || flatten[0]=='+' || proxy->dial_prefix==NULL){
+			ms_message("No need to add a prefix");
+			/* prefix is already there */
+			copy_result(flatten,result,result_len,proxy->dial_escape_plus);
+			ms_free(flatten);
+			return 0;
+		}else if (proxy->dial_prefix){
+			char *prefixed;
+			int skipped=0;
+			ms_message("Need to prefix with %s",proxy->dial_prefix);
+			if (numlen==10){
+				/*remove initial number before prepending prefix*/
+				skipped=1;
+			}
+			prefixed=append_prefix(flatten+skipped,proxy->dial_prefix);
+			ms_free(flatten);
+			copy_result(prefixed,result,result_len,proxy->dial_escape_plus);
+			ms_free(prefixed);
+		}
+	}else strncpy(result,username,result_len);
+	return 0;
+}
+
 /**
  * Commits modification made to the proxy configuration.
 **/
@@ -669,6 +798,8 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC
 	lp_config_set_int(config,key,"reg_expires",obj->expires);
 	lp_config_set_int(config,key,"reg_sendregister",obj->reg_sendregister);
 	lp_config_set_int(config,key,"publish",obj->publish);
+	lp_config_set_int(config,key,"dial_escape_plus",obj->dial_escape_plus);
+	lp_config_set_string(config,key,"dial_prefix",obj->dial_prefix);
 }
 
 
@@ -702,6 +833,9 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LpConfig *config
 	linphone_proxy_config_enableregister(cfg,lp_config_get_int(config,key,"reg_sendregister",0));
 	
 	linphone_proxy_config_enable_publish(cfg,lp_config_get_int(config,key,"publish",0));
+
+	linphone_proxy_config_set_dial_escape_plus(cfg,lp_config_get_int(config,key,"dial_escape_plus",0));
+	linphone_proxy_config_set_dial_prefix(cfg,lp_config_get_string(config,key,"dial_prefix",NULL));
 	
 	tmp=lp_config_get_string(config,key,"type",NULL);
 	if (tmp!=NULL && strlen(tmp)>0)