/* belle-sip - SIP (RFC3261) library. Copyright (C) 2010 Belledonne Communications SARL 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, see . */ #define _CRT_RAND_S #include #include #include #include "belle_sip_internal.h" #include "clock_gettime.h" /*for apple*/ #ifndef WIN32 #include #include /*for gettimeofday*/ #include /* available on POSIX system only */ #else #include #endif static FILE *__log_file=0; /** *@param file a FILE pointer where to output the belle logs. * **/ void belle_sip_set_log_file(FILE *file) { __log_file=file; } static void __belle_sip_logv_out(belle_sip_log_level lev, const char *fmt, va_list args); belle_sip_log_function_t belle_sip_logv_out=__belle_sip_logv_out; /** *@param func: your logging function, compatible with the OrtpLogFunc prototype. * **/ void belle_sip_set_log_handler(belle_sip_log_function_t func){ belle_sip_logv_out=func; } belle_sip_log_function_t belle_sip_get_log_handler(){ return belle_sip_logv_out; } unsigned int __belle_sip_log_mask=BELLE_SIP_LOG_WARNING|BELLE_SIP_LOG_ERROR|BELLE_SIP_LOG_FATAL; /** * @ param level: either BELLE_SIP_LOG_DEBUG, BELLE_SIP_LOG_MESSAGE, BELLE_SIP_LOG_WARNING, BELLE_SIP_LOG_ERROR * BELLE_SIP_LOG_FATAL . **/ void belle_sip_set_log_level(int level){ __belle_sip_log_mask=(level<<1)-1; } char * belle_sip_strdup_vprintf(const char *fmt, va_list ap) { /* Guess we need no more than 100 bytes. */ int n, size = 200; char *p,*np; #ifndef WIN32 va_list cap;/*copy of our argument list: a va_list cannot be re-used (SIGSEGV on linux 64 bits)*/ #endif if ((p = (char *) malloc (size)) == NULL) return NULL; while (1) { /* Try to print in the allocated space. */ #ifndef WIN32 va_copy(cap,ap); n = vsnprintf (p, size, fmt, cap); va_end(cap); #else /*this works on 32 bits, luckily*/ n = vsnprintf (p, size, fmt, ap); #endif /* If that worked, return the string. */ if (n > -1 && n < size) return p; //printf("Reallocing space.\n"); /* Else try again with more space. */ if (n > -1) /* glibc 2.1 */ size = n + 1; /* precisely what is needed */ else /* glibc 2.0 */ size *= 2; /* twice the old size */ if ((np = (char *) realloc (p, size)) == NULL) { free(p); return NULL; } else { p = np; } } } char *belle_sip_strdup_printf(const char *fmt,...){ char *ret; va_list args; va_start (args, fmt); ret=belle_sip_strdup_vprintf(fmt, args); va_end (args); return ret; } belle_sip_error_code belle_sip_snprintf(char *buff, size_t buff_size, size_t *offset, const char *fmt, ...) { belle_sip_error_code ret; va_list args; va_start(args, fmt); ret = belle_sip_snprintf_valist(buff, buff_size, offset, fmt, args); va_end(args); return ret; } belle_sip_error_code belle_sip_snprintf_valist(char *buff, size_t buff_size, size_t *offset, const char *fmt, va_list args) { int ret; belle_sip_error_code error = BELLE_SIP_OK; ret = vsnprintf(buff + *offset, buff_size - *offset, fmt, args); if ((ret < 0) || (ret >= (buff_size - *offset))) { error = BELLE_SIP_BUFFER_OVERFLOW; *offset = buff_size; } else { *offset += ret; } return error; } #if defined(WIN32) || defined(_WIN32_WCE) #define ENDLINE "\r\n" #else #define ENDLINE "\n" #endif #if defined(WIN32) || defined(_WIN32_WCE) void belle_sip_logv(int level, const char *fmt, va_list args) { if (belle_sip_logv_out!=NULL && belle_sip_log_level_enabled(level)) belle_sip_logv_out(level,fmt,args); if ((level)==BELLE_SIP_LOG_FATAL) abort(); } #endif #ifdef WIN32 static int belle_sip_gettimeofday (struct timeval *tv, void* tz) { union { __int64 ns100; /*time since 1 Jan 1601 in 100ns units */ FILETIME fileTime; } now; GetSystemTimeAsFileTime (&now.fileTime); tv->tv_usec = (long) ((now.ns100 / 10LL) % 1000000LL); tv->tv_sec = (long) ((now.ns100 - 116444736000000000LL) / 10000000LL); return 0; } #else #define belle_sip_gettimeofday gettimeofday #endif static void __belle_sip_logv_out(belle_sip_log_level lev, const char *fmt, va_list args){ const char *lname="undef"; char *msg; struct timeval tp; struct tm *lt; #ifndef WIN32 struct tm tmstorage; #endif time_t curtime; belle_sip_gettimeofday(&tp,NULL); curtime=tp.tv_sec; #ifdef WIN32 lt = localtime(&curtime); #else lt = localtime_r(&curtime,&tmstorage); #endif if (__log_file==NULL) __log_file=stderr; switch(lev){ case BELLE_SIP_LOG_DEBUG: lname="debug"; break; case BELLE_SIP_LOG_MESSAGE: lname="message"; break; case BELLE_SIP_LOG_WARNING: lname="warning"; break; case BELLE_SIP_LOG_ERROR: lname="error"; break; case BELLE_SIP_LOG_FATAL: lname="fatal"; break; default: belle_sip_fatal("Bad level !"); } msg=belle_sip_strdup_vprintf(fmt,args); #if defined(_MSC_VER) && !defined(_WIN32_WCE) #ifndef _UNICODE OutputDebugStringA(msg); OutputDebugStringA("\r\n"); #else { int len=strlen(msg); wchar_t *tmp=(wchar_t*)belle_sip_malloc((len+1)*sizeof(wchar_t)); mbstowcs(tmp,msg,len); OutputDebugStringW(tmp); OutputDebugStringW(L"\r\n"); belle_sip_free(tmp); } #endif #endif fprintf(__log_file,"%i-%.2i-%.2i %.2i:%.2i:%.2i:%.3i belle-sip-%s-%s" ENDLINE,1900+lt->tm_year,lt->tm_mon+1,lt->tm_mday,lt->tm_hour,lt->tm_min,lt->tm_sec,(int)(tp.tv_usec/1000), lname,msg); fflush(__log_file); free(msg); } belle_sip_list_t* belle_sip_list_new(void *data){ belle_sip_list_t* new_elem=belle_sip_new0(belle_sip_list_t); new_elem->data=data; return new_elem; } belle_sip_list_t* belle_sip_list_append_link(belle_sip_list_t* elem,belle_sip_list_t *new_elem){ belle_sip_list_t* it=elem; if (elem==NULL) return new_elem; if (new_elem==NULL) return elem; while (it->next!=NULL) it=belle_sip_list_next(it); it->next=new_elem; new_elem->prev=it; return elem; } belle_sip_list_t* belle_sip_list_append(belle_sip_list_t* elem, void * data){ belle_sip_list_t* new_elem=belle_sip_list_new(data); return belle_sip_list_append_link(elem,new_elem); } belle_sip_list_t* belle_sip_list_prepend(belle_sip_list_t* elem, void *data){ belle_sip_list_t* new_elem=belle_sip_list_new(data); if (elem!=NULL) { new_elem->next=elem; elem->prev=new_elem; } return new_elem; } belle_sip_list_t * belle_sip_list_last_elem(const belle_sip_list_t *l){ if (l==NULL) return NULL; while(l->next){ l=l->next; } return (belle_sip_list_t*)l; } belle_sip_list_t* belle_sip_list_concat(belle_sip_list_t* first, belle_sip_list_t* second){ belle_sip_list_t* it=first; if (it==NULL) return second; if (second==NULL) return first; while(it->next!=NULL) it=belle_sip_list_next(it); it->next=second; second->prev=it; return first; } belle_sip_list_t* belle_sip_list_free(belle_sip_list_t* list){ belle_sip_list_t* elem = list; belle_sip_list_t* tmp; if (list==NULL) return NULL; while(elem->next!=NULL) { tmp = elem; elem = elem->next; belle_sip_free(tmp); } belle_sip_free(elem); return NULL; } belle_sip_list_t * belle_sip_list_free_with_data(belle_sip_list_t *list, void (*freefunc)(void*)){ belle_sip_list_t* elem = list; belle_sip_list_t* tmp; if (list==NULL) return NULL; while(elem->next!=NULL) { tmp = elem; elem = elem->next; freefunc(tmp->data); belle_sip_free(tmp); } freefunc(elem->data); belle_sip_free(elem); return NULL; } belle_sip_list_t* _belle_sip_list_remove(belle_sip_list_t* first, void *data, int warn_if_not_found){ belle_sip_list_t* it; it=belle_sip_list_find(first,data); if (it) return belle_sip_list_delete_link(first,it); else if (warn_if_not_found){ belle_sip_warning("belle_sip_list_remove: no element with %p data was in the list", data); } return first; } belle_sip_list_t* belle_sip_list_remove(belle_sip_list_t* first, void *data){ return _belle_sip_list_remove(first, data, TRUE); } int belle_sip_list_size(const belle_sip_list_t* first){ int n=0; while(first!=NULL){ ++n; first=first->next; } return n; } void belle_sip_list_for_each(const belle_sip_list_t* list, void (*func)(void *)){ for(;list!=NULL;list=list->next){ func(list->data); } } void belle_sip_list_for_each2(const belle_sip_list_t* list, void (*func)(void *, void *), void *user_data){ for(;list!=NULL;list=list->next){ func(list->data,user_data); } } belle_sip_list_t * belle_sip_list_pop_front(belle_sip_list_t *list, void **front_data){ belle_sip_list_t *front_elem=list; if (front_elem==NULL){ *front_data=NULL; return NULL; } *front_data=front_elem->data; list=belle_sip_list_remove_link(list,front_elem); belle_sip_free(front_elem); return list; } belle_sip_list_t* belle_sip_list_remove_link(belle_sip_list_t* list, belle_sip_list_t* elem){ belle_sip_list_t* ret; if (elem==list){ ret=elem->next; elem->prev=NULL; elem->next=NULL; if (ret!=NULL) ret->prev=NULL; return ret; } elem->prev->next=elem->next; if (elem->next!=NULL) elem->next->prev=elem->prev; elem->next=NULL; elem->prev=NULL; return list; } belle_sip_list_t * belle_sip_list_delete_link(belle_sip_list_t* list, belle_sip_list_t* elem){ belle_sip_list_t *ret=belle_sip_list_remove_link(list,elem); belle_sip_free(elem); return ret; } belle_sip_list_t* belle_sip_list_find(belle_sip_list_t* list, void *data){ for(;list!=NULL;list=list->next){ if (list->data==data) return list; } return NULL; } belle_sip_list_t* belle_sip_list_find_custom(const belle_sip_list_t* list, belle_sip_compare_func compare_func, const void *user_data){ for(;list!=NULL;list=list->next){ if (compare_func(list->data,user_data)==0) return (belle_sip_list_t *)list; } return NULL; } belle_sip_list_t *belle_sip_list_delete_custom(belle_sip_list_t *list, belle_sip_compare_func compare_func, const void *user_data){ belle_sip_list_t *elem=belle_sip_list_find_custom(list,compare_func,user_data); if (elem!=NULL){ list=belle_sip_list_delete_link(list,elem); } return list; } void * belle_sip_list_nth_data(const belle_sip_list_t* list, int index){ int i; for(i=0;list!=NULL;list=list->next,++i){ if (i==index) return list->data; } belle_sip_error("belle_sip_list_nth_data: no such index in list."); return NULL; } int belle_sip_list_position(const belle_sip_list_t* list, belle_sip_list_t* elem){ int i; for(i=0;list!=NULL;list=list->next,++i){ if (elem==list) return i; } belle_sip_error("belle_sip_list_position: no such element in list."); return -1; } int belle_sip_list_index(const belle_sip_list_t* list, void *data){ int i; for(i=0;list!=NULL;list=list->next,++i){ if (data==list->data) return i; } belle_sip_error("belle_sip_list_index: no such element in list."); return -1; } belle_sip_list_t* belle_sip_list_insert_sorted(belle_sip_list_t* list, void *data, int (*compare_func)(const void *, const void*)){ belle_sip_list_t* it,*previt=NULL; belle_sip_list_t* nelem; belle_sip_list_t* ret=list; if (list==NULL) return belle_sip_list_append(list,data); else{ nelem=belle_sip_list_new(data); for(it=list;it!=NULL;it=it->next){ previt=it; if (compare_func(data,it->data)<=0){ nelem->prev=it->prev; nelem->next=it; if (it->prev!=NULL) it->prev->next=nelem; else{ ret=nelem; } it->prev=nelem; return ret; } } previt->next=nelem; nelem->prev=previt; } return ret; } belle_sip_list_t* belle_sip_list_insert(belle_sip_list_t* list, belle_sip_list_t* before, void *data){ belle_sip_list_t* elem; if (list==NULL || before==NULL) return belle_sip_list_append(list,data); for(elem=list;elem!=NULL;elem=belle_sip_list_next(elem)){ if (elem==before){ if (elem->prev==NULL) return belle_sip_list_prepend(list,data); else{ belle_sip_list_t* nelem=belle_sip_list_new(data); nelem->prev=elem->prev; nelem->next=elem; elem->prev->next=nelem; elem->prev=nelem; } } } return list; } belle_sip_list_t* belle_sip_list_copy(const belle_sip_list_t* list){ belle_sip_list_t* copy=NULL; const belle_sip_list_t* iter; for(iter=list;iter!=NULL;iter=belle_sip_list_next(iter)){ copy=belle_sip_list_append(copy,iter->data); } return copy; } belle_sip_list_t* belle_sip_list_copy_with_data(const belle_sip_list_t* list, void* (*copyfunc)(void*)){ belle_sip_list_t* copy=NULL; const belle_sip_list_t* iter; for(iter=list;iter!=NULL;iter=belle_sip_list_next(iter)){ copy=belle_sip_list_append(copy,copyfunc(iter->data)); } return copy; } char * belle_sip_concat (const char *str, ...) { va_list ap; size_t allocated = 100; char *result = (char *) malloc (allocated); if (result != NULL) { char *newp; char *wp; const char* s; va_start (ap, str); wp = result; for (s = str; s != NULL; s = va_arg (ap, const char *)) { size_t len = strlen (s); /* Resize the allocated memory if necessary. */ if (wp + len + 1 > result + allocated) { allocated = (allocated + len) * 2; newp = (char *) realloc (result, allocated); if (newp == NULL) { free (result); return NULL; } wp = newp + (wp - result); result = newp; } memcpy (wp, s, len); wp +=len; } /* Terminate the result string. */ *wp++ = '\0'; /* Resize memory to the optimal size. */ newp = realloc (result, wp - result); if (newp != NULL) result = newp; va_end (ap); } return result; } void *belle_sip_malloc(size_t size){ return malloc(size); } void *belle_sip_malloc0(size_t size){ void *p=malloc(size); memset(p,0,size); return p; } void *belle_sip_realloc(void *ptr, size_t size){ return realloc(ptr,size); } void belle_sip_free(void *ptr){ free(ptr); } char * belle_sip_strdup(const char *s){ return strdup(s); } #ifndef WIN32 static int find_best_clock_id () { struct timespec ts; static int clock_id=-1; #ifndef ANDROID #define DEFAULT_CLOCK_MODE CLOCK_MONOTONIC #else #define DEFAULT_CLOCK_MODE CLOCK_REALTIME /*monotonic clock stop during sleep mode*/ #endif if (clock_id==-1) { if (clock_gettime(DEFAULT_CLOCK_MODE,&ts)!=1){ clock_id=DEFAULT_CLOCK_MODE; } else if (clock_gettime(CLOCK_REALTIME,&ts)!=1){ clock_id=CLOCK_REALTIME; } else { belle_sip_fatal("Cannot find suitable clock mode"); } } return clock_id; } uint64_t belle_sip_time_ms(void){ struct timespec ts; if (clock_gettime(find_best_clock_id(),&ts)==-1){ belle_sip_error("clock_gettime() error for clock_id=%i: %s",find_best_clock_id(),strerror(errno)); return 0; } return (ts.tv_sec*1000LL) + (ts.tv_nsec/1000000LL); } #else uint64_t belle_sip_time_ms(void){ #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) return GetTickCount(); #else return GetTickCount64(); #endif } #endif /** * parser parameter pair */ belle_sip_param_pair_t* belle_sip_param_pair_new(const char* name,const char* value) { belle_sip_param_pair_t* lPair = (belle_sip_param_pair_t*)belle_sip_new0(belle_sip_param_pair_t); lPair->name=name?belle_sip_strdup(name):NULL; lPair->value=value?belle_sip_strdup(value):NULL; return lPair; } void belle_sip_param_pair_destroy(belle_sip_param_pair_t* pair) { if (pair->name) belle_sip_free(pair->name); if (pair->value) belle_sip_free(pair->value); belle_sip_free(pair); } int belle_sip_param_pair_comp_func(const belle_sip_param_pair_t *a, const char*b) { return strcmp(a->name,b); } int belle_sip_param_pair_case_comp_func(const belle_sip_param_pair_t *a, const char*b) { return strcasecmp(a->name,b); } char* _belle_sip_str_dup_and_unquote_string(const char* quoted_string) { size_t value_size = strlen(quoted_string); char* unquoted_string = belle_sip_malloc0(value_size-2+1); strncpy(unquoted_string,quoted_string+1,value_size-2); return unquoted_string; } char *belle_sip_unquote_strdup(const char *str){ const char *p; if (str==NULL) return NULL; for(p=str;*p!='\0';++p){ switch(*p){ case ' ': case '\t': break; case '"': return _belle_sip_str_dup_and_unquote_string(p); default: return belle_sip_strdup(str); break; } } return belle_sip_strdup(str); } #if defined(WIN32) && !defined(_MSC_VER) #include static int belle_sip_wincrypto_random(unsigned int *rand_number){ static HCRYPTPROV hProv=(HCRYPTPROV)-1; static int initd=0; if (!initd){ if (!CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)){ belle_sip_error("Could not acquire a windows crypto context"); return -1; } initd=TRUE; } if (hProv==(HCRYPTPROV)-1) return -1; if (!CryptGenRandom(hProv,4,(BYTE*)rand_number)){ belle_sip_error("CryptGenRandom() failed."); return -1; } return 0; } #endif unsigned int belle_sip_random(void){ #if defined(__linux) || defined(__APPLE__) static int fd=-1; if (fd==-1) fd=open("/dev/urandom",O_RDONLY); if (fd!=-1){ unsigned int tmp; if (read(fd,&tmp,4)!=4){ belle_sip_error("Reading /dev/urandom failed."); }else return tmp; }else belle_sip_error("Could not open /dev/urandom"); #elif defined(WIN32) static int initd=0; unsigned int ret; #ifdef _MSC_VER /*rand_s() is pretty nice and simple function but is not wrapped by mingw.*/ if (rand_s(&ret)==0){ return ret; } #else if (belle_sip_wincrypto_random(&ret)==0){ return ret; } #endif /* Windows's rand() is unsecure but is used as a fallback*/ if (!initd) { srand((unsigned int)belle_sip_time_ms()); initd=1; belle_sip_warning("Random generator is using rand(), this is unsecure !"); } return rand()<<16 | rand(); #endif /*fallback to UNIX random()*/ #ifndef WIN32 return (unsigned int) random(); #endif } static const char *symbols="aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789-~"; /** * Write a random text token of supplied size. **/ char * belle_sip_random_token(char *ret, size_t size){ unsigned int val=0; unsigned int i; for(i=0;i>6; } ret[i]=0; return ret; } /** * Write random bytes of supplied size. **/ unsigned char * belle_sip_random_bytes(unsigned char *ret, size_t size){ unsigned int val=0; unsigned int i; for(i=0;i>8; } return ret; } typedef struct bits_reader{ const uint8_t *buffer; size_t buf_size; int bit_index; }bits_reader_t; static void bits_reader_init(bits_reader_t *reader, const uint8_t *buffer, size_t bufsize){ reader->buffer=buffer; reader->buf_size=bufsize; reader->bit_index=0; } static int bits_reader_read(bits_reader_t *reader, int count, unsigned int *ret){ unsigned int tmp; size_t byte_index=reader->bit_index/8; size_t bit_index=reader->bit_index % 8; int shift=32-bit_index-count; if (count>=24){ belle_sip_error("This bit reader cannot read more than 24 bits at once."); return -1; } if (byte_indexbuf_size) tmp=((unsigned int)reader->buffer[byte_index++])<<24; else{ belle_sip_error("Bit reader goes end of stream."); return -1; } if (byte_indexbuf_size) tmp|=((unsigned int)reader->buffer[byte_index++])<<16; if (byte_indexbuf_size) tmp|=((unsigned int)reader->buffer[byte_index++])<<8; if (byte_indexbuf_size) tmp|=((unsigned int)reader->buffer[byte_index++]); tmp=tmp>>shift; tmp=tmp & ((1<bit_index+=count; *ret=tmp; return 0; } char * belle_sip_octets_to_text(const uint8_t *hash, size_t hash_len, char *ret, size_t size){ int i; bits_reader_t bitctx; bits_reader_init(&bitctx,hash,hash_len); for(i=0;i<(int)size-1;++i){ unsigned int val=0; if (bits_reader_read(&bitctx,6,&val)==0){ ret[i]=symbols[val]; }else break; } ret[i]=0; return ret; } void belle_sip_util_copy_headers(belle_sip_message_t *orig, belle_sip_message_t *dest, const char*header, int multiple){ const belle_sip_list_t *elem; elem=belle_sip_message_get_headers(orig,header); for (;elem!=NULL;elem=elem->next){ belle_sip_header_t *ref_header=(belle_sip_header_t*)elem->data; if (ref_header){ ref_header=(belle_sip_header_t*)belle_sip_object_clone((belle_sip_object_t*)ref_header); if (!multiple){ belle_sip_message_set_header(dest,ref_header); break; }else belle_sip_message_add_header(dest,ref_header); } } } int belle_sip_get_char (const char*a,int n,char*out) { if (*a=='%' && n>2) { unsigned int tmp; sscanf(a+1,"%02x",&tmp); *out=(char)tmp; return 3; } else { *out=*a; return 1; } } char* belle_sip_to_unescaped_string(const char* buff) { char *output_buff=belle_sip_malloc(strlen(buff)+1); unsigned int i; unsigned int out_buff_index=0; for(i=0; buff[i]!='\0'; out_buff_index++) { i+=belle_sip_get_char(buff+i,3,output_buff+out_buff_index); } output_buff[out_buff_index]='\0'; return output_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_sip_uri_username_noescapes() { static char noescapes[BELLE_SIP_NO_ESCAPES_SIZE] = {0}; if (noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] == 0) { // concurrent initialization should not be an issue /*user = 1*( unreserved / escaped / user-unreserved ) unreserved = alphanum / mark mark = "-" / "_" / "." / "!" / "~" / "*" / "'" / "(" / ")" user-unreserved = "&" / "=" / "+" / "$" / "," / ";" / "?" / "/" */ noescapes_add_alfanums(noescapes); /*mark*/ noescapes_add_list(noescapes, "-_.!~*'()"); /*user-unreserved*/ noescapes_add_list(noescapes, "&=+$,;?/"); noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] = 1; // initialized // print_noescapes_map(noescapes, "uri_username"); } return noescapes; } /* * * password = *( unreserved / escaped / "&" / "=" / "+" / "$" / "," ) * */ static const char *get_sip_uri_userpasswd_noescapes() { static char noescapes[BELLE_SIP_NO_ESCAPES_SIZE] = {0}; if (noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] == 0) { // unreserved noescapes_add_alfanums(noescapes); noescapes_add_list(noescapes, "-_.!~*'()"); noescapes_add_list(noescapes, "&=+$,"); noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] = 1; // initialized } return noescapes; } static const char *get_sip_uri_parameter_noescapes() { static char noescapes[BELLE_SIP_NO_ESCAPES_SIZE] = {0}; if (noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] == 0) { /* 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 / "-" / "." / "!" / "%" / "*" / "_" / "+" / "`" / "'" / "~" ) */ //param-unreserved = noescapes_add_list(noescapes,"[]/:&+$"); // 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 const char *get_sip_uri_header_noescapes() { static char noescapes[BELLE_SIP_NO_ESCAPES_SIZE] = {0}; if (noescapes[BELLE_SIP_NO_ESCAPES_SIZE-1] == 0) { /* unreserved = alphanum / mark mark = "-" / "_" / "." / "!" / "~" / "*" / "'" / "(" / ")" escaped = "%" HEXDIG HEXDIG //.... header = hname "=" hvalue hname = 1*( hnv-unreserved / unreserved / escaped ) hvalue = *( hnv-unreserved / unreserved / escaped ) hnv-unreserved = "[" / "]" / "/" / "?" / ":" / "+" / "$" */ // unreserved //alphanum noescapes_add_alfanums(noescapes); //mark noescapes_add_list(noescapes, "-_.!~*'()"); noescapes_add_list(noescapes, "[]/?:+$"); //hnv-unreserved 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) { size_t outbuf_size=strlen(buff); size_t orig_size=outbuf_size; char *output_buff=(char*)belle_sip_malloc(outbuf_size+1); int i; int out_buff_index=0; for(i=0; buff[i] != '\0'; i++) { int c = ((unsigned char*)buff)[i]; if (outbuf_sized_name+strlen(ent->d_name)-strlen(file_type), file_type, strlen(file_type))==0) ) { char *name_with_path=belle_sip_strdup_printf("%s/%s",path,ent->d_name); file_list = belle_sip_list_append(file_list, name_with_path); } res = readdir_r(dir, ent, &result); } if (res != 0) { belle_sip_error("Error while reading the [%s] directory: %s.", path, strerror(errno)); } free(ent); closedir(dir); #endif return file_list; } int belle_sip_mkdir(const char *path) { #ifdef WIN32 return _mkdir(path); #else return mkdir(path, 0700); #endif }