Commit 1eee5504 authored by Guillaume Beraudo's avatar Guillaume Beraudo
Browse files

Better handling of escaping & C++ exports

parent a0b22b83
...@@ -87,6 +87,9 @@ BELLESIP_EXPORT const belle_sip_list_t* belle_sip_message_get_headers(const bell ...@@ -87,6 +87,9 @@ BELLESIP_EXPORT const belle_sip_list_t* belle_sip_message_get_headers(const bell
* @return a newly allocated list of belle_sip_header_t * @return a newly allocated list of belle_sip_header_t
* */ * */
BELLESIP_EXPORT belle_sip_list_t* belle_sip_message_get_all_headers(const belle_sip_message_t *message); BELLESIP_EXPORT belle_sip_list_t* belle_sip_message_get_all_headers(const belle_sip_message_t *message);
BELLESIP_EXPORT void belle_sip_message_add_first(belle_sip_message_t *msg, belle_sip_header_t* header);
/** /**
* add an header to this message * add an header to this message
* @param msg * @param msg
......
...@@ -1407,7 +1407,7 @@ char* belle_sip_header_replaces_value_to_escaped_string(const belle_sip_header_r ...@@ -1407,7 +1407,7 @@ char* belle_sip_header_replaces_value_to_escaped_string(const belle_sip_header_r
error=belle_sip_parameters_marshal(BELLE_SIP_PARAMETERS(replaces), buff, buff_size, &offset); error=belle_sip_parameters_marshal(BELLE_SIP_PARAMETERS(replaces), buff, buff_size, &offset);
if (error!=BELLE_SIP_OK) return NULL; if (error!=BELLE_SIP_OK) return NULL;
buff[offset]='\0'; buff[offset]='\0';
return belle_sip_to_escaped_string(buff); return strdup(buff);
} }
belle_sip_header_replaces_t* belle_sip_header_replaces_create(const char* call_id,const char* from_tag,const char* to_tag) { belle_sip_header_replaces_t* belle_sip_header_replaces_create(const char* call_id,const char* from_tag,const char* to_tag) {
......
...@@ -885,7 +885,8 @@ belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* t ...@@ -885,7 +885,8 @@ belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* t
* returns a char, even if entry is escaped*/ * returns a char, even if entry is escaped*/
int belle_sip_get_char (const char*a,int n,char*out); int belle_sip_get_char (const char*a,int n,char*out);
/*return an escaped string*/ /*return an escaped string*/
BELLESIP_INTERNAL_EXPORT char* belle_sip_to_escaped_string(const char* buff) ; BELLESIP_INTERNAL_EXPORT char* belle_sip_uri_to_escaped_username(const char* buff) ;
BELLESIP_INTERNAL_EXPORT char* belle_sip_uri_to_escaped_parameter(const char* buff) ;
BELLESIP_INTERNAL_EXPORT char* belle_sip_to_unescaped_string(const char* buff) ; BELLESIP_INTERNAL_EXPORT char* belle_sip_to_unescaped_string(const char* buff) ;
......
...@@ -1345,14 +1345,23 @@ scope { belle_sip_uri_t* current; } ...@@ -1345,14 +1345,23 @@ scope { belle_sip_uri_t* current; }
uri_parameter //all parameters are considered as other uri_parameter //all parameters are considered as other
: other_param ; : other_param ;
other_param other_param
: pname { belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS($uri_parameters::current) : pname {
,(const char *)$pname.text->chars char* unescaped_parameters = belle_sip_to_unescaped_string((const char *) $pname.text->chars);
,NULL);} belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS($uri_parameters::current)
,unescaped_parameters
,NULL);
belle_sip_free(unescaped_parameters);
}
| |
(pname EQUAL pvalue) { (pname EQUAL pvalue) {
belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS($uri_parameters::current) char* unescaped_pname = belle_sip_to_unescaped_string((const char *) $pname.text->chars);
,(const char *)$pname.text->chars char* unescaped_pvalue = belle_sip_to_unescaped_string((const char *) $pvalue.text->chars);
,(const char *)$pvalue.text->chars);} belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS($uri_parameters::current)
,unescaped_pname
,unescaped_pvalue);
belle_sip_free(unescaped_pname);
belle_sip_free(unescaped_pvalue);
}
; ;
pname pname
......
...@@ -52,20 +52,20 @@ belle_sip_error_code belle_sip_parameters_marshal(const belle_sip_parameters_t* ...@@ -52,20 +52,20 @@ belle_sip_error_code belle_sip_parameters_marshal(const belle_sip_parameters_t*
for(;list!=NULL;list=list->next){ for(;list!=NULL;list=list->next){
belle_sip_param_pair_t* container = (belle_sip_param_pair_t* )(list->data); belle_sip_param_pair_t* container = (belle_sip_param_pair_t* )(list->data);
if (container->value) { if (container->value) {
error=belle_sip_snprintf(buff,buff_size,offset,";%s=%s",container->name,container->value); error=belle_sip_snprintf(buff,buff_size,offset,";%s=%s", container->name, container->value);
} else { } else {
error=belle_sip_snprintf(buff,buff_size,offset,";%s",container->name); error=belle_sip_snprintf(buff,buff_size,offset,";%s", container->name);
} }
if (error!=BELLE_SIP_OK) return error; if (error!=BELLE_SIP_OK) return error;
} }
return error; return error;
} }
BELLE_SIP_NEW_HEADER(parameters,header,"parameters") BELLE_SIP_NEW_HEADER(parameters,header,"parameters")
const belle_sip_list_t * belle_sip_parameters_get_parameters(const belle_sip_parameters_t* obj) { const belle_sip_list_t *belle_sip_parameters_get_parameters(const belle_sip_parameters_t* obj) {
return obj->param_list; return obj->param_list;
} }
const char* belle_sip_parameters_get_parameter_base(const belle_sip_parameters_t* params,const char* name,belle_sip_compare_func func) { const char* belle_sip_parameters_get_parameter_base(const belle_sip_parameters_t* params,const char* name,belle_sip_compare_func func) {
belle_sip_list_t * lResult = belle_sip_list_find_custom(params->param_list, func, name); belle_sip_list_t * lResult = belle_sip_list_find_custom(params->param_list, func, name);
if (lResult) { if (lResult) {
return ((belle_sip_param_pair_t*)(lResult->data))->value; return ((belle_sip_param_pair_t*)(lResult->data))->value;
......
...@@ -69,6 +69,12 @@ static void belle_sip_uri_clone(belle_sip_uri_t* uri, const belle_sip_uri_t *ori ...@@ -69,6 +69,12 @@ static void belle_sip_uri_clone(belle_sip_uri_t* uri, const belle_sip_uri_t *ori
} }
static void encode_params(belle_sip_param_pair_t* container, belle_sip_list_t** newlist) {
char *escapedName = belle_sip_uri_to_escaped_parameter(container->name);
char *escapedValue = container->value? belle_sip_uri_to_escaped_parameter(container->value) : NULL;
*newlist = belle_sip_list_append(*newlist, belle_sip_param_pair_new(escapedName, escapedValue));
}
belle_sip_error_code belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buff, size_t buff_size, size_t *offset) { belle_sip_error_code belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buff, size_t buff_size, size_t *offset) {
const belle_sip_list_t* list=belle_sip_parameters_get_parameters(uri->header_list); const belle_sip_list_t* list=belle_sip_parameters_get_parameters(uri->header_list);
belle_sip_error_code error=BELLE_SIP_OK; belle_sip_error_code error=BELLE_SIP_OK;
...@@ -77,7 +83,7 @@ belle_sip_error_code belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buf ...@@ -77,7 +83,7 @@ belle_sip_error_code belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buf
if (error!=BELLE_SIP_OK) return error; if (error!=BELLE_SIP_OK) return error;
if (uri->user) { if (uri->user) {
char* escaped_username=belle_sip_to_escaped_string(uri->user); char* escaped_username=belle_sip_uri_to_escaped_username(uri->user);
error=belle_sip_snprintf(buff,buff_size,offset,"%s@",escaped_username); error=belle_sip_snprintf(buff,buff_size,offset,"%s@",escaped_username);
belle_sip_free(escaped_username); belle_sip_free(escaped_username);
if (error!=BELLE_SIP_OK) return error; if (error!=BELLE_SIP_OK) return error;
...@@ -96,8 +102,15 @@ belle_sip_error_code belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buf ...@@ -96,8 +102,15 @@ belle_sip_error_code belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buf
error=belle_sip_snprintf(buff,buff_size,offset,":%i",uri->port); error=belle_sip_snprintf(buff,buff_size,offset,":%i",uri->port);
if (error!=BELLE_SIP_OK) return error; if (error!=BELLE_SIP_OK) return error;
} }
error=belle_sip_parameters_marshal(&uri->params,buff,buff_size,offset);
if (error!=BELLE_SIP_OK) return error; {
belle_sip_parameters_t *encparams = belle_sip_parameters_new();
belle_sip_list_for_each2((void*)uri->params.param_list, (void*)encode_params, &encparams->param_list);
error=belle_sip_parameters_marshal(encparams,buff,buff_size,offset);
// belle_sip_list_free_with_data(encparams->param_list, belle_sip_object_unref);
belle_sip_object_unref((void*)encparams);
if (error!=BELLE_SIP_OK) return error;
}
for(;list!=NULL;list=list->next){ for(;list!=NULL;list=list->next){
belle_sip_param_pair_t* container = list->data; belle_sip_param_pair_t* container = list->data;
......
...@@ -797,51 +797,109 @@ char* belle_sip_to_unescaped_string(const char* buff) { ...@@ -797,51 +797,109 @@ char* belle_sip_to_unescaped_string(const char* buff) {
return belle_sip_strdup(output_buff); return belle_sip_strdup(output_buff);
} }
char* belle_sip_to_escaped_string(const char* buff) { #define BELLE_SIP_NO_ESCAPES_SIZE 257
static void noescapes_add_list(char noescapes[BELLE_SIP_NO_ESCAPES_SIZE], const char *allowed) {
while (*allowed) {
noescapes[(unsigned int) *allowed] = 1;
++allowed;
}
}
static void noescapes_add_range(char noescapes[BELLE_SIP_NO_ESCAPES_SIZE], char first, char last) {
memset(noescapes + (unsigned int)first, 1, last-first+1);
}
static void noescapes_add_alfanums(char noescapes[BELLE_SIP_NO_ESCAPES_SIZE]) {
noescapes_add_range(noescapes, '0', '9');
noescapes_add_range(noescapes, 'A', 'Z');
noescapes_add_range(noescapes, 'a', 'z');
}
/*
static void print_noescapes_map(char noescapes[BELLE_SIP_NO_ESCAPES_SIZE], const char *name) {
unsigned int i;
printf("Noescapes %s :", name);
for (i=' '; i <= '~'; ++i) {
if (noescapes[i] == 1) printf ("%c", i);
//if (noescapes[i] == 1) printf ("%c %d - %d\n", i, (char)i, noescapes[i]);
}
printf ("init: %d\n", noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1]);
}
*/
static const char *get_uri_username_noescapes() {
static char noescapes[BELLE_SIP_NO_ESCAPES_SIZE] = {0};
if (noescapes[BELLE_SIP_NO_ESCAPES_SIZE] == 0) {
// concurrent initialization should not be an issue
noescapes_add_list(noescapes, "[]/?:+$-_.!~*\()");
noescapes_add_alfanums(noescapes);
noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] = 1; // initialized
// print_noescapes_map(noescapes, "uri_username");
}
return noescapes;
}
static const char *get_uri_parameter_noescapes() {
static char noescapes[BELLE_SIP_NO_ESCAPES_SIZE] = {0};
if (noescapes[BELLE_SIP_NO_ESCAPES_SIZE] == 0) {
/*
uri-parameters = *( ";" uri-parameter)
uri-parameter = transport-param / user-param / method-p*aram
/ ttl-param / maddr-param / lr-param / other-param
transport-param = "transport="
( "udp" / "tcp" / "sctp" / "tls"
/ other-transport)
other-transport = token
user-param = "user=" ( "phone" / "ip" / other-user)
other-user = token
method-param = "method=" Method
ttl-param = "ttl=" ttl
maddr-param = "maddr=" host
lr-param = "lr"
other-param = pname [ "=" pvalue ]
pname = 1*paramchar
pvalue = 1*paramchar
paramchar = param-unreserved / unreserved / escaped
param-unreserved = "[" / "]" / "/" / ":" / "&" / "+" / "$"
unreserved = alphanum / mark
mark = "-" / "_" / "." / "!" / "~" / "*" / "'"
/ "(" / ")"
escaped = "%" HEXDIG HEXDIG
token = 1*(alphanum / "-" / "." / "!" / "%" / "*"
/ "_" / "+" / "`" / "'" / "~" )
*/
// token
noescapes_add_alfanums(noescapes);
noescapes_add_list(noescapes, "-.!%*_+`'~");
// unreserved
noescapes_add_list(noescapes, "-_.!~*'()");
noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] = 1; // initialized
// print_noescapes_map(noescapes, "uri_parameter");
}
return noescapes;
}
static char* belle_sip_escape(const char* buff, const char *noescapes) {
char output_buff[BELLE_SIP_MAX_TO_STRING_SIZE]; char output_buff[BELLE_SIP_MAX_TO_STRING_SIZE];
unsigned int i; unsigned int i;
unsigned int out_buff_index=0; unsigned int out_buff_index=0;
output_buff[BELLE_SIP_MAX_TO_STRING_SIZE-1]='\0'; for(i=0; buff[i] != '\0' && out_buff_index < sizeof(output_buff)-4; i++) {
for(i=0;buff[i]!='\0' &&i<BELLE_SIP_MAX_TO_STRING_SIZE-4 /*to make sure last param can be stored in escaped form*/;i++) { /*-4 to make sure last param can be stored in escaped form*/
const char c = buff[i];
/*hvalue = *( hnv-unreserved / unreserved / escaped ) if (noescapes[(unsigned int) c] == 1) {
hnv-unreserved = "[" / "]" / "/" / "?" / ":" / "+" / "$" output_buff[out_buff_index++]=c;
unreserved = alphanum / mark } else {
mark = "-" / "_" / "." / "!" / "~" / "*" / "'" out_buff_index+=sprintf(output_buff+out_buff_index,"%%%02x", c);
/ "(" / ")"*/
switch(buff[i]) {
case '[' :
case ']' :
case '/' :
case '?' :
case ':' :
case '+' :
case '$' :
case '-' :
case '_' :
case '.' :
case '!' :
case '~' :
case '*' :
case '\'' :
case '(' :
case ')' :
output_buff[out_buff_index++]=buff[i];
break;
default:
/*serach for alfanum*/
if ((buff[i]>='0' && buff[i]<='9')
|| (buff[i]>='A' && buff[i]<='Z')
|| (buff[i]>='a' && buff[i]<='z')
|| (buff[i]=='\0')) {
output_buff[out_buff_index++]=buff[i];
} else {
out_buff_index+=sprintf(output_buff+out_buff_index,"%%%02x",buff[i]);
}
break;
} }
} }
output_buff[out_buff_index]='\0'; output_buff[out_buff_index]='\0';
return belle_sip_strdup(output_buff); return belle_sip_strdup(output_buff);
} }
char* belle_sip_uri_to_escaped_username(const char* buff) {
return belle_sip_escape(buff, get_uri_username_noescapes());
}
char* belle_sip_uri_to_escaped_parameter(const char* buff) {
return belle_sip_escape(buff, get_uri_parameter_noescapes());
}
...@@ -116,6 +116,11 @@ headers_container_t * get_or_create_container(belle_sip_message_t *message, cons ...@@ -116,6 +116,11 @@ headers_container_t * get_or_create_container(belle_sip_message_t *message, cons
return headers_container; return headers_container;
} }
void belle_sip_message_add_first(belle_sip_message_t *message,belle_sip_header_t* header) {
headers_container_t *headers_container=get_or_create_container(message,belle_sip_header_get_name(header));
headers_container->header_list=belle_sip_list_prepend(headers_container->header_list,belle_sip_object_ref(header));
}
void belle_sip_message_add_header(belle_sip_message_t *message,belle_sip_header_t* header) { void belle_sip_message_add_header(belle_sip_message_t *message,belle_sip_header_t* header) {
headers_container_t *headers_container=get_or_create_container(message,belle_sip_header_get_name(header)); headers_container_t *headers_container=get_or_create_container(message,belle_sip_header_get_name(header));
headers_container->header_list=belle_sip_list_append(headers_container->header_list,belle_sip_object_ref(header)); headers_container->header_list=belle_sip_list_append(headers_container->header_list,belle_sip_object_ref(header));
......
...@@ -194,6 +194,22 @@ static void test_escaped_username(void) { ...@@ -194,6 +194,22 @@ static void test_escaped_username(void) {
belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri)); belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
} }
static void test_escaped_parameter(void) {
belle_sip_uri_t* L_tmp;
belle_sip_uri_t * L_uri = belle_sip_uri_parse("sip:toto@titi.com;pa%3Dram=aa%40bb;o%40");
char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri));
belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
L_tmp = belle_sip_uri_parse(l_raw_uri); // should not work in the general case...
L_uri = BELLE_SIP_URI(belle_sip_object_clone(BELLE_SIP_OBJECT(L_tmp)));
belle_sip_object_unref(BELLE_SIP_OBJECT(L_tmp));
belle_sip_free(l_raw_uri);
CU_ASSERT_STRING_EQUAL(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(L_uri), "pa=ram"), "aa@bb");
CU_ASSERT_TRUE(belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(L_uri), "o@"));
CU_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(L_uri), "titi.com");
belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri));
}
static void test_uri_equals(void) { static void test_uri_equals(void) {
belle_sip_uri_t* a; belle_sip_uri_t* a;
belle_sip_uri_t* b; belle_sip_uri_t* b;
...@@ -313,6 +329,7 @@ test_t uri_tests[] = { ...@@ -313,6 +329,7 @@ test_t uri_tests[] = {
{ "Simple URI", testSIMPLEURI }, { "Simple URI", testSIMPLEURI },
{ "Complex URI", testCOMPLEXURI }, { "Complex URI", testCOMPLEXURI },
{ "Escaped username", test_escaped_username }, { "Escaped username", test_escaped_username },
{ "Escaped parameter", test_escaped_parameter },
{ "IP host", test_ip_host }, { "IP host", test_ip_host },
{ "lr", test_lr }, { "lr", test_lr },
{ "maddr", test_maddr }, { "maddr", test_maddr },
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment