fixed Content-Lenght bug in build_res_buf_with_body_from_sip_req.
[sip-router] / ut.h
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  *    info@iptel.org
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-02-28 scratchpad compatibility abandoned (jiri)
32  * 2003-02-13 strlower added (janakj)
33  * 2003-01-29 pathmax added (jiri)
34  * 2003-01-28 scratchpad removed (jiri)
35  * 2003-01-18 un_escape function introduced for convenience of code needing
36  *            the complex&slow feature of unescaping
37  */
38
39
40 #ifndef ut_h
41 #define ut_h
42
43 #include "comp_defs.h"
44
45 #include <sys/types.h>
46 #include <sys/time.h>
47 #include <limits.h>
48 #include <unistd.h>
49 #include <ctype.h>
50
51 #include "config.h"
52 #include "dprint.h"
53 #include "str.h"
54
55
56 struct sip_msg;
57
58 /* returns string beginning and length without insignificant chars */
59 #define trim_len( _len, _begin, _mystr ) \
60         do{     static char _c; \
61                 (_len)=(_mystr).len; \
62                 while ((_len) && ((_c=(_mystr).s[(_len)-1])==0 || _c=='\r' || \
63                                         _c=='\n' || _c==' ' || _c=='\t' )) \
64                         (_len)--; \
65                 (_begin)=(_mystr).s; \
66                 while ((_len) && ((_c=*(_begin))==' ' || _c=='\t')) { \
67                         (_len)--;\
68                         (_begin)++; \
69                 } \
70         }while(0)
71
72 #define trim_r( _mystr ) \
73         do{     static char _c; \
74                 while( ((_mystr).len) && ( ((_c=(_mystr).s[(_mystr).len-1]))==0 ||\
75                                                                         _c=='\r' || _c=='\n' ) \
76                                 ) \
77                         (_mystr).len--; \
78         }while(0)
79
80
81 #define  translate_pointer( _new_buf , _org_buf , _p) \
82         ( (_p)?(_new_buf + (_p-_org_buf)):(0) )
83
84 #define via_len(_via) \
85         ((_via)->bsize-((_via)->name.s-\
86                 ((_via)->hdr.s+(_via)->hdr.len)))
87
88
89 /* char to hex conversion table */
90 static char fourbits2char[16] = { '0', '1', '2', '3', '4', '5',
91         '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
92
93
94 /* converts a str to an u. short, returns the u. short and sets *err on
95  * error and if err!=null
96   */
97 static inline unsigned short str2s(char* s, unsigned int len,
98                                                                         int *err)
99 {
100         unsigned short ret;
101         int i;
102         unsigned char *limit;
103         unsigned char *init;
104         unsigned char* str;
105
106         /*init*/
107         str=(unsigned char*)s;
108         ret=i=0;
109         limit=str+len;
110         init=str;
111
112         for(;str<limit ;str++){
113                 if ( (*str <= '9' ) && (*str >= '0') ){
114                                 ret=ret*10+*str-'0';
115                                 i++;
116                                 if (i>5) goto error_digits;
117                 }else{
118                                 //error unknown char
119                                 goto error_char;
120                 }
121         }
122         if (err) *err=0;
123         return ret;
124
125 error_digits:
126         DBG("str2s: ERROR: too many letters in [%.*s]\n", (int)len, init);
127         if (err) *err=1;
128         return 0;
129 error_char:
130         DBG("str2s: ERROR: unexpected char %c in %.*s\n", *str, (int)len, init);
131         if (err) *err=1;
132         return 0;
133 }
134
135
136
137 static inline int btostr( char *p,  unsigned char val)
138 {
139         unsigned int a,b,i =0;
140
141         if ( (a=val/100)!=0 )
142                 *(p+(i++)) = a+'0';         /*first digit*/
143         if ( (b=val%100/10)!=0 || a)
144                 *(p+(i++)) = b+'0';        /*second digit*/
145         *(p+(i++)) = '0'+val%10;              /*third digit*/
146
147         return i;
148 }
149
150
151 #define INT2STR_MAX_LEN 11 /* 10 digits + 0 */
152
153 /* returns a pointer to a static buffer containing l in asciiz & sets len */
154 static inline char* int2str(unsigned int l, int* len)
155 {
156         static char r[INT2STR_MAX_LEN];
157         int i;
158         
159         i=9;
160         r[10]=0; /* null terminate */
161         do{
162                 r[i]=l%10+'0';
163                 i--;
164                 l/=10;
165         }while(l && (i>=0));
166         if (l && (i<0)){
167                 LOG(L_CRIT, "BUG: int2str: overflow\n");
168         }
169         if (len) *len=9-i;
170         return &r[i+1];
171 }
172
173
174
175 /* faster memchr version */
176 static inline char* q_memchr(char* p, int c, unsigned int size)
177 {
178         char* end;
179
180         end=p+size;
181         for(;p<end;p++){
182                 if (*p==(unsigned char)c) return p;
183         }
184         return 0;
185 }
186         
187
188 inline static int reverse_hex2int( char *c, int len )
189 {
190         char *pc;
191         int r;
192         char mychar;
193
194         r=0;
195         for (pc=c+len-1; len>0; pc--, len--) {
196                 r <<= 4 ;
197                 mychar=*pc;
198                 if ( mychar >='0' && mychar <='9') r+=mychar -'0';
199                 else if (mychar >='a' && mychar <='f') r+=mychar -'a'+10;
200                 else if (mychar  >='A' && mychar <='F') r+=mychar -'A'+10;
201                 else return -1;
202         }
203         return r;
204 }
205
206 inline static int int2reverse_hex( char **c, int *size, int nr )
207 {
208         unsigned short digit;
209
210         if (*size && nr==0) {
211                 **c = '0';
212                 (*c)++;
213                 (*size)--;
214                 return 1;
215         }
216
217         while (*size && nr ) {
218                 digit = nr & 0xf ;
219                 **c= digit >= 10 ? digit + 'a' - 10 : digit + '0';
220                 nr >>= 4;
221                 (*c)++;
222                 (*size)--;
223         }
224         return nr ? -1 /* number not processed; too little space */ : 1;
225 }
226
227 /* double output length assumed ; does NOT zero-terminate */
228 inline static int string2hex( 
229         /* input */ unsigned char *str, int len,
230         /* output */ char *hex )
231 {
232         int orig_len;
233
234         if (len==0) {
235                 *hex='0';
236                 return 1;
237         }
238
239         orig_len=len;
240         while ( len ) {
241
242                 *hex=fourbits2char[(*str) >> 4];
243                 hex++;
244                 *hex=fourbits2char[(*str) & 0xf];
245                 hex++;
246                 len--;
247                 str++;
248
249         }
250         return orig_len-len;
251 }
252
253 /* portable sleep in microseconds (no interrupt handling now) */
254
255 inline static void sleep_us( unsigned int nusecs )
256 {
257         struct timeval tval;
258         tval.tv_sec=nusecs/100000;
259         tval.tv_usec=nusecs%1000000;
260         select(0, NULL, NULL, NULL, &tval );
261 }
262
263
264 /* portable determination of max_path */
265 inline static int pathmax()
266 {
267 #ifdef PATH_MAX
268         static int pathmax=PATH_MAX;
269 #else
270         static int pathmax=0;
271 #endif
272         if (pathmax==0) { /* init */
273                 pathmax=pathconf("/", _PC_PATH_MAX);
274                 pathmax=(pathmax<=0)?PATH_MAX_GUESS:pathmax+1;
275         }
276         return pathmax;
277 }
278
279 inline static int hex2int(char hex_digit)
280 {
281         if (hex_digit>='0' && hex_digit<='9')
282                 return hex_digit-'0';
283         if (hex_digit>='a' && hex_digit<='f')
284                 return hex_digit-'a'+10;
285         if (hex_digit>='A' && hex_digit<='F')
286                 return hex_digit-'A'+10;
287         /* no valid hex digit ... */
288         LOG(L_ERR, "ERROR: hex2int: '%c' is no hex char\n", hex_digit );
289         return -1;
290 }
291
292 /* Un-escape URI user  -- it takes a pointer to original user
293    str, as well as the new, unescaped one, which MUST have
294    an allocated buffer linked to the 'str' structure ;
295    (the buffer can be allocated with the same length as
296    the original string -- the output string is always
297    shorter (if escaped characters occur) or same-long
298    as the original one).
299
300    only printeable characters are permitted
301
302         <0 is returned on an uneascaping error, length of the
303         unescaped string otherwise
304 */
305 inline static int un_escape(str *user, str *new_user ) 
306 {
307         int i, j, value;
308         int hi, lo;
309
310         if( new_user==0 || new_user->s==0) {
311                 LOG(L_CRIT, "BUG: un_escape: called with invalid param\n");
312                 return -1;
313         }
314
315         new_user->len = 0;
316         j = 0;
317
318         for (i = 0; i < user->len; i++) {
319                 if (user->s[i] == '%') {
320                         if (i + 2 >= user->len) {
321                                 LOG(L_ERR, "ERROR: un_escape: escape sequence too short in"
322                                         " '%.*s' @ %d\n",
323                                         user->len, user->s, i );
324                                 goto error;
325                         }
326                         hi=hex2int(user->s[i + 1]);
327                         if (hi<0) {
328                                 LOG(L_ERR, "ERROR: un_escape: non-hex high digit in an escape sequence in"
329                                         " '%.*s' @ %d\n",
330                                         user->len, user->s, i+1 );
331                                 goto error;
332                         }
333                         lo=hex2int(user->s[i + 2]);
334                         if (lo<0) {
335                                 LOG(L_ERR, "ERROR: non-hex low digit in an escape sequence in "
336                                         "'%.*s' @ %d\n",
337                                         user->len, user->s, i+2 );
338                                 goto error;
339                         }
340                         value=(hi<<4)+lo;
341                         if (value < 32 || value > 126) {
342                                 LOG(L_ERR, "ERROR: non-ASCII escaped character in '%.*s' @ %d\n",
343                                         user->len, user->s, i );
344                                 goto error;
345                         }
346                         new_user->s[j] = value;
347                         i+=2; /* consume the two hex digits, for cycle will move to the next char */
348                 } else {
349                         new_user->s[j] = user->s[i];
350                 }
351         j++; /* good -- we translated another character */
352         }
353         new_user->len = j;
354         return j;
355
356 error:
357         new_user->len = j;
358         return -1;
359
360
361
362 /*
363  * Convert a string to lower case
364  */
365 static inline void strlower(str* _s)
366 {
367         int i;
368
369         for(i = 0; i < _s->len; i++) {
370                 _s->s[i] = tolower(_s->s[i]);
371         }
372 }
373
374
375 #endif