/src/opensips/parser/parse_content.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2001-2003 FhG Fokus |
3 | | * |
4 | | * This file is part of opensips, a free SIP server. |
5 | | * |
6 | | * opensips is free software; you can redistribute it and/or modify |
7 | | * it under the terms of the GNU General Public License as published by |
8 | | * the Free Software Foundation; either version 2 of the License, or |
9 | | * (at your option) any later version |
10 | | * |
11 | | * opensips is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License |
17 | | * along with this program; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | * |
20 | | * History: |
21 | | * 2003-08-04 parse_content_type_hdr separates type from subtype inside |
22 | | * the mime type (bogdan) |
23 | | * 2003-08-04 CPL subtype added (bogdan) |
24 | | * 2003-08-05 parse_accept_hdr function added (bogdan) |
25 | | * 2011-06-22 ISUP subtype added (roger) |
26 | | */ |
27 | | |
28 | | |
29 | | #include <stdio.h> |
30 | | #include <stdlib.h> |
31 | | #include <sys/types.h> |
32 | | #include <unistd.h> |
33 | | #include "../mem/mem.h" |
34 | | #include "../dprint.h" |
35 | | #include "../str.h" |
36 | | #include "../ut.h" |
37 | | #include "../errinfo.h" |
38 | | #include "parse_content.h" |
39 | | |
40 | | |
41 | | #define is_mime_char(_c_) \ |
42 | 8.70k | (isalnum((int)_c_) || (_c_)=='-' || (_c_)=='+' || (_c_)=='.') |
43 | | #define is_char_equal(_c_,_cs_) \ |
44 | 6.19k | ( (isalpha((int)_c_)?(((_c_)|0x20)==(_cs_)):((_c_)==(_cs_)))==1 ) |
45 | | |
46 | | |
47 | | /* |
48 | | * Node of the type's tree; this tree contains all the known types; |
49 | | */ |
50 | | typedef struct type_node_s { |
51 | | char c; /* char contained by this node */ |
52 | | unsigned char final; /* says what mime type/subtype was detected |
53 | | * if string ends at this node */ |
54 | | unsigned char nr_sons; /* the number of sub-nodes */ |
55 | | int next; /* the next sibling node */ |
56 | | }type_node_t; |
57 | | |
58 | | |
59 | | static type_node_t type_tree[] = { |
60 | | {'t',TYPE_UNKNOWN,1,4}, /* 0 */ |
61 | | {'e',TYPE_UNKNOWN,1,-1}, |
62 | | {'x',TYPE_UNKNOWN,1,-1}, |
63 | | {'t',TYPE_TEXT,0,-1}, |
64 | | {'m',TYPE_UNKNOWN,2,19}, /* 4 */ |
65 | | {'e',TYPE_UNKNOWN,1,11}, /* 5 */ |
66 | | {'s',TYPE_UNKNOWN,1,-1}, |
67 | | {'s',TYPE_UNKNOWN,1,-1}, |
68 | | {'a',TYPE_UNKNOWN,1,-1}, |
69 | | {'g',TYPE_UNKNOWN,1,-1}, |
70 | | {'e',TYPE_MESSAGE,0,-1}, |
71 | | {'u',TYPE_UNKNOWN,1,-1}, /* 11 */ |
72 | | {'l',TYPE_UNKNOWN,1,-1}, |
73 | | {'t',TYPE_UNKNOWN,1,-1}, |
74 | | {'i',TYPE_UNKNOWN,1,-1}, |
75 | | {'p',TYPE_UNKNOWN,1,-1}, |
76 | | {'a',TYPE_UNKNOWN,1,-1}, |
77 | | {'r',TYPE_UNKNOWN,1,-1}, |
78 | | {'t',TYPE_MULTIPART,0,-1}, |
79 | | {'a',TYPE_UNKNOWN,1,-1}, /* 19 */ |
80 | | {'p',TYPE_UNKNOWN,1,-1}, |
81 | | {'p',TYPE_UNKNOWN,1,-1}, |
82 | | {'l',TYPE_UNKNOWN,1,-1}, |
83 | | {'i',TYPE_UNKNOWN,1,-1}, |
84 | | {'c',TYPE_UNKNOWN,1,-1}, |
85 | | {'a',TYPE_UNKNOWN,1,-1}, |
86 | | {'t',TYPE_UNKNOWN,1,-1}, |
87 | | {'i',TYPE_UNKNOWN,1,-1}, |
88 | | {'o',TYPE_UNKNOWN,1,-1}, |
89 | | {'n',TYPE_APPLICATION,0,-1}, |
90 | | }; |
91 | | |
92 | | |
93 | | static type_node_t subtype_tree[] = { |
94 | | {'p',SUBTYPE_UNKNOWN,2,12}, /* 0 */ |
95 | | {'l',SUBTYPE_UNKNOWN,1,5}, |
96 | | {'a',SUBTYPE_UNKNOWN,1,-1}, |
97 | | {'i',SUBTYPE_UNKNOWN,1,-1}, |
98 | | {'n',SUBTYPE_PLAIN,0,-1}, |
99 | | {'i',SUBTYPE_UNKNOWN,1,-1}, /* 5 */ |
100 | | {'d',SUBTYPE_UNKNOWN,1,-1}, |
101 | | {'f',SUBTYPE_UNKNOWN,1,-1}, |
102 | | {'+',SUBTYPE_UNKNOWN,1,-1}, |
103 | | {'x',SUBTYPE_UNKNOWN,1,-1}, |
104 | | {'m',SUBTYPE_UNKNOWN,1,-1}, |
105 | | {'l',SUBTYPE_PIDFXML,0,-1}, |
106 | | {'s',SUBTYPE_UNKNOWN,2,36}, /* 12 */ |
107 | | {'d',SUBTYPE_UNKNOWN,1,15}, |
108 | | {'p',SUBTYPE_SDP,0,-1}, |
109 | | {'i',SUBTYPE_UNKNOWN,1,-1}, /* 15 */ |
110 | | {'m',SUBTYPE_UNKNOWN,1,-1}, |
111 | | {'p',SUBTYPE_UNKNOWN,1,-1}, |
112 | | {'l',SUBTYPE_UNKNOWN,1,-1}, |
113 | | {'e',SUBTYPE_UNKNOWN,1,-1}, |
114 | | {'-',SUBTYPE_UNKNOWN,1,-1}, |
115 | | {'m',SUBTYPE_UNKNOWN,1,-1}, |
116 | | {'e',SUBTYPE_UNKNOWN,1,-1}, |
117 | | {'s',SUBTYPE_UNKNOWN,1,-1}, |
118 | | {'s',SUBTYPE_UNKNOWN,1,-1}, |
119 | | {'a',SUBTYPE_UNKNOWN,1,-1}, |
120 | | {'g',SUBTYPE_UNKNOWN,1,-1}, |
121 | | {'e',SUBTYPE_UNKNOWN,1,-1}, |
122 | | {'-',SUBTYPE_UNKNOWN,1,-1}, |
123 | | {'s',SUBTYPE_UNKNOWN,1,-1}, |
124 | | {'u',SUBTYPE_UNKNOWN,1,-1}, |
125 | | {'m',SUBTYPE_UNKNOWN,1,-1}, |
126 | | {'m',SUBTYPE_UNKNOWN,1,-1}, |
127 | | {'a',SUBTYPE_UNKNOWN,1,-1}, |
128 | | {'r',SUBTYPE_UNKNOWN,1,-1}, |
129 | | {'y',SUBTYPE_SMS,0,-1}, |
130 | | {'c',SUBTYPE_UNKNOWN,1,45}, /* 36 */ |
131 | | {'p',SUBTYPE_UNKNOWN,2,-1}, |
132 | | {'i',SUBTYPE_UNKNOWN,1,40}, |
133 | | {'m',SUBTYPE_CPIM,0,-1}, |
134 | | {'l',SUBTYPE_UNKNOWN,1,-1}, /* 40 */ |
135 | | {'+',SUBTYPE_UNKNOWN,1,-1}, |
136 | | {'x',SUBTYPE_UNKNOWN,1,-1}, |
137 | | {'m',SUBTYPE_UNKNOWN,1,-1}, |
138 | | {'l',SUBTYPE_CPLXML,0,-1}, |
139 | | {'r',SUBTYPE_UNKNOWN,2,59}, /* 45 */ |
140 | | {'l',SUBTYPE_UNKNOWN,1,53}, |
141 | | {'m',SUBTYPE_UNKNOWN,1,-1}, |
142 | | {'i',SUBTYPE_UNKNOWN,1,-1}, |
143 | | {'+',SUBTYPE_UNKNOWN,1,-1}, |
144 | | {'x',SUBTYPE_UNKNOWN,1,-1}, |
145 | | {'m',SUBTYPE_UNKNOWN,1,-1}, |
146 | | {'l',SUBTYPE_RLMIXML,0,-1}, |
147 | | {'e',SUBTYPE_UNKNOWN,1,-1}, /* 53 */ |
148 | | {'l',SUBTYPE_UNKNOWN,1,-1}, |
149 | | {'a',SUBTYPE_UNKNOWN,1,-1}, |
150 | | {'t',SUBTYPE_UNKNOWN,1,-1}, |
151 | | {'e',SUBTYPE_UNKNOWN,1,-1}, |
152 | | {'d',SUBTYPE_RELATED,0,-1}, |
153 | | {'l',SUBTYPE_UNKNOWN,1,68}, /* 59 */ |
154 | | {'p',SUBTYPE_UNKNOWN,1,-1}, |
155 | | {'i',SUBTYPE_UNKNOWN,1,-1}, |
156 | | {'d',SUBTYPE_UNKNOWN,1,-1}, |
157 | | {'f',SUBTYPE_UNKNOWN,1,-1}, |
158 | | {'+',SUBTYPE_UNKNOWN,1,-1}, |
159 | | {'x',SUBTYPE_UNKNOWN,1,-1}, |
160 | | {'m',SUBTYPE_UNKNOWN,1,-1}, |
161 | | {'l',SUBTYPE_LPIDFXML,0,-1}, |
162 | | {'w',SUBTYPE_UNKNOWN,1,83}, /* 68 */ |
163 | | {'a',SUBTYPE_UNKNOWN,1,-1}, |
164 | | {'t',SUBTYPE_UNKNOWN,1,-1}, |
165 | | {'c',SUBTYPE_UNKNOWN,1,-1}, |
166 | | {'h',SUBTYPE_UNKNOWN,1,-1}, |
167 | | {'e',SUBTYPE_UNKNOWN,1,-1}, |
168 | | {'r',SUBTYPE_UNKNOWN,1,-1}, |
169 | | {'i',SUBTYPE_UNKNOWN,1,-1}, |
170 | | {'n',SUBTYPE_UNKNOWN,1,-1}, |
171 | | {'f',SUBTYPE_UNKNOWN,1,-1}, |
172 | | {'o',SUBTYPE_UNKNOWN,1,-1}, |
173 | | {'+',SUBTYPE_UNKNOWN,1,-1}, |
174 | | {'x',SUBTYPE_UNKNOWN,1,-1}, |
175 | | {'m',SUBTYPE_UNKNOWN,1,-1}, |
176 | | {'l',SUBTYPE_WATCHERINFOXML,0,-1}, |
177 | | {'x',SUBTYPE_UNKNOWN,2,105}, /* 83 */ |
178 | | {'p',SUBTYPE_UNKNOWN,1,92}, |
179 | | {'i',SUBTYPE_UNKNOWN,1,-1}, |
180 | | {'d',SUBTYPE_UNKNOWN,1,-1}, |
181 | | {'f',SUBTYPE_UNKNOWN,1,-1}, |
182 | | {'+',SUBTYPE_UNKNOWN,1,-1}, |
183 | | {'x',SUBTYPE_UNKNOWN,1,-1}, |
184 | | {'m',SUBTYPE_UNKNOWN,1,-1}, |
185 | | {'l',SUBTYPE_XPIDFXML,0,-1}, |
186 | | {'m',SUBTYPE_UNKNOWN,1,-1}, /* 92 */ |
187 | | {'l',SUBTYPE_UNKNOWN,1,-1}, |
188 | | {'+',SUBTYPE_UNKNOWN,1,-1}, |
189 | | {'m',SUBTYPE_UNKNOWN,1,-1}, |
190 | | {'s',SUBTYPE_UNKNOWN,1,-1}, |
191 | | {'r',SUBTYPE_UNKNOWN,1,-1}, |
192 | | {'t',SUBTYPE_UNKNOWN,1,-1}, |
193 | | {'c',SUBTYPE_UNKNOWN,1,-1}, |
194 | | {'.',SUBTYPE_UNKNOWN,1,-1}, |
195 | | {'p',SUBTYPE_UNKNOWN,1,-1}, |
196 | | {'i',SUBTYPE_UNKNOWN,1,-1}, |
197 | | {'d',SUBTYPE_UNKNOWN,1,-1}, |
198 | | {'f',SUBTYPE_XML_MSRTC_PIDF,0,-1}, |
199 | | {'e',SUBTYPE_UNKNOWN,1,118}, /* 105 */ |
200 | | {'x',SUBTYPE_UNKNOWN,1,-1}, |
201 | | {'t',SUBTYPE_UNKNOWN,1,-1}, |
202 | | {'e',SUBTYPE_UNKNOWN,1,-1}, |
203 | | {'r',SUBTYPE_UNKNOWN,1,-1}, |
204 | | {'n',SUBTYPE_UNKNOWN,1,-1}, |
205 | | {'a',SUBTYPE_UNKNOWN,1,-1}, |
206 | | {'l',SUBTYPE_UNKNOWN,1,-1}, |
207 | | {'-',SUBTYPE_UNKNOWN,1,-1}, |
208 | | {'b',SUBTYPE_UNKNOWN,1,-1}, |
209 | | {'o',SUBTYPE_UNKNOWN,1,-1}, |
210 | | {'d',SUBTYPE_UNKNOWN,1,-1}, |
211 | | {'y',SUBTYPE_EXTERNAL_BODY,0,-1}, |
212 | | {'m',SUBTYPE_UNKNOWN,1,123}, /* 118 */ |
213 | | {'i',SUBTYPE_UNKNOWN,1,-1}, |
214 | | {'x',SUBTYPE_UNKNOWN,1,-1}, |
215 | | {'e',SUBTYPE_UNKNOWN,1,-1}, |
216 | | {'d',SUBTYPE_MIXED,0,-1}, |
217 | | {'i',SUBTYPE_UNKNOWN,1,-1}, /* 123 */ |
218 | | {'s',SUBTYPE_UNKNOWN,1,-1}, |
219 | | {'u',SUBTYPE_UNKNOWN,1,-1}, |
220 | | {'p',SUBTYPE_ISUP,0,-1}, |
221 | | |
222 | | }; |
223 | | char str_contenttype[50]; |
224 | | |
225 | | |
226 | | |
227 | | char* parse_content_length( char* buffer, char* end, int* length) |
228 | 7.52k | { |
229 | 7.52k | int number; |
230 | 7.52k | char *p, *numstart; |
231 | | |
232 | 7.52k | p = buffer; |
233 | | /* search the beginning of the number */ |
234 | 7.53k | while ( p<end && (*p==' ' || *p=='\t' |
235 | 7.53k | || (*p=='\r' && p+1<end && *(p+1)=='\n') |
236 | 7.53k | || (*p=='\n' && p+1<end && (*(p+1)==' '||*(p+1)=='\t')) )) |
237 | 5 | p++; |
238 | 7.52k | if (p==end) |
239 | 0 | goto error; |
240 | | /* parse the number */ |
241 | 7.52k | numstart = p; |
242 | 7.52k | number = 0; |
243 | 17.1k | while (p<end && *p>='0' && *p<='9') { |
244 | | /* do not actually cause an integer overflow, as it is UB! --liviu */ |
245 | 9.63k | if (number >= INT_MAX/10) { |
246 | 5 | LM_ERR("integer overflow risk at pos %d in length value [%.*s]\n", |
247 | 5 | (int)(p-buffer),(int)(end-buffer), buffer); |
248 | 5 | return NULL; |
249 | 5 | } |
250 | | |
251 | 9.63k | number = number*10 + ((*p)-'0'); |
252 | 9.63k | p++; |
253 | 9.63k | } |
254 | 7.52k | if (p==end || p==numstart) |
255 | 82 | goto error; |
256 | | |
257 | | /* now we should have only spaces at the end */ |
258 | 11.9k | while ( p<end && (*p==' ' || *p=='\t' |
259 | 11.9k | || (*p=='\n' && p+1<end && (*(p+1)==' '||*(p+1)=='\t')) )) |
260 | 4.53k | p++; |
261 | 7.44k | if (p==end) |
262 | 27 | goto error; |
263 | | /* the header ends proper? */ |
264 | 7.41k | if ( (*(p++)!='\n') && (*(p-1)!='\r' || p==end || *(p++)!='\n' ) ) |
265 | 44 | goto error; |
266 | | |
267 | 7.37k | *length = number; |
268 | 7.37k | return p; |
269 | 153 | error: |
270 | 153 | LM_ERR("parse error at pos %ld, dec-char: %d, start/p/end: %p/%p/%p\n", |
271 | 153 | (long)(p - buffer), p < end && (end-buffer) ? *p:-1, buffer, p, end); |
272 | 153 | return NULL; |
273 | 7.41k | } |
274 | | |
275 | | |
276 | | |
277 | | char* decode_mime_type(char *start, char *end, unsigned int *mime_type, content_t * con) |
278 | 670 | { |
279 | 670 | int node; |
280 | 670 | char *mark; |
281 | 670 | char *p; |
282 | | |
283 | 670 | p = start; |
284 | | |
285 | 670 | LM_DBG("Decoding MIME type for:[%.*s]\n",(int)(end-start),start); |
286 | | |
287 | | /* search the beginning of the type */ |
288 | 670 | while ( p<end && (*p==' ' || *p=='\t' || (*p=='\r' && *(p+1)=='\n') || |
289 | 666 | (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) )) |
290 | 0 | p++; |
291 | 670 | if (p==end) |
292 | 4 | goto error; |
293 | | |
294 | | /* parse the type */ |
295 | 666 | if (*p=='*') { |
296 | 32 | *mime_type = TYPE_ALL<<16; |
297 | 32 | p++; |
298 | 634 | } else { |
299 | 634 | node = 0; |
300 | 634 | mark = p; |
301 | 3.26k | while (p<end && is_mime_char(*p) ) { |
302 | 4.37k | while ( node!=-1 && !is_char_equal(*p,type_tree[node].c) ){ |
303 | 1.74k | node = type_tree[node].next; |
304 | 1.74k | } |
305 | 2.62k | if (node!=-1 && type_tree[node].nr_sons) |
306 | 408 | node++; |
307 | 2.62k | p++; |
308 | 2.62k | } |
309 | 634 | if (p==end || mark==p) |
310 | 48 | goto error; |
311 | 586 | if (node!=-1) |
312 | 68 | *mime_type = type_tree[node].final<<16; |
313 | 518 | else |
314 | 518 | *mime_type = TYPE_UNKNOWN<<16; |
315 | 586 | } |
316 | | |
317 | | /* search the '/' separator */ |
318 | 1.95k | while ( p<end && (*p==' ' || *p=='\t' || |
319 | 1.92k | (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) )) |
320 | 1.33k | p++; |
321 | 618 | if ( p==end || *(p++)!='/') |
322 | 124 | goto error; |
323 | | |
324 | | /* search the beginning of the sub-type */ |
325 | 1.78k | while ( p<end && (*p==' ' || *p=='\t' || |
326 | 1.75k | (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) )) |
327 | 1.29k | p++; |
328 | 494 | if (p==end) |
329 | 32 | goto error; |
330 | | |
331 | | /* parse the sub-type */ |
332 | 462 | if (*p=='*') { |
333 | 12 | *mime_type |= SUBTYPE_ALL; |
334 | 12 | p++; |
335 | 450 | } else { |
336 | 450 | node = 0; |
337 | 450 | mark = p; |
338 | 2.78k | while (p<end && (is_mime_char(*p) || *p == '_')) { |
339 | 5.63k | while(node!=-1 && !is_char_equal(*p,subtype_tree[node].c) ) |
340 | 3.30k | node = subtype_tree[node].next; |
341 | 2.33k | if (node!=-1 && subtype_tree[node].nr_sons) |
342 | 184 | node++; |
343 | 2.33k | p++; |
344 | 2.33k | } |
345 | 450 | if (p==mark) |
346 | 34 | goto error; |
347 | 416 | if (node!=-1) |
348 | 62 | *mime_type |= subtype_tree[node].final; |
349 | 354 | else |
350 | 354 | *mime_type |= SUBTYPE_UNKNOWN; |
351 | 416 | } |
352 | | |
353 | | /* now its possible to have some spaces */ |
354 | 1.76k | while ( p<end && (*p==' ' || *p=='\t' || |
355 | 1.70k | (*p=='\n' && (*(p+1)==' '||*(p+1)=='\t')) )) |
356 | 1.33k | p++; |
357 | | |
358 | | /* if there are params, ignore them!! -> eat everything to |
359 | | * the end or to the first ',' */ |
360 | 428 | if ( p<end && *p==';' ) |
361 | 226 | { |
362 | 226 | if( con == NULL) |
363 | 0 | for(p++; p<end && *p!=','; p++); |
364 | 226 | else |
365 | 226 | { |
366 | 226 | str params_str; |
367 | 226 | param_hooks_t phooks; |
368 | 226 | param_t * cur; |
369 | | |
370 | 226 | params_str.s = p; |
371 | 226 | params_str.len = end - p ; |
372 | | |
373 | 226 | if (parse_params(¶ms_str, CLASS_ANY, &phooks, &con->params) < 0) |
374 | 60 | goto error; |
375 | | |
376 | 166 | p = params_str.s; |
377 | | |
378 | 166 | cur = con->params; |
379 | | |
380 | 3.33k | while(cur) |
381 | 3.17k | { |
382 | 3.17k | if( cur->name.len == 8 && !strncasecmp(cur->name.s,"boundary",cur->name.len ) ) |
383 | 230 | con->boundary = cur->body; |
384 | | |
385 | 3.17k | if( cur->name.len == 5 && !strncasecmp(cur->name.s,"start",cur->name.len ) ) |
386 | 208 | con->start = cur->body; |
387 | | |
388 | 3.17k | cur = cur ->next; |
389 | 3.17k | } |
390 | | |
391 | 166 | } |
392 | 226 | } |
393 | | |
394 | | /* is this the correct end? */ |
395 | 368 | if (p!=end && *p!=',' ) |
396 | 138 | goto error; |
397 | | |
398 | | /* check the format of the decoded mime */ |
399 | 230 | if ((*mime_type)>>16==TYPE_ALL && ((*mime_type)&0x00ff)!=SUBTYPE_ALL) { |
400 | 16 | LM_ERR("invalid mime format found " |
401 | 16 | " <*/submime> in [%.*s]!!\n", (int)(end-start),start); |
402 | 16 | return 0; |
403 | 16 | } |
404 | | |
405 | 214 | return p; |
406 | 440 | error: |
407 | 440 | LM_ERR("parse error near in [%.*s] char" |
408 | 440 | "[%d][%c] offset=%d\n", (int)(end-start),start,*p,*p,(int)(p-start)); |
409 | 440 | return 0; |
410 | 230 | } |
411 | | |
412 | | |
413 | | |
414 | | /* returns: > 0 mime found |
415 | | * = 0 hdr not found |
416 | | * =-1 error */ |
417 | | int parse_content_type_hdr( struct sip_msg *msg ) |
418 | 718 | { |
419 | 718 | char *end; |
420 | 718 | char *ret; |
421 | 718 | unsigned int mime; |
422 | 718 | content_t * rez; |
423 | | |
424 | | /* is the header already found? */ |
425 | 718 | if ( msg->content_type==0 ) { |
426 | | /* if not, found it */ |
427 | 48 | if ( parse_headers(msg, HDR_CONTENTTYPE_F, 0)==-1) |
428 | 0 | goto error; |
429 | 48 | if ( msg->content_type==0 ) { |
430 | 48 | LM_DBG("missing Content-Type header\n"); |
431 | 48 | return 0; |
432 | 48 | } |
433 | 48 | } |
434 | | |
435 | | /* maybe the header is already parsed! */ |
436 | 670 | if ( msg->content_type->parsed!=0) |
437 | 0 | return get_content_type(msg); |
438 | | |
439 | 670 | rez = (content_t*) pkg_malloc(sizeof (content_t)); |
440 | 670 | if (rez == NULL) |
441 | 0 | { |
442 | 0 | LM_ERR("Unable to allocate memory\n"); |
443 | 0 | goto error; |
444 | 0 | } |
445 | 670 | memset(rez, 0, sizeof (content_t)); |
446 | | |
447 | | /* it seams we have to parse it! :-( */ |
448 | 670 | end = msg->content_type->body.s + msg->content_type->body.len; |
449 | 670 | ret = decode_mime_type(msg->content_type->body.s, end , &mime, rez); |
450 | 670 | if (ret==0) |
451 | 456 | goto parse_error; |
452 | 214 | if (ret!=end) { |
453 | 110 | LM_ERR("the header CONTENT_TYPE contains " |
454 | 110 | "more then one mime type :-(!\n"); |
455 | 110 | goto parse_error; |
456 | 110 | } |
457 | 104 | if ((mime&0x00ff)==SUBTYPE_ALL || (mime>>16)==TYPE_ALL) { |
458 | 10 | LM_ERR("invalid mime with wildcard '*' in Content-Type hdr!\n"); |
459 | 10 | goto parse_error; |
460 | 10 | } |
461 | | |
462 | | |
463 | 94 | rez->type = mime; |
464 | 94 | msg->content_type->parsed = rez; |
465 | 94 | return mime; |
466 | | |
467 | 576 | parse_error: |
468 | 576 | pkg_free(rez); |
469 | 576 | set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, |
470 | 576 | "error parsing CT-TYPE header"); |
471 | 576 | set_err_reply(400, "bad headers"); |
472 | | |
473 | 576 | error: |
474 | 576 | return -1; |
475 | 576 | } |
476 | | |
477 | | |
478 | | |
479 | | /* returns: > 0 ok |
480 | | * = 0 hdr not found |
481 | | * = -1 error */ |
482 | | int parse_accept_hdr( struct sip_msg *msg ) |
483 | 0 | { |
484 | 0 | static unsigned int mimes[MAX_MIMES_NR]; |
485 | 0 | int nr_mimes; |
486 | 0 | unsigned int mime; |
487 | 0 | char *end; |
488 | 0 | char *ret; |
489 | | |
490 | | /* is the header already found? */ |
491 | 0 | if ( msg->accept==0 ) { |
492 | | /* if not, found it */ |
493 | 0 | if ( parse_headers(msg, HDR_ACCEPT_F, 0)==-1) |
494 | 0 | goto error; |
495 | 0 | if ( msg->accept==0 ) { |
496 | 0 | LM_DBG("missing Accept header\n"); |
497 | 0 | return 0; |
498 | 0 | } |
499 | 0 | } |
500 | | |
501 | | /* maybe the header is already parsed! */ |
502 | 0 | if ( msg->accept->parsed!=0) |
503 | 0 | return 1; |
504 | | |
505 | | /* it seams we have to parse it! :-( */ |
506 | 0 | ret = msg->accept->body.s; |
507 | 0 | end = ret + msg->accept->body.len; |
508 | 0 | nr_mimes = 0; |
509 | 0 | while (1){ |
510 | 0 | ret = decode_mime_type(ret, end , &mime, NULL); |
511 | 0 | if (ret==0) |
512 | 0 | goto parse_error; |
513 | | /* a new mime was found -> put it into array */ |
514 | 0 | if (nr_mimes==MAX_MIMES_NR) { |
515 | 0 | LM_ERR("accept hdr contains more than" |
516 | 0 | " %d mime type -> buffer overflow!!\n",MAX_MIMES_NR); |
517 | 0 | goto error; |
518 | 0 | } |
519 | 0 | mimes[nr_mimes++] = mime; |
520 | | /* is another mime following? */ |
521 | 0 | if (ret==end ) |
522 | 0 | break; |
523 | | /* parse the mime separator ',' */ |
524 | 0 | if (*ret!=',' || ret+1==end) { |
525 | 0 | LM_ERR("parse error between mimes at " |
526 | 0 | "char <%x> (offset=%d) in <%.*s>!\n", |
527 | 0 | *ret, (int)(ret-msg->accept->body.s), |
528 | 0 | msg->accept->body.len, msg->accept->body.s); |
529 | 0 | goto parse_error; |
530 | 0 | } |
531 | | /* skip the ',' */ |
532 | 0 | ret++; |
533 | 0 | } |
534 | | |
535 | | /* copy and link the mime buffer into the message */ |
536 | 0 | msg->accept->parsed = (void*)pkg_malloc((nr_mimes+1)*sizeof(int)); |
537 | 0 | if (msg->accept->parsed==0) { |
538 | 0 | LM_ERR("no more pkg memory\n"); |
539 | 0 | goto error; |
540 | 0 | } |
541 | 0 | memcpy(msg->accept->parsed,mimes,nr_mimes*sizeof(int)); |
542 | | /* make the buffer null terminated */ |
543 | 0 | ((int*)msg->accept->parsed)[nr_mimes] = 0; |
544 | |
|
545 | 0 | return 1; |
546 | | |
547 | 0 | parse_error: |
548 | 0 | set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, |
549 | 0 | "error parsing ACCEPT header"); |
550 | 0 | set_err_reply(400, "bad headers"); |
551 | 0 | error: |
552 | 0 | return -1; |
553 | 0 | } |
554 | | |
555 | | void free_contenttype(content_t ** con) |
556 | 94 | { |
557 | | |
558 | 94 | if (*con) |
559 | 94 | { |
560 | 94 | if((*con)->params) |
561 | 44 | free_params((*con)->params); |
562 | 94 | pkg_free(*con); |
563 | 94 | } |
564 | 94 | *con = 0; |
565 | 94 | } |
566 | | |
567 | | char* convert_mime2string_CT(int contenttype) |
568 | 0 | { |
569 | 0 | #define SET_TYPE_PTRS(_type_) \ |
570 | 0 | do { \ |
571 | 0 | subtype_start = type_start + sizeof(_type_) - 1; \ |
572 | 0 | memcpy(type_start, _type_, sizeof(_type_) - 1); \ |
573 | 0 | } while(0); |
574 | |
|
575 | 0 | #define SET_SUBTYPE_PTR(_subtype_) memcpy(subtype_start, _subtype_, sizeof(_subtype_)) |
576 | | |
577 | | /* last 16 bits */ |
578 | 0 | int type = contenttype >> 16; |
579 | | /* only first 16 bits */ |
580 | 0 | int subtype = contenttype & (0xFF); |
581 | 0 | char* type_start; |
582 | 0 | char* subtype_start; |
583 | |
|
584 | 0 | memset(str_contenttype, 0 , sizeof(str_contenttype)); |
585 | 0 | type_start = str_contenttype; |
586 | |
|
587 | 0 | switch (type) { |
588 | 0 | case TYPE_TEXT: |
589 | 0 | SET_TYPE_PTRS("text/"); |
590 | 0 | break; |
591 | 0 | case TYPE_MESSAGE: |
592 | 0 | SET_TYPE_PTRS("message/"); |
593 | 0 | break; |
594 | 0 | case TYPE_APPLICATION: |
595 | 0 | SET_TYPE_PTRS("application/"); |
596 | 0 | break; |
597 | 0 | case TYPE_MULTIPART: |
598 | 0 | SET_TYPE_PTRS("multipart/"); |
599 | 0 | break; |
600 | 0 | case TYPE_ALL: |
601 | 0 | SET_TYPE_PTRS("*/"); |
602 | 0 | break; |
603 | 0 | case TYPE_UNKNOWN: |
604 | 0 | SET_TYPE_PTRS("unknown/"); |
605 | 0 | break; |
606 | 0 | default: |
607 | 0 | LM_ERR("invalid type\n"); |
608 | 0 | return 0; |
609 | 0 | } |
610 | | |
611 | 0 | switch (subtype) { |
612 | 0 | case SUBTYPE_PLAIN: |
613 | 0 | SET_SUBTYPE_PTR("plain"); |
614 | 0 | break; |
615 | 0 | case SUBTYPE_CPIM: |
616 | 0 | SET_SUBTYPE_PTR("cpim"); |
617 | 0 | break; |
618 | 0 | case SUBTYPE_SDP: |
619 | 0 | SET_SUBTYPE_PTR("sdp"); |
620 | 0 | break; |
621 | 0 | case SUBTYPE_CPLXML: |
622 | 0 | SET_SUBTYPE_PTR("cplxml"); |
623 | 0 | break; |
624 | 0 | case SUBTYPE_PIDFXML: |
625 | 0 | SET_SUBTYPE_PTR("pidfxml"); |
626 | 0 | break; |
627 | 0 | case SUBTYPE_RLMIXML: |
628 | 0 | SET_SUBTYPE_PTR("rlmixml"); |
629 | 0 | break; |
630 | 0 | case SUBTYPE_RELATED: |
631 | 0 | SET_SUBTYPE_PTR("related"); |
632 | 0 | break; |
633 | 0 | case SUBTYPE_LPIDFXML: |
634 | 0 | SET_SUBTYPE_PTR("lpidfxml"); |
635 | 0 | break; |
636 | 0 | case SUBTYPE_XPIDFXML: |
637 | 0 | SET_SUBTYPE_PTR("xpidfxml"); |
638 | 0 | break; |
639 | 0 | case SUBTYPE_WATCHERINFOXML: |
640 | 0 | SET_SUBTYPE_PTR("watcherinfoxml"); |
641 | 0 | break; |
642 | 0 | case SUBTYPE_EXTERNAL_BODY: |
643 | 0 | SET_SUBTYPE_PTR("external_body"); |
644 | 0 | break; |
645 | 0 | case SUBTYPE_XML_MSRTC_PIDF: |
646 | 0 | SET_SUBTYPE_PTR("xmlmsrtcpidf"); |
647 | 0 | break; |
648 | 0 | case SUBTYPE_SMS: |
649 | 0 | SET_SUBTYPE_PTR("sms"); |
650 | 0 | break; |
651 | 0 | case SUBTYPE_MIXED: |
652 | 0 | SET_SUBTYPE_PTR("mixed"); |
653 | 0 | break; |
654 | 0 | case SUBTYPE_ISUP: |
655 | 0 | SET_SUBTYPE_PTR("isup"); |
656 | 0 | break; |
657 | 0 | case SUBTYPE_ALL: |
658 | 0 | SET_SUBTYPE_PTR("*"); |
659 | 0 | break; |
660 | 0 | case SUBTYPE_UNKNOWN: |
661 | 0 | SET_SUBTYPE_PTR("unknown"); |
662 | 0 | break; |
663 | 0 | default: |
664 | 0 | LM_ERR("invalid subtype\n"); |
665 | 0 | return 0; |
666 | 0 | } |
667 | | |
668 | 0 | return str_contenttype; |
669 | |
|
670 | 0 | #undef SET_TYPE_PTRS |
671 | 0 | #undef SET_SUBTYPE_PTR |
672 | 0 | } |
673 | | |
674 | | |
675 | | |