ut.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /*
  2. *$Id$
  3. *
  4. * - various general purpose functions
  5. *
  6. * Copyright (C) 2001-2003 Fhg Fokus
  7. *
  8. * This file is part of ser, a free SIP server.
  9. *
  10. * ser is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version
  14. *
  15. * For a license to use the ser software under conditions
  16. * other than those described here, or to purchase support for this
  17. * software, please contact iptel.org by e-mail at the following addresses:
  18. * [email protected]
  19. *
  20. * ser is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program; if not, write to the Free Software
  27. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  28. *
  29. * History
  30. * ------
  31. * 2003-01-18 un_escape function introduced for convenience of code needing
  32. * the complex&slow feature of unescaping
  33. */
  34. #ifndef ut_h
  35. #define ut_h
  36. #include <sys/types.h>
  37. #include <sys/time.h>
  38. #include <unistd.h>
  39. #include "dprint.h"
  40. #include "str.h"
  41. struct sip_msg;
  42. /* returns string beginning and length without insignificant chars */
  43. #define trim_len( _len, _begin, _mystr ) \
  44. do{ static char _c; \
  45. (_len)=(_mystr).len; \
  46. while ((_len) && ((_c=(_mystr).s[(_len)-1])==0 || _c=='\r' || \
  47. _c=='\n' || _c==' ' || _c=='\t' )) \
  48. (_len)--; \
  49. (_begin)=(_mystr).s; \
  50. while ((_len) && ((_c=*(_begin))==' ' || _c=='\t')) { \
  51. (_len)--;\
  52. (_begin)++; \
  53. } \
  54. }while(0)
  55. #define trim_r( _mystr ) \
  56. do{ static char _c; \
  57. while( ((_mystr).len) && ( ((_c=(_mystr).s[(_mystr).len-1]))==0 ||\
  58. _c=='\r' || _c=='\n' ) \
  59. ) \
  60. (_mystr).len--; \
  61. }while(0)
  62. #define translate_pointer( _new_buf , _org_buf , _p) \
  63. ( (_p)?(_new_buf + (_p-_org_buf)):(0) )
  64. #define via_len(_via) \
  65. ((_via)->bsize-((_via)->name.s-\
  66. ((_via)->hdr.s+(_via)->hdr.len)))
  67. #define via_s(_via,_p_msg) \
  68. translate_pointer((_p_msg)->orig,(_p_msg)->buf,(_via)->name.s)
  69. /* char to hex conversion table */
  70. static char fourbits2char[16] = { '0', '1', '2', '3', '4', '5',
  71. '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
  72. /* converts a str to an u. short, returns the u. short and sets *err on
  73. * error and if err!=null
  74. */
  75. static inline unsigned short str2s(unsigned char* str, unsigned int len,
  76. int *err)
  77. {
  78. unsigned short ret;
  79. int i;
  80. unsigned char *limit;
  81. unsigned char *init;
  82. /*init*/
  83. ret=i=0;
  84. limit=str+len;
  85. init=str;
  86. for(;str<limit ;str++){
  87. if ( (*str <= '9' ) && (*str >= '0') ){
  88. ret=ret*10+*str-'0';
  89. i++;
  90. if (i>5) goto error_digits;
  91. }else{
  92. //error unknown char
  93. goto error_char;
  94. }
  95. }
  96. if (err) *err=0;
  97. return ret;
  98. error_digits:
  99. DBG("str2s: ERROR: too many letters in [%.*s]\n", (int)len, init);
  100. if (err) *err=1;
  101. return 0;
  102. error_char:
  103. DBG("str2s: ERROR: unexpected char %c in %.*s\n", *str, (int)len, init);
  104. if (err) *err=1;
  105. return 0;
  106. }
  107. static inline int btostr( char *p, unsigned char val)
  108. {
  109. unsigned int a,b,i =0;
  110. if ( (a=val/100)!=0 )
  111. *(p+(i++)) = a+'0'; /*first digit*/
  112. if ( (b=val%100/10)!=0 || a)
  113. *(p+(i++)) = b+'0'; /*second digit*/
  114. *(p+(i++)) = '0'+val%10; /*third digit*/
  115. return i;
  116. }
  117. /* faster memchr version */
  118. static inline char* q_memchr(char* p, int c, unsigned int size)
  119. {
  120. char* end;
  121. end=p+size;
  122. for(;p<end;p++){
  123. if (*p==(unsigned char)c) return p;
  124. }
  125. return 0;
  126. }
  127. inline static int reverse_hex2int( char *c, int len )
  128. {
  129. char *pc;
  130. int r;
  131. char mychar;
  132. r=0;
  133. for (pc=c+len-1; len>0; pc--, len--) {
  134. r <<= 4 ;
  135. mychar=*pc;
  136. if ( mychar >='0' && mychar <='9') r+=mychar -'0';
  137. else if (mychar >='a' && mychar <='f') r+=mychar -'a'+10;
  138. else if (mychar >='A' && mychar <='F') r+=mychar -'A'+10;
  139. else return -1;
  140. }
  141. return r;
  142. }
  143. inline static int int2reverse_hex( char **c, int *size, int nr )
  144. {
  145. unsigned short digit;
  146. if (*size && nr==0) {
  147. **c = '0';
  148. (*c)++;
  149. (*size)--;
  150. return 1;
  151. }
  152. while (*size && nr ) {
  153. digit = nr & 0xf ;
  154. **c= digit >= 10 ? digit + 'a' - 10 : digit + '0';
  155. nr >>= 4;
  156. (*c)++;
  157. (*size)--;
  158. }
  159. return nr ? -1 /* number not processed; too little space */ : 1;
  160. }
  161. /* double output length assumed ; does NOT zero-terminate */
  162. inline static int string2hex(
  163. /* input */ unsigned char *str, int len,
  164. /* output */ char *hex )
  165. {
  166. int orig_len;
  167. if (len==0) {
  168. *hex='0';
  169. return 1;
  170. }
  171. orig_len=len;
  172. while ( len ) {
  173. *hex=fourbits2char[(*str) >> 4];
  174. hex++;
  175. *hex=fourbits2char[(*str) & 0xf];
  176. hex++;
  177. len--;
  178. str++;
  179. }
  180. return orig_len-len;
  181. }
  182. /* portable sleep in microseconds (no interrupt handling now) */
  183. inline static void sleep_us( unsigned int nusecs )
  184. {
  185. struct timeval tval;
  186. tval.tv_sec=nusecs/100000;
  187. tval.tv_usec=nusecs%1000000;
  188. select(0, NULL, NULL, NULL, &tval );
  189. }
  190. inline static int hex2int(char hex_digit)
  191. {
  192. if (hex_digit>='0' && hex_digit<='9')
  193. return hex_digit-'0';
  194. if (hex_digit>='a' && hex_digit<='f')
  195. return hex_digit-'a'+10;
  196. if (hex_digit>='A' && hex_digit<='F')
  197. return hex_digit-'A'+10;
  198. /* no valid hex digit ... */
  199. LOG(L_ERR, "ERROR: hex2int: '%c' is no hex char\n", hex_digit );
  200. return -1;
  201. }
  202. /* Un-escape URI user -- it takes a pointer to original user
  203. str, as well as the new, unescaped one, which MUST have
  204. an allocated buffer linked to the 'str' structure ;
  205. (the buffer can be allocated with the same length as
  206. the original string -- the output string is always
  207. shorter (if escaped characters occur) or same-long
  208. as the original one).
  209. only printeable characters are permitted
  210. <0 is returned on an uneascaping error, length of the
  211. unescaped string otherwise
  212. */
  213. inline static int un_escape(str *user, str *new_user )
  214. {
  215. int i, j, value;
  216. int hi, lo;
  217. if( new_user==0 || new_user->s==0) {
  218. LOG(L_CRIT, "BUG: un_escape: called with invalid param\n");
  219. return -1;
  220. }
  221. new_user->len = 0;
  222. j = 0;
  223. for (i = 0; i < user->len; i++) {
  224. if (user->s[i] == '%') {
  225. if (i + 2 >= user->len) {
  226. LOG(L_ERR, "ERROR: un_escape: escape sequence too short in"
  227. " '%.*s' @ %d\n",
  228. user->len, user->s, i );
  229. goto error;
  230. }
  231. hi=hex2int(user->s[i + 1]);
  232. if (hi<0) {
  233. LOG(L_ERR, "ERROR: un_escape: non-hex high digit in an escape sequence in"
  234. " '%.*s' @ %d\n",
  235. user->len, user->s, i+1 );
  236. goto error;
  237. }
  238. lo=hex2int(user->s[i + 2]);
  239. if (lo<0) {
  240. LOG(L_ERR, "ERROR: non-hex low digit in an escape sequence in "
  241. "'%.*s' @ %d\n",
  242. user->len, user->s, i+2 );
  243. goto error;
  244. }
  245. value=(hi<<4)+lo;
  246. if (value < 32 || value > 126) {
  247. LOG(L_ERR, "ERROR: non-ASCII escaped character in '%.*s' @ %d\n",
  248. user->len, user->s, i );
  249. goto error;
  250. }
  251. new_user->s[j] = value;
  252. i+=2; /* consume the two hex digits, for cycle will move to the next char */
  253. } else {
  254. new_user->s[j] = user->s[i];
  255. }
  256. j++; /* good -- we translated another character */
  257. }
  258. new_user->len = j;
  259. return j;
  260. error:
  261. new_user->len = j;
  262. return -1;
  263. }
  264. #endif